diff options
Diffstat (limited to 'bson/util/builder.h')
-rw-r--r-- | bson/util/builder.h | 87 |
1 files changed, 72 insertions, 15 deletions
diff --git a/bson/util/builder.h b/bson/util/builder.h index 6f4ff9e..710c2d4 100644 --- a/bson/util/builder.h +++ b/bson/util/builder.h @@ -20,8 +20,6 @@ #include <string> #include <string.h> #include <stdio.h> -#include <boost/shared_ptr.hpp> - #include "../inline_decls.h" #include "../stringdata.h" @@ -49,11 +47,47 @@ namespace mongo { void msgasserted(int msgid, const char *msg); - class BufBuilder { + class TrivialAllocator { + public: + void* Malloc(size_t sz) { return malloc(sz); } + void* Realloc(void *p, size_t sz) { return realloc(p, sz); } + void Free(void *p) { free(p); } + }; + + class StackAllocator { + public: + enum { SZ = 512 }; + void* Malloc(size_t sz) { + if( sz <= SZ ) return buf; + return malloc(sz); + } + void* Realloc(void *p, size_t sz) { + if( p == buf ) { + if( sz <= SZ ) return buf; + void *d = malloc(sz); + memcpy(d, p, SZ); + return d; + } + return realloc(p, sz); + } + void Free(void *p) { + if( p != buf ) + free(p); + } + private: + char buf[SZ]; + }; + + template< class Allocator > + class _BufBuilder { + // non-copyable, non-assignable + _BufBuilder( const _BufBuilder& ); + _BufBuilder& operator=( const _BufBuilder& ); + Allocator al; public: - BufBuilder(int initsize = 512) : size(initsize) { + _BufBuilder(int initsize = 512) : size(initsize) { if ( size > 0 ) { - data = (char *) malloc(size); + data = (char *) al.Malloc(size); if( data == 0 ) msgasserted(10000, "out of memory BufBuilder"); } @@ -62,22 +96,23 @@ namespace mongo { } l = 0; } - ~BufBuilder() { - kill(); - } + ~_BufBuilder() { kill(); } void kill() { if ( data ) { - free(data); + al.Free(data); data = 0; } } - void reset( int maxSize = 0 ) { + void reset() { + l = 0; + } + void reset( int maxSize ) { l = 0; if ( maxSize && size > maxSize ) { - free(data); - data = (char*)malloc(maxSize); + al.Free(data); + data = (char*)al.Malloc(maxSize); size = maxSize; } } @@ -94,6 +129,9 @@ namespace mongo { /* assume ownership of the buffer - you must then free() it */ void decouple() { data = 0; } + void appendUChar(unsigned char j) { + *((unsigned char*)grow(sizeof(unsigned char))) = j; + } void appendChar(char j) { *((char*)grow(sizeof(char))) = j; } @@ -131,13 +169,15 @@ namespace mongo { appendBuf(&s, sizeof(T)); } - void appendStr(const StringData &str , bool includeEOO = true ) { - const int len = str.size() + ( includeEOO ? 1 : 0 ); + void appendStr(const StringData &str , bool includeEndingNull = true ) { + const int len = str.size() + ( includeEndingNull ? 1 : 0 ); memcpy(grow(len), str.data(), len); } + /** @return length of current string */ int len() const { return l; } void setlen( int newLen ) { l = newLen; } + /** @return size of the buffer */ int getSize() const { return size; } /* returns the pre-grow write position */ @@ -160,7 +200,7 @@ namespace mongo { a = l + 16 * 1024; if ( a > BufferMaxSize ) msgasserted(13548, "BufBuilder grow() > 64MB"); - data = (char *) realloc(data, a); + data = (char *) al.Realloc(data, a); size= a; } @@ -171,6 +211,21 @@ namespace mongo { friend class StringBuilder; }; + typedef _BufBuilder<TrivialAllocator> BufBuilder; + + /** The StackBufBuilder builds smaller datasets on the stack instead of using malloc. + this can be significantly faster for small bufs. However, you can not decouple() the + buffer with StackBufBuilder. + While designed to be a variable on the stack, if you were to dynamically allocate one, + nothing bad would happen. In fact in some circumstances this might make sense, say, + embedded in some other object. + */ + class StackBufBuilder : public _BufBuilder<StackAllocator> { + public: + StackBufBuilder() : _BufBuilder<StackAllocator>(StackAllocator::SZ) { } + void decouple(); // not allowed. not implemented. + }; + #if defined(_WIN32) #pragma warning( push ) // warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. @@ -236,6 +291,8 @@ namespace mongo { void reset( int maxSize = 0 ) { _buf.reset( maxSize ); } std::string str() const { return std::string(_buf.data, _buf.l); } + + int len() const { return _buf.l; } private: BufBuilder _buf; |