00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #pragma once
00019
00020 #include <string>
00021 #include <string.h>
00022 #include <stdio.h>
00023 #include <boost/shared_ptr.hpp>
00024
00025 #include "../inline_decls.h"
00026 #include "../stringdata.h"
00027
00028 namespace mongo {
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 const int BSONObjMaxUserSize = 16 * 1024 * 1024;
00039
00040
00041
00042
00043
00044 const int BSONObjMaxInternalSize = BSONObjMaxUserSize + ( 16 * 1024 );
00045
00046 const int BufferMaxSize = 64 * 1024 * 1024;
00047
00048 class StringBuilder;
00049
00050 void msgasserted(int msgid, const char *msg);
00051
00052 class BufBuilder {
00053 public:
00054 BufBuilder(int initsize = 512) : size(initsize) {
00055 if ( size > 0 ) {
00056 data = (char *) malloc(size);
00057 if( data == 0 )
00058 msgasserted(10000, "out of memory BufBuilder");
00059 }
00060 else {
00061 data = 0;
00062 }
00063 l = 0;
00064 }
00065 ~BufBuilder() {
00066 kill();
00067 }
00068
00069 void kill() {
00070 if ( data ) {
00071 free(data);
00072 data = 0;
00073 }
00074 }
00075
00076 void reset( int maxSize = 0 ) {
00077 l = 0;
00078 if ( maxSize && size > maxSize ) {
00079 free(data);
00080 data = (char*)malloc(maxSize);
00081 size = maxSize;
00082 }
00083 }
00084
00088 char* skip(int n) { return grow(n); }
00089
00090
00091 char* buf() { return data; }
00092 const char* buf() const { return data; }
00093
00094
00095 void decouple() { data = 0; }
00096
00097 void appendChar(char j) {
00098 *((char*)grow(sizeof(char))) = j;
00099 }
00100 void appendNum(char j) {
00101 *((char*)grow(sizeof(char))) = j;
00102 }
00103 void appendNum(short j) {
00104 *((short*)grow(sizeof(short))) = j;
00105 }
00106 void appendNum(int j) {
00107 *((int*)grow(sizeof(int))) = j;
00108 }
00109 void appendNum(unsigned j) {
00110 *((unsigned*)grow(sizeof(unsigned))) = j;
00111 }
00112 void appendNum(bool j) {
00113 *((bool*)grow(sizeof(bool))) = j;
00114 }
00115 void appendNum(double j) {
00116 *((double*)grow(sizeof(double))) = j;
00117 }
00118 void appendNum(long long j) {
00119 *((long long*)grow(sizeof(long long))) = j;
00120 }
00121 void appendNum(unsigned long long j) {
00122 *((unsigned long long*)grow(sizeof(unsigned long long))) = j;
00123 }
00124
00125 void appendBuf(const void *src, size_t len) {
00126 memcpy(grow((int) len), src, len);
00127 }
00128
00129 template<class T>
00130 void appendStruct(const T& s) {
00131 appendBuf(&s, sizeof(T));
00132 }
00133
00134 void appendStr(const StringData &str , bool includeEOO = true ) {
00135 const int len = str.size() + ( includeEOO ? 1 : 0 );
00136 memcpy(grow(len), str.data(), len);
00137 }
00138
00139 int len() const { return l; }
00140 void setlen( int newLen ) { l = newLen; }
00141 int getSize() const { return size; }
00142
00143
00144 inline char* grow(int by) {
00145 int oldlen = l;
00146 l += by;
00147 if ( l > size ) {
00148 grow_reallocate();
00149 }
00150 return data + oldlen;
00151 }
00152
00153 private:
00154
00155 void NOINLINE_DECL grow_reallocate() {
00156 int a = size * 2;
00157 if ( a == 0 )
00158 a = 512;
00159 if ( l > a )
00160 a = l + 16 * 1024;
00161 if ( a > BufferMaxSize )
00162 msgasserted(13548, "BufBuilder grow() > 64MB");
00163 data = (char *) realloc(data, a);
00164 size= a;
00165 }
00166
00167 char *data;
00168 int l;
00169 int size;
00170
00171 friend class StringBuilder;
00172 };
00173
00174 #if defined(_WIN32)
00175 #pragma warning( push )
00176
00177 #pragma warning( disable : 4996 )
00178 #endif
00179
00181 class StringBuilder {
00182 public:
00183 StringBuilder( int initsize=256 )
00184 : _buf( initsize ) {
00185 }
00186
00187 StringBuilder& operator<<( double x ) {
00188 return SBNUM( x , 25 , "%g" );
00189 }
00190 StringBuilder& operator<<( int x ) {
00191 return SBNUM( x , 11 , "%d" );
00192 }
00193 StringBuilder& operator<<( unsigned x ) {
00194 return SBNUM( x , 11 , "%u" );
00195 }
00196 StringBuilder& operator<<( long x ) {
00197 return SBNUM( x , 22 , "%ld" );
00198 }
00199 StringBuilder& operator<<( unsigned long x ) {
00200 return SBNUM( x , 22 , "%lu" );
00201 }
00202 StringBuilder& operator<<( long long x ) {
00203 return SBNUM( x , 22 , "%lld" );
00204 }
00205 StringBuilder& operator<<( unsigned long long x ) {
00206 return SBNUM( x , 22 , "%llu" );
00207 }
00208 StringBuilder& operator<<( short x ) {
00209 return SBNUM( x , 8 , "%hd" );
00210 }
00211 StringBuilder& operator<<( char c ) {
00212 _buf.grow( 1 )[0] = c;
00213 return *this;
00214 }
00215
00216 void appendDoubleNice( double x ) {
00217 int prev = _buf.l;
00218 char * start = _buf.grow( 32 );
00219 int z = sprintf( start , "%.16g" , x );
00220 assert( z >= 0 );
00221 _buf.l = prev + z;
00222 if( strchr(start, '.') == 0 && strchr(start, 'E') == 0 && strchr(start, 'N') == 0 ) {
00223 write( ".0" , 2 );
00224 }
00225 }
00226
00227 void write( const char* buf, int len) { memcpy( _buf.grow( len ) , buf , len ); }
00228
00229 void append( const StringData& str ) { memcpy( _buf.grow( str.size() ) , str.data() , str.size() ); }
00230
00231 StringBuilder& operator<<( const StringData& str ) {
00232 append( str );
00233 return *this;
00234 }
00235
00236 void reset( int maxSize = 0 ) { _buf.reset( maxSize ); }
00237
00238 std::string str() const { return std::string(_buf.data, _buf.l); }
00239
00240 private:
00241 BufBuilder _buf;
00242
00243
00244 StringBuilder( const StringBuilder& );
00245 StringBuilder& operator=( const StringBuilder& );
00246
00247 template <typename T>
00248 StringBuilder& SBNUM(T val,int maxSize,const char *macro) {
00249 int prev = _buf.l;
00250 int z = sprintf( _buf.grow(maxSize) , macro , (val) );
00251 assert( z >= 0 );
00252 _buf.l = prev + z;
00253 return *this;
00254 }
00255 };
00256
00257 #if defined(_WIN32)
00258 #pragma warning( pop )
00259 #endif
00260
00261 }