|
MongoDB
2.0.3
|
00001 /* builder.h */ 00002 00003 /* Copyright 2009 10gen Inc. 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #pragma once 00019 00020 #include <string> 00021 #include <string.h> 00022 #include <stdio.h> 00023 #include "../inline_decls.h" 00024 #include "../stringdata.h" 00025 00026 namespace mongo { 00027 00028 /* Note the limit here is rather arbitrary and is simply a standard. generally the code works 00029 with any object that fits in ram. 00030 00031 Also note that the server has some basic checks to enforce this limit but those checks are not exhaustive 00032 for example need to check for size too big after 00033 update $push (append) operation 00034 various db.eval() type operations 00035 */ 00036 const int BSONObjMaxUserSize = 16 * 1024 * 1024; 00037 00038 /* 00039 Sometimeswe we need objects slightly larger - an object in the replication local.oplog 00040 is slightly larger than a user object for example. 00041 */ 00042 const int BSONObjMaxInternalSize = BSONObjMaxUserSize + ( 16 * 1024 ); 00043 00044 const int BufferMaxSize = 64 * 1024 * 1024; 00045 00046 class StringBuilder; 00047 00048 void msgasserted(int msgid, const char *msg); 00049 00050 class TrivialAllocator { 00051 public: 00052 void* Malloc(size_t sz) { return malloc(sz); } 00053 void* Realloc(void *p, size_t sz) { return realloc(p, sz); } 00054 void Free(void *p) { free(p); } 00055 }; 00056 00057 class StackAllocator { 00058 public: 00059 enum { SZ = 512 }; 00060 void* Malloc(size_t sz) { 00061 if( sz <= SZ ) return buf; 00062 return malloc(sz); 00063 } 00064 void* Realloc(void *p, size_t sz) { 00065 if( p == buf ) { 00066 if( sz <= SZ ) return buf; 00067 void *d = malloc(sz); 00068 if ( d == 0 ) 00069 msgasserted( 15912 , "out of memory StackAllocator::Realloc" ); 00070 memcpy(d, p, SZ); 00071 return d; 00072 } 00073 return realloc(p, sz); 00074 } 00075 void Free(void *p) { 00076 if( p != buf ) 00077 free(p); 00078 } 00079 private: 00080 char buf[SZ]; 00081 }; 00082 00083 template< class Allocator > 00084 class _BufBuilder { 00085 // non-copyable, non-assignable 00086 _BufBuilder( const _BufBuilder& ); 00087 _BufBuilder& operator=( const _BufBuilder& ); 00088 Allocator al; 00089 public: 00090 _BufBuilder(int initsize = 512) : size(initsize) { 00091 if ( size > 0 ) { 00092 data = (char *) al.Malloc(size); 00093 if( data == 0 ) 00094 msgasserted(10000, "out of memory BufBuilder"); 00095 } 00096 else { 00097 data = 0; 00098 } 00099 l = 0; 00100 } 00101 ~_BufBuilder() { kill(); } 00102 00103 void kill() { 00104 if ( data ) { 00105 al.Free(data); 00106 data = 0; 00107 } 00108 } 00109 00110 void reset() { 00111 l = 0; 00112 } 00113 void reset( int maxSize ) { 00114 l = 0; 00115 if ( maxSize && size > maxSize ) { 00116 al.Free(data); 00117 data = (char*)al.Malloc(maxSize); 00118 if ( data == 0 ) 00119 msgasserted( 15913 , "out of memory BufBuilder::reset" ); 00120 size = maxSize; 00121 } 00122 } 00123 00127 char* skip(int n) { return grow(n); } 00128 00129 /* note this may be deallocated (realloced) if you keep writing. */ 00130 char* buf() { return data; } 00131 const char* buf() const { return data; } 00132 00133 /* assume ownership of the buffer - you must then free() it */ 00134 void decouple() { data = 0; } 00135 00136 void appendUChar(unsigned char j) { 00137 *((unsigned char*)grow(sizeof(unsigned char))) = j; 00138 } 00139 void appendChar(char j) { 00140 *((char*)grow(sizeof(char))) = j; 00141 } 00142 void appendNum(char j) { 00143 *((char*)grow(sizeof(char))) = j; 00144 } 00145 void appendNum(short j) { 00146 *((short*)grow(sizeof(short))) = j; 00147 } 00148 void appendNum(int j) { 00149 *((int*)grow(sizeof(int))) = j; 00150 } 00151 void appendNum(unsigned j) { 00152 *((unsigned*)grow(sizeof(unsigned))) = j; 00153 } 00154 void appendNum(bool j) { 00155 *((bool*)grow(sizeof(bool))) = j; 00156 } 00157 void appendNum(double j) { 00158 *((double*)grow(sizeof(double))) = j; 00159 } 00160 void appendNum(long long j) { 00161 *((long long*)grow(sizeof(long long))) = j; 00162 } 00163 void appendNum(unsigned long long j) { 00164 *((unsigned long long*)grow(sizeof(unsigned long long))) = j; 00165 } 00166 00167 void appendBuf(const void *src, size_t len) { 00168 memcpy(grow((int) len), src, len); 00169 } 00170 00171 template<class T> 00172 void appendStruct(const T& s) { 00173 appendBuf(&s, sizeof(T)); 00174 } 00175 00176 void appendStr(const StringData &str , bool includeEndingNull = true ) { 00177 const int len = str.size() + ( includeEndingNull ? 1 : 0 ); 00178 memcpy(grow(len), str.data(), len); 00179 } 00180 00182 int len() const { return l; } 00183 void setlen( int newLen ) { l = newLen; } 00185 int getSize() const { return size; } 00186 00187 /* returns the pre-grow write position */ 00188 inline char* grow(int by) { 00189 int oldlen = l; 00190 l += by; 00191 if ( l > size ) { 00192 grow_reallocate(); 00193 } 00194 return data + oldlen; 00195 } 00196 00197 private: 00198 /* "slow" portion of 'grow()' */ 00199 void NOINLINE_DECL grow_reallocate() { 00200 int a = size * 2; 00201 if ( a == 0 ) 00202 a = 512; 00203 if ( l > a ) 00204 a = l + 16 * 1024; 00205 if ( a > BufferMaxSize ) 00206 msgasserted(13548, "BufBuilder grow() > 64MB"); 00207 data = (char *) al.Realloc(data, a); 00208 size= a; 00209 } 00210 00211 char *data; 00212 int l; 00213 int size; 00214 00215 friend class StringBuilder; 00216 }; 00217 00218 typedef _BufBuilder<TrivialAllocator> BufBuilder; 00219 00227 class StackBufBuilder : public _BufBuilder<StackAllocator> { 00228 public: 00229 StackBufBuilder() : _BufBuilder<StackAllocator>(StackAllocator::SZ) { } 00230 void decouple(); // not allowed. not implemented. 00231 }; 00232 00233 #if defined(_WIN32) 00234 #pragma warning( push ) 00235 // warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 00236 #pragma warning( disable : 4996 ) 00237 #endif 00238 00240 class StringBuilder { 00241 public: 00242 StringBuilder( int initsize=256 ) 00243 : _buf( initsize ) { 00244 } 00245 00246 StringBuilder& operator<<( double x ) { 00247 return SBNUM( x , 25 , "%g" ); 00248 } 00249 StringBuilder& operator<<( int x ) { 00250 return SBNUM( x , 11 , "%d" ); 00251 } 00252 StringBuilder& operator<<( unsigned x ) { 00253 return SBNUM( x , 11 , "%u" ); 00254 } 00255 StringBuilder& operator<<( long x ) { 00256 return SBNUM( x , 22 , "%ld" ); 00257 } 00258 StringBuilder& operator<<( unsigned long x ) { 00259 return SBNUM( x , 22 , "%lu" ); 00260 } 00261 StringBuilder& operator<<( long long x ) { 00262 return SBNUM( x , 22 , "%lld" ); 00263 } 00264 StringBuilder& operator<<( unsigned long long x ) { 00265 return SBNUM( x , 22 , "%llu" ); 00266 } 00267 StringBuilder& operator<<( short x ) { 00268 return SBNUM( x , 8 , "%hd" ); 00269 } 00270 StringBuilder& operator<<( char c ) { 00271 _buf.grow( 1 )[0] = c; 00272 return *this; 00273 } 00274 00275 void appendDoubleNice( double x ) { 00276 int prev = _buf.l; 00277 char * start = _buf.grow( 32 ); 00278 int z = sprintf( start , "%.16g" , x ); 00279 assert( z >= 0 ); 00280 _buf.l = prev + z; 00281 if( strchr(start, '.') == 0 && strchr(start, 'E') == 0 && strchr(start, 'N') == 0 ) { 00282 write( ".0" , 2 ); 00283 } 00284 } 00285 00286 void write( const char* buf, int len) { memcpy( _buf.grow( len ) , buf , len ); } 00287 00288 void append( const StringData& str ) { memcpy( _buf.grow( str.size() ) , str.data() , str.size() ); } 00289 00290 StringBuilder& operator<<( const StringData& str ) { 00291 append( str ); 00292 return *this; 00293 } 00294 00295 void reset( int maxSize = 0 ) { _buf.reset( maxSize ); } 00296 00297 std::string str() const { return std::string(_buf.data, _buf.l); } 00298 00299 int len() const { return _buf.l; } 00300 00301 private: 00302 BufBuilder _buf; 00303 00304 // non-copyable, non-assignable 00305 StringBuilder( const StringBuilder& ); 00306 StringBuilder& operator=( const StringBuilder& ); 00307 00308 template <typename T> 00309 StringBuilder& SBNUM(T val,int maxSize,const char *macro) { 00310 int prev = _buf.l; 00311 int z = sprintf( _buf.grow(maxSize) , macro , (val) ); 00312 assert( z >= 0 ); 00313 _buf.l = prev + z; 00314 return *this; 00315 } 00316 }; 00317 00318 #if defined(_WIN32) 00319 #pragma warning( pop ) 00320 #endif 00321 00322 } // namespace mongo
1.8.0