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");
118 void reset(
int maxSize ) {
120 if ( maxSize && size > maxSize ) {
122 data = (
char*)al.Malloc(maxSize);
124 msgasserted( 15913 ,
"out of memory BufBuilder::reset" );
132 char*
skip(
int n) {
return grow(n); }
135 char* buf() {
return data; }
136 const char* buf()
const {
return data; }
139 void decouple() { data = 0; }
141 void appendUChar(
unsigned char j) {
142 BOOST_STATIC_ASSERT(CHAR_BIT == 8);
145 void appendChar(
char j) {
148 void appendNum(
char j) {
151 void appendNum(
short j) {
152 BOOST_STATIC_ASSERT(
sizeof(
short) == 2);
155 void appendNum(
int j) {
156 BOOST_STATIC_ASSERT(
sizeof(
int) == 4);
159 void appendNum(
unsigned j) {
164#if __cplusplus >= 201103L
165 void appendNum(
bool j) =
delete;
167 void appendNum(
bool j) {
172 void appendNum(
double j) {
173 BOOST_STATIC_ASSERT(
sizeof(
double) == 8);
176 void appendNum(
long long j) {
177 BOOST_STATIC_ASSERT(
sizeof(
long long) == 8);
180 void appendNum(
unsigned long long j) {
184 void appendBuf(
const void *src,
size_t len) {
185 memcpy(grow((
int)
len), src,
len);
189 void appendStruct(
const T& s) {
190 appendBuf(&s,
sizeof(T));
193 void appendStr(
const StringData &str ,
bool includeEndingNull =
true ) {
194 const int len = str.size() + ( includeEndingNull ? 1 : 0 );
195 str.copyTo( grow(
len), includeEndingNull );
199 int len()
const {
return l; }
200 void setlen(
int newLen ) { l = newLen; }
205 inline char* grow(
int by) {
208 if ( newLen > size ) {
209 grow_reallocate(newLen);
212 return data + oldlen;
217 void appendNumImpl(T t) {
222 DataView(grow(
sizeof(t))).writeLE(t);
227 void NOINLINE_DECL grow_reallocate(
int newLen) {
231 if ( a > BufferMaxSize ) {
232 std::stringstream ss;
233 ss <<
"BufBuilder attempted to grow() to " << a <<
" bytes, past the 64MB limit.";
234 msgasserted(13548, ss.str().c_str());
236 data = (
char *) al.Realloc(data, a);
238 msgasserted( 16070 ,
"out of memory BufBuilder::grow_reallocate" );
246 friend class StringBuilderImpl<Allocator>;
249 typedef _BufBuilder<TrivialAllocator> BufBuilder;
265#pragma push_macro("snprintf")
266#define snprintf _snprintf
270 template <
typename Allocator>
274 static const size_t MONGO_DBL_SIZE = 3 + DBL_MANT_DIG - DBL_MIN_EXP + 1;
275 static const size_t MONGO_S32_SIZE = 12;
276 static const size_t MONGO_U32_SIZE = 11;
277 static const size_t MONGO_S64_SIZE = 23;
278 static const size_t MONGO_U64_SIZE = 22;
279 static const size_t MONGO_S16_SIZE = 7;
280 static const size_t MONGO_PTR_SIZE = 19;
285 return SBNUM( x , MONGO_DBL_SIZE ,
"%g" );
288 return SBNUM( x , MONGO_S32_SIZE ,
"%d" );
291 return SBNUM( x , MONGO_U32_SIZE ,
"%u" );
294 return SBNUM( x , MONGO_S64_SIZE ,
"%ld" );
297 return SBNUM( x , MONGO_U64_SIZE ,
"%lu" );
300 return SBNUM( x , MONGO_S64_SIZE ,
"%lld" );
303 return SBNUM( x , MONGO_U64_SIZE ,
"%llu" );
306 return SBNUM( x , MONGO_S16_SIZE ,
"%hd" );
309 if (
sizeof(x) == 8) {
310 return SBNUM(x, MONGO_PTR_SIZE,
"0x%llX");
313 return SBNUM(x, MONGO_PTR_SIZE,
"0x%lX");
317 _buf.grow( 1 )[0] = c;
321 return *
this << StringData(str);
328 void appendDoubleNice(
double x ) {
329 const int prev = _buf.l;
330 const int maxSize = 32;
331 char * start = _buf.grow( maxSize );
332 int z = snprintf( start , maxSize ,
"%.16g" , x );
334 verify( z < maxSize );
336 if( strchr(start,
'.') == 0 && strchr(start,
'E') == 0 && strchr(start,
'N') == 0 ) {
341 void write(
const char* buf,
int len) { memcpy( _buf.grow(
len ) , buf ,
len ); }
343 void append(
const StringData& str ) { str.copyTo( _buf.grow( str.size() ),
false ); }
345 void reset(
int maxSize = 0 ) { _buf.reset( maxSize ); }
347 std::string str()
const {
return std::string(_buf.data, _buf.l); }
350 int len()
const {
return _buf.l; }
359 template <
typename T>
362 int z = snprintf( _buf.grow(maxSize) , maxSize , macro , (val) );
364 verify( z < maxSize );
370 typedef StringBuilderImpl<TrivialAllocator> StringBuilder;
371 typedef StringBuilderImpl<StackAllocator> StackStringBuilder;
375#pragma pop_macro("snprintf")
The StackBufBuilder builds smaller datasets on the stack instead of using malloc.
Definition builder.h:258
std::stringstream deals with locale so this is a lot faster than std::stringstream for UTF8
Definition builder.h:271
int len() const
size of current string
Definition builder.h:350
char * skip(int n)
leave room for some stuff later
Definition builder.h:132
int getSize() const
Definition builder.h:202
int len() const
Definition builder.h:199
the main MongoDB namespace
Definition bulk_operation_builder.h:24