// @file bsonmisc.h
/* Copyright 2009 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
#pragma once
#include "mongo/bson/bsonelement.h"
#include "mongo/bson/bsonobj.h"
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;
}
BSONObj order() const { return _order; }
private:
BSONObj _order;
};
typedef std::set BSONObjSet;
enum FieldCompareResult {
LEFT_SUBFIELD = -2,
LEFT_BEFORE = -1,
SAME = 0,
RIGHT_BEFORE = 1 ,
RIGHT_SUBFIELD = 2
};
/** 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:
std::cout << BSON( GENOID << "z" << 3 ); // { _id : ..., z : 3 }
*/
struct GENOIDLabeler { };
extern GENOIDLabeler GENOID;
/* Utility class to add a Date element with the current time
Example:
std::cout << BSON( "created" << DATENOW ); // { created : "2009-10-09 11:41:42" }
*/
struct DateNowLabeler { };
extern DateNowLabeler DATENOW;
/* Utility class to assign a NULL value to a given attribute
Example:
std::cout << BSON( "a" << BSONNULL ); // { a : null }
*/
struct NullLabeler { };
extern NullLabeler BSONNULL;
/* Utility class to assign an Undefined value to a given attribute
Example:
std::cout << BSON( "a" << BSONUndefined ); // { a : undefined }
*/
struct UndefinedLabeler { };
extern UndefinedLabeler BSONUndefined;
/* Utility class to add the minKey (minus infinity) to a given attribute
Example:
std::cout << BSON( "a" << MINKEY ); // { "a" : { "$minKey" : 1 } }
*/
struct MinKeyLabeler { };
extern MinKeyLabeler MINKEY;
struct MaxKeyLabeler { };
extern MaxKeyLabeler MAXKEY;
// Utility class to implement GT, GTE, etc as described above.
class Labeler {
public:
struct Label {
explicit Label( const char *l ) : l_( l ) {}
const char *l_;
};
Labeler( const Label &l, BSONObjBuilderValueStream *s ) : l_( l ), s_( s ) {}
template
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_;
};
// Utility class to allow adding a std::string to BSON as a Symbol
struct BSONSymbol {
explicit BSONSymbol(StringData sym) :symbol(sym) {}
StringData symbol;
};
// Utility class to allow adding a std::string to BSON as Code
struct BSONCode {
explicit BSONCode(StringData str) :code(str) {}
StringData code;
};
// Utility class to allow adding CodeWScope to BSON
struct BSONCodeWScope {
explicit BSONCodeWScope(StringData str, const BSONObj& obj) :code(str), scope(obj) {}
StringData code;
BSONObj scope;
};
// Utility class to allow adding a RegEx to BSON
struct BSONRegEx {
explicit BSONRegEx(StringData pat, StringData f="") :pattern(pat), flags(f) {}
StringData pattern;
StringData flags;
};
// Utility class to allow adding binary data to BSON
struct BSONBinData {
BSONBinData(const void* d, int l, BinDataType t) :data(d), length(l), type(t) {}
const void* data;
int length;
BinDataType type;
};
// Utility class to allow adding deprecated DBRef type to BSON
struct BSONDBRef {
BSONDBRef(StringData nameSpace, const OID& o) :ns(nameSpace), oid(o) {}
StringData ns;
OID oid;
};
extern Labeler::Label GT;
extern Labeler::Label GTE;
extern Labeler::Label LT;
extern Labeler::Label LTE;
extern Labeler::Label NE;
extern Labeler::Label NIN;
extern Labeler::Label BSIZE;
// $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
BSONObjBuilder& operator<<( T value );
BSONObjBuilder& operator<<(const DateNowLabeler& id);
BSONObjBuilder& operator<<(const NullLabeler& id);
BSONObjBuilder& operator<<(const UndefinedLabeler& id);
BSONObjBuilder& operator<<(const MinKeyLabeler& id);
BSONObjBuilder& operator<<(const MaxKeyLabeler& id);
Labeler operator<<( const Labeler::Label &l );
void endField( StringData nextFieldName = StringData() );
bool subobjStarted() const { return _fieldName != 0; }
// The following methods provide API compatibility with BSONArrayBuilder
BufBuilder& subobjStart();
BufBuilder& subarrayStart();
// This method should only be called from inside of implementations of
// BSONObjBuilder& operator<<(BSONObjBuilderValueStream&, SOME_TYPE)
// to provide the return value.
BSONObjBuilder& builder() { return *_builder; }
private:
StringData _fieldName;
BSONObjBuilder * _builder;
bool haveSubobj() const { return _subobj.get() != 0; }
BSONObjBuilder *subobj();
std::unique_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 x )
x = _sizes[i];
}
return x;
}
private:
enum { SIZE = 10 };
int _pos;
int _sizes[SIZE];
};
// considers order
bool fieldsMatch(const BSONObj& lhs, const BSONObj& rhs);
}