Skip to content

Commit

Permalink
Fixed bson parser to work for regexp correctly on 0.4.x
Browse files Browse the repository at this point in the history
  • Loading branch information
christkv committed Mar 12, 2012
1 parent 15b00ad commit 6e6e320
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 7 deletions.
42 changes: 38 additions & 4 deletions lib/bson/bson.js
Expand Up @@ -279,7 +279,7 @@ function calculateElement(name, value, serializeFunctions) {
}
case 'function':
// WTF for 0.4.X where typeof /someregexp/ === 'function'
if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') {
if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') {
return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1
+ (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1
} else {
Expand Down Expand Up @@ -405,9 +405,10 @@ var supportsBuffer = typeof Buffer != 'undefined';
*/
var packElement = function(name, value, checkKeys, buffer, index, serializeFunctions) {
var startIndex = index;

switch(typeof value) {
case 'string':
// console.log("---------------------------- string name :: " + name)
// Encode String type
buffer[index++] = BSON.BSON_DATA_STRING;
// Number of written bytes
Expand All @@ -434,6 +435,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
// Return index
return index;
case 'number':
// console.log("---------------------------- number name :: " + name)
// We have an integer value
if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) {
// If the value fits in 32 bits encode as int, if it fits in a double
Expand Down Expand Up @@ -501,6 +503,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct

return index;
case 'undefined':
// console.log("---------------------------- undefined name :: " + name)
// Set long type
buffer[index++] = BSON.BSON_DATA_NULL;
// Number of written bytes
Expand All @@ -510,6 +513,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
buffer[index - 1] = 0;
return index;
case 'boolean':
// console.log("---------------------------- boolean name :: " + name)
// Write the type
buffer[index++] = BSON.BSON_DATA_BOOLEAN;
// Number of written bytes
Expand All @@ -523,6 +527,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
case 'object':
if(value === null || value instanceof MinKey || value instanceof MaxKey
|| value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') {
// console.log("---------------------------- min_key|max_key name :: " + name)
// Write the type of either min or max key
if(value === null) {
buffer[index++] = BSON.BSON_DATA_NULL;
Expand All @@ -539,6 +544,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
buffer[index - 1] = 0;
return index;
} else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') {
// console.log("---------------------------- object_id name :: " + name)
// Write the type
buffer[index++] = BSON.BSON_DATA_OID;
// Number of written bytes
Expand All @@ -553,6 +559,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
index = index + 12;
return index;
} else if(value instanceof Date) {
// console.log("---------------------------- date name :: " + name)
// Write the type
buffer[index++] = BSON.BSON_DATA_DATE;
// Number of written bytes
Expand All @@ -577,6 +584,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
buffer[index++] = (highBits >> 24) & 0xff;
return index;
} else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
// console.log("---------------------------- buffer name :: " + name)
// Write the type
buffer[index++] = BSON.BSON_DATA_BINARY;
// Number of written bytes
Expand All @@ -599,6 +607,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
index = index + size;
return index;
} else if(value instanceof Long || value instanceof Timestamp || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Timestamp') {
// console.log("---------------------------- long|timestamp name :: " + name)
// Write the type
buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP;
// Number of written bytes
Expand All @@ -621,6 +630,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
buffer[index++] = (highBits >> 24) & 0xff;
return index;
} else if(value instanceof Double || value['_bsontype'] == 'Double') {
// console.log("---------------------------- double name :: " + name)
// Encode as double
buffer[index++] = BSON.BSON_DATA_NUMBER;
// Number of written bytes
Expand All @@ -634,6 +644,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
index = index + 8;
return index;
} else if(value instanceof Code || value['_bsontype'] == 'Code') {
// console.log("---------------------------- code name :: " + name)
if(value.scope != null && Object.keys(value.scope).length > 0) {
// Write the type
buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE;
Expand Down Expand Up @@ -715,6 +726,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
return index;
}
} else if(value instanceof Binary || value['_bsontype'] == 'Binary') {
// console.log("---------------------------- binary name :: " + name)
// Write the type
buffer[index++] = BSON.BSON_DATA_BINARY;
// Number of written bytes
Expand All @@ -739,6 +751,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
index = index + value.position;
return index;
} else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') {
// console.log("---------------------------- symbol name :: " + name)
// Write the type
buffer[index++] = BSON.BSON_DATA_SYMBOL;
// Number of written bytes
Expand All @@ -761,6 +774,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
buffer[index++] = 0x00;
return index;
} else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') {
// console.log("---------------------------- dbref name :: " + name)
// Write the type
buffer[index++] = BSON.BSON_DATA_OBJECT;
// Number of written bytes
Expand Down Expand Up @@ -793,6 +807,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
// Return the end index
return endIndex;
} else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') {
// console.log("---------------------------- regexp name :: " + name)
// Write the type
buffer[index++] = BSON.BSON_DATA_REGEXP;
// Number of written bytes
Expand All @@ -815,6 +830,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
buffer[index++] = 0x00;
return index;
} else {
// console.log("---------------------------- object|array :: " + name)
// Write the type
buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT;
// Number of written bytes
Expand All @@ -835,7 +851,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
}
case 'function':
// WTF for 0.4.X where typeof /someregexp/ === 'function'
if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') {
if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') {
// Write the type
buffer[index++] = BSON.BSON_DATA_REGEXP;
// Number of written bytes
Expand All @@ -847,7 +863,7 @@ var packElement = function(name, value, checkKeys, buffer, index, serializeFunct
// Write the regular expression string
buffer.write(value.source, index, 'utf8');
// Adjust the index
index = index + supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source);
index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source));
// Write zero
buffer[index++] = 0x00;
// Write the parameters
Expand Down Expand Up @@ -1162,12 +1178,14 @@ BSON.deserialize = function(buffer, options, isArray) {
switch(elementType) {
case BSON.BSON_DATA_OID:
var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('binary', index, index + 12) : convertArraytoUtf8BinaryString(buffer, index, index + 12);
// console.log("================================================ object_id :: " + name)
// Decode the oid
object[name] = new ObjectID(string);
// Update index
index = index + 12;
break;
case BSON.BSON_DATA_STRING:
// console.log("================================================ string :: " + name)
// Read the content of the field
var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
// Add string to object
Expand All @@ -1176,31 +1194,37 @@ BSON.deserialize = function(buffer, options, isArray) {
index = index + stringSize;
break;
case BSON.BSON_DATA_INT:
// console.log("================================================ int :: " + name)
// Decode the 32bit value
object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
break;
case BSON.BSON_DATA_NUMBER:
// console.log("================================================ number :: " + name)
// Decode the double value
object[name] = readIEEE754(buffer, index, 'little', 52, 8);
// Update the index
index = index + 8;
break;
case BSON.BSON_DATA_DATE:
// console.log("================================================ date :: " + name)
// Unpack the low and high bits
var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
// Set date object
object[name] = new Date(new Long(lowBits, highBits).toNumber());
break;
case BSON.BSON_DATA_BOOLEAN:
// console.log("================================================ boolean :: " + name)
// Parse the boolean value
object[name] = buffer[index++] == 1;
break;
case BSON.BSON_DATA_NULL:
// console.log("================================================ null :: " + name)
// Parse the boolean value
object[name] = null;
break;
case BSON.BSON_DATA_BINARY:
// console.log("================================================ binary :: " + name)
// Decode the size of the binary blob
var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
// Decode the subtype
Expand All @@ -1220,6 +1244,7 @@ BSON.deserialize = function(buffer, options, isArray) {
index = index + binarySize;
break;
case BSON.BSON_DATA_ARRAY:
// console.log("================================================ array :: " + name)
options['index'] = index;
// Decode the size of the array document
var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
Expand All @@ -1229,6 +1254,7 @@ BSON.deserialize = function(buffer, options, isArray) {
index = index + objectSize;
break;
case BSON.BSON_DATA_OBJECT:
// console.log("================================================ object :: " + name)
options['index'] = index;
// Decode the size of the object document
var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
Expand All @@ -1238,6 +1264,7 @@ BSON.deserialize = function(buffer, options, isArray) {
index = index + objectSize;
break;
case BSON.BSON_DATA_REGEXP:
// console.log("================================================ regexp :: " + name)
// Create the regexp
var source = readCStyleString();
var regExpOptions = readCStyleString();
Expand All @@ -1262,6 +1289,7 @@ BSON.deserialize = function(buffer, options, isArray) {
object[name] = new RegExp(source, optionsArray.join(''));
break;
case BSON.BSON_DATA_LONG:
// console.log("================================================ long :: " + name)
// Unpack the low and high bits
var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
Expand All @@ -1271,6 +1299,7 @@ BSON.deserialize = function(buffer, options, isArray) {
object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long;
break;
case BSON.BSON_DATA_SYMBOL:
// console.log("================================================ symbol :: " + name)
// Read the content of the field
var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
// Add string to object
Expand All @@ -1279,21 +1308,25 @@ BSON.deserialize = function(buffer, options, isArray) {
index = index + stringSize;
break;
case BSON.BSON_DATA_TIMESTAMP:
// console.log("================================================ timestamp :: " + name)
// Unpack the low and high bits
var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
// Set the object
object[name] = new Timestamp(lowBits, highBits);
break;
case BSON.BSON_DATA_MIN_KEY:
// console.log("================================================ min_key :: " + name)
// Parse the object
object[name] = new MinKey();
break;
case BSON.BSON_DATA_MAX_KEY:
// console.log("================================================ max_key :: " + name)
// Parse the object
object[name] = new MaxKey();
break;
case BSON.BSON_DATA_CODE:
// console.log("================================================ code :: " + name)
// Read the content of the field
var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
// Function string
Expand All @@ -1320,6 +1353,7 @@ BSON.deserialize = function(buffer, options, isArray) {
index = index + stringSize;
break;
case BSON.BSON_DATA_CODE_W_SCOPE:
// console.log("================================================ code_w_scope :: " + name)
// Read the content of the field
var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
Expand Down
6 changes: 3 additions & 3 deletions test/node/bson_parser_comparision_test.js
Expand Up @@ -425,7 +425,7 @@ exports['Serialize document with special operators'] = function(test) {
var simple_string_serialized_2 = bsonC.serialize(doc, false, true, true);

// Should serialize to the same value
assert.equal(simple_string_serialized_2.toString('hex'), simple_string_serialized.toString('hex'))
assert.equal(simple_string_serialized_2.toString('base64'), simple_string_serialized.toString('base64'))
var doc1 = bsonJS.deserialize(simple_string_serialized_2);
var doc2 = bsonC.deserialize(simple_string_serialized);
assert.deepEqual(doc1, doc2)
Expand All @@ -442,7 +442,7 @@ exports['Create ObjectID from hex string'] = function(test) {
var docC = {_id: ObjectID.createFromHexString(hexId), 'funds.remaining': {$gte: 1.222}, 'transactions.id': {$ne: ObjectID.createFromHexString(hexId)}};
var docJSBin = bsonJS.serialize(docJS, false, true, true);
var docCBin = bsonC.serialize(docC, false, true, true);
assert.equal(docCBin.toString('hex'), docJSBin.toString('hex'));
assert.equal(docCBin.toString('base64'), docJSBin.toString('base64'));
test.done();
}

Expand All @@ -454,6 +454,6 @@ exports['Serialize big complex document'] = function(test) {
var doc = {"DateTime": "Tue Nov 40 2011 17:27:55 GMT+0000 (WEST)","isActive": true,"Media": {"URL": "http://videos.sapo.pt/Tc85NsjaKjj8o5aV7Ubb"},"Title": "Lisboa fecha a ganhar 0.19%","SetPosition": 60,"Type": "videos","Thumbnail": [{"URL": "http://rd3.videos.sapo.pt/Tc85NsjaKjj8o5aV7Ubb/pic/320x240","Dimensions": {"Height": 240,"Width": 320}}],"Source": {"URL": "http://videos.sapo.pt","SetID": "1288","SourceID": "http://videos.sapo.pt/tvnet/rss2","SetURL": "http://noticias.sapo.pt/videos/tv-net_1288/","ItemID": "Tc85NsjaKjj8o5aV7Ubb","Name": "SAPO Vídeos"},"Category": "Tec_ciencia","Description": "Lisboa fecha a ganhar 0.19%","GalleryID": new ObjectID("4eea2a634ce8573200000000"),"InternalRefs": {"RegisterDate": "Thu Dec 15 2011 17:12:51 GMT+0000 (WEST)","ChangeDate": "Thu Dec 15 2011 17:12:51 GMT+0000 (WEST)","Hash": 332279244514},"_id": new ObjectID("4eea2a96e52778160000003a")}
var docJSBin = bsonJS.serialize(doc, false, true, true);
var docCBin = bsonC.serialize(doc, false, true, true);
assert.equal(docCBin.toString('hex'), docJSBin.toString('hex'));
assert.equal(docCBin.toString('base64'), docJSBin.toString('base64'));
test.done();
}

0 comments on commit 6e6e320

Please sign in to comment.