summaryrefslogtreecommitdiff
path: root/node_modules/webworker-threads/src/bson.h
blob: 6f484b16b4d8b76d4c990cd15f2c281e4ead8c9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
//===========================================================================

#ifndef BSON_H_
#define BSON_H_

#ifdef __sun
#include <alloca.h>
#endif

//===========================================================================

#define USE_MISALIGNED_MEMORY_ACCESS 1

#include <node.h>
#include <node_object_wrap.h>
#include <v8.h>

using namespace v8;
using namespace node;

//===========================================================================

enum BsonType
{
	BSON_TYPE_NUMBER		= 1,
	BSON_TYPE_STRING		= 2,
	BSON_TYPE_OBJECT		= 3,
	BSON_TYPE_ARRAY			= 4,
	BSON_TYPE_BINARY		= 5,
	BSON_TYPE_UNDEFINED		= 6,
	BSON_TYPE_OID			= 7,
	BSON_TYPE_BOOLEAN		= 8,
	BSON_TYPE_DATE			= 9,
	BSON_TYPE_NULL			= 10,
	BSON_TYPE_REGEXP		= 11,
	BSON_TYPE_CODE			= 13,
	BSON_TYPE_SYMBOL		= 14,
	BSON_TYPE_CODE_W_SCOPE	= 15,
	BSON_TYPE_INT			= 16,
	BSON_TYPE_TIMESTAMP		= 17,
	BSON_TYPE_LONG			= 18,
	BSON_TYPE_MAX_KEY		= 0x7f,
	BSON_TYPE_MIN_KEY		= 0xff
};

//===========================================================================

template<typename T> class BSONSerializer;

class BSON : public ObjectWrap {
public:    
	BSON();
	~BSON() {}

	static void Initialize(Handle<Object> target);
	static Handle<Value> BSONDeserializeStream(const Arguments &args);

	// JS based objects
	static Handle<Value> BSONSerialize(const Arguments &args);
	static Handle<Value> BSONDeserialize(const Arguments &args);

	// Calculate size of function
	static Handle<Value> CalculateObjectSize(const Arguments &args);
	static Handle<Value> SerializeWithBufferAndIndex(const Arguments &args);

	// Constructor used for creating new BSON objects from C++
	static Persistent<FunctionTemplate> constructor_template;

private:
	static Handle<Value> New(const Arguments &args);
	static Handle<Value> deserialize(BSON *bson, char *data, uint32_t dataLength, uint32_t startIndex, bool is_array_item);

	// BSON type instantiate functions
	Persistent<Function> longConstructor;
	Persistent<Function> objectIDConstructor;
	Persistent<Function> binaryConstructor;
	Persistent<Function> codeConstructor;
	Persistent<Function> dbrefConstructor;
	Persistent<Function> symbolConstructor;
	Persistent<Function> doubleConstructor;
	Persistent<Function> timestampConstructor;
	Persistent<Function> minKeyConstructor;
	Persistent<Function> maxKeyConstructor;

	// Equality Objects
	Persistent<String> longString;
	Persistent<String> objectIDString;
	Persistent<String> binaryString;
	Persistent<String> codeString;
	Persistent<String> dbrefString;
	Persistent<String> symbolString;
	Persistent<String> doubleString;
	Persistent<String> timestampString;
	Persistent<String> minKeyString;
	Persistent<String> maxKeyString;

	// Equality speed up comparison objects
	Persistent<String> _bsontypeString;
	Persistent<String> _longLowString;
	Persistent<String> _longHighString;
	Persistent<String> _objectIDidString;
	Persistent<String> _binaryPositionString;
	Persistent<String> _binarySubTypeString;
	Persistent<String> _binaryBufferString;
	Persistent<String> _doubleValueString;
	Persistent<String> _symbolValueString;

	Persistent<String> _dbRefRefString;
	Persistent<String> _dbRefIdRefString;
	Persistent<String> _dbRefDbRefString;
	Persistent<String> _dbRefNamespaceString;
	Persistent<String> _dbRefDbString;
	Persistent<String> _dbRefOidString;

	Persistent<String> _codeCodeString;
	Persistent<String> _codeScopeString;
	Persistent<String> _toBSONString;

public: Local<Object> GetSerializeObject(const Handle<Value>& object);

	template<typename T> friend class BSONSerializer;
	friend class BSONDeserializer;
};

//===========================================================================

class CountStream
{
public:
	CountStream() : count(0) { }

	void	WriteByte(int value)									{ ++count; }
	void	WriteByte(const Handle<Object>&, const Handle<String>&)	{ ++count; }
	void	WriteBool(const Handle<Value>& value)					{ ++count; }
	void	WriteInt32(int32_t value)								{ count += 4; }
	void	WriteInt32(const Handle<Value>& value)					{ count += 4; }
	void	WriteInt32(const Handle<Object>& object, const Handle<String>& key) { count += 4; }
	void	WriteInt64(int64_t value)								{ count += 8; }
	void	WriteInt64(const Handle<Value>& value)					{ count += 8; }
	void	WriteDouble(double value)								{ count += 8; }
	void	WriteDouble(const Handle<Value>& value)					{ count += 8; }
	void	WriteDouble(const Handle<Object>&, const Handle<String>&) { count += 8; }
	void	WriteUInt32String(uint32_t name)						{ char buffer[32]; count += sprintf(buffer, "%u", name) + 1; }
	void	WriteLengthPrefixedString(const Local<String>& value)	{ count += value->Utf8Length()+5; }
	void	WriteObjectId(const Handle<Object>& object, const Handle<String>& key)				{ count += 12; }
	void	WriteString(const Local<String>& value)					{ count += value->Utf8Length() + 1; }	// This returns the number of bytes exclusive of the NULL terminator
	void	WriteData(const char* data, size_t length)				{ count += length; }

	void*	BeginWriteType()										{ ++count; return NULL; }
	void	CommitType(void*, BsonType)								{ }
	void*	BeginWriteSize()										{ count += 4; return NULL; }
	void	CommitSize(void*)										{ }

	size_t GetSerializeSize() const									{ return count; }

	// Do nothing. CheckKey is implemented for DataStream
	void	CheckKey(const Local<String>&)							{ }

private:
	size_t	count;
};

class DataStream
{
public:
	DataStream(char* aDestinationBuffer) : destinationBuffer(aDestinationBuffer), p(aDestinationBuffer) { }

	void	WriteByte(int value)									{ *p++ = value; }
	void	WriteByte(const Handle<Object>& object, const Handle<String>& key)	{ *p++ = object->Get(key)->Int32Value(); }
#if USE_MISALIGNED_MEMORY_ACCESS
	void	WriteInt32(int32_t value)								{ *reinterpret_cast<int32_t*>(p) = value; p += 4; }
	void	WriteInt64(int64_t value)								{ *reinterpret_cast<int64_t*>(p) = value; p += 8; }
	void	WriteDouble(double value)								{ *reinterpret_cast<double*>(p) = value; p += 8; }
#else
	void	WriteInt32(int32_t value)								{ memcpy(p, &value, 4); p += 4; }
	void	WriteInt64(int64_t value)								{ memcpy(p, &value, 8); p += 8; }
	void	WriteDouble(double value)								{ memcpy(p, &value, 8); p += 8; }
#endif
	void	WriteBool(const Handle<Value>& value)					{ WriteByte(value->BooleanValue() ? 1 : 0); }
	void	WriteInt32(const Handle<Value>& value)					{ WriteInt32(value->Int32Value());			}
	void	WriteInt32(const Handle<Object>& object, const Handle<String>& key) { WriteInt32(object->Get(key)); }
	void	WriteInt64(const Handle<Value>& value)					{ WriteInt64(value->IntegerValue());		}
	void	WriteDouble(const Handle<Value>& value)					{ WriteDouble(value->NumberValue());		}
	void	WriteDouble(const Handle<Object>& object, const Handle<String>& key) { WriteDouble(object->Get(key)); }
	void	WriteUInt32String(uint32_t name)						{ p += sprintf(p, "%u", name) + 1;			}
	void	WriteLengthPrefixedString(const Local<String>& value)	{ WriteInt32(value->Utf8Length()+1); WriteString(value); }
	void	WriteObjectId(const Handle<Object>& object, const Handle<String>& key);
	void	WriteString(const Local<String>& value)					{ p += value->WriteUtf8(p); }		// This returns the number of bytes inclusive of the NULL terminator.
	void	WriteData(const char* data, size_t length)				{ memcpy(p, data, length); p += length; }

	void*	BeginWriteType()										{ void* returnValue = p; p++; return returnValue; }
	void	CommitType(void* beginPoint, BsonType value)			{ *reinterpret_cast<unsigned char*>(beginPoint) = value; }
	void*	BeginWriteSize()										{ void* returnValue = p; p += 4; return returnValue; }

#if USE_MISALIGNED_MEMORY_ACCESS
	void	CommitSize(void* beginPoint)							{ *reinterpret_cast<int32_t*>(beginPoint) = (int32_t) (p - (char*) beginPoint); }
#else
	void	CommitSize(void* beginPoint)							{ int32_t value = (int32_t) (p - (char*) beginPoint); memcpy(beginPoint, &value, 4); }
#endif

	size_t GetSerializeSize() const									{ return p - destinationBuffer; }

	void	CheckKey(const Local<String>& keyName);

protected:
	char *const	destinationBuffer;		// base, never changes
	char*		p;						// cursor into buffer
};

template<typename T> class BSONSerializer : public T
{
private:
	typedef T Inherited;

public:
	BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions) : Inherited(), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { }
	BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions, char* parentParam) : Inherited(parentParam), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { }

	void SerializeDocument(const Handle<Value>& value);
	void SerializeArray(const Handle<Value>& value);
	void SerializeValue(void* typeLocation, const Handle<Value>& value);

private:
	bool		checkKeys;
	bool		serializeFunctions;
	BSON*		bson;
};

//===========================================================================

class BSONDeserializer
{
public:
	BSONDeserializer(BSON* aBson, char* data, size_t length);
	BSONDeserializer(BSONDeserializer& parentSerializer, size_t length);

	Handle<Value> DeserializeDocument();

	bool			HasMoreData() const { return p < pEnd; }
	Local<String>	ReadCString();
	uint32_t		ReadIntegerString();
	int32_t			ReadRegexOptions();
	Local<String>	ReadString();
	Local<String>	ReadObjectId();

	unsigned char	ReadByte()			{ return *reinterpret_cast<unsigned char*>(p++); }
#if USE_MISALIGNED_MEMORY_ACCESS
	int32_t			ReadInt32()			{ int32_t returnValue = *reinterpret_cast<int32_t*>(p); p += 4; return returnValue; }
	uint32_t		ReadUInt32()		{ uint32_t returnValue = *reinterpret_cast<uint32_t*>(p); p += 4; return returnValue; }
	int64_t			ReadInt64()			{ int64_t returnValue = *reinterpret_cast<int64_t*>(p); p += 8; return returnValue; }
	double			ReadDouble()		{ double returnValue = *reinterpret_cast<double*>(p); p += 8; return returnValue; }
#else
	int32_t			ReadInt32()			{ int32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; }
	uint32_t		ReadUInt32()		{ uint32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; }
	int64_t			ReadInt64()			{ int64_t returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; }
	double			ReadDouble()		{ double returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; }
#endif

	size_t			GetSerializeSize() const { return p - pStart; }

private:
	Handle<Value> DeserializeArray();
	Handle<Value> DeserializeValue(BsonType type);
	Handle<Value> DeserializeDocumentInternal();
	Handle<Value> DeserializeArrayInternal();

	BSON*		bson;
	char* const pStart;
	char*		p;
	char* const	pEnd;
};

//===========================================================================

#endif  // BSON_H_

//===========================================================================