BSONObj nextJsObj( const char *context ) { BSONObj ret = DbMessage::nextJsObj(); if ( objcheck && !ret.valid() ) { // TODO provide more debugging info cout << "invalid object in " << context << ": " << ret.hexDump() << endl; } return ret; }
bool debug( const BSONObj& o , int depth=0) { string prefix = ""; for ( int i=0; i<depth; i++ ) { prefix += "\t\t\t"; } int read = 4; try { cout << prefix << "--- new object ---\n"; cout << prefix << "\t size : " << o.objsize() << "\n"; BSONObjIterator i(o); while ( i.more() ) { BSONElement e = i.next(); cout << prefix << "\t\t " << e.fieldName() << "\n" << prefix << "\t\t\t type:" << setw(3) << e.type() << " size: " << e.size() << endl; if ( ( read + e.size() ) > o.objsize() ) { cout << prefix << " SIZE DOES NOT WORK" << endl; return false; } read += e.size(); try { e.validate(); if ( e.isABSONObj() ) { if ( ! debug( e.Obj() , depth + 1 ) ) { //return false; cout << prefix << "\t\t\t BAD BAD BAD" << endl; if ( e.size() < 1000 ) { cout << "---\n" << e.Obj().hexDump() << "\n---" << endl; } } } else if ( e.type() == String && ! isValidUTF8( e.valuestr() ) ) { cout << prefix << "\t\t\t" << "bad utf8 String!" << endl; } else if ( logger::globalLogDomain()->shouldLog(logger::LogSeverity::Debug(1)) ) { cout << prefix << "\t\t\t" << e << endl; } } catch ( std::exception& e ) { cout << prefix << "\t\t\t bad value: " << e.what() << endl; } } } catch ( std::exception& e ) { cout << prefix << "\tbad\t" << e.what() << endl; cout << "----\n" << o.hexDump() << "\n---" << endl; } return true; }
bool debug( const BSONObj& o , int depth=0) { string prefix = ""; for ( int i=0; i<depth; i++ ) { prefix += "\t\t\t"; } int read = 4; try { cout << prefix << "--- new object ---\n"; cout << prefix << "\t size : " << o.objsize() << "\n"; // Note: this will recursively check each level of the bson and will also be called by // this function at each level. While inefficient, it shouldn't effect correctness. const Status status = validateBSON(o.objdata(), o.objsize()); if (!status.isOK()) { cout << prefix << "\t OBJECT IS INVALID: " << status.reason() << '\n' << prefix << "\t attempting to print as much as possible" << endl; } BSONObjIterator i(o); while ( i.more() ) { // This call verifies it is safe to call size() and fieldName() but doesn't check // whether the element extends past the end of the object. That is done below. BSONElement e = i.next(/*checkEnd=*/true); cout << prefix << "\t\t " << e.fieldName() << "\n" << prefix << "\t\t\t type:" << setw(3) << e.type() << " size: " << e.size() << endl; if ( ( read + e.size() ) > o.objsize() ) { cout << prefix << " SIZE DOES NOT WORK" << endl; return false; } read += e.size(); try { if ( e.isABSONObj() ) { if ( ! debug( e.Obj() , depth + 1 ) ) { //return false; cout << prefix << "\t\t\t BAD BAD BAD" << endl; if ( e.size() < 1000 ) { cout << "---\n" << e.Obj().hexDump() << "\n---" << endl; } } } else if ( e.type() == String && ! isValidUTF8( e.valuestr() ) ) { cout << prefix << "\t\t\t" << "bad utf8 String!" << endl; } else if ( logger::globalLogDomain()->shouldLog(logger::LogSeverity::Debug(1)) ) { cout << prefix << "\t\t\t" << e << endl; } } catch ( std::exception& e ) { cout << prefix << "\t\t\t bad value: " << e.what() << endl; } } } catch ( std::exception& e ) { cout << prefix << "\tbad\t" << e.what() << endl; cout << "----\n" << o.hexDump() << "\n---" << endl; } return true; }