summaryrefslogtreecommitdiff
path: root/bson/util/builder.h
diff options
context:
space:
mode:
Diffstat (limited to 'bson/util/builder.h')
-rw-r--r--bson/util/builder.h87
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;