25#include <boost/static_assert.hpp>
27#include "mongo/base/data_view.h"
28#include "mongo/base/string_data.h"
29#include "mongo/bson/inline_decls.h"
30#include "mongo/util/assert_util.h"
42 const int BSONObjMaxUserSize = 16 * 1024 * 1024;
48 const int BSONObjMaxInternalSize = BSONObjMaxUserSize + ( 16 * 1024 );
50 const int BufferMaxSize = 64 * 1024 * 1024;
52 template <
typename Allocator>
53 class StringBuilderImpl;
57 void* Malloc(
size_t sz) {
return malloc(sz); }
58 void* Realloc(
void *p,
size_t sz) {
return realloc(p, sz); }
59 void Free(
void *p) { free(p); }
65 void* Malloc(
size_t sz) {
66 if( sz <= SZ )
return buf;
69 void* Realloc(
void *p,
size_t sz) {
71 if( sz <= SZ )
return buf;
74 msgasserted( 15912 ,
"out of memory StackAllocator::Realloc" );
78 return realloc(p, sz);
88 template<
class Allocator >
97 data = (
char *) al.Malloc(size);
99 msgasserted(10000,
"out of memory BufBuilder");
120 void reset(
int maxSize ) {
123 if ( maxSize && size > maxSize ) {
125 data = (
char*)al.Malloc(maxSize);
127 msgasserted( 15913 ,
"out of memory BufBuilder::reset" );
135 char*
skip(
int n) {
return grow(n); }
138 char* buf() {
return data; }
139 const char* buf()
const {
return data; }
142 void decouple() { data = 0; }
144 void appendUChar(
unsigned char j) {
145 BOOST_STATIC_ASSERT(CHAR_BIT == 8);
148 void appendChar(
char j) {
151 void appendNum(
char j) {
154 void appendNum(
short j) {
155 BOOST_STATIC_ASSERT(
sizeof(
short) == 2);
158 void appendNum(
int j) {
159 BOOST_STATIC_ASSERT(
sizeof(
int) == 4);
162 void appendNum(
unsigned j) {
167#if __cplusplus >= 201103L
168 void appendNum(
bool j) =
delete;
170 void appendNum(
bool j) {
175 void appendNum(
double j) {
176 BOOST_STATIC_ASSERT(
sizeof(
double) == 8);
179 void appendNum(
long long j) {
180 BOOST_STATIC_ASSERT(
sizeof(
long long) == 8);
183 void appendNum(
unsigned long long j) {
187 void appendBuf(
const void *src,
size_t len) {
188 memcpy(grow((
int)
len), src,
len);
192 void appendStruct(
const T& s) {
193 appendBuf(&s,
sizeof(T));
196 void appendStr(
const StringData &str ,
bool includeEndingNull =
true ) {
197 const int len = str.size() + ( includeEndingNull ? 1 : 0 );
198 str.copyTo( grow(
len), includeEndingNull );
202 int len()
const {
return l; }
203 void setlen(
int newLen ) { l = newLen; }
208 inline char* grow(
int by) {
211 int minSize = newLen + reservedBytes;
212 if ( minSize > size ) {
213 grow_reallocate(minSize);
216 return data + oldlen;
223 int minSize = l + reservedBytes + bytes;
225 grow_reallocate(minSize);
228 reservedBytes += bytes;
237 invariant(reservedBytes >= bytes);
238 reservedBytes -= bytes;
243 void appendNumImpl(T t) {
248 DataView(grow(
sizeof(t))).writeLE(t);
253 void NOINLINE_DECL grow_reallocate(
int minSize) {
258 if ( a > BufferMaxSize ) {
259 std::stringstream ss;
260 ss <<
"BufBuilder attempted to grow() to " << a <<
" bytes, past the 64MB limit.";
261 msgasserted(13548, ss.str().c_str());
263 data = (
char *) al.Realloc(data, a);
265 msgasserted( 16070 ,
"out of memory BufBuilder::grow_reallocate" );
274 friend class StringBuilderImpl<Allocator>;
277 typedef _BufBuilder<TrivialAllocator> BufBuilder;
293#pragma push_macro("snprintf")
294#define snprintf _snprintf
298 template <
typename Allocator>
302 static const size_t MONGO_DBL_SIZE = 3 + DBL_MANT_DIG - DBL_MIN_EXP + 1;
303 static const size_t MONGO_S32_SIZE = 12;
304 static const size_t MONGO_U32_SIZE = 11;
305 static const size_t MONGO_S64_SIZE = 23;
306 static const size_t MONGO_U64_SIZE = 22;
307 static const size_t MONGO_S16_SIZE = 7;
308 static const size_t MONGO_PTR_SIZE = 19;
313 return SBNUM( x , MONGO_DBL_SIZE ,
"%g" );
316 return SBNUM( x , MONGO_S32_SIZE ,
"%d" );
319 return SBNUM( x , MONGO_U32_SIZE ,
"%u" );
322 return SBNUM( x , MONGO_S64_SIZE ,
"%ld" );
325 return SBNUM( x , MONGO_U64_SIZE ,
"%lu" );
328 return SBNUM( x , MONGO_S64_SIZE ,
"%lld" );
331 return SBNUM( x , MONGO_U64_SIZE ,
"%llu" );
334 return SBNUM( x , MONGO_S16_SIZE ,
"%hd" );
337 if (
sizeof(x) == 8) {
338 return SBNUM(x, MONGO_PTR_SIZE,
"0x%llX");
341 return SBNUM(x, MONGO_PTR_SIZE,
"0x%lX");
345 _buf.grow( 1 )[0] = c;
349 return *
this << StringData(str);
356 void appendDoubleNice(
double x ) {
357 const int prev = _buf.l;
358 const int maxSize = 32;
359 char * start = _buf.grow( maxSize );
360 int z = snprintf( start , maxSize ,
"%.16g" , x );
362 verify( z < maxSize );
364 if( strchr(start,
'.') == 0 && strchr(start,
'E') == 0 && strchr(start,
'N') == 0 ) {
369 void write(
const char* buf,
int len) { memcpy( _buf.grow(
len ) , buf ,
len ); }
371 void append(
const StringData& str ) { str.copyTo( _buf.grow( str.size() ),
false ); }
373 void reset(
int maxSize = 0 ) { _buf.reset( maxSize ); }
375 std::string str()
const {
return std::string(_buf.data, _buf.l); }
378 int len()
const {
return _buf.l; }
387 template <
typename T>
390 int z = snprintf( _buf.grow(maxSize) , maxSize , macro , (val) );
392 verify( z < maxSize );
398 typedef StringBuilderImpl<TrivialAllocator> StringBuilder;
399 typedef StringBuilderImpl<StackAllocator> StackStringBuilder;
403#pragma pop_macro("snprintf")
The StackBufBuilder builds smaller datasets on the stack instead of using malloc.
Definition builder.h:286
std::stringstream deals with locale so this is a lot faster than std::stringstream for UTF8
Definition builder.h:299
int len() const
size of current string
Definition builder.h:378
void reserveBytes(int bytes)
Reserve room for some number of bytes to be claimed at a later time.
Definition builder.h:222
char * skip(int n)
leave room for some stuff later
Definition builder.h:135
int getSize() const
Definition builder.h:205
int len() const
Definition builder.h:202
void claimReservedBytes(int bytes)
Claim an earlier reservation of some number of bytes.
Definition builder.h:236
the main MongoDB namespace
Definition bulk_operation_builder.h:24