void BSONElement::validate() const { switch( type() ) { case DBRef: case Code: case Symbol: case String: massert( "Invalid dbref/code/string/symbol size", valuestrsize() > 0 && valuestrsize() - 1 == strnlen( valuestr(), valuestrsize() ) ); break; case CodeWScope: { int totalSize = *( int * )( value() ); massert( "Invalid CodeWScope size", totalSize >= 8 ); int strSizeWNull = *( int * )( value() + 4 ); massert( "Invalid CodeWScope string size", totalSize >= strSizeWNull + 4 + 4 ); massert( "Invalid CodeWScope string size", strSizeWNull > 0 && strSizeWNull - 1 == strnlen( codeWScopeCode(), strSizeWNull ) ); massert( "Invalid CodeWScope size", totalSize >= strSizeWNull + 4 + 4 + 4 ); int objSize = *( int * )( value() + 4 + 4 + strSizeWNull ); massert( "Invalid CodeWScope object size", totalSize == 4 + 4 + strSizeWNull + objSize ); // Subobject validation handled elsewhere. } case Object: // We expect Object size validation to be handled elsewhere. default: break; } }
std::string BSONElement::_asCode() const { switch (type()) { case mongo::String: case Code: return std::string(valuestr(), valuestrsize() - 1); case CodeWScope: return std::string(codeWScopeCode(), ConstDataView(valuestr()).read<LittleEndian<int>>() - 1); default: log() << "can't convert type: " << (int)(type()) << " to code" << std::endl; } uassert(10062, "not code", 0); return ""; }
string BSONElement::toString( bool includeFieldName ) const { stringstream s; if ( includeFieldName && type() != EOO ) s << fieldName() << ": "; switch ( type() ) { case EOO: return "EOO"; case Date: s << "Date(" << hex << date() << ')'; break; case RegEx: { s << "/" << regex() << '/'; const char *p = regexFlags(); if ( p ) s << p; } break; case NumberDouble: { stringstream tmp; tmp.precision( 16 ); tmp << number(); string n = tmp.str(); s << n; // indicate this is a double: if( strchr(n.c_str(), '.') == 0 && strchr(n.c_str(), 'E') == 0 && strchr(n.c_str(), 'N') == 0 ) s << ".0"; } break; case NumberInt: s.precision( 16 ); s << number(); //s << "(" << ( type() == NumberInt ? "int" : "double" ) << ")"; break; case Bool: s << ( boolean() ? "true" : "false" ); break; case Object: case Array: s << embeddedObject().toString(); break; case Undefined: s << "undefined"; break; case jstNULL: s << "null"; break; case MaxKey: s << "MaxKey"; break; case MinKey: s << "MinKey"; break; case CodeWScope: s << "CodeWScope( " << codeWScopeCode() << ", " << codeWScopeObject().toString() << ")"; break; case Code: if ( valuestrsize() > 80 ) s << string(valuestr()).substr(0, 70) << "..."; else { s << valuestr(); } break; case Symbol: case String: if ( valuestrsize() > 80 ) s << '"' << string(valuestr()).substr(0, 70) << "...\""; else { s << '"' << valuestr() << '"'; } break; case DBRef: s << "DBRef('" << valuestr() << "',"; { OID *x = (OID *) (valuestr() + valuestrsize()); s << *x << ')'; } break; case jstOID: s << "ObjId("; s << __oid() << ')'; break; case BinData: s << "BinData"; break; case Timestamp: s << "Timestamp " << timestampTime() << "|" << timestampInc(); break; default: s << "?type=" << type(); break; } return s.str(); }
void BSONElement::toString( StringBuilder& s, bool includeFieldName, bool full, bool redactValues, int depth) const { if (depth > BSONObj::maxToStringRecursionDepth) { // check if we want the full/complete string if (full) { StringBuilder s; s << "Reached maximum recursion depth of "; s << BSONObj::maxToStringRecursionDepth; uassert(16150, s.str(), full != true); } s << "..."; return; } if (includeFieldName && type() != EOO) s << fieldName() << ": "; switch (type()) { case Object: return embeddedObject().toString(s, false, full, redactValues, depth + 1); case mongo::Array: return embeddedObject().toString(s, true, full, redactValues, depth + 1); default: break; } if (redactValues) { s << "\"###\""; return; } switch (type()) { case EOO: s << "EOO"; break; case mongo::Date: s << "new Date(" << date().toMillisSinceEpoch() << ')'; break; case RegEx: { s << "/" << regex() << '/'; const char* p = regexFlags(); if (p) s << p; } break; case NumberDouble: s.appendDoubleNice(number()); break; case NumberLong: s << _numberLong(); break; case NumberInt: s << _numberInt(); break; case NumberDecimal: s << _numberDecimal().toString(); break; case mongo::Bool: s << (boolean() ? "true" : "false"); break; case Undefined: s << "undefined"; break; case jstNULL: s << "null"; break; case MaxKey: s << "MaxKey"; break; case MinKey: s << "MinKey"; break; case CodeWScope: s << "CodeWScope( " << codeWScopeCode() << ", " << codeWScopeObject().toString() << ")"; break; case Code: if (!full && valuestrsize() > 80) { s.write(valuestr(), 70); s << "..."; } else { s.write(valuestr(), valuestrsize() - 1); } break; case Symbol: case mongo::String: s << '"'; if (!full && valuestrsize() > 160) { s.write(valuestr(), 150); s << "...\""; } else { s.write(valuestr(), valuestrsize() - 1); s << '"'; } break; case DBRef: s << "DBRef('" << valuestr() << "',"; s << mongo::OID::from(valuestr() + valuestrsize()) << ')'; break; case jstOID: s << "ObjectId('"; s << __oid() << "')"; break; case BinData: { int len; const char* data = binDataClean(len); // If the BinData is a correctly sized newUUID, display it as such. if (binDataType() == newUUID && len == 16) { // 4 Octets - 2 Octets - 2 Octets - 2 Octets - 6 Octets s << "UUID(\""; s << toHexLower(&data[0], 4); s << "-"; s << toHexLower(&data[4], 2); s << "-"; s << toHexLower(&data[6], 2); s << "-"; s << toHexLower(&data[8], 2); s << "-"; s << toHexLower(&data[10], 6); s << "\")"; break; } s << "BinData(" << binDataType() << ", "; if (!full && len > 80) { s << toHex(data, 70) << "...)"; } else { s << toHex(data, len) << ")"; } } break; case bsonTimestamp: { // Convert from Milliseconds to Seconds for consistent Timestamp printing. auto secs = duration_cast<Seconds>(timestampTime().toDurationSinceEpoch()); s << "Timestamp(" << secs.count() << ", " << timestampInc() << ")"; } break; default: s << "?type=" << type(); break; } }