w_strstream.h

00001 /* -*- mode:C++; c-basic-offset:4 -*-
00002      Shore-MT -- Multi-threaded port of the SHORE storage manager
00003    
00004                        Copyright (c) 2007-2009
00005       Data Intensive Applications and Systems Labaratory (DIAS)
00006                Ecole Polytechnique Federale de Lausanne
00007    
00008                          All Rights Reserved.
00009    
00010    Permission to use, copy, modify and distribute this software and
00011    its documentation is hereby granted, provided that both the
00012    copyright notice and this permission notice appear in all copies of
00013    the software, derivative works or modified versions, and any
00014    portions thereof, and that both notices appear in supporting
00015    documentation.
00016    
00017    This code is distributed in the hope that it will be useful, but
00018    WITHOUT ANY WARRANTY; without even the implied warranty of
00019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS
00020    DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
00021    RESULTING FROM THE USE OF THIS SOFTWARE.
00022 */
00023 
00024 /*<std-header orig-src='shore' incl-file-exclusion='W_STRSTREAM_H'>
00025 
00026  $Id: w_strstream.h,v 1.18 2010/05/26 01:20:26 nhall Exp $
00027 
00028 SHORE -- Scalable Heterogeneous Object REpository
00029 
00030 Copyright (c) 1994-99 Computer Sciences Department, University of
00031                       Wisconsin -- Madison
00032 All Rights Reserved.
00033 
00034 Permission to use, copy, modify and distribute this software and its
00035 documentation is hereby granted, provided that both the copyright
00036 notice and this permission notice appear in all copies of the
00037 software, derivative works or modified versions, and any portions
00038 thereof, and that both notices appear in supporting documentation.
00039 
00040 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
00041 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
00042 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
00043 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00044 
00045 This software was developed with support by the Advanced Research
00046 Project Agency, ARPA order number 018 (formerly 8230), monitored by
00047 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
00048 Further funding for this work was provided by DARPA through
00049 Rome Research Laboratory Contract No. F30602-97-2-0247.
00050 
00051 */
00052 
00053 #ifndef W_STRSTREAM_H
00054 #define W_STRSTREAM_H
00055 
00056 #include "w_defines.h"
00057 
00058 /*  -- do not edit anything above this line --   </std-header>*/
00059 
00060 #include <w_workaround.h>
00061 
00062 /*
00063  * Shore only supports "shore strstreams", which are a compatability
00064  * layer which
00065  *
00066  *   1) works with either strstream (or eventually) stringstream.
00067  *   2) provides automatic string deallocation, the most error-prone
00068  *      use of strstreams with allocated memory.
00069  *   3) Provides for static buffer non-dynamic streams to eliminate
00070  *      a large amount of duplicate shore code (forthcoming).
00071  *
00072  * The c_str() method _guarantees_ that the returned c-string WILL
00073  * be nul-terminated.  This prevents unterminated string bugs.  This
00074  * occurs at the expense of something else.  That cost is increasing
00075  * the buffer size on a dynamically allocated string.  Or, with a
00076  * fixed buffer, over-writing the last valid character (at the end
00077  * of the buffer) with a nul.   The implementation has low
00078  * overhead in the expected case that the string is nul-terminated
00079  * by 'ends'.
00080  *
00081  * To access the contents without any funky appending behavior, the
00082  * proper way to do that is with address+length.  That is done with
00083  * the data() method and then pcount() for the length of the buffer.
00084  *
00085  * The auto-deallocation mimics the behavior of newer stringstreams,
00086  * 
00087  */
00088 
00089 #ifdef W_USE_COMPAT_STRSTREAM
00090 #include "w_compat_strstream.h"
00091 #else
00092 #include <strstream>
00093 #endif
00094 #include <cstring>
00095 
00096 #if defined(W_USE_COMPAT_STRSTREAM)
00097 /* #define instead of typedef so everything is hidden, and not available
00098    or conflicting with other users. */
00099 #define    istrstream       shore_compat::istrstream
00100 #define    ostrstream       shore_compat::ostrstream
00101 #define    strstreambuf     shore_compat::strstreambuf
00102 #endif
00103 
00104 /**\brief Input string stream based on shore_compat::istrstream
00105  */
00106 class w_istrstream : public istrstream {
00107 public:
00108     /// Construct using strlen(s)
00109     w_istrstream(const char *s)
00110     : istrstream(VCPP_BUG_1 s, strlen(s))
00111     {
00112     }
00113 
00114     /// Construct using a given length
00115     w_istrstream(const char *s, size_t l)
00116     : istrstream(VCPP_BUG_1 s, l)
00117     {
00118     }
00119 
00120 };
00121 
00122 /**\brief Output string stream based on shore_compat::ostrstream
00123  */
00124 class w_ostrstream : public ostrstream {
00125 
00126 public:
00127     /// Construct w/o any length limit
00128     w_ostrstream()
00129     : ostrstream()
00130     {
00131     }
00132 
00133     /// Construct with given limit
00134     w_ostrstream(char *s, size_t l)
00135     : ostrstream(s, l)
00136     {
00137     }
00138 
00139     ~w_ostrstream()
00140     {
00141     }
00142 
00143     /// Return a pointer to nul-terminated output string.
00144     const char *c_str()
00145     {
00146         const char    *s = str();
00147         int        l = pcount();
00148         int        last = (l == 0 ? 0 : l-1);
00149 
00150         // ensure it is nul-terminated
00151         if (s[last] != '\0') {
00152             *this << ends;
00153 
00154             // it could move with the addition
00155             s = str();
00156             int    l2 = pcount();
00157             last = (l2 == 0 ? 0 : l2-1);
00158 
00159             // no growth ... the end string didn't fit
00160             // over-write the last valid char.
00161             // a throw would be a possibility too.
00162             if (l == l2 || s[last] != '\0')
00163                 ((char *)s)[last] = '\0';
00164         }
00165         return s;
00166     }
00167 
00168     /* Data() + size() allows access to buffer with nulls */
00169     /// Return a pointer to buffer.
00170     const char *data()
00171     {
00172         return str();
00173     }
00174 
00175     /// Return a pointer to copy of nul-terminated string. Delegates
00176     /// responsibility for freeing to the caller.
00177     const char *new_c_str()
00178     {
00179         /* A snapshot of the buffer as it currently is .. but still frozen */
00180         const char *s = c_str();
00181         char *t = new char[strlen(s) + 1]; 
00182         if (t)
00183             strcpy(t, s);
00184         return t;
00185     }
00186 
00187 };
00188 
00189 
00190 #if defined(__GNUG__)
00191 /* Older strstreams have different buffer semantics than newer ones */
00192 #if W_GCC_THIS_VER < W_GCC_VER(3,0)
00193 #define W_STRSTREAM_NEED_SETB
00194 #endif
00195 #endif
00196 
00197 
00198 /* XXX this would be easy as a template, but too much effort to maintain,
00199    and the stack issue would still be there. */
00200 
00201 /// Fixed-len buffer-based w_ostrstream
00202 class w_ostrstream_buf : public w_ostrstream {
00203     // maximum stack frame impingement
00204     enum { default_buf_size = 128 };
00205 
00206     char    *_buf;
00207     size_t    _buf_size;
00208 
00209     char    _default_buf[default_buf_size];
00210 
00211     // access underlying functions ... disgusting, but scoped funky
00212     class w_ostrstreambuf : public strstreambuf {
00213     public:
00214         void public_setbuf(char *start, size_t len)
00215         {
00216             // nothing to read
00217             setg(start, start, start);
00218 
00219             // just the buf to write
00220             setp(start, start + len);
00221 
00222 #ifdef W_STRSTREAM_NEED_SETB
00223             // and the underlying buffer too
00224             setb(start, start+len);
00225 #undef W_STRSTREAM_NEED_SETB
00226 #endif
00227         }
00228     };
00229 
00230 public:
00231     w_ostrstream_buf(size_t len)
00232     : w_ostrstream(_default_buf, default_buf_size),
00233       _buf(_default_buf),
00234       _buf_size(len <= default_buf_size ? len : (size_t)default_buf_size) // min
00235     {
00236         if (len > _buf_size)
00237             _buf = new char[len];
00238 
00239         if (len != _buf_size) {
00240             _buf_size = len;
00241             ((w_ostrstreambuf*) rdbuf())->public_setbuf(_buf, _buf_size);
00242         }
00243     }
00244 
00245     ~w_ostrstream_buf()
00246     {
00247         if (_buf != _default_buf)
00248             delete [] _buf;
00249         _buf = 0;
00250         _buf_size = 0;
00251     }
00252 };
00253 
00254 #ifdef W_USE_COMPAT_STRSTREAM
00255 #undef istrstream
00256 #undef ostrstream
00257 #undef strstreambuf
00258 #endif
00259 
00260 
00261 
00262 /*<std-footer incl-file-exclusion='W_STRSTREAM_H'>  -- do not edit anything below this line -- */
00263 
00264 #endif          /*</std-footer>*/

Generated on Wed Jul 7 17:22:32 2010 for Shore Storage Manager by  doxygen 1.4.7