diff options
author | Antonin Kral <a.kral@bobek.cz> | 2010-08-11 12:38:57 +0200 |
---|---|---|
committer | Antonin Kral <a.kral@bobek.cz> | 2010-08-11 12:38:57 +0200 |
commit | 7645618fd3914cb8a20561625913c20d49504a49 (patch) | |
tree | 8370f846f58f6d71165b7a0e2eda04648584ec76 /bson/util/builder.h | |
parent | 68c73c3c7608b4c87f07440dc3232801720b1168 (diff) | |
download | mongodb-7645618fd3914cb8a20561625913c20d49504a49.tar.gz |
Imported Upstream version 1.6.0
Diffstat (limited to 'bson/util/builder.h')
-rw-r--r-- | bson/util/builder.h | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/bson/util/builder.h b/bson/util/builder.h new file mode 100644 index 0000000..75a1ad8 --- /dev/null +++ b/bson/util/builder.h @@ -0,0 +1,226 @@ +/* builder.h */ + +/* Copyright 2009 10gen Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <string> +#include <string.h> +#include <stdio.h> +#include <boost/shared_ptr.hpp> + +#include "../inline_decls.h" +#include "../stringdata.h" + +namespace mongo { + + class StringBuilder; + + void msgasserted(int msgid, const char *msg); + + class BufBuilder { + public: + BufBuilder(int initsize = 512) : size(initsize) { + if ( size > 0 ) { + data = (char *) malloc(size); + if( data == 0 ) + msgasserted(10000, "out of memory BufBuilder"); + } else { + data = 0; + } + l = 0; + } + ~BufBuilder() { + kill(); + } + + void kill() { + if ( data ) { + free(data); + data = 0; + } + } + + void reset( int maxSize = 0 ){ + l = 0; + if ( maxSize && size > maxSize ){ + free(data); + data = (char*)malloc(maxSize); + size = maxSize; + } + } + + /* leave room for some stuff later */ + char* skip(int n) { return grow(n); } + + /* note this may be deallocated (realloced) if you keep writing. */ + char* buf() { return data; } + const char* buf() const { return data; } + + /* assume ownership of the buffer - you must then free() it */ + void decouple() { data = 0; } + + void appendChar(char j){ + *((char*)grow(sizeof(char))) = j; + } + void appendNum(char j){ + *((char*)grow(sizeof(char))) = j; + } + void appendNum(short j) { + *((short*)grow(sizeof(short))) = j; + } + void appendNum(int j) { + *((int*)grow(sizeof(int))) = j; + } + void appendNum(unsigned j) { + *((unsigned*)grow(sizeof(unsigned))) = j; + } + void appendNum(bool j) { + *((bool*)grow(sizeof(bool))) = j; + } + void appendNum(double j) { + *((double*)grow(sizeof(double))) = j; + } + void appendNum(long long j) { + *((long long*)grow(sizeof(long long))) = j; + } + void appendNum(unsigned long long j) { + *((unsigned long long*)grow(sizeof(unsigned long long))) = j; + } + + void appendBuf(const void *src, size_t len) { + memcpy(grow((int) len), src, len); + } + + 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; + } + + /* returns the pre-grow write position */ + inline char* grow(int by) { + int oldlen = l; + l += by; + if ( l > size ) { + grow_reallocate(); + } + return data + oldlen; + } + + int getSize() const { return size; } + + private: + /* "slow" portion of 'grow()' */ + 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"); + data = (char *) realloc(data, a); + size= a; + } + + char *data; + int l; + int size; + + friend class StringBuilder; + }; + +#if defined(_WIN32) +#pragma warning( disable : 4996 ) +#endif + + class StringBuilder { + public: + StringBuilder( int initsize=256 ) + : _buf( initsize ){ + } + +#define SBNUM(val,maxSize,macro) \ + int prev = _buf.l; \ + int z = sprintf( _buf.grow(maxSize) , macro , (val) ); \ + _buf.l = prev + z; \ + return *this; + + StringBuilder& operator<<( double x ){ + SBNUM( x , 25 , "%g" ); + } + StringBuilder& operator<<( int x ){ + SBNUM( x , 11 , "%d" ); + } + StringBuilder& operator<<( unsigned x ){ + SBNUM( x , 11 , "%u" ); + } + StringBuilder& operator<<( long x ){ + SBNUM( x , 22 , "%ld" ); + } + StringBuilder& operator<<( unsigned long x ){ + SBNUM( x , 22 , "%lu" ); + } + StringBuilder& operator<<( long long x ){ + SBNUM( x , 22 , "%lld" ); + } + StringBuilder& operator<<( unsigned long long x ){ + SBNUM( x , 22 , "%llu" ); + } + StringBuilder& operator<<( short x ){ + SBNUM( x , 8 , "%hd" ); + } + StringBuilder& operator<<( char c ){ + _buf.grow( 1 )[0] = c; + return *this; + } +#undef SBNUM + + 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 ){ + append( str ); + return *this; + } + + // access + + void reset( int maxSize = 0 ){ + _buf.reset( maxSize ); + } + + std::string str(){ + return std::string(_buf.data, _buf.l); + } + + private: + BufBuilder _buf; + }; + +} // namespace mongo |