arnaucube
arnaucube/comunicationLeapPublic Self-hosted repository
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