MongoDB  2.1.1-pre-
bsonmisc.h
00001 // @file bsonmisc.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 namespace mongo {
00021 
00022     int getGtLtOp(const BSONElement& e);
00023 
00024     struct BSONElementCmpWithoutField {
00025         bool operator()( const BSONElement &l, const BSONElement &r ) const {
00026             return l.woCompare( r, false ) < 0;
00027         }
00028     };
00029 
00030     class BSONObjCmp {
00031     public:
00032         BSONObjCmp( const BSONObj &order = BSONObj() ) : _order( order ) {}
00033         bool operator()( const BSONObj &l, const BSONObj &r ) const {
00034             return l.woCompare( r, _order ) < 0;
00035         }
00036         BSONObj order() const { return _order; }
00037     private:
00038         BSONObj _order;
00039     };
00040 
00041     typedef set<BSONObj,BSONObjCmp> BSONObjSet;
00042 
00043     enum FieldCompareResult {
00044         LEFT_SUBFIELD = -2,
00045         LEFT_BEFORE = -1,
00046         SAME = 0,
00047         RIGHT_BEFORE = 1 ,
00048         RIGHT_SUBFIELD = 2
00049     };
00050 
00051     FieldCompareResult compareDottedFieldNames( const string& l , const string& r );
00052 
00066 #define BSON(x) (( mongo::BSONObjBuilder(64) << x ).obj())
00067 
00073 #define BSON_ARRAY(x) (( mongo::BSONArrayBuilder() << x ).arr())
00074 
00075     /* Utility class to auto assign object IDs.
00076        Example:
00077          cout << BSON( GENOID << "z" << 3 ); // { _id : ..., z : 3 }
00078     */
00079     extern struct GENOIDLabeler { } GENOID;
00080 
00081     /* Utility class to add a Date element with the current time
00082        Example:
00083          cout << BSON( "created" << DATENOW ); // { created : "2009-10-09 11:41:42" }
00084     */
00085     extern struct DateNowLabeler { } DATENOW;
00086 
00087     /* Utility class to assign a NULL value to a given attribute
00088        Example:
00089          cout << BSON( "a" << BSONNULL ); // { a : null }
00090     */
00091     extern struct NullLabeler { } BSONNULL;
00092 
00093     /* Utility class to add the minKey (minus infinity) to a given attribute
00094        Example:
00095          cout << BSON( "a" << MINKEY ); // { "a" : { "$minKey" : 1 } }
00096     */
00097     extern struct MinKeyLabeler { } MINKEY;
00098     extern struct MaxKeyLabeler { } MAXKEY;
00099 
00100     // Utility class to implement GT, GTE, etc as described above.
00101     class Labeler {
00102     public:
00103         struct Label {
00104             Label( const char *l ) : l_( l ) {}
00105             const char *l_;
00106         };
00107         Labeler( const Label &l, BSONObjBuilderValueStream *s ) : l_( l ), s_( s ) {}
00108         template<class T>
00109         BSONObjBuilder& operator<<( T value );
00110 
00111         /* the value of the element e is appended i.e. for
00112              "age" << GT << someElement
00113            one gets
00114              { age : { $gt : someElement's value } }
00115         */
00116         BSONObjBuilder& operator<<( const BSONElement& e );
00117     private:
00118         const Label &l_;
00119         BSONObjBuilderValueStream *s_;
00120     };
00121 
00122     extern Labeler::Label GT;
00123     extern Labeler::Label GTE;
00124     extern Labeler::Label LT;
00125     extern Labeler::Label LTE;
00126     extern Labeler::Label NE;
00127     extern Labeler::Label SIZE;
00128 
00129 
00130     // $or helper: OR(BSON("x" << GT << 7), BSON("y" << LT << 6));
00131     // becomes   : {$or: [{x: {$gt: 7}}, {y: {$lt: 6}}]}
00132     inline BSONObj OR(const BSONObj& a, const BSONObj& b);
00133     inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c);
00134     inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c, const BSONObj& d);
00135     inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c, const BSONObj& d, const BSONObj& e);
00136     inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c, const BSONObj& d, const BSONObj& e, const BSONObj& f);
00137     // definitions in bsonobjbuilder.h b/c of incomplete types
00138 
00139     // Utility class to implement BSON( key << val ) as described above.
00140     class BSONObjBuilderValueStream : public boost::noncopyable {
00141     public:
00142         friend class Labeler;
00143         BSONObjBuilderValueStream( BSONObjBuilder * builder );
00144 
00145         BSONObjBuilder& operator<<( const BSONElement& e );
00146 
00147         template<class T>
00148         BSONObjBuilder& operator<<( T value );
00149 
00150         BSONObjBuilder& operator<<(DateNowLabeler& id);
00151 
00152         BSONObjBuilder& operator<<(NullLabeler& id);
00153 
00154         BSONObjBuilder& operator<<(MinKeyLabeler& id);
00155         BSONObjBuilder& operator<<(MaxKeyLabeler& id);
00156 
00157         Labeler operator<<( const Labeler::Label &l );
00158 
00159         void endField( const char *nextFieldName = 0 );
00160         bool subobjStarted() const { return _fieldName != 0; }
00161 
00162     private:
00163         const char * _fieldName;
00164         BSONObjBuilder * _builder;
00165 
00166         bool haveSubobj() const { return _subobj.get() != 0; }
00167         BSONObjBuilder *subobj();
00168         auto_ptr< BSONObjBuilder > _subobj;
00169     };
00170 
00174     class BSONSizeTracker {
00175     public:
00176         BSONSizeTracker() {
00177             _pos = 0;
00178             for ( int i=0; i<SIZE; i++ )
00179                 _sizes[i] = 512; // this is the default, so just be consistent
00180         }
00181 
00182         ~BSONSizeTracker() {
00183         }
00184 
00185         void got( int size ) {
00186             _sizes[_pos++] = size;
00187             if ( _pos >= SIZE )
00188                 _pos = 0;
00189         }
00190 
00194         int getSize() const {
00195             int x = 16; // sane min
00196             for ( int i=0; i<SIZE; i++ ) {
00197                 if ( _sizes[i] > x )
00198                     x = _sizes[i];
00199             }
00200             return x;
00201         }
00202 
00203     private:
00204         enum { SIZE = 10 };
00205         int _pos;
00206         int _sizes[SIZE];
00207     };
00208 
00209     // considers order
00210     bool fieldsMatch(const BSONObj& lhs, const BSONObj& rhs);
00211 }