/**
* Copyright (C) 2014 MongoDB 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.
*/
#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault
#include "mongo/db/jsobj.h"
#include
#include "mongo/bson/timestamp.h"
#include "mongo/util/log.h"
namespace mongo {
using std::string;
void BSONObjBuilder::appendMinForType(StringData fieldName, int t) {
switch (t) {
// Shared canonical types
case NumberInt:
case NumberDouble:
case NumberLong:
case NumberDecimal:
append(fieldName, std::numeric_limits::quiet_NaN());
return;
case Symbol:
case String:
append(fieldName, "");
return;
case Date:
// min varies with V0 and V1 indexes, so we go one type lower.
appendBool(fieldName, true);
// appendDate( fieldName , numeric_limits::min() );
return;
case bsonTimestamp:
appendTimestamp(fieldName, 0);
return;
case Undefined: // shared with EOO
appendUndefined(fieldName);
return;
// Separate canonical types
case MinKey:
appendMinKey(fieldName);
return;
case MaxKey:
appendMaxKey(fieldName);
return;
case jstOID: {
OID o;
appendOID(fieldName, &o);
return;
}
case Bool:
appendBool(fieldName, false);
return;
case jstNULL:
appendNull(fieldName);
return;
case Object:
append(fieldName, BSONObj());
return;
case Array:
appendArray(fieldName, BSONObj());
return;
case BinData:
appendBinData(fieldName, 0, BinDataGeneral, (const char*)0);
return;
case RegEx:
appendRegex(fieldName, "");
return;
case DBRef: {
OID o;
appendDBRef(fieldName, "", o);
return;
}
case Code:
appendCode(fieldName, "");
return;
case CodeWScope:
appendCodeWScope(fieldName, "", BSONObj());
return;
};
log() << "type not supported for appendMinElementForType: " << t;
uassert(10061, "type not supported for appendMinElementForType", false);
}
void BSONObjBuilder::appendMaxForType(StringData fieldName, int t) {
switch (t) {
// Shared canonical types
case NumberInt:
case NumberDouble:
case NumberLong:
case NumberDecimal:
append(fieldName, std::numeric_limits::infinity());
return;
case Symbol:
case String:
appendMinForType(fieldName, Object);
return;
case Date:
appendDate(fieldName,
Date_t::fromMillisSinceEpoch(std::numeric_limits::max()));
return;
case bsonTimestamp:
append(fieldName, Timestamp::max());
return;
case Undefined: // shared with EOO
appendUndefined(fieldName);
return;
// Separate canonical types
case MinKey:
appendMinKey(fieldName);
return;
case MaxKey:
appendMaxKey(fieldName);
return;
case jstOID: {
OID o = OID::max();
appendOID(fieldName, &o);
return;
}
case Bool:
appendBool(fieldName, true);
return;
case jstNULL:
appendNull(fieldName);
return;
case Object:
appendMinForType(fieldName, Array);
return;
case Array:
appendMinForType(fieldName, BinData);
return;
case BinData:
appendMinForType(fieldName, jstOID);
return;
case RegEx:
appendMinForType(fieldName, DBRef);
return;
case DBRef:
appendMinForType(fieldName, Code);
return;
case Code:
appendMinForType(fieldName, CodeWScope);
return;
case CodeWScope:
// This upper bound may change if a new bson type is added.
appendMinForType(fieldName, MaxKey);
return;
}
log() << "type not supported for appendMaxElementForType: " << t;
uassert(14853, "type not supported for appendMaxElementForType", false);
}
BSONObjBuilder& BSONObjBuilder::appendDate(StringData fieldName, Date_t dt) {
_b.appendNum((char)Date);
_b.appendStr(fieldName);
_b.appendNum(dt.toMillisSinceEpoch());
return *this;
}
/* add all the fields from the object specified to this object */
BSONObjBuilder& BSONObjBuilder::appendElements(BSONObj x) {
if (!x.isEmpty())
_b.appendBuf(x.objdata() + 4, // skip over leading length
x.objsize() - 5); // ignore leading length and trailing \0
return *this;
}
/* add all the fields from the object specified to this object if they don't exist */
BSONObjBuilder& BSONObjBuilder::appendElementsUnique(BSONObj x) {
std::set have;
{
BSONObjIterator i = iterator();
while (i.more())
have.insert(i.next().fieldName());
}
BSONObjIterator it(x);
while (it.more()) {
BSONElement e = it.next();
if (have.count(e.fieldName()))
continue;
append(e);
}
return *this;
}
void BSONObjBuilder::appendKeys(const BSONObj& keyPattern, const BSONObj& values) {
BSONObjIterator i(keyPattern);
BSONObjIterator j(values);
while (i.more() && j.more()) {
appendAs(j.next(), i.next().fieldName());
}
verify(!i.more());
verify(!j.more());
}
BSONObjIterator BSONObjBuilder::iterator() const {
const char* s = _b.buf() + _offset;
const char* e = _b.buf() + _b.len();
return BSONObjIterator(s, e);
}
bool BSONObjBuilder::hasField(StringData name) const {
BSONObjIterator i = iterator();
while (i.more())
if (name == i.next().fieldName())
return true;
return false;
}
const string BSONObjBuilder::numStrs[] = {
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14",
"15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44",
"45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74",
"75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
};
// This is to ensure that BSONObjBuilder doesn't try to use numStrs before the strings have
// been constructed I've tested just making numStrs a char[][], but the overhead of
// constructing the strings each time was too high numStrsReady will be 0 until after
// numStrs is initialized because it is a static variable
bool BSONObjBuilder::numStrsReady = (numStrs[0].size() > 0);
} // namespace mongo