comunicationLeap/node_modules/nan/nan.h
node_modules/nan/nan.hRaw
1/**********************************************************************************
2 * NAN - Native Abstractions for Node.js
3 *
4 * Copyright (c) 2013 NAN contributors:
5 * - Rod Vagg <https://github.com/rvagg>
6 * - Benjamin Byholm <https://github.com/kkoopa>
7 * - Trevor Norris <https://github.com/trevnorris>
8 *
9 * MIT +no-false-attribs License <https://github.com/rvagg/nan/blob/master/LICENSE>
10 *
11 * Version 0.3.2 (current Node unstable: 0.11.6, Node stable: 0.10.17)
12 *
13 * ChangeLog:
14 * * 0.3.2 Aug 30 2013
15 * - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent
16 * in NanAsyncWorker
17 *
18 * * 0.3.1 Aug 20 2013
19 * - fix "not all control paths return a value" compile warning on some platforms
20 *
21 * * 0.3.0 Aug 19 2013
22 * - Made NAN work with NPM
23 * - Lots of fixes to NanFromV8String, pulling in features from new Node core
24 * - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API
25 * - Added optional error number argument for NanThrowError()
26 * - Added NanInitPersistent()
27 * - Added NanReturnNull() and NanReturnEmptyString()
28 * - Added NanLocker and NanUnlocker
29 * - Added missing scopes
30 * - Made sure to clear disposed Persistent handles
31 * - Changed NanAsyncWorker to allocate error messages on the heap
32 * - Changed NanThrowError(Local<Value>) to NanThrowError(Handle<Value>)
33 * - Fixed leak in NanAsyncWorker when errmsg is used
34 *
35 * * 0.2.2 Aug 5 2013
36 * - Fixed usage of undefined variable with node::BASE64 in NanFromV8String()
37 *
38 * * 0.2.1 Aug 5 2013
39 * - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for
40 * NanFromV8String()
41 *
42 * * 0.2.0 Aug 5 2013
43 * - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR,
44 * NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY
45 * - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS,
46 * _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS,
47 * _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS,
48 * _NAN_PROPERTY_QUERY_ARGS
49 * - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer
50 * - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT,
51 * NAN_WEAK_CALLBACK_DATA, NanMakeWeak
52 * - Renamed THROW_ERROR to _NAN_THROW_ERROR
53 * - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*)
54 * - Added NanBufferUse(char*, uint32_t)
55 * - Added NanNewContextHandle(v8::ExtensionConfiguration*,
56 * v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Value>)
57 * - Fixed broken NanCallback#GetFunction()
58 * - Added optional encoding and size arguments to NanFromV8String()
59 * - Added NanGetPointerSafe() and NanSetPointerSafe()
60 * - Added initial test suite (to be expanded)
61 * - Allow NanUInt32OptionValue to convert any Number object
62 *
63 * * 0.1.0 Jul 21 2013
64 * - Added `NAN_GETTER`, `NAN_SETTER`
65 * - Added `NanThrowError` with single Local<Value> argument
66 * - Added `NanNewBufferHandle` with single uint32_t argument
67 * - Added `NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>)`
68 * - Added `Local<Function> NanCallback#GetFunction()`
69 * - Added `NanCallback#Call(int, Local<Value>[])`
70 * - Deprecated `NanCallback#Run(int, Local<Value>[])` in favour of Call
71 *
72 * See https://github.com/rvagg/nan for the latest update to this file
73 **********************************************************************************/
74
75#ifndef NAN_H
76#define NAN_H
77
78#include <node.h>
79#include <node_buffer.h>
80#include <string.h>
81
82// some generic helpers
83
84template<class T> static inline bool NanSetPointerSafe(T *var, T val) {
85 if (var) {
86 *var = val;
87 return true;
88 } else {
89 return false;
90 }
91}
92
93template<class T> static inline T NanGetPointerSafe(
94 T *var,
95 T fallback = reinterpret_cast<T>(0)) {
96 if (var) {
97 return *var;
98 } else {
99 return fallback;
100 }
101}
102
103#define NanSymbol(value) v8::String::NewSymbol(value)
104
105static inline bool NanBooleanOptionValue(
106 v8::Local<v8::Object> optionsObj
107 , v8::Handle<v8::String> opt, bool def) {
108
109 if (def) {
110 return optionsObj.IsEmpty()
111 || !optionsObj->Has(opt)
112 || optionsObj->Get(opt)->BooleanValue();
113 } else {
114 return !optionsObj.IsEmpty()
115 && optionsObj->Has(opt)
116 && optionsObj->Get(opt)->BooleanValue();
117 }
118}
119
120static inline bool NanBooleanOptionValue(
121 v8::Local<v8::Object> optionsObj
122 , v8::Handle<v8::String> opt) {
123 return NanBooleanOptionValue(optionsObj, opt, false);
124}
125
126static inline uint32_t NanUInt32OptionValue(
127 v8::Local<v8::Object> optionsObj
128 , v8::Handle<v8::String> opt
129 , uint32_t def) {
130
131 return !optionsObj.IsEmpty()
132 && optionsObj->Has(opt)
133 && optionsObj->Get(opt)->IsNumber()
134 ? optionsObj->Get(opt)->Uint32Value()
135 : def;
136}
137
138#if (NODE_MODULE_VERSION > 0x000B)
139// Node 0.11+ (0.11.3 and below won't compile with these)
140
141static v8::Isolate* nan_isolate = v8::Isolate::GetCurrent();
142
143# define _NAN_METHOD_ARGS const v8::FunctionCallbackInfo<v8::Value>& args
144# define NAN_METHOD(name) void name(_NAN_METHOD_ARGS)
145# define _NAN_GETTER_ARGS const v8::PropertyCallbackInfo<v8::Value>& args
146# define NAN_GETTER(name) \
147 void name(v8::Local<v8::String> property, _NAN_GETTER_ARGS)
148# define _NAN_SETTER_ARGS const v8::PropertyCallbackInfo<void>& args
149# define NAN_SETTER(name) \
150 void name( \
151 v8::Local<v8::String> property \
152 , v8::Local<v8::Value> value \
153 , _NAN_SETTER_ARGS)
154# define _NAN_PROPERTY_GETTER_ARGS \
155 const v8::PropertyCallbackInfo<v8::Value>& args
156# define NAN_PROPERTY_GETTER(name) \
157 void name(v8::Local<v8::String> property \
158 , _NAN_PROPERTY_GETTER_ARGS)
159# define _NAN_PROPERTY_SETTER_ARGS \
160 const v8::PropertyCallbackInfo<v8::Value>& args
161# define NAN_PROPERTY_SETTER(name) \
162 void name(v8::Local<v8::String> property \
163 , v8::Local<v8::Value> value \
164 , _NAN_PROPERTY_SETTER_ARGS)
165# define _NAN_PROPERTY_ENUMERATOR_ARGS \
166 const v8::PropertyCallbackInfo<v8::Array>& args
167# define NAN_PROPERTY_ENUMERATOR(name) \
168 void name(_NAN_PROPERTY_ENUMERATOR_ARGS)
169# define _NAN_PROPERTY_DELETER_ARGS \
170 const v8::PropertyCallbackInfo<v8::Boolean>& args
171# define NAN_PROPERTY_DELETER(name) \
172 void name( \
173 v8::Local<v8::String> property \
174 , _NAN_PROPERTY_DELETER_ARGS)
175# define _NAN_PROPERTY_QUERY_ARGS \
176 const v8::PropertyCallbackInfo<v8::Integer>& args
177# define NAN_PROPERTY_QUERY(name) \
178 void name(v8::Local<v8::String> property, _NAN_PROPERTY_QUERY_ARGS)
179# define NanGetInternalFieldPointer(object, index) \
180 object->GetAlignedPointerFromInternalField(index)
181# define NanSetInternalFieldPointer(object, index, value) \
182 object->SetAlignedPointerInInternalField(index, value)
183
184# define NAN_WEAK_CALLBACK(type, name) \
185 void name( \
186 v8::Isolate* isolate, \
187 v8::Persistent<v8::Object>* object, \
188 type data)
189# define NAN_WEAK_CALLBACK_OBJECT (*object)
190# define NAN_WEAK_CALLBACK_DATA(type) ((type) data)
191
192# define NanScope() v8::HandleScope scope(nan_isolate)
193# define NanLocker() v8::Locker locker(nan_isolate)
194# define NanUnlocker() v8::Unlocker unlocker(nan_isolate)
195# define NanReturnValue(value) return args.GetReturnValue().Set(value)
196# define NanReturnUndefined() return
197# define NanReturnNull() return args.GetReturnValue().SetNull()
198# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString()
199# define NanAssignPersistent(type, handle, obj) handle.Reset(nan_isolate, obj)
200# define NanInitPersistent(type, name, obj) \
201 v8::Persistent<type> name(nan_isolate, obj)
202# define NanObjectWrapHandle(obj) obj->handle()
203# define NanMakeWeak(handle, parameter, callback) \
204 handle.MakeWeak(nan_isolate, parameter, callback)
205
206# define _NAN_THROW_ERROR(fun, errmsg) \
207 do { \
208 NanScope(); \
209 v8::ThrowException(fun(v8::String::New(errmsg))); \
210 } while (0);
211
212 inline static void NanThrowError(const char* errmsg) {
213 _NAN_THROW_ERROR(v8::Exception::Error, errmsg);
214 }
215
216 inline static void NanThrowError(v8::Handle<v8::Value> error) {
217 NanScope();
218 v8::ThrowException(error);
219 }
220
221 inline static void NanThrowError(const char *msg, const int errorNumber) {
222 v8::Local<v8::Value> err = v8::Exception::Error(v8::String::New(msg));
223 v8::Local<v8::Object> obj = err.As<v8::Object>();
224 obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber));
225 NanThrowError(err);
226 }
227
228 inline static void NanThrowTypeError(const char* errmsg) {
229 _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg);
230 }
231
232 inline static void NanThrowRangeError(const char* errmsg) {
233 _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg);
234 }
235
236 template<class T> static inline void NanDispose(v8::Persistent<T> &handle) {
237 handle.Dispose(nan_isolate);
238 handle.Clear();
239 }
240
241 static inline v8::Local<v8::Object> NanNewBufferHandle (
242 char *data,
243 size_t length,
244 node::smalloc::FreeCallback callback,
245 void *hint) {
246 return node::Buffer::New(data, length, callback, hint);
247 }
248
249 static inline v8::Local<v8::Object> NanNewBufferHandle (
250 char *data, uint32_t size) {
251 return node::Buffer::New(data, size);
252 }
253
254 static inline v8::Local<v8::Object> NanNewBufferHandle (uint32_t size) {
255 return node::Buffer::New(size);
256 }
257
258 static inline v8::Local<v8::Object> NanBufferUse(char* data, uint32_t size) {
259 return node::Buffer::Use(data, size);
260 }
261
262 template <class TypeName>
263 inline v8::Local<TypeName> NanPersistentToLocal(
264 const v8::Persistent<TypeName>& persistent) {
265 if (persistent.IsWeak()) {
266 return v8::Local<TypeName>::New(nan_isolate, persistent);
267 } else {
268 return *reinterpret_cast<v8::Local<TypeName>*>(
269 const_cast<v8::Persistent<TypeName>*>(&persistent));
270 }
271 }
272
273 inline bool NanHasInstance(
274 v8::Persistent<v8::FunctionTemplate>& function_template
275 , v8::Handle<v8::Value> value) {
276 return NanPersistentToLocal(function_template)->HasInstance(value);
277 }
278
279 static inline v8::Local<v8::Context> NanNewContextHandle(
280 v8::ExtensionConfiguration* extensions = NULL,
281 v8::Handle<v8::ObjectTemplate> tmpl = v8::Handle<v8::ObjectTemplate>(),
282 v8::Handle<v8::Value> obj = v8::Handle<v8::Value>()) {
283 return v8::Local<v8::Context>::New(nan_isolate, v8::Context::New(
284 nan_isolate, extensions, tmpl, obj));
285 }
286
287#else
288// Node 0.8 and 0.10
289
290# define _NAN_METHOD_ARGS const v8::Arguments& args
291# define NAN_METHOD(name) v8::Handle<v8::Value> name(_NAN_METHOD_ARGS)
292# define _NAN_GETTER_ARGS const v8::AccessorInfo &args
293# define NAN_GETTER(name) \
294 v8::Handle<v8::Value> name(v8::Local<v8::String> property, _NAN_GETTER_ARGS)
295# define _NAN_SETTER_ARGS const v8::AccessorInfo &args
296# define NAN_SETTER(name) \
297 void name( \
298 v8::Local<v8::String> property \
299 , v8::Local<v8::Value> value \
300 , _NAN_SETTER_ARGS)
301# define _NAN_PROPERTY_GETTER_ARGS const v8::AccessorInfo& args
302# define NAN_PROPERTY_GETTER(name) \
303 v8::Handle<v8::Value> name(v8::Local<v8::String> property \
304 , _NAN_PROPERTY_GETTER_ARGS)
305# define _NAN_PROPERTY_SETTER_ARGS const v8::AccessorInfo& args
306# define NAN_PROPERTY_SETTER(name) \
307 v8::Handle<v8::Value> name(v8::Local<v8::String> property \
308 , v8::Local<v8::Value> value \
309 , _NAN_PROPERTY_SETTER_ARGS)
310# define _NAN_PROPERTY_ENUMERATOR_ARGS const v8::AccessorInfo& args
311# define NAN_PROPERTY_ENUMERATOR(name) \
312 v8::Handle<v8::Array> name(_NAN_PROPERTY_ENUMERATOR_ARGS)
313# define _NAN_PROPERTY_DELETER_ARGS const v8::AccessorInfo& args
314# define NAN_PROPERTY_DELETER(name) \
315 v8::Handle<v8::Boolean> name( \
316 v8::Local<v8::String> property \
317 , _NAN_PROPERTY_DELETER_ARGS)
318# define _NAN_PROPERTY_QUERY_ARGS const v8::AccessorInfo& args
319# define NAN_PROPERTY_QUERY(name) \
320 v8::Handle<v8::Integer> name( \
321 v8::Local<v8::String> property \
322 , _NAN_PROPERTY_QUERY_ARGS)
323
324# define NanGetInternalFieldPointer(object, index) \
325 object->GetPointerFromInternalField(index)
326# define NanSetInternalFieldPointer(object, index, value) \
327 object->SetPointerInInternalField(index, value)
328# define NAN_WEAK_CALLBACK(type, name) void name( \
329 v8::Persistent<v8::Value> object, \
330 void *data)
331# define NAN_WEAK_CALLBACK_OBJECT object
332# define NAN_WEAK_CALLBACK_DATA(type) ((type) data)
333
334# define NanScope() v8::HandleScope scope
335# define NanLocker() v8::Locker locker
336# define NanUnlocker() v8::Unlocker unlocker
337# define NanReturnValue(value) return scope.Close(value)
338# define NanReturnUndefined() return v8::Undefined()
339# define NanReturnNull() return v8::Null()
340# define NanReturnEmptyString() return v8::String::Empty()
341# define NanInitPersistent(type, name, obj) \
342 v8::Persistent<type> name = v8::Persistent<type>::New(obj)
343# define NanAssignPersistent(type, handle, obj) \
344 handle = v8::Persistent<type>::New(obj)
345# define NanObjectWrapHandle(obj) obj->handle_
346# define NanMakeWeak(handle, parameters, callback) \
347 handle.MakeWeak(parameters, callback)
348
349# define _NAN_THROW_ERROR(fun, errmsg) \
350 do { \
351 NanScope(); \
352 return v8::ThrowException(fun(v8::String::New(errmsg))); \
353 } while (0);
354
355 inline static v8::Handle<v8::Value> NanThrowError(const char* errmsg) {
356 _NAN_THROW_ERROR(v8::Exception::Error, errmsg);
357 }
358
359 inline static v8::Handle<v8::Value> NanThrowError(
360 v8::Handle<v8::Value> error) {
361 NanScope();
362 return v8::ThrowException(error);
363 }
364
365 inline static v8::Handle<v8::Value> NanThrowError(
366 const char *msg,
367 const int errorNumber) {
368 v8::Local<v8::Value> err = v8::Exception::Error(v8::String::New(msg));
369 v8::Local<v8::Object> obj = err.As<v8::Object>();
370 obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber));
371 return NanThrowError(err);
372 }
373
374 inline static v8::Handle<v8::Value> NanThrowTypeError(const char* errmsg) {
375 _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg);
376 }
377
378 inline static v8::Handle<v8::Value> NanThrowRangeError(const char* errmsg) {
379 _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg);
380 }
381
382 template<class T> static inline void NanDispose(v8::Persistent<T> &handle) {
383 handle.Dispose();
384 handle.Clear();
385 }
386
387 static inline v8::Local<v8::Object> NanNewBufferHandle (
388 char *data,
389 size_t length,
390 node::Buffer::free_callback callback,
391 void *hint) {
392 return v8::Local<v8::Object>::New(
393 node::Buffer::New(data, length, callback, hint)->handle_);
394 }
395
396 static inline v8::Local<v8::Object> NanNewBufferHandle (
397 char *data, uint32_t size) {
398 return v8::Local<v8::Object>::New(node::Buffer::New(data, size)->handle_);
399 }
400
401 static inline v8::Local<v8::Object> NanNewBufferHandle (uint32_t size) {
402 return v8::Local<v8::Object>::New(node::Buffer::New(size)->handle_);
403 }
404
405 static inline void FreeData(char *data, void *hint) {
406 delete[] data;
407 }
408
409 static inline v8::Local<v8::Object> NanBufferUse(char* data, uint32_t size) {
410 return v8::Local<v8::Object>::New(
411 node::Buffer::New(data, size, FreeData, NULL)->handle_);
412 }
413
414 template <class TypeName>
415 inline v8::Local<TypeName> NanPersistentToLocal(
416 const v8::Persistent<TypeName>& persistent) {
417 if (persistent.IsWeak()) {
418 return v8::Local<TypeName>::New(persistent);
419 } else {
420 return *reinterpret_cast<v8::Local<TypeName>*>(
421 const_cast<v8::Persistent<TypeName>*>(&persistent));
422 }
423 }
424
425 inline bool NanHasInstance(
426 v8::Persistent<v8::FunctionTemplate>& function_template
427 , v8::Handle<v8::Value> value) {
428 return function_template->HasInstance(value);
429 }
430
431 static inline v8::Local<v8::Context> NanNewContextHandle(
432 v8::ExtensionConfiguration* extensions = NULL
433 , v8::Handle<v8::ObjectTemplate> tmpl =
434 v8::Handle<v8::ObjectTemplate>()
435 , v8::Handle<v8::Value> obj = v8::Handle<v8::Value>()
436 ) {
437 v8::Persistent<v8::Context> ctx =
438 v8::Context::New(extensions, tmpl, obj);
439 v8::Local<v8::Context> lctx = v8::Local<v8::Context>::New(ctx);
440 ctx.Dispose();
441 return lctx;
442 }
443
444#endif // node version
445
446class NanCallback {
447 public:
448 NanCallback(const v8::Local<v8::Function> &fn) {
449 NanScope();
450 v8::Local<v8::Object> obj = v8::Object::New();
451 obj->Set(NanSymbol("callback"), fn);
452 NanAssignPersistent(v8::Object, handle, obj);
453 }
454
455 ~NanCallback() {
456 if (handle.IsEmpty()) return;
457 handle.Dispose();
458 handle.Clear();
459 }
460
461 inline v8::Local<v8::Function> GetFunction () {
462 return NanPersistentToLocal(handle)->Get(NanSymbol("callback"))
463 .As<v8::Function>();
464 }
465
466 // deprecated
467 void Run(int argc, v8::Local<v8::Value> argv[]) {
468 Call(argc, argv);
469 }
470
471 void Call(int argc, v8::Local<v8::Value> argv[]) {
472 NanScope();
473
474 v8::Local<v8::Function> callback = NanPersistentToLocal(handle)->
475 Get(NanSymbol("callback")).As<v8::Function>();
476 v8::TryCatch try_catch;
477 callback->Call(v8::Context::GetCurrent()->Global(), argc, argv);
478 if (try_catch.HasCaught()) {
479 node::FatalException(try_catch);
480 }
481 }
482
483 private:
484 v8::Persistent<v8::Object> handle;
485};
486
487/* abstract */ class NanAsyncWorker {
488public:
489 NanAsyncWorker (NanCallback *callback) : callback(callback) {
490 request.data = this;
491 errmsg = NULL;
492 }
493
494 virtual ~NanAsyncWorker () {
495 NanScope();
496
497 if (!persistentHandle.IsEmpty())
498 NanDispose(persistentHandle);
499 if (callback)
500 delete callback;
501 if (errmsg)
502 delete errmsg;
503 }
504
505 virtual void WorkComplete () {
506 NanScope();
507
508 if (errmsg == NULL)
509 HandleOKCallback();
510 else
511 HandleErrorCallback();
512 delete callback;
513 callback = NULL;
514 }
515
516 virtual void Execute () =0;
517
518 uv_work_t request;
519
520protected:
521 v8::Persistent<v8::Object> persistentHandle;
522 NanCallback *callback;
523 const char *errmsg;
524
525 void SavePersistent(const char *key, v8::Local<v8::Object> &obj) {
526 NanScope();
527
528 v8::Local<v8::Object> handle = NanPersistentToLocal(persistentHandle);
529 handle->Set(NanSymbol(key), obj);
530 }
531
532 v8::Local<v8::Object> GetFromPersistent(const char *key) {
533 NanScope();
534
535 v8::Local<v8::Object> handle = NanPersistentToLocal(persistentHandle);
536 return handle->Get(NanSymbol(key)).As<v8::Object>();
537 }
538
539 virtual void HandleOKCallback () {
540 NanScope();
541
542 callback->Call(0, NULL);
543 };
544
545 virtual void HandleErrorCallback () {
546 NanScope();
547
548 v8::Local<v8::Value> argv[] = {
549 v8::Exception::Error(v8::String::New(errmsg))
550 };
551 callback->Call(1, argv);
552 }
553};
554
555inline void NanAsyncExecute (uv_work_t* req) {
556 NanAsyncWorker *worker = static_cast<NanAsyncWorker*>(req->data);
557 worker->Execute();
558}
559
560inline void NanAsyncExecuteComplete (uv_work_t* req) {
561 NanAsyncWorker* worker = static_cast<NanAsyncWorker*>(req->data);
562 worker->WorkComplete();
563 delete worker;
564}
565
566inline void NanAsyncQueueWorker (NanAsyncWorker* worker) {
567 uv_queue_work(
568 uv_default_loop()
569 , &worker->request
570 , NanAsyncExecute
571 , (uv_after_work_cb)NanAsyncExecuteComplete
572 );
573}
574
575//// Base 64 ////
576
577#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)
578
579
580// Doesn't check for padding at the end. Can be 1-2 bytes over.
581static inline size_t _nan_base64_decoded_size_fast(size_t size) {
582 size_t remainder = size % 4;
583
584 size = (size / 4) * 3;
585 if (remainder) {
586 if (size == 0 && remainder == 1) {
587 // special case: 1-byte input cannot be decoded
588 size = 0;
589 } else {
590 // non-padded input, add 1 or 2 extra bytes
591 size += 1 + (remainder == 3);
592 }
593 }
594
595 return size;
596}
597
598template <typename TypeName>
599static size_t _nan_base64_decoded_size(const TypeName* src, size_t size) {
600 if (size == 0)
601 return 0;
602
603 if (src[size - 1] == '=')
604 size--;
605 if (size > 0 && src[size - 1] == '=')
606 size--;
607
608 return _nan_base64_decoded_size_fast(size);
609}
610
611
612// supports regular and URL-safe base64
613static const int _nan_unbase64_table[] =
614 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1,
615 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
616 -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63,
617 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
618 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
619 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
620 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
621 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
622 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
623 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
624 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
625 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
626 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
627 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
628 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
629 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
630 };
631
632#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)]
633
634
635template <typename TypeName>
636static size_t _nan_base64_decode(char* buf,
637 size_t len,
638 const TypeName* src,
639 const size_t srcLen) {
640 char a, b, c, d;
641 char* dst = buf;
642 char* dstEnd = buf + len;
643 const TypeName* srcEnd = src + srcLen;
644
645 while (src < srcEnd && dst < dstEnd) {
646 int remaining = srcEnd - src;
647
648 while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
649 if (remaining == 0 || *src == '=') break;
650 a = _nan_unbase64(*src++);
651
652 while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
653 if (remaining <= 1 || *src == '=') break;
654 b = _nan_unbase64(*src++);
655
656 *dst++ = (a << 2) | ((b & 0x30) >> 4);
657 if (dst == dstEnd) break;
658
659 while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
660 if (remaining <= 2 || *src == '=') break;
661 c = _nan_unbase64(*src++);
662
663 *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2);
664 if (dst == dstEnd) break;
665
666 while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
667 if (remaining <= 3 || *src == '=') break;
668 d = _nan_unbase64(*src++);
669
670 *dst++ = ((c & 0x03) << 6) | (d & 0x3F);
671 }
672
673 return dst - buf;
674}
675
676//// HEX ////
677
678template <typename TypeName>
679unsigned _nan_hex2bin(TypeName c) {
680 if (c >= '0' && c <= '9') return c - '0';
681 if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
682 if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
683 return static_cast<unsigned>(-1);
684}
685
686
687template <typename TypeName>
688static size_t _nan_hex_decode(char* buf,
689 size_t len,
690 const TypeName* src,
691 const size_t srcLen) {
692 size_t i;
693 for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) {
694 unsigned a = _nan_hex2bin(src[i * 2 + 0]);
695 unsigned b = _nan_hex2bin(src[i * 2 + 1]);
696 if (!~a || !~b) return i;
697 buf[i] = a * 16 + b;
698 }
699
700 return i;
701}
702
703static bool _NanGetExternalParts(
704 v8::Handle<v8::Value> val
705 , const char** data
706 , size_t* len) {
707
708 if (node::Buffer::HasInstance(val)) {
709 *data = node::Buffer::Data(val.As<v8::Object>());
710 *len = node::Buffer::Length(val.As<v8::Object>());
711 return true;
712
713 }
714
715 assert(val->IsString());
716 v8::Local<v8::String> str = v8::Local<v8::String>::New(val.As<v8::String>());
717
718 if (str->IsExternalAscii()) {
719 const v8::String::ExternalAsciiStringResource* ext;
720 ext = str->GetExternalAsciiStringResource();
721 *data = ext->data();
722 *len = ext->length();
723 return true;
724
725 } else if (str->IsExternal()) {
726 const v8::String::ExternalStringResource* ext;
727 ext = str->GetExternalStringResource();
728 *data = reinterpret_cast<const char*>(ext->data());
729 *len = ext->length();
730 return true;
731 }
732
733 return false;
734}
735
736namespace Nan {
737 enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
738}
739
740static inline char* NanFromV8String(
741 v8::Handle<v8::Value> from
742 , enum Nan::Encoding encoding = Nan::UTF8
743 , size_t *datalen = NULL
744 , char *buf = NULL
745 , size_t buflen = 0
746 , int flags = v8::String::NO_NULL_TERMINATION
747 | v8::String::HINT_MANY_WRITES_EXPECTED) {
748
749 NanScope();
750
751 size_t sz_;
752 size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION);
753 char *data = NULL;
754 size_t len;
755 bool is_extern = _NanGetExternalParts(
756 from
757 , const_cast<const char**>(&data)
758 , &len);
759
760 if (is_extern && !term_len) {
761 NanSetPointerSafe(datalen, len);
762 return data;
763 }
764
765 v8::Local<v8::String> toStr = from->ToString();
766
767 char *to = buf;
768
769 v8::String::AsciiValue value(toStr);
770 switch(encoding) {
771 case Nan::ASCII:
772#if NODE_MODULE_VERSION < 0x0C
773 sz_ = toStr->Length();
774 if (to == NULL) {
775 to = new char[sz_ + term_len];
776 } else {
777 assert(buflen >= sz_ + term_len && "too small buffer");
778 }
779 NanSetPointerSafe<size_t>(
780 datalen
781 , toStr->WriteAscii(to, 0, sz_ + term_len, flags));
782 return to;
783#endif
784 case Nan::BINARY:
785 case Nan::BUFFER:
786 sz_ = toStr->Length();
787 if (to == NULL) {
788 to = new char[sz_ + term_len];
789 } else {
790 assert(buflen >= sz_ + term_len && "too small buffer");
791 }
792#if NODE_MODULE_VERSION < 0x0C
793 // TODO(isaacs): THIS IS AWFUL!!!
794 // AGREE(kkoopa)
795 {
796 uint16_t* twobytebuf = new uint16_t[sz_ + term_len];
797
798 size_t len = toStr->Write(twobytebuf, 0, sz_ + term_len, flags);
799
800 for (size_t i = 0; i < sz_ + term_len && i < len + term_len; i++) {
801 unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
802 to[i] = *b;
803 }
804
805 NanSetPointerSafe<size_t>(datalen, len);
806
807 delete[] twobytebuf;
808 return to;
809 }
810#else
811 NanSetPointerSafe<size_t>(
812 datalen,
813 toStr->WriteOneByte(
814 reinterpret_cast<uint8_t *>(to)
815 , 0
816 , sz_ + term_len
817 , flags));
818 return to;
819#endif
820 case Nan::UTF8:
821 sz_ = toStr->Utf8Length();
822 if (to == NULL) {
823 to = new char[sz_ + term_len];
824 } else {
825 assert(buflen >= sz_ + term_len && "too small buffer");
826 }
827 NanSetPointerSafe<size_t>(
828 datalen
829 , toStr->WriteUtf8(to, sz_ + term_len, NULL, flags) - term_len);
830 return to;
831 case Nan::BASE64:
832 sz_ = _nan_base64_decoded_size(*value, toStr->Length());
833 if (to == NULL) {
834 to = new char[sz_ + term_len];
835 } else {
836 assert(buflen >= sz_ + term_len);
837 }
838 NanSetPointerSafe<size_t>(
839 datalen
840 , _nan_base64_decode(to, sz_, *value, value.length()));
841 if (term_len) {
842 to[sz_] = '\0';
843 }
844 return to;
845 case Nan::UCS2:
846 {
847 sz_ = toStr->Length();
848 if (to == NULL) {
849 to = new char[(sz_ + term_len) * 2];
850 } else {
851 assert(buflen >= (sz_ + term_len) * 2 && "too small buffer");
852 }
853
854 int bc = 2 * toStr->Write(
855 reinterpret_cast<uint16_t *>(to)
856 , 0
857 , sz_ + term_len
858 , flags);
859 NanSetPointerSafe<size_t>(datalen, bc);
860 return to;
861 }
862 case Nan::HEX:
863 sz_ = toStr->Length();
864 assert(!(sz_ & 1) && "bad hex data");
865 if (to == NULL) {
866 to = new char[sz_ / 2 + term_len];
867 } else {
868 assert(buflen >= sz_ / 2 + term_len && "too small buffer");
869 }
870
871 NanSetPointerSafe<size_t>(
872 datalen
873 , _nan_hex_decode(to, sz_ / 2, *value, value.length()));
874 if (term_len) {
875 to[sz_ / 2] = '\0';
876 }
877 return to;
878 default:
879 assert(0 && "unknown encoding");
880 }
881 return to;
882}
883
884#endif