00001 // @file alignedbuilder.h 00002 00019 #pragma once 00020 00021 #include "../bson/stringdata.h" 00022 00023 namespace mongo { 00024 00026 class AlignedBuilder { 00027 public: 00028 AlignedBuilder(unsigned init_size); 00029 ~AlignedBuilder() { kill(); } 00030 00032 void reset() { 00033 _len = 0; 00034 const unsigned sizeCap = 128*1024*1024; 00035 if (_p._size > sizeCap) 00036 _realloc(sizeCap, _len); 00037 } 00038 00040 const char* buf() const { return _p._data; } 00041 00045 size_t skip(unsigned n) { 00046 unsigned l = len(); 00047 grow(n); 00048 return l; 00049 } 00050 00051 char* atOfs(unsigned ofs) { return _p._data + ofs; } 00052 00053 void appendChar(char j) { 00054 *((char*)grow(sizeof(char))) = j; 00055 } 00056 void appendNum(char j) { 00057 *((char*)grow(sizeof(char))) = j; 00058 } 00059 void appendNum(short j) { 00060 *((short*)grow(sizeof(short))) = j; 00061 } 00062 void appendNum(int j) { 00063 *((int*)grow(sizeof(int))) = j; 00064 } 00065 void appendNum(unsigned j) { 00066 *((unsigned*)grow(sizeof(unsigned))) = j; 00067 } 00068 void appendNum(bool j) { 00069 *((bool*)grow(sizeof(bool))) = j; 00070 } 00071 void appendNum(double j) { 00072 *((double*)grow(sizeof(double))) = j; 00073 } 00074 void appendNum(long long j) { 00075 *((long long*)grow(sizeof(long long))) = j; 00076 } 00077 void appendNum(unsigned long long j) { 00078 *((unsigned long long*)grow(sizeof(unsigned long long))) = j; 00079 } 00080 00081 void appendBuf(const void *src, size_t len) { memcpy(grow((unsigned) len), src, len); } 00082 00083 template<class T> 00084 void appendStruct(const T& s) { appendBuf(&s, sizeof(T)); } 00085 00086 void appendStr(const StringData &str , bool includeEOO = true ) { 00087 const unsigned len = str.size() + ( includeEOO ? 1 : 0 ); 00088 assert( len < (unsigned) BSONObjMaxUserSize ); 00089 memcpy(grow(len), str.data(), len); 00090 } 00091 00093 unsigned len() const { return _len; } 00094 00095 private: 00096 static const unsigned Alignment = 8192; 00097 00099 inline char* grow(unsigned by) { 00100 unsigned oldlen = _len; 00101 _len += by; 00102 if ( _len > _p._size ) { 00103 growReallocate(oldlen); 00104 } 00105 return _p._data + oldlen; 00106 } 00107 00108 void growReallocate(unsigned oldLenInUse); 00109 void kill(); 00110 void mallocSelfAligned(unsigned sz); 00111 void _malloc(unsigned sz); 00112 void _realloc(unsigned newSize, unsigned oldLenInUse); 00113 void _free(void*); 00114 00115 struct AllocationInfo { 00116 char *_data; 00117 void *_allocationAddress; 00118 unsigned _size; 00119 } _p; 00120 unsigned _len; // bytes in use 00121 }; 00122 00123 }