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.h149
1 files changed, 86 insertions, 63 deletions
diff --git a/bson/util/builder.h b/bson/util/builder.h
index 9d9eda2..6f4ff9e 100644
--- a/bson/util/builder.h
+++ b/bson/util/builder.h
@@ -27,6 +27,24 @@
namespace mongo {
+ /* Note the limit here is rather arbitrary and is simply a standard. generally the code works
+ with any object that fits in ram.
+
+ Also note that the server has some basic checks to enforce this limit but those checks are not exhaustive
+ for example need to check for size too big after
+ update $push (append) operation
+ various db.eval() type operations
+ */
+ const int BSONObjMaxUserSize = 16 * 1024 * 1024;
+
+ /*
+ Sometimeswe we need objects slightly larger - an object in the replication local.oplog
+ is slightly larger than a user object for example.
+ */
+ const int BSONObjMaxInternalSize = BSONObjMaxUserSize + ( 16 * 1024 );
+
+ const int BufferMaxSize = 64 * 1024 * 1024;
+
class StringBuilder;
void msgasserted(int msgid, const char *msg);
@@ -38,7 +56,8 @@ namespace mongo {
data = (char *) malloc(size);
if( data == 0 )
msgasserted(10000, "out of memory BufBuilder");
- } else {
+ }
+ else {
data = 0;
}
l = 0;
@@ -54,16 +73,18 @@ namespace mongo {
}
}
- void reset( int maxSize = 0 ){
+ void reset( int maxSize = 0 ) {
l = 0;
- if ( maxSize && size > maxSize ){
+ if ( maxSize && size > maxSize ) {
free(data);
data = (char*)malloc(maxSize);
size = maxSize;
- }
+ }
}
- /* leave room for some stuff later */
+ /** leave room for some stuff later
+ @return point to region that was skipped. pointer may change later (on realloc), so for immediate use only
+ */
char* skip(int n) { return grow(n); }
/* note this may be deallocated (realloced) if you keep writing. */
@@ -73,10 +94,10 @@ namespace mongo {
/* assume ownership of the buffer - you must then free() it */
void decouple() { data = 0; }
- void appendChar(char j){
+ void appendChar(char j) {
*((char*)grow(sizeof(char))) = j;
}
- void appendNum(char j){
+ void appendNum(char j) {
*((char*)grow(sizeof(char))) = j;
}
void appendNum(short j) {
@@ -105,18 +126,19 @@ namespace mongo {
memcpy(grow((int) len), src, len);
}
+ template<class T>
+ void appendStruct(const T& s) {
+ appendBuf(&s, sizeof(T));
+ }
+
void appendStr(const StringData &str , bool includeEOO = true ) {
const int len = str.size() + ( includeEOO ? 1 : 0 );
memcpy(grow(len), str.data(), len);
}
- int len() const {
- return l;
- }
-
- void setlen( int newLen ){
- l = newLen;
- }
+ int len() const { return l; }
+ void setlen( int newLen ) { l = newLen; }
+ int getSize() const { return size; }
/* returns the pre-grow write position */
inline char* grow(int by) {
@@ -128,18 +150,16 @@ namespace mongo {
return data + oldlen;
}
- int getSize() const { return size; }
-
private:
/* "slow" portion of 'grow()' */
- void NOINLINE_DECL grow_reallocate(){
+ void NOINLINE_DECL grow_reallocate() {
int a = size * 2;
if ( a == 0 )
a = 512;
if ( l > a )
a = l + 16 * 1024;
- if( a > 64 * 1024 * 1024 )
- msgasserted(10000, "BufBuilder grow() > 64MB");
+ if ( a > BufferMaxSize )
+ msgasserted(13548, "BufBuilder grow() > 64MB");
data = (char *) realloc(data, a);
size= a;
}
@@ -152,87 +172,90 @@ namespace mongo {
};
#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.
#pragma warning( disable : 4996 )
#endif
+ /** stringstream deals with locale so this is a lot faster than std::stringstream for UTF8 */
class StringBuilder {
public:
StringBuilder( int initsize=256 )
- : _buf( initsize ){
+ : _buf( initsize ) {
}
-#define SBNUM(val,maxSize,macro) \
- int prev = _buf.l; \
- int z = sprintf( _buf.grow(maxSize) , macro , (val) ); \
- assert( z >= 0 ); \
- _buf.l = prev + z; \
- return *this;
-
- StringBuilder& operator<<( double x ){
- SBNUM( x , 25 , "%g" );
+ StringBuilder& operator<<( double x ) {
+ return SBNUM( x , 25 , "%g" );
}
- StringBuilder& operator<<( int x ){
- SBNUM( x , 11 , "%d" );
+ StringBuilder& operator<<( int x ) {
+ return SBNUM( x , 11 , "%d" );
}
- StringBuilder& operator<<( unsigned x ){
- SBNUM( x , 11 , "%u" );
+ StringBuilder& operator<<( unsigned x ) {
+ return SBNUM( x , 11 , "%u" );
}
- StringBuilder& operator<<( long x ){
- SBNUM( x , 22 , "%ld" );
+ StringBuilder& operator<<( long x ) {
+ return SBNUM( x , 22 , "%ld" );
}
- StringBuilder& operator<<( unsigned long x ){
- SBNUM( x , 22 , "%lu" );
+ StringBuilder& operator<<( unsigned long x ) {
+ return SBNUM( x , 22 , "%lu" );
}
- StringBuilder& operator<<( long long x ){
- SBNUM( x , 22 , "%lld" );
+ StringBuilder& operator<<( long long x ) {
+ return SBNUM( x , 22 , "%lld" );
}
- StringBuilder& operator<<( unsigned long long x ){
- SBNUM( x , 22 , "%llu" );
+ StringBuilder& operator<<( unsigned long long x ) {
+ return SBNUM( x , 22 , "%llu" );
}
- StringBuilder& operator<<( short x ){
- SBNUM( x , 8 , "%hd" );
+ StringBuilder& operator<<( short x ) {
+ return SBNUM( x , 8 , "%hd" );
}
- StringBuilder& operator<<( char c ){
+ StringBuilder& operator<<( char c ) {
_buf.grow( 1 )[0] = c;
return *this;
}
-#undef SBNUM
- void appendDoubleNice( double x ){
+ void appendDoubleNice( double x ) {
int prev = _buf.l;
char * start = _buf.grow( 32 );
int z = sprintf( start , "%.16g" , x );
assert( z >= 0 );
_buf.l = prev + z;
- if( strchr(start, '.') == 0 && strchr(start, 'E') == 0 && strchr(start, 'N') == 0 ){
+ if( strchr(start, '.') == 0 && strchr(start, 'E') == 0 && strchr(start, 'N') == 0 ) {
write( ".0" , 2 );
}
}
- void write( const char* buf, int len){
- memcpy( _buf.grow( len ) , buf , len );
- }
+ void write( const char* buf, int len) { memcpy( _buf.grow( len ) , buf , len ); }
- void append( const StringData& str ){
- memcpy( _buf.grow( str.size() ) , str.data() , str.size() );
- }
- StringBuilder& operator<<( const StringData& str ){
+ void append( const StringData& str ) { memcpy( _buf.grow( str.size() ) , str.data() , str.size() ); }
+
+ StringBuilder& operator<<( const StringData& str ) {
append( str );
return *this;
}
-
- // access
- void reset( int maxSize = 0 ){
- _buf.reset( maxSize );
- }
-
- std::string str(){
- return std::string(_buf.data, _buf.l);
- }
+ void reset( int maxSize = 0 ) { _buf.reset( maxSize ); }
+
+ std::string str() const { return std::string(_buf.data, _buf.l); }
private:
BufBuilder _buf;
+
+ // non-copyable, non-assignable
+ StringBuilder( const StringBuilder& );
+ StringBuilder& operator=( const StringBuilder& );
+
+ template <typename T>
+ StringBuilder& SBNUM(T val,int maxSize,const char *macro) {
+ int prev = _buf.l;
+ int z = sprintf( _buf.grow(maxSize) , macro , (val) );
+ assert( z >= 0 );
+ _buf.l = prev + z;
+ return *this;
+ }
};
+#if defined(_WIN32)
+#pragma warning( pop )
+#endif
+
} // namespace mongo