00001 00019 #pragma once 00020 00021 #include "jsobj.h" 00022 #include "dur.h" 00023 00024 namespace mongo { 00025 00029 class BSONElementManipulator { 00030 public: 00031 BSONElementManipulator( const BSONElement &element ) : 00032 _element( element ) { 00033 assert( !_element.eoo() ); 00034 } 00038 void initTimestamp(); 00039 00041 void setNumber(double d) { 00042 if ( _element.type() == NumberDouble ) *reinterpret_cast< double * >( value() ) = d; 00043 else if ( _element.type() == NumberInt ) *reinterpret_cast< int * >( value() ) = (int) d; 00044 else assert(0); 00045 } 00046 void SetNumber(double d) { 00047 if ( _element.type() == NumberDouble ) 00048 *getDur().writing( reinterpret_cast< double * >( value() ) ) = d; 00049 else if ( _element.type() == NumberInt ) 00050 *getDur().writing( reinterpret_cast< int * >( value() ) ) = (int) d; 00051 else assert(0); 00052 } 00053 void setLong(long long n) { 00054 assert( _element.type() == NumberLong ); 00055 *reinterpret_cast< long long * >( value() ) = n; 00056 } 00057 void SetLong(long long n) { 00058 assert( _element.type() == NumberLong ); 00059 *getDur().writing( reinterpret_cast< long long * >(value()) ) = n; 00060 } 00061 void setInt(int n) { 00062 assert( _element.type() == NumberInt ); 00063 *reinterpret_cast< int * >( value() ) = n; 00064 } 00065 void SetInt(int n) { 00066 assert( _element.type() == NumberInt ); 00067 getDur().writingInt( *reinterpret_cast< int * >( value() ) ) = n; 00068 } 00069 00070 00073 void replaceTypeAndValue( const BSONElement &e ) { 00074 *data() = e.type(); 00075 memcpy( value(), e.value(), e.valuesize() ); 00076 } 00077 00078 /* dur:: version */ 00079 void ReplaceTypeAndValue( const BSONElement &e ) { 00080 char *d = data(); 00081 char *v = value(); 00082 int valsize = e.valuesize(); 00083 int ofs = (int) (v-d); 00084 dassert( ofs > 0 ); 00085 char *p = (char *) getDur().writingPtr(d, valsize + ofs); 00086 *p = e.type(); 00087 memcpy( p + ofs, e.value(), valsize ); 00088 } 00089 00090 static void lookForTimestamps( const BSONObj& obj ) { 00091 // If have a Timestamp field as the first or second element, 00092 // update it to a Date field set to OpTime::now().asDate(). The 00093 // replacement policy is a work in progress. 00094 00095 BSONObjIterator i( obj ); 00096 for( int j = 0; i.moreWithEOO() && j < 2; ++j ) { 00097 BSONElement e = i.next(); 00098 if ( e.eoo() ) 00099 break; 00100 if ( e.type() == Timestamp ) { 00101 BSONElementManipulator( e ).initTimestamp(); 00102 break; 00103 } 00104 } 00105 } 00106 private: 00107 char *data() { return nonConst( _element.rawdata() ); } 00108 char *value() { return nonConst( _element.value() ); } 00109 static char *nonConst( const char *s ) { return const_cast< char * >( s ); } 00110 00111 const BSONElement _element; 00112 }; 00113 00114 } // namespace mongo