bson.cc 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. //===========================================================================
  2. #include <stdarg.h>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #ifdef __clang__
  8. #pragma clang diagnostic push
  9. #pragma clang diagnostic ignored "-Wunused-parameter"
  10. #endif
  11. #include <v8.h>
  12. // this and the above block must be around the v8.h header otherwise
  13. // v8 is not happy
  14. #ifdef __clang__
  15. #pragma clang diagnostic pop
  16. #endif
  17. #include <node.h>
  18. #include <node_version.h>
  19. #include <node_buffer.h>
  20. #include <cmath>
  21. #include <iostream>
  22. #include <limits>
  23. #include <vector>
  24. #include <errno.h>
  25. #if defined(__sun) || defined(_AIX)
  26. #include <alloca.h>
  27. #endif
  28. #include "bson.h"
  29. void die(const char *message) {
  30. if(errno) {
  31. perror(message);
  32. } else {
  33. printf("ERROR: %s\n", message);
  34. }
  35. exit(1);
  36. }
  37. //===========================================================================
  38. // Equality Objects
  39. static const char* LONG_CLASS_NAME = "Long";
  40. static const char* OBJECT_ID_CLASS_NAME = "ObjectID";
  41. static const char* BINARY_CLASS_NAME = "Binary";
  42. static const char* CODE_CLASS_NAME = "Code";
  43. static const char* DBREF_CLASS_NAME = "DBRef";
  44. static const char* SYMBOL_CLASS_NAME = "Symbol";
  45. static const char* DOUBLE_CLASS_NAME = "Double";
  46. static const char* TIMESTAMP_CLASS_NAME = "Timestamp";
  47. static const char* MIN_KEY_CLASS_NAME = "MinKey";
  48. static const char* MAX_KEY_CLASS_NAME = "MaxKey";
  49. // Equality speed up comparison objects
  50. static const char* BSONTYPE_PROPERTY_NAME = "_bsontype";
  51. static const char* LONG_LOW_PROPERTY_NAME = "low_";
  52. static const char* LONG_HIGH_PROPERTY_NAME = "high_";
  53. static const char* OBJECT_ID_ID_PROPERTY_NAME = "id";
  54. static const char* BINARY_POSITION_PROPERTY_NAME = "position";
  55. static const char* BINARY_SUBTYPE_PROPERTY_NAME = "sub_type";
  56. static const char* BINARY_BUFFER_PROPERTY_NAME = "buffer";
  57. static const char* DOUBLE_VALUE_PROPERTY_NAME = "value";
  58. static const char* SYMBOL_VALUE_PROPERTY_NAME = "value";
  59. static const char* DBREF_REF_PROPERTY_NAME = "$ref";
  60. static const char* DBREF_ID_REF_PROPERTY_NAME = "$id";
  61. static const char* DBREF_DB_REF_PROPERTY_NAME = "$db";
  62. static const char* DBREF_NAMESPACE_PROPERTY_NAME = "namespace";
  63. static const char* DBREF_DB_PROPERTY_NAME = "db";
  64. static const char* DBREF_OID_PROPERTY_NAME = "oid";
  65. static const char* CODE_CODE_PROPERTY_NAME = "code";
  66. static const char* CODE_SCOPE_PROPERTY_NAME = "scope";
  67. static const char* TO_BSON_PROPERTY_NAME = "toBSON";
  68. void DataStream::WriteObjectId(const Local<Object>& object, const Local<String>& key)
  69. {
  70. uint16_t buffer[12];
  71. NanGet(object, key)->ToString()->Write(buffer, 0, 12);
  72. for(uint32_t i = 0; i < 12; ++i)
  73. {
  74. *p++ = (char) buffer[i];
  75. }
  76. }
  77. void ThrowAllocatedStringException(size_t allocationSize, const char* format, ...)
  78. {
  79. va_list args;
  80. va_start(args, format);
  81. char* string = (char*) malloc(allocationSize);
  82. if(string == NULL) die("Failed to allocate ThrowAllocatedStringException");
  83. vsprintf(string, format, args);
  84. va_end(args);
  85. throw string;
  86. }
  87. void DataStream::CheckKey(const Local<String>& keyName)
  88. {
  89. size_t keyLength = keyName->Utf8Length();
  90. if(keyLength == 0) return;
  91. // Allocate space for the key, do not need to zero terminate as WriteUtf8 does it
  92. char* keyStringBuffer = (char*) alloca(keyLength + 1);
  93. // Write the key to the allocated buffer
  94. keyName->WriteUtf8(keyStringBuffer);
  95. // Check for the zero terminator
  96. char* terminator = strchr(keyStringBuffer, 0x00);
  97. // If the location is not at the end of the string we've got an illegal 0x00 byte somewhere
  98. if(terminator != &keyStringBuffer[keyLength]) {
  99. ThrowAllocatedStringException(64+keyLength, "key %s must not contain null bytes", keyStringBuffer);
  100. }
  101. if(keyStringBuffer[0] == '$')
  102. {
  103. ThrowAllocatedStringException(64+keyLength, "key %s must not start with '$'", keyStringBuffer);
  104. }
  105. if(strchr(keyStringBuffer, '.') != NULL)
  106. {
  107. ThrowAllocatedStringException(64+keyLength, "key %s must not contain '.'", keyStringBuffer);
  108. }
  109. }
  110. template<typename T> void BSONSerializer<T>::SerializeDocument(const Local<Value>& value)
  111. {
  112. void* documentSize = this->BeginWriteSize();
  113. Local<Object> object = bson->GetSerializeObject(value);
  114. // Get the object property names
  115. Local<Array> propertyNames = object->GetPropertyNames();
  116. // Length of the property
  117. int propertyLength = propertyNames->Length();
  118. for(int i = 0; i < propertyLength; ++i)
  119. {
  120. const Local<String>& propertyName = NanGet(propertyNames, i)->ToString();
  121. if(checkKeys) this->CheckKey(propertyName);
  122. const Local<Value>& propertyValue = NanGet(object, propertyName);
  123. if((serializeFunctions || !propertyValue->IsFunction()) && !propertyValue->IsUndefined())
  124. {
  125. void* typeLocation = this->BeginWriteType();
  126. this->WriteString(propertyName);
  127. SerializeValue(typeLocation, propertyValue, false);
  128. }
  129. }
  130. this->WriteByte(0);
  131. this->CommitSize(documentSize);
  132. }
  133. template<typename T> void BSONSerializer<T>::SerializeArray(const Local<Value>& value)
  134. {
  135. void* documentSize = this->BeginWriteSize();
  136. Local<Array> array = Local<Array>::Cast(value->ToObject());
  137. uint32_t arrayLength = array->Length();
  138. for(uint32_t i = 0; i < arrayLength; ++i)
  139. {
  140. void* typeLocation = this->BeginWriteType();
  141. this->WriteUInt32String(i);
  142. SerializeValue(typeLocation, NanGet(array, i), true);
  143. }
  144. this->WriteByte(0);
  145. this->CommitSize(documentSize);
  146. }
  147. // This is templated so that we can use this function to both count the number of bytes, and to serialize those bytes.
  148. // The template approach eliminates almost all of the inspection of values unless they're required (eg. string lengths)
  149. // and ensures that there is always consistency between bytes counted and bytes written by design.
  150. template<typename T> void BSONSerializer<T>::SerializeValue(void* typeLocation, const Local<Value> constValue, bool isArray)
  151. {
  152. Local<Value> value = constValue;
  153. // Check for toBSON function
  154. if(value->IsObject()) {
  155. Local<Object> object = value->ToObject();
  156. if(NanHas(object, "toBSON")) {
  157. const Local<Value>& toBSON = NanGet(object, "toBSON");
  158. if(!toBSON->IsFunction()) ThrowAllocatedStringException(64, "toBSON is not a function");
  159. value = Local<Function>::Cast(toBSON)->Call(object, 0, NULL);
  160. }
  161. }
  162. // Process all the values
  163. if(value->IsNumber())
  164. {
  165. double doubleValue = value->NumberValue();
  166. int intValue = (int) doubleValue;
  167. if(intValue == doubleValue)
  168. {
  169. this->CommitType(typeLocation, BSON_TYPE_INT);
  170. this->WriteInt32(intValue);
  171. }
  172. else
  173. {
  174. this->CommitType(typeLocation, BSON_TYPE_NUMBER);
  175. this->WriteDouble(doubleValue);
  176. }
  177. }
  178. else if(value->IsString())
  179. {
  180. this->CommitType(typeLocation, BSON_TYPE_STRING);
  181. this->WriteLengthPrefixedString(value->ToString());
  182. }
  183. else if(value->IsBoolean())
  184. {
  185. this->CommitType(typeLocation, BSON_TYPE_BOOLEAN);
  186. this->WriteBool(value);
  187. }
  188. else if(value->IsArray())
  189. {
  190. this->CommitType(typeLocation, BSON_TYPE_ARRAY);
  191. SerializeArray(value);
  192. }
  193. else if(value->IsDate())
  194. {
  195. this->CommitType(typeLocation, BSON_TYPE_DATE);
  196. this->WriteInt64(value);
  197. }
  198. else if(value->IsRegExp())
  199. {
  200. this->CommitType(typeLocation, BSON_TYPE_REGEXP);
  201. const Local<RegExp>& regExp = Local<RegExp>::Cast(value);
  202. this->WriteString(regExp->GetSource());
  203. int flags = regExp->GetFlags();
  204. if(flags & RegExp::kGlobal) this->WriteByte('s');
  205. if(flags & RegExp::kIgnoreCase) this->WriteByte('i');
  206. if(flags & RegExp::kMultiline) this->WriteByte('m');
  207. this->WriteByte(0);
  208. }
  209. else if(value->IsFunction())
  210. {
  211. this->CommitType(typeLocation, BSON_TYPE_CODE);
  212. this->WriteLengthPrefixedString(value->ToString());
  213. }
  214. else if(value->IsObject())
  215. {
  216. const Local<Object>& object = value->ToObject();
  217. if(NanHas(object, BSONTYPE_PROPERTY_NAME))
  218. {
  219. const Local<String>& constructorString = NanGet(object, BSONTYPE_PROPERTY_NAME)->ToString();
  220. if(NanStr(LONG_CLASS_NAME)->StrictEquals(constructorString))
  221. {
  222. this->CommitType(typeLocation, BSON_TYPE_LONG);
  223. this->WriteInt32(object, NanStr(LONG_LOW_PROPERTY_NAME));
  224. this->WriteInt32(object, NanStr(LONG_HIGH_PROPERTY_NAME));
  225. }
  226. else if(NanStr(TIMESTAMP_CLASS_NAME)->StrictEquals(constructorString))
  227. {
  228. this->CommitType(typeLocation, BSON_TYPE_TIMESTAMP);
  229. this->WriteInt32(object, NanStr(LONG_LOW_PROPERTY_NAME));
  230. this->WriteInt32(object, NanStr(LONG_HIGH_PROPERTY_NAME));
  231. }
  232. else if(NanStr(OBJECT_ID_CLASS_NAME)->StrictEquals(constructorString))
  233. {
  234. this->CommitType(typeLocation, BSON_TYPE_OID);
  235. this->WriteObjectId(object, NanStr(OBJECT_ID_ID_PROPERTY_NAME));
  236. }
  237. else if(NanStr(BINARY_CLASS_NAME)->StrictEquals(constructorString))
  238. {
  239. this->CommitType(typeLocation, BSON_TYPE_BINARY);
  240. uint32_t length = NanGet(object, BINARY_POSITION_PROPERTY_NAME)->Uint32Value();
  241. Local<Object> bufferObj = NanGet(object, BINARY_BUFFER_PROPERTY_NAME)->ToObject();
  242. this->WriteInt32(length);
  243. this->WriteByte(object, NanStr(BINARY_SUBTYPE_PROPERTY_NAME)); // write subtype
  244. // If type 0x02 write the array length aswell
  245. if(NanGet(object, BINARY_SUBTYPE_PROPERTY_NAME)->Int32Value() == 0x02) {
  246. this->WriteInt32(length);
  247. }
  248. // Write the actual data
  249. this->WriteData(node::Buffer::Data(bufferObj), length);
  250. }
  251. else if(NanStr(DOUBLE_CLASS_NAME)->StrictEquals(constructorString))
  252. {
  253. this->CommitType(typeLocation, BSON_TYPE_NUMBER);
  254. this->WriteDouble(object, NanStr(DOUBLE_VALUE_PROPERTY_NAME));
  255. }
  256. else if(NanStr(SYMBOL_CLASS_NAME)->StrictEquals(constructorString))
  257. {
  258. this->CommitType(typeLocation, BSON_TYPE_SYMBOL);
  259. this->WriteLengthPrefixedString(NanGet(object, SYMBOL_VALUE_PROPERTY_NAME)->ToString());
  260. }
  261. else if(NanStr(CODE_CLASS_NAME)->StrictEquals(constructorString))
  262. {
  263. const Local<String>& function = NanGet(object, CODE_CODE_PROPERTY_NAME)->ToString();
  264. const Local<Object>& scope = NanGet(object, CODE_SCOPE_PROPERTY_NAME)->ToObject();
  265. // For Node < 0.6.X use the GetPropertyNames
  266. #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 6
  267. uint32_t propertyNameLength = scope->GetPropertyNames()->Length();
  268. #else
  269. uint32_t propertyNameLength = scope->GetOwnPropertyNames()->Length();
  270. #endif
  271. if(propertyNameLength > 0)
  272. {
  273. this->CommitType(typeLocation, BSON_TYPE_CODE_W_SCOPE);
  274. void* codeWidthScopeSize = this->BeginWriteSize();
  275. this->WriteLengthPrefixedString(function->ToString());
  276. SerializeDocument(scope);
  277. this->CommitSize(codeWidthScopeSize);
  278. }
  279. else
  280. {
  281. this->CommitType(typeLocation, BSON_TYPE_CODE);
  282. this->WriteLengthPrefixedString(function->ToString());
  283. }
  284. }
  285. else if(NanStr(DBREF_CLASS_NAME)->StrictEquals(constructorString))
  286. {
  287. this->CommitType(typeLocation, BSON_TYPE_OBJECT);
  288. void* dbRefSize = this->BeginWriteSize();
  289. void* refType = this->BeginWriteType();
  290. this->WriteData("$ref", 5);
  291. SerializeValue(refType, NanGet(object, DBREF_NAMESPACE_PROPERTY_NAME), false);
  292. void* idType = this->BeginWriteType();
  293. this->WriteData("$id", 4);
  294. SerializeValue(idType, NanGet(object, DBREF_OID_PROPERTY_NAME), false);
  295. const Local<Value>& refDbValue = NanGet(object, DBREF_DB_PROPERTY_NAME);
  296. if(!refDbValue->IsUndefined())
  297. {
  298. void* dbType = this->BeginWriteType();
  299. this->WriteData("$db", 4);
  300. SerializeValue(dbType, refDbValue, false);
  301. }
  302. this->WriteByte(0);
  303. this->CommitSize(dbRefSize);
  304. }
  305. else if(NanStr(MIN_KEY_CLASS_NAME)->StrictEquals(constructorString))
  306. {
  307. this->CommitType(typeLocation, BSON_TYPE_MIN_KEY);
  308. }
  309. else if(NanStr(MAX_KEY_CLASS_NAME)->StrictEquals(constructorString))
  310. {
  311. this->CommitType(typeLocation, BSON_TYPE_MAX_KEY);
  312. }
  313. }
  314. else if(node::Buffer::HasInstance(value))
  315. {
  316. this->CommitType(typeLocation, BSON_TYPE_BINARY);
  317. #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3
  318. Local<Object> buffer = ObjectWrap::Unwrap<Buffer>(value->ToObject());
  319. uint32_t length = object->length();
  320. #else
  321. uint32_t length = node::Buffer::Length(value->ToObject());
  322. #endif
  323. this->WriteInt32(length);
  324. this->WriteByte(0);
  325. this->WriteData(node::Buffer::Data(value->ToObject()), length);
  326. }
  327. else
  328. {
  329. this->CommitType(typeLocation, BSON_TYPE_OBJECT);
  330. SerializeDocument(value);
  331. }
  332. }
  333. else if(value->IsNull())
  334. {
  335. this->CommitType(typeLocation, BSON_TYPE_NULL);
  336. }
  337. else if(value->IsUndefined() && isArray)
  338. {
  339. this->CommitType(typeLocation, BSON_TYPE_NULL);
  340. }
  341. }
  342. // Data points to start of element list, length is length of entire document including '\0' but excluding initial size
  343. BSONDeserializer::BSONDeserializer(BSON* aBson, char* data, size_t length)
  344. : bson(aBson),
  345. pStart(data),
  346. p(data),
  347. pEnd(data + length - 1)
  348. {
  349. if(*pEnd != '\0') ThrowAllocatedStringException(64, "Missing end of document marker '\\0'");
  350. }
  351. BSONDeserializer::BSONDeserializer(BSONDeserializer& parentSerializer, size_t length)
  352. : bson(parentSerializer.bson),
  353. pStart(parentSerializer.p),
  354. p(parentSerializer.p),
  355. pEnd(parentSerializer.p + length - 1)
  356. {
  357. parentSerializer.p += length;
  358. if(pEnd > parentSerializer.pEnd) ThrowAllocatedStringException(64, "Child document exceeds parent's bounds");
  359. if(*pEnd != '\0') ThrowAllocatedStringException(64, "Missing end of document marker '\\0'");
  360. }
  361. Local<Value> BSONDeserializer::ReadCString() {
  362. char* start = p;
  363. while(*p++ && (p < pEnd)) { }
  364. if(p > pEnd) {
  365. return Nan::Null();
  366. }
  367. return Unmaybe(Nan::New<String>(start, (int32_t) (p-start-1) ));
  368. }
  369. int32_t BSONDeserializer::ReadRegexOptions() {
  370. int32_t options = 0;
  371. for(;;) {
  372. switch(*p++) {
  373. case '\0': return options;
  374. case 's': options |= RegExp::kGlobal; break;
  375. case 'i': options |= RegExp::kIgnoreCase; break;
  376. case 'm': options |= RegExp::kMultiline; break;
  377. }
  378. }
  379. }
  380. uint32_t BSONDeserializer::ReadIntegerString() {
  381. uint32_t value = 0;
  382. while(*p) {
  383. if(*p < '0' || *p > '9') ThrowAllocatedStringException(64, "Invalid key for array");
  384. value = value * 10 + *p++ - '0';
  385. }
  386. ++p;
  387. return value;
  388. }
  389. Local<String> BSONDeserializer::ReadString() {
  390. uint32_t length = ReadUInt32();
  391. char* start = p;
  392. p += length;
  393. return Unmaybe(Nan::New<String>(start, length-1));
  394. }
  395. Local<String> BSONDeserializer::ReadObjectId() {
  396. uint16_t objectId[12];
  397. for(size_t i = 0; i < 12; ++i) {
  398. objectId[i] = *reinterpret_cast<unsigned char*>(p++);
  399. }
  400. return Unmaybe(Nan::New<String>(objectId, 12));
  401. }
  402. Local<Value> BSONDeserializer::DeserializeDocument(bool promoteLongs) {
  403. uint32_t length = ReadUInt32();
  404. if(length < 5) ThrowAllocatedStringException(64, "Bad BSON: Document is less than 5 bytes");
  405. BSONDeserializer documentDeserializer(*this, length-4);
  406. return documentDeserializer.DeserializeDocumentInternal(promoteLongs);
  407. }
  408. Local<Value> BSONDeserializer::DeserializeDocumentInternal(bool promoteLongs) {
  409. Local<Object> returnObject = Unmaybe(Nan::New<Object>());
  410. while(HasMoreData()) {
  411. BsonType type = (BsonType) ReadByte();
  412. const Local<Value>& name = ReadCString();
  413. if(name->IsNull()) ThrowAllocatedStringException(64, "Bad BSON Document: illegal CString");
  414. // name->Is
  415. const Local<Value>& value = DeserializeValue(type, promoteLongs);
  416. returnObject->ForceSet(name, value);
  417. }
  418. if(p != pEnd) ThrowAllocatedStringException(64, "Bad BSON Document: Serialize consumed unexpected number of bytes");
  419. // From JavaScript:
  420. // if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']);
  421. if(NanHas(returnObject, DBREF_ID_REF_PROPERTY_NAME)) {
  422. Local<Value> argv[] = { NanGet(returnObject, DBREF_REF_PROPERTY_NAME), NanGet(returnObject, DBREF_ID_REF_PROPERTY_NAME), NanGet(returnObject, DBREF_DB_REF_PROPERTY_NAME) };
  423. return Nan::New(bson->dbrefConstructor)->NewInstance(3, argv);
  424. } else {
  425. return returnObject;
  426. }
  427. }
  428. Local<Value> BSONDeserializer::DeserializeArray(bool promoteLongs) {
  429. uint32_t length = ReadUInt32();
  430. if(length < 5) ThrowAllocatedStringException(64, "Bad BSON: Array Document is less than 5 bytes");
  431. BSONDeserializer documentDeserializer(*this, length-4);
  432. return documentDeserializer.DeserializeArrayInternal(promoteLongs);
  433. }
  434. Local<Value> BSONDeserializer::DeserializeArrayInternal(bool promoteLongs) {
  435. Local<Array> returnArray = Unmaybe(Nan::New<Array>());
  436. while(HasMoreData()) {
  437. BsonType type = (BsonType) ReadByte();
  438. uint32_t index = ReadIntegerString();
  439. const Local<Value>& value = DeserializeValue(type, promoteLongs);
  440. returnArray->Set(index, value);
  441. }
  442. if(p != pEnd) ThrowAllocatedStringException(64, "Bad BSON Array: Serialize consumed unexpected number of bytes");
  443. return returnArray;
  444. }
  445. Local<Value> BSONDeserializer::DeserializeValue(BsonType type, bool promoteLongs)
  446. {
  447. switch(type)
  448. {
  449. case BSON_TYPE_STRING:
  450. return ReadString();
  451. case BSON_TYPE_INT:
  452. return Nan::New<Integer>(ReadInt32());
  453. case BSON_TYPE_NUMBER:
  454. return Nan::New<Number>(ReadDouble());
  455. case BSON_TYPE_NULL:
  456. return Nan::Null();
  457. case BSON_TYPE_UNDEFINED:
  458. return Nan::Null();
  459. case BSON_TYPE_TIMESTAMP: {
  460. int32_t lowBits = ReadInt32();
  461. int32_t highBits = ReadInt32();
  462. Local<Value> argv[] = { Nan::New<Int32>(lowBits), Nan::New<Int32>(highBits) };
  463. return Nan::New(bson->timestampConstructor)->NewInstance(2, argv);
  464. }
  465. case BSON_TYPE_BOOLEAN:
  466. return (ReadByte() != 0) ? Nan::True() : Nan::False();
  467. case BSON_TYPE_REGEXP: {
  468. const Local<Value>& regex = ReadCString();
  469. if(regex->IsNull()) ThrowAllocatedStringException(64, "Bad BSON Document: illegal CString");
  470. int32_t options = ReadRegexOptions();
  471. return Unmaybe(Nan::New<RegExp>(regex->ToString(), (RegExp::Flags) options));
  472. }
  473. case BSON_TYPE_CODE: {
  474. const Local<Value>& code = ReadString();
  475. const Local<Value>& scope = Unmaybe(Nan::New<Object>());
  476. Local<Value> argv[] = { code, scope };
  477. return Nan::New(bson->codeConstructor)->NewInstance(2, argv);
  478. }
  479. case BSON_TYPE_CODE_W_SCOPE: {
  480. ReadUInt32();
  481. const Local<Value>& code = ReadString();
  482. const Local<Value>& scope = DeserializeDocument(promoteLongs);
  483. Local<Value> argv[] = { code, scope->ToObject() };
  484. return Nan::New(bson->codeConstructor)->NewInstance(2, argv);
  485. }
  486. case BSON_TYPE_OID: {
  487. Local<Value> argv[] = { ReadObjectId() };
  488. return Nan::New(bson->objectIDConstructor)->NewInstance(1, argv);
  489. }
  490. case BSON_TYPE_BINARY: {
  491. uint32_t length = ReadUInt32();
  492. uint32_t subType = ReadByte();
  493. if(subType == 0x02) {
  494. length = ReadInt32();
  495. }
  496. Local<Object> buffer = Unmaybe(Nan::CopyBuffer(p, length));
  497. p += length;
  498. Local<Value> argv[] = { buffer, Nan::New<Uint32>(subType) };
  499. return Nan::New(bson->binaryConstructor)->NewInstance(2, argv);
  500. }
  501. case BSON_TYPE_LONG: {
  502. // Read 32 bit integers
  503. int32_t lowBits = (int32_t) ReadInt32();
  504. int32_t highBits = (int32_t) ReadInt32();
  505. // Promote long is enabled
  506. if(promoteLongs) {
  507. // If value is < 2^53 and >-2^53
  508. if((highBits < 0x200000 || (highBits == 0x200000 && lowBits == 0)) && highBits >= -0x200000) {
  509. // Adjust the pointer and read as 64 bit value
  510. p -= 8;
  511. // Read the 64 bit value
  512. int64_t finalValue = (int64_t) ReadInt64();
  513. return Nan::New<Number>(finalValue);
  514. }
  515. }
  516. // Decode the Long value
  517. Local<Value> argv[] = { Nan::New<Int32>(lowBits), Nan::New<Int32>(highBits) };
  518. return Nan::New(bson->longConstructor)->NewInstance(2, argv);
  519. }
  520. case BSON_TYPE_DATE:
  521. return Unmaybe(Nan::New<Date>((double) ReadInt64()));
  522. case BSON_TYPE_ARRAY:
  523. return DeserializeArray(promoteLongs);
  524. case BSON_TYPE_OBJECT:
  525. return DeserializeDocument(promoteLongs);
  526. case BSON_TYPE_SYMBOL: {
  527. const Local<String>& string = ReadString();
  528. Local<Value> argv[] = { string };
  529. return Nan::New(bson->symbolConstructor)->NewInstance(1, argv);
  530. }
  531. case BSON_TYPE_MIN_KEY:
  532. return Nan::New(bson->minKeyConstructor)->NewInstance();
  533. case BSON_TYPE_MAX_KEY:
  534. return Nan::New(bson->maxKeyConstructor)->NewInstance();
  535. default:
  536. ThrowAllocatedStringException(64, "Unhandled BSON Type: %d", type);
  537. }
  538. return Nan::Null();
  539. }
  540. // statics
  541. Persistent<FunctionTemplate> BSON::constructor_template;
  542. BSON::BSON() : ObjectWrap()
  543. {
  544. }
  545. BSON::~BSON()
  546. {
  547. Nan::HandleScope scope;
  548. // dispose persistent handles
  549. buffer.Reset();
  550. longConstructor.Reset();
  551. objectIDConstructor.Reset();
  552. binaryConstructor.Reset();
  553. codeConstructor.Reset();
  554. dbrefConstructor.Reset();
  555. symbolConstructor.Reset();
  556. doubleConstructor.Reset();
  557. timestampConstructor.Reset();
  558. minKeyConstructor.Reset();
  559. maxKeyConstructor.Reset();
  560. }
  561. void BSON::Initialize(v8::Local<v8::Object> target) {
  562. // Grab the scope of the call from Node
  563. Nan::HandleScope scope;
  564. // Define a new function template
  565. Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(New);
  566. t->InstanceTemplate()->SetInternalFieldCount(1);
  567. t->SetClassName(NanStr("BSON"));
  568. // Instance methods
  569. Nan::SetPrototypeMethod(t, "calculateObjectSize", CalculateObjectSize);
  570. Nan::SetPrototypeMethod(t, "serialize", BSONSerialize);
  571. Nan::SetPrototypeMethod(t, "serializeWithBufferAndIndex", SerializeWithBufferAndIndex);
  572. Nan::SetPrototypeMethod(t, "deserialize", BSONDeserialize);
  573. Nan::SetPrototypeMethod(t, "deserializeStream", BSONDeserializeStream);
  574. constructor_template.Reset(t);
  575. target->ForceSet(NanStr("BSON"), t->GetFunction());
  576. }
  577. // Create a new instance of BSON and passing it the existing context
  578. NAN_METHOD(BSON::New) {
  579. Nan::HandleScope scope;
  580. // Var maximum bson size
  581. size_t maxBSONSize = MAX_BSON_SIZE;
  582. // Check that we have an array
  583. if(info.Length() >= 1 && info[0]->IsArray()) {
  584. // Cast the array to a local reference
  585. Local<Array> array = Local<Array>::Cast(info[0]);
  586. // If we have an options object we can set the maximum bson size to enforce
  587. if(info.Length() == 2 && info[1]->IsObject()) {
  588. Local<Object> options = info[1]->ToObject();
  589. // Do we have a value set
  590. if(NanHas(options, "maxBSONSize") && NanGet(options, "maxBSONSize")->IsNumber()) {
  591. maxBSONSize = (size_t)NanGet(options, "maxBSONSize")->Int32Value();
  592. }
  593. }
  594. if(array->Length() > 0) {
  595. // Create a bson object instance and return it
  596. BSON *bson = new BSON();
  597. bson->maxBSONSize = maxBSONSize;
  598. // Allocate a new Buffer
  599. bson->buffer.Reset(Unmaybe(Nan::NewBuffer(sizeof(char) * maxBSONSize)));
  600. // Defined the classmask
  601. uint32_t foundClassesMask = 0;
  602. // Iterate over all entries to save the instantiate functions
  603. for(uint32_t i = 0; i < array->Length(); i++) {
  604. // Let's get a reference to the function
  605. Local<Function> func = Local<Function>::Cast(NanGet(array, i));
  606. Local<String> functionName = func->GetName()->ToString();
  607. // Save the functions making them persistant handles (they don't get collected)
  608. if(functionName->StrictEquals(NanStr(LONG_CLASS_NAME))) {
  609. bson->longConstructor.Reset(func);
  610. foundClassesMask |= 1;
  611. } else if(functionName->StrictEquals(NanStr(OBJECT_ID_CLASS_NAME))) {
  612. bson->objectIDConstructor.Reset(func);
  613. foundClassesMask |= 2;
  614. } else if(functionName->StrictEquals(NanStr(BINARY_CLASS_NAME))) {
  615. bson->binaryConstructor.Reset(func);
  616. foundClassesMask |= 4;
  617. } else if(functionName->StrictEquals(NanStr(CODE_CLASS_NAME))) {
  618. bson->codeConstructor.Reset(func);
  619. foundClassesMask |= 8;
  620. } else if(functionName->StrictEquals(NanStr(DBREF_CLASS_NAME))) {
  621. bson->dbrefConstructor.Reset(func);
  622. foundClassesMask |= 0x10;
  623. } else if(functionName->StrictEquals(NanStr(SYMBOL_CLASS_NAME))) {
  624. bson->symbolConstructor.Reset(func);
  625. foundClassesMask |= 0x20;
  626. } else if(functionName->StrictEquals(NanStr(DOUBLE_CLASS_NAME))) {
  627. bson->doubleConstructor.Reset(func);
  628. foundClassesMask |= 0x40;
  629. } else if(functionName->StrictEquals(NanStr(TIMESTAMP_CLASS_NAME))) {
  630. bson->timestampConstructor.Reset(func);
  631. foundClassesMask |= 0x80;
  632. } else if(functionName->StrictEquals(NanStr(MIN_KEY_CLASS_NAME))) {
  633. bson->minKeyConstructor.Reset(func);
  634. foundClassesMask |= 0x100;
  635. } else if(functionName->StrictEquals(NanStr(MAX_KEY_CLASS_NAME))) {
  636. bson->maxKeyConstructor.Reset(func);
  637. foundClassesMask |= 0x200;
  638. }
  639. }
  640. // Check if we have the right number of constructors otherwise throw an error
  641. if(foundClassesMask != 0x3ff) {
  642. delete bson;
  643. return Nan::ThrowError("Missing function constructor for either [Long/ObjectID/Binary/Code/DbRef/Symbol/Double/Timestamp/MinKey/MaxKey]");
  644. } else {
  645. bson->Wrap(info.This());
  646. info.GetReturnValue().Set(info.This());
  647. }
  648. } else {
  649. return Nan::ThrowError("No types passed in");
  650. }
  651. } else {
  652. return Nan::ThrowTypeError("First argument passed in must be an array of types");
  653. }
  654. }
  655. //------------------------------------------------------------------------------------------------
  656. //------------------------------------------------------------------------------------------------
  657. //------------------------------------------------------------------------------------------------
  658. //------------------------------------------------------------------------------------------------
  659. NAN_METHOD(BSON::BSONDeserialize) {
  660. Nan::HandleScope scope;
  661. // Fail if the first argument is not a string or a buffer
  662. if(info.Length() > 1 && !info[0]->IsString() && !node::Buffer::HasInstance(info[0]))
  663. return Nan::ThrowError("First Argument must be a Buffer or String.");
  664. // Promote longs
  665. bool promoteLongs = true;
  666. // If we have an options object
  667. if(info.Length() == 2 && info[1]->IsObject()) {
  668. Local<Object> options = info[1]->ToObject();
  669. if(NanHas(options, "promoteLongs")) {
  670. promoteLongs = NanGet(options, "promoteLongs")->ToBoolean()->Value();
  671. }
  672. }
  673. // Define pointer to data
  674. Local<Object> obj = info[0]->ToObject();
  675. // Unpack the BSON parser instance
  676. BSON *bson = ObjectWrap::Unwrap<BSON>(info.This());
  677. // If we passed in a buffer, let's unpack it, otherwise let's unpack the string
  678. if(node::Buffer::HasInstance(obj)) {
  679. #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3
  680. Local<Object> buffer = ObjectWrap::Unwrap<Buffer>(obj);
  681. char* data = buffer->data();
  682. size_t length = buffer->length();
  683. #else
  684. char* data = node::Buffer::Data(obj);
  685. size_t length = node::Buffer::Length(obj);
  686. #endif
  687. // Validate that we have at least 5 bytes
  688. if(length < 5) return Nan::ThrowError("corrupt bson message < 5 bytes long");
  689. try {
  690. BSONDeserializer deserializer(bson, data, length);
  691. // deserializer.promoteLongs = promoteLongs;
  692. info.GetReturnValue().Set(deserializer.DeserializeDocument(promoteLongs));
  693. } catch(char* exception) {
  694. Local<String> error = NanStr(exception);
  695. free(exception);
  696. return Nan::ThrowError(error);
  697. }
  698. } else {
  699. // The length of the data for this encoding
  700. ssize_t len = Nan::DecodeBytes(info[0]);
  701. // Validate that we have at least 5 bytes
  702. if(len < 5) return Nan::ThrowError("corrupt bson message < 5 bytes long");
  703. // Let's define the buffer size
  704. char* data = (char *)malloc(len);
  705. if(data == NULL) die("Failed to allocate char buffer for BSON serialization");
  706. Nan::DecodeWrite(data, len, info[0]);
  707. try {
  708. BSONDeserializer deserializer(bson, data, len);
  709. // deserializer.promoteLongs = promoteLongs;
  710. Local<Value> result = deserializer.DeserializeDocument(promoteLongs);
  711. free(data);
  712. info.GetReturnValue().Set(result);
  713. } catch(char* exception) {
  714. Local<String> error = NanStr(exception);
  715. free(exception);
  716. free(data);
  717. return Nan::ThrowError(error);
  718. }
  719. }
  720. }
  721. Local<Object> BSON::GetSerializeObject(const Local<Value>& argValue)
  722. {
  723. Local<Object> object = argValue->ToObject();
  724. if(NanHas(object, TO_BSON_PROPERTY_NAME)) {
  725. const Local<Value>& toBSON = NanGet(object, TO_BSON_PROPERTY_NAME);
  726. if(!toBSON->IsFunction()) ThrowAllocatedStringException(64, "toBSON is not a function");
  727. Local<Value> result = Local<Function>::Cast(toBSON)->Call(object, 0, NULL);
  728. if(!result->IsObject()) ThrowAllocatedStringException(64, "toBSON function did not return an object");
  729. return result->ToObject();
  730. } else {
  731. return object;
  732. }
  733. }
  734. NAN_METHOD(BSON::BSONSerialize) {
  735. Nan::HandleScope scope;
  736. // Unpack the objects
  737. if(info.Length() == 1 && !info[0]->IsObject()) return Nan::ThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]");
  738. if(info.Length() == 2 && !info[0]->IsObject() && !info[1]->IsBoolean()) return Nan::ThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]");
  739. if(info.Length() == 3 && !info[0]->IsObject() && !info[1]->IsBoolean() && !info[2]->IsBoolean()) return Nan::ThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]");
  740. if(info.Length() == 4 && !info[0]->IsObject() && !info[1]->IsBoolean() && !info[2]->IsBoolean() && !info[3]->IsBoolean()) return Nan::ThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean] or [object, boolean, boolean, boolean]");
  741. if(info.Length() > 4) return Nan::ThrowError("One, two, tree or four arguments required - [object] or [object, boolean] or [object, boolean, boolean] or [object, boolean, boolean, boolean]");
  742. // Check if we have an array as the object
  743. if(info[0]->IsArray()) return Nan::ThrowError("Only javascript objects supported");
  744. // Unpack the BSON parser instance
  745. BSON *bson = ObjectWrap::Unwrap<BSON>(info.This());
  746. // Calculate the total size of the document in binary form to ensure we only allocate memory once
  747. // With serialize function
  748. bool serializeFunctions = (info.Length() >= 4) && info[3]->BooleanValue();
  749. char *final = NULL;
  750. char *serialized_object = NULL;
  751. size_t object_size;
  752. try {
  753. Local<Object> object = bson->GetSerializeObject(info[0]);
  754. // Get a local reference to the persistant buffer
  755. Local<Object> o = Nan::New(bson->buffer);
  756. // Get a reference to the buffer *char pointer
  757. serialized_object = node::Buffer::Data(o);
  758. // Check if we have a boolean value
  759. bool checkKeys = info.Length() >= 3 && info[1]->IsBoolean() && info[1]->BooleanValue();
  760. BSONSerializer<DataStream> data(bson, checkKeys, serializeFunctions, serialized_object);
  761. data.SerializeDocument(object);
  762. // Get the object size
  763. object_size = data.GetSerializeSize();
  764. // Copy the correct size
  765. final = (char *)malloc(sizeof(char) * object_size);
  766. // Copy to the final
  767. memcpy(final, serialized_object, object_size);
  768. // Assign pointer
  769. serialized_object = final;
  770. } catch(char *err_msg) {
  771. free(final);
  772. Local<String> error = NanStr(err_msg);
  773. free(err_msg);
  774. return Nan::ThrowError(error);
  775. } catch(const char *err_msg) {
  776. free(final);
  777. Local<String> error = NanStr(err_msg);
  778. return Nan::ThrowError(error);
  779. }
  780. // If we have 3 arguments
  781. if(info.Length() == 3 || info.Length() == 4) {
  782. // NewBuffer takes ownership on the memory, so no need to free the final allocation
  783. Local<Object> buffer = Unmaybe(Nan::NewBuffer(serialized_object, object_size));
  784. info.GetReturnValue().Set(buffer);
  785. } else {
  786. Local<Value> bin_value = Nan::Encode(serialized_object, object_size)->ToString();
  787. free(final);
  788. info.GetReturnValue().Set(bin_value);
  789. }
  790. }
  791. NAN_METHOD(BSON::CalculateObjectSize) {
  792. Nan::HandleScope scope;
  793. // Ensure we have a valid object
  794. if(info.Length() == 1 && !info[0]->IsObject()) return Nan::ThrowError("One argument required - [object]");
  795. if(info.Length() == 2 && !info[0]->IsObject() && !info[1]->IsBoolean()) return Nan::ThrowError("Two arguments required - [object, boolean]");
  796. if(info.Length() > 3) return Nan::ThrowError("One or two arguments required - [object] or [object, boolean]");
  797. // Unpack the BSON parser instance
  798. BSON *bson = ObjectWrap::Unwrap<BSON>(info.This());
  799. bool serializeFunctions = (info.Length() >= 2) && info[1]->BooleanValue();
  800. BSONSerializer<CountStream> countSerializer(bson, false, serializeFunctions);
  801. countSerializer.SerializeDocument(info[0]);
  802. // Return the object size
  803. info.GetReturnValue().Set(Nan::New<Uint32>((uint32_t) countSerializer.GetSerializeSize()));
  804. }
  805. NAN_METHOD(BSON::SerializeWithBufferAndIndex) {
  806. Nan::HandleScope scope;
  807. // Ensure we have the correct values
  808. if(info.Length() > 5) return Nan::ThrowError("Four or five parameters required [object, boolean, Buffer, int] or [object, boolean, Buffer, int, boolean]");
  809. if(info.Length() == 4 && !info[0]->IsObject() && !info[1]->IsBoolean() && !node::Buffer::HasInstance(info[2]) && !info[3]->IsUint32()) return Nan::ThrowError("Four parameters required [object, boolean, Buffer, int]");
  810. if(info.Length() == 5 && !info[0]->IsObject() && !info[1]->IsBoolean() && !node::Buffer::HasInstance(info[2]) && !info[3]->IsUint32() && !info[4]->IsBoolean()) return Nan::ThrowError("Four parameters required [object, boolean, Buffer, int, boolean]");
  811. uint32_t index;
  812. size_t object_size;
  813. try {
  814. BSON *bson = ObjectWrap::Unwrap<BSON>(info.This());
  815. Local<Object> obj = info[2]->ToObject();
  816. char* data = node::Buffer::Data(obj);
  817. size_t length = node::Buffer::Length(obj);
  818. index = info[3]->Uint32Value();
  819. bool checkKeys = info.Length() >= 4 && info[1]->IsBoolean() && info[1]->BooleanValue();
  820. bool serializeFunctions = (info.Length() == 5) && info[4]->BooleanValue();
  821. BSONSerializer<DataStream> dataSerializer(bson, checkKeys, serializeFunctions, data+index);
  822. dataSerializer.SerializeDocument(bson->GetSerializeObject(info[0]));
  823. object_size = dataSerializer.GetSerializeSize();
  824. if(object_size + index > length) return Nan::ThrowError("Serious error - overflowed buffer!!");
  825. } catch(char *exception) {
  826. Local<String> error = NanStr(exception);
  827. free(exception);
  828. return Nan::ThrowError(error);
  829. } catch(const char *exception) {
  830. Local<String> error = NanStr(exception);
  831. return Nan::ThrowError(error);
  832. }
  833. info.GetReturnValue().Set(Nan::New<Uint32>((uint32_t) (index + object_size - 1)));
  834. }
  835. NAN_METHOD(BSON::BSONDeserializeStream) {
  836. Nan::HandleScope scope;
  837. // At least 3 arguments required
  838. if(info.Length() < 5) return Nan::ThrowError("Arguments required (Buffer(data), Number(index in data), Number(number of documents to deserialize), Array(results), Number(index in the array), Object(optional))");
  839. // If the number of argumets equals 3
  840. if(info.Length() >= 5) {
  841. if(!node::Buffer::HasInstance(info[0])) return Nan::ThrowError("First argument must be Buffer instance");
  842. if(!info[1]->IsUint32()) return Nan::ThrowError("Second argument must be a positive index number");
  843. if(!info[2]->IsUint32()) return Nan::ThrowError("Third argument must be a positive number of documents to deserialize");
  844. if(!info[3]->IsArray()) return Nan::ThrowError("Fourth argument must be an array the size of documents to deserialize");
  845. if(!info[4]->IsUint32()) return Nan::ThrowError("Sixth argument must be a positive index number");
  846. }
  847. // If we have 4 arguments
  848. if(info.Length() == 6 && !info[5]->IsObject()) return Nan::ThrowError("Fifth argument must be an object with options");
  849. // Define pointer to data
  850. Local<Object> obj = info[0]->ToObject();
  851. uint32_t numberOfDocuments = info[2]->Uint32Value();
  852. uint32_t index = info[1]->Uint32Value();
  853. uint32_t resultIndex = info[4]->Uint32Value();
  854. bool promoteLongs = true;
  855. // Check for the value promoteLongs in the options object
  856. if(info.Length() == 6) {
  857. Local<Object> options = info[5]->ToObject();
  858. // Check if we have the promoteLong variable
  859. if(NanHas(options, "promoteLongs")) {
  860. promoteLongs = NanGet(options, "promoteLongs")->ToBoolean()->Value();
  861. }
  862. }
  863. // Unpack the BSON parser instance
  864. BSON *bson = ObjectWrap::Unwrap<BSON>(info.This());
  865. // Unpack the buffer variable
  866. #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3
  867. Local<Object> buffer = ObjectWrap::Unwrap<Buffer>(obj);
  868. char* data = buffer->data();
  869. size_t length = buffer->length();
  870. #else
  871. char* data = node::Buffer::Data(obj);
  872. size_t length = node::Buffer::Length(obj);
  873. #endif
  874. // Fetch the documents
  875. Local<Object> documents = info[3]->ToObject();
  876. BSONDeserializer deserializer(bson, data+index, length-index);
  877. for(uint32_t i = 0; i < numberOfDocuments; i++) {
  878. try {
  879. documents->Set(i + resultIndex, deserializer.DeserializeDocument(promoteLongs));
  880. } catch (char* exception) {
  881. Local<String> error = NanStr(exception);
  882. free(exception);
  883. return Nan::ThrowError(error);
  884. }
  885. }
  886. // Return new index of parsing
  887. info.GetReturnValue().Set(Nan::New<Uint32>((uint32_t) (index + deserializer.GetSerializeSize())));
  888. }
  889. // Exporting function
  890. extern "C" void init(Local<Object> target) {
  891. Nan::HandleScope scope;
  892. BSON::Initialize(target);
  893. }
  894. NODE_MODULE(bson, BSON::Initialize);