0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 01:21:03 +01:00
mongodb/bson/bsonmisc.h
2010-07-19 13:42:09 -04:00

196 lines
6.1 KiB
C++

// @file bsonmisc.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
namespace mongo {
int getGtLtOp(const BSONElement& e);
struct BSONElementCmpWithoutField {
bool operator()( const BSONElement &l, const BSONElement &r ) const {
return l.woCompare( r, false ) < 0;
}
};
class BSONObjCmp {
public:
BSONObjCmp( const BSONObj &_order = BSONObj() ) : order( _order ) {}
bool operator()( const BSONObj &l, const BSONObj &r ) const {
return l.woCompare( r, order ) < 0;
}
private:
BSONObj order;
};
class BSONObjCmpDefaultOrder : public BSONObjCmp {
public:
BSONObjCmpDefaultOrder() : BSONObjCmp( BSONObj() ) {}
};
typedef set< BSONObj, BSONObjCmpDefaultOrder > BSONObjSetDefaultOrder;
enum FieldCompareResult {
LEFT_SUBFIELD = -2,
LEFT_BEFORE = -1,
SAME = 0,
RIGHT_BEFORE = 1 ,
RIGHT_SUBFIELD = 2
};
FieldCompareResult compareDottedFieldNames( const string& l , const string& r );
/** Use BSON macro to build a BSONObj from a stream
e.g.,
BSON( "name" << "joe" << "age" << 33 )
with auto-generated object id:
BSON( GENOID << "name" << "joe" << "age" << 33 )
The labels GT, GTE, LT, LTE, NE can be helpful for stream-oriented construction
of a BSONObj, particularly when assembling a Query. For example,
BSON( "a" << GT << 23.4 << NE << 30 << "b" << 2 ) produces the object
{ a: { \$gt: 23.4, \$ne: 30 }, b: 2 }.
*/
#define BSON(x) (( mongo::BSONObjBuilder(64) << x ).obj())
/** Use BSON_ARRAY macro like BSON macro, but without keys
BSONArray arr = BSON_ARRAY( "hello" << 1 << BSON( "foo" << BSON_ARRAY( "bar" << "baz" << "qux" ) ) );
*/
#define BSON_ARRAY(x) (( mongo::BSONArrayBuilder() << x ).arr())
/* Utility class to auto assign object IDs.
Example:
cout << BSON( GENOID << "z" << 3 ); // { _id : ..., z : 3 }
*/
extern struct GENOIDLabeler { } GENOID;
/* Utility class to add a Date element with the current time
Example:
cout << BSON( "created" << DATENOW ); // { created : "2009-10-09 11:41:42" }
*/
extern struct DateNowLabeler { } DATENOW;
// Utility class to implement GT, GTE, etc as described above.
class Labeler {
public:
struct Label {
Label( const char *l ) : l_( l ) {}
const char *l_;
};
Labeler( const Label &l, BSONObjBuilderValueStream *s ) : l_( l ), s_( s ) {}
template<class T>
BSONObjBuilder& operator<<( T value );
/* the value of the element e is appended i.e. for
"age" << GT << someElement
one gets
{ age : { $gt : someElement's value } }
*/
BSONObjBuilder& operator<<( const BSONElement& e );
private:
const Label &l_;
BSONObjBuilderValueStream *s_;
};
extern Labeler::Label GT;
extern Labeler::Label GTE;
extern Labeler::Label LT;
extern Labeler::Label LTE;
extern Labeler::Label NE;
extern Labeler::Label SIZE;
// $or helper: OR(BSON("x" << GT << 7), BSON("y" << LT << 6));
// becomes : {$or: [{x: {$gt: 7}}, {y: {$lt: 6}}]}
inline BSONObj OR(const BSONObj& a, const BSONObj& b);
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c);
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c, const BSONObj& d);
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c, const BSONObj& d, const BSONObj& e);
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c, const BSONObj& d, const BSONObj& e, const BSONObj& f);
// definitions in bsonobjbuilder.h b/c of incomplete types
// Utility class to implement BSON( key << val ) as described above.
class BSONObjBuilderValueStream : public boost::noncopyable {
public:
friend class Labeler;
BSONObjBuilderValueStream( BSONObjBuilder * builder );
BSONObjBuilder& operator<<( const BSONElement& e );
template<class T>
BSONObjBuilder& operator<<( T value );
BSONObjBuilder& operator<<(DateNowLabeler& id);
Labeler operator<<( const Labeler::Label &l );
void endField( const char *nextFieldName = 0 );
bool subobjStarted() const { return _fieldName != 0; }
private:
const char * _fieldName;
BSONObjBuilder * _builder;
bool haveSubobj() const { return _subobj.get() != 0; }
BSONObjBuilder *subobj();
auto_ptr< BSONObjBuilder > _subobj;
};
/**
used in conjuction with BSONObjBuilder, allows for proper buffer size to prevent crazy memory usage
*/
class BSONSizeTracker {
public:
BSONSizeTracker(){
_pos = 0;
for ( int i=0; i<SIZE; i++ )
_sizes[i] = 512; // this is the default, so just be consistent
}
~BSONSizeTracker(){
}
void got( int size ){
_sizes[_pos++] = size;
if ( _pos >= SIZE )
_pos = 0;
}
/**
* right now choosing largest size
*/
int getSize() const {
int x = 16; // sane min
for ( int i=0; i<SIZE; i++ ){
if ( _sizes[i] > x )
x = _sizes[i];
}
return x;
}
private:
enum { SIZE = 10 };
int _pos;
int _sizes[SIZE];
};
}