MongoDB  2.1.1-pre-
bsonobj.h
00001 // @file bsonobj.h
00002 
00003 /*    Copyright 2009 10gen Inc.
00004  *
00005  *    Licensed under the Apache License, Version 2.0 (the "License");
00006  *    you may not use this file except in compliance with the License.
00007  *    You may obtain a copy of the License at
00008  *
00009  *    http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  *    Unless required by applicable law or agreed to in writing, software
00012  *    distributed under the License is distributed on an "AS IS" BASIS,
00013  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  *    See the License for the specific language governing permissions and
00015  *    limitations under the License.
00016  */
00017 
00018 #pragma once
00019 
00020 #include <boost/noncopyable.hpp>
00021 #include <boost/intrusive_ptr.hpp>
00022 #include <set>
00023 #include <list>
00024 #include <vector>
00025 #include "util/atomic_int.h"
00026 #include "util/builder.h"
00027 #include "stringdata.h"
00028 
00029 namespace mongo {
00030 
00031     typedef set< BSONElement, BSONElementCmpWithoutField > BSONElementSet;
00032     typedef multiset< BSONElement, BSONElementCmpWithoutField > BSONElementMSet;
00033 
00072     class BSONObj {
00073     public:
00074 
00078         explicit BSONObj(const char *msgdata) {
00079             init(msgdata);
00080         }
00081 
00086         class Holder;
00087         explicit BSONObj(Holder* holder) {
00088             init(holder);
00089         }
00090 
00091         explicit BSONObj(const Record *r);
00092 
00094         BSONObj();
00095 
00096         ~BSONObj() { 
00097             _objdata = 0; // defensive
00098         }
00099 
00128         bool isOwned() const { return _holder.get() != 0; }
00129 
00133         BSONObj getOwned() const;
00134 
00136         BSONObj copy() const;
00137 
00141         string toString( bool isArray = false, bool full=false ) const;
00142         void toString(StringBuilder& s, bool isArray = false, bool full=false ) const;
00143 
00147         string jsonString( JsonStringFormat format = Strict, int pretty = 0 ) const;
00148 
00150         int addFields(BSONObj& from, set<string>& fields); /* returns n added */
00151 
00155         BSONObj removeField(const StringData& name) const;
00156 
00160         int nFields() const;
00161 
00163         int getFieldNames(set<string>& fields) const;
00164 
00169         BSONElement getFieldDotted(const char *name) const;
00174         BSONElement getFieldDotted(const string& name) const {
00175             return getFieldDotted( name.c_str() );
00176         }
00177 
00182         void getFieldsDotted(const StringData& name, BSONElementSet &ret, bool expandLastArray = true ) const;
00183         void getFieldsDotted(const StringData& name, BSONElementMSet &ret, bool expandLastArray = true ) const;
00184 
00188         BSONElement getFieldDottedOrArray(const char *&name) const;
00189 
00193         BSONElement getField(const StringData& name) const;
00194 
00201         void getFields(unsigned n, const char **fieldNames, BSONElement *fields) const;
00202 
00206         BSONElement operator[] (const char *field) const {
00207             return getField(field);
00208         }
00209 
00210         BSONElement operator[] (const string& field) const {
00211             return getField(field);
00212         }
00213 
00214         BSONElement operator[] (int field) const {
00215             StringBuilder ss;
00216             ss << field;
00217             string s = ss.str();
00218             return getField(s.c_str());
00219         }
00220 
00222         bool hasField( const char * name ) const { return !getField(name).eoo(); }
00224         bool hasElement(const char *name) const { return hasField(name); }
00225 
00227         const char * getStringField(const char *name) const;
00228 
00230         BSONObj getObjectField(const char *name) const;
00231 
00233         int getIntField(const char *name) const;
00234 
00238         bool getBoolField(const char *name) const;
00239 
00245         BSONObj extractFieldsUnDotted(BSONObj pattern) const;
00246 
00252         BSONObj extractFields(const BSONObj &pattern , bool fillWithNull=false) const;
00253 
00254         BSONObj filterFieldsUndotted(const BSONObj &filter, bool inFilter) const;
00255 
00256         BSONElement getFieldUsingIndexNames(const char *fieldName, const BSONObj &indexKey) const;
00257 
00261         bool couldBeArray() const;
00262 
00264         const char *objdata() const {
00265             return _objdata;
00266         }
00268         int objsize() const { return *(reinterpret_cast<const int*>(objdata())); }
00269 
00271         bool isValid() const;
00272 
00276         bool okForStorage() const;
00277 
00279         bool isEmpty() const { return objsize() <= 5; }
00280 
00281         void dump() const;
00282 
00284         string hexDump() const;
00285 
00291         int woCompare(const BSONObj& r, const Ordering &o,
00292                       bool considerFieldName=true) const;
00293 
00299         int woCompare(const BSONObj& r, const BSONObj &ordering = BSONObj(),
00300                       bool considerFieldName=true) const;
00301 
00302         bool operator<( const BSONObj& other ) const { return woCompare( other ) < 0; }
00303         bool operator<=( const BSONObj& other ) const { return woCompare( other ) <= 0; }
00304         bool operator>( const BSONObj& other ) const { return woCompare( other ) > 0; }
00305         bool operator>=( const BSONObj& other ) const { return woCompare( other ) >= 0; }
00306 
00310         int woSortOrder( const BSONObj& r , const BSONObj& sortKey , bool useDotted=false ) const;
00311 
00312         bool equal(const BSONObj& r) const;
00313 
00317         bool binaryEqual(const BSONObj& r) const {
00318             int os = objsize();
00319             if ( os == r.objsize() ) {
00320                 return (os == 0 || memcmp(objdata(),r.objdata(),os)==0);
00321             }
00322             return false;
00323         }
00324 
00326         BSONElement firstElement() const { return BSONElement(objdata() + 4); }
00327 
00331         const char * firstElementFieldName() const { 
00332             const char *p = objdata() + 4;
00333             return *p == EOO ? "" : p+1;
00334         }
00335 
00336         BSONType firstElementType() const { 
00337             const char *p = objdata() + 4;
00338             return (BSONType) *p;
00339         }
00340 
00346         bool getObjectID(BSONElement& e) const;
00347 
00349         int hash() const {
00350             unsigned x = 0;
00351             const char *p = objdata();
00352             for ( int i = 0; i < objsize(); i++ )
00353                 x = x * 131 + p[i];
00354             return (x & 0x7fffffff) | 0x8000000; // must be > 0
00355         }
00356 
00357         // Return a version of this object where top level elements of types
00358         // that are not part of the bson wire protocol are replaced with
00359         // string identifier equivalents.
00360         // TODO Support conversion of element types other than min and max.
00361         BSONObj clientReadable() const;
00362 
00365         BSONObj replaceFieldNames( const BSONObj &obj ) const;
00366 
00368         bool valid() const;
00369 
00371         string md5() const;
00372 
00373         bool operator==( const BSONObj& other ) const { return equal( other ); }
00374         bool operator!=(const BSONObj& other) const { return !operator==( other); }
00375 
00376         enum MatchType {
00377             Equality = 0,
00378             LT = 0x1,
00379             LTE = 0x3,
00380             GTE = 0x6,
00381             GT = 0x4,
00382             opIN = 0x8, // { x : { $in : [1,2,3] } }
00383             NE = 0x9,
00384             opSIZE = 0x0A,
00385             opALL = 0x0B,
00386             NIN = 0x0C,
00387             opEXISTS = 0x0D,
00388             opMOD = 0x0E,
00389             opTYPE = 0x0F,
00390             opREGEX = 0x10,
00391             opOPTIONS = 0x11,
00392             opELEM_MATCH = 0x12,
00393             opNEAR = 0x13,
00394             opWITHIN = 0x14,
00395             opMAX_DISTANCE=0x15
00396         };
00397 
00399         void elems(vector<BSONElement> &) const;
00401         void elems(list<BSONElement> &) const;
00402 
00411         template <class T>
00412         void Vals(vector<T> &) const;
00414         template <class T>
00415         void Vals(list<T> &) const;
00416 
00418         template <class T>
00419         void vals(vector<T> &) const;
00421         template <class T>
00422         void vals(list<T> &) const;
00423 
00424         friend class BSONObjIterator;
00425         typedef BSONObjIterator iterator;
00426 
00433         BSONObjIterator begin() const;
00434 
00435         void appendSelfToBufBuilder(BufBuilder& b) const {
00436             assert( objsize() );
00437             b.appendBuf(reinterpret_cast<const void *>( objdata() ), objsize());
00438         }
00439 
00440 #pragma pack(1)
00441         class Holder : boost::noncopyable {
00442         private:
00443             Holder(); // this class should never be explicitly created
00444             AtomicUInt refCount;
00445         public:
00446             char data[4]; // start of object
00447 
00448             void zero() { refCount.zero(); }
00449 
00450             // these are called automatically by boost::intrusive_ptr
00451             friend void intrusive_ptr_add_ref(Holder* h) { h->refCount++; }
00452             friend void intrusive_ptr_release(Holder* h) {
00453 #if defined(_DEBUG) // cant use dassert or DEV here
00454                 assert((int)h->refCount > 0); // make sure we haven't already freed the buffer
00455 #endif
00456                 if(--(h->refCount) == 0){
00457 #if defined(_DEBUG)
00458                     unsigned sz = (unsigned&) *h->data;
00459                     assert(sz < BSONObjMaxInternalSize * 3);
00460                     memset(h->data, 0xdd, sz);
00461 #endif
00462                     free(h);
00463                 }
00464             }
00465         };
00466 #pragma pack()
00467 
00468     private:
00469         const char *_objdata;
00470         boost::intrusive_ptr< Holder > _holder;
00471 
00472         void _assertInvalid() const;
00473 
00474         void init(Holder *holder) {
00475             _holder = holder; // holder is now managed by intrusive_ptr
00476             init(holder->data);
00477         }
00478         void init(const char *data) {
00479             _objdata = data;
00480             if ( !isValid() )
00481                 _assertInvalid();
00482         }
00483     };
00484 
00485     ostream& operator<<( ostream &s, const BSONObj &o );
00486     ostream& operator<<( ostream &s, const BSONElement &e );
00487 
00488     StringBuilder& operator<<( StringBuilder &s, const BSONObj &o );
00489     StringBuilder& operator<<( StringBuilder &s, const BSONElement &e );
00490 
00491 
00492     struct BSONArray : BSONObj {
00493         // Don't add anything other than forwarding constructors!!!
00494         BSONArray(): BSONObj() {}
00495         explicit BSONArray(const BSONObj& obj): BSONObj(obj) {}
00496     };
00497 
00498 }