http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-noline/metadata.json
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-noline/metadata.json
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-noline/metadata.json
new file mode 100644
index 0000000..56ef280
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-noline/metadata.json
@@ -0,0 +1,629 @@
+{
+    "line_map": [
+        {
+            "original_line": 1, 
+            "combined_line": 114, 
+            "original_file": "duk_internal.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 159, 
+            "original_file": "duk_replacements.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 187, 
+            "original_file": "duk_jmpbuf.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 211, 
+            "original_file": "duk_exception.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 229, 
+            "original_file": "duk_forwdecl.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 351, 
+            "original_file": "duk_tval.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 869, 
+            "original_file": "duk_builtins.h"
+        }, 
+        {
+            "original_line": 52, 
+            "combined_line": 1723, 
+            "original_file": "duk_internal.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 1724, 
+            "original_file": "duk_util.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 2254, 
+            "original_file": "duk_strings.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 2506, 
+            "original_file": "duk_js_bytecode.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 2711, 
+            "original_file": "duk_lexer.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 3143, 
+            "original_file": "duk_js_compiler.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 3370, 
+            "original_file": "duk_regexp.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 3452, 
+            "original_file": "duk_heaphdr.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 4202, 
+            "original_file": "duk_api_internal.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 4396, 
+            "original_file": "duk_hstring.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 4615, 
+            "original_file": "duk_hobject.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 5541, 
+            "original_file": "duk_hcompiledfunction.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 5780, 
+            "original_file": "duk_hnativefunction.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 5812, 
+            "original_file": "duk_hbufferobject.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 5945, 
+            "original_file": "duk_hthread.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 6325, 
+            "original_file": "duk_hbuffer.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 6653, 
+            "original_file": "duk_heap.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 7249, 
+            "original_file": "duk_debugger.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 7393, 
+            "original_file": "duk_debug.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 7578, 
+            "original_file": "duk_error.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 8017, 
+            "original_file": "duk_unicode.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 8284, 
+            "original_file": "duk_json.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 8352, 
+            "original_file": "duk_js.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 8451, 
+            "original_file": "duk_numconv.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 8541, 
+            "original_file": "duk_bi_protos.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 8610, 
+            "original_file": "duk_selftest.h"
+        }, 
+        {
+            "original_line": 78, 
+            "combined_line": 8622, 
+            "original_file": "duk_internal.h"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 8624, 
+            "original_file": "duk_replacements.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 8706, 
+            "original_file": "duk_strings.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 8821, 
+            "original_file": "duk_debug_macros.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 8965, 
+            "original_file": "duk_builtins.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 9741, 
+            "original_file": "duk_error_macros.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 9904, 
+            "original_file": "duk_unicode_support.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 11077, 
+            "original_file": "duk_util_misc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 11299, 
+            "original_file": "duk_util_hashprime.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 11376, 
+            "original_file": "duk_hobject_class.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 11508, 
+            "original_file": "duk_alloc_default.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 11542, 
+            "original_file": "duk_api_buffer.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 11615, 
+            "original_file": "duk_api_bytecode.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 12342, 
+            "original_file": "duk_api_call.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 12897, 
+            "original_file": "duk_api_codec.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 13535, 
+            "original_file": "duk_api_compile.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 13729, 
+            "original_file": "duk_api_debug.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 13992, 
+            "original_file": "duk_api_heap.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 14126, 
+            "original_file": "duk_api_logging.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 14178, 
+            "original_file": "duk_api_memory.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 14281, 
+            "original_file": "duk_api_object.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 14891, 
+            "original_file": "duk_api_stack.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 19549, 
+            "original_file": "duk_api_string.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 19880, 
+            "original_file": "duk_api_var.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 19966, 
+            "original_file": "duk_bi_array.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 21411, 
+            "original_file": "duk_bi_boolean.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 21479, 
+            "original_file": "duk_bi_buffer.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 24361, 
+            "original_file": "duk_bi_date.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 26089, 
+            "original_file": "duk_bi_date_unix.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 26398, 
+            "original_file": "duk_bi_date_windows.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 26496, 
+            "original_file": "duk_bi_duktape.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 26817, 
+            "original_file": "duk_bi_error.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 27200, 
+            "original_file": "duk_bi_function.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 27546, 
+            "original_file": "duk_bi_global.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 28834, 
+            "original_file": "duk_bi_json.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 31977, 
+            "original_file": "duk_bi_logger.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 32277, 
+            "original_file": "duk_bi_math.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 32625, 
+            "original_file": "duk_bi_number.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 32865, 
+            "original_file": "duk_bi_object.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 33442, 
+            "original_file": "duk_bi_pointer.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 33516, 
+            "original_file": "duk_bi_proxy.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 33582, 
+            "original_file": "duk_bi_regexp.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 33791, 
+            "original_file": "duk_bi_string.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 35105, 
+            "original_file": "duk_bi_thread.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 35410, 
+            "original_file": "duk_bi_thrower.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 35420, 
+            "original_file": "duk_debug_fixedbuffer.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 35489, 
+            "original_file": "duk_debug_heap.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 35736, 
+            "original_file": "duk_debug_vsnprintf.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 36785, 
+            "original_file": "duk_debugger.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 39558, 
+            "original_file": "duk_error_augment.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 40125, 
+            "original_file": "duk_error_longjmp.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 40170, 
+            "original_file": "duk_error_misc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 40302, 
+            "original_file": "duk_error_throw.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 40483, 
+            "original_file": "duk_hbuffer_alloc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 40615, 
+            "original_file": "duk_hbuffer_ops.c"
+        }, 
+        {
+            "original_line": 2, 
+            "combined_line": 40698, 
+            "original_file": "duk_hbufferobject_misc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 40717, 
+            "original_file": "duk_heap_alloc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 41759, 
+            "original_file": "duk_heap_hashstring.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 41879, 
+            "original_file": "duk_heap_markandsweep.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 43300, 
+            "original_file": "duk_heap_memory.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 43684, 
+            "original_file": "duk_heap_misc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 43763, 
+            "original_file": "duk_heap_refcount.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 44377, 
+            "original_file": "duk_heap_stringcache.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 44675, 
+            "original_file": "duk_heap_stringtable.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 45856, 
+            "original_file": "duk_hobject_alloc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 46048, 
+            "original_file": "duk_hobject_enum.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 46674, 
+            "original_file": "duk_hobject_finalizer.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 46784, 
+            "original_file": "duk_hobject_misc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 46836, 
+            "original_file": "duk_hobject_pc2line.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 47086, 
+            "original_file": "duk_hobject_props.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 53085, 
+            "original_file": "duk_hstring_misc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 53130, 
+            "original_file": "duk_hthread_alloc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 53225, 
+            "original_file": "duk_hthread_builtins.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 54061, 
+            "original_file": "duk_hthread_misc.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 54169, 
+            "original_file": "duk_hthread_stacks.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 54645, 
+            "original_file": "duk_js_call.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 57372, 
+            "original_file": "duk_js_compiler.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 65237, 
+            "original_file": "duk_js_executor.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 69744, 
+            "original_file": "duk_js_ops.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 71114, 
+            "original_file": "duk_js_var.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 72935, 
+            "original_file": "duk_lexer.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 75002, 
+            "original_file": "duk_numconv.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 77268, 
+            "original_file": "duk_regexp_compiler.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 78340, 
+            "original_file": "duk_regexp_executor.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 79348, 
+            "original_file": "duk_selftest.c"
+        }, 
+        {
+            "original_line": 2, 
+            "combined_line": 79722, 
+            "original_file": "duk_tval.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 79859, 
+            "original_file": "duk_unicode_tables.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 85978, 
+            "original_file": "duk_util_bitdecoder.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 86048, 
+            "original_file": "duk_util_bitencoder.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 86091, 
+            "original_file": "duk_util_bufwriter.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 86451, 
+            "original_file": "duk_util_hashbytes.c"
+        }, 
+        {
+            "original_line": 1, 
+            "combined_line": 86508, 
+            "original_file": "duk_util_tinyrandom.c"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_alloc_default.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_alloc_default.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_alloc_default.c
new file mode 100644
index 0000000..d882bd7
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_alloc_default.c
@@ -0,0 +1,34 @@
+/*
+ *  Default allocation functions.
+ *
+ *  Assumes behavior such as malloc allowing zero size, yielding
+ *  a NULL or a unique pointer which is a no-op for free.
+ */
+
+#include "duk_internal.h"
+
+#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
+DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
+       void *res;
+       DUK_UNREF(udata);
+       res = DUK_ANSI_MALLOC(size);
+       DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
+                            (unsigned long) size, (void *) res));
+       return res;
+}
+
+DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, 
duk_size_t newsize) {
+       void *res;
+       DUK_UNREF(udata);
+       res = DUK_ANSI_REALLOC(ptr, newsize);
+       DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
+                            (void *) ptr, (unsigned long) newsize, (void *) 
res));
+       return res;
+}
+
+DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
+       DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
+       DUK_UNREF(udata);
+       DUK_ANSI_FREE(ptr);
+}
+#endif  /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_buffer.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_buffer.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_buffer.c
new file mode 100644
index 0000000..3c12681
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_buffer.c
@@ -0,0 +1,73 @@
+/*
+ *  Buffer
+ */
+
+#include "duk_internal.h"
+
+DUK_EXTERNAL void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, 
duk_size_t new_size) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_hbuffer_dynamic *h;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index);
+       DUK_ASSERT(h != NULL);
+
+       if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
+               DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
+       }
+
+       /* maximum size check is handled by callee */
+       duk_hbuffer_resize(thr, h, new_size);
+
+       return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
+}
+
+DUK_EXTERNAL void *duk_steal_buffer(duk_context *ctx, duk_idx_t index, 
duk_size_t *out_size) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_hbuffer_dynamic *h;
+       void *ptr;
+       duk_size_t sz;
+
+       DUK_ASSERT(ctx != NULL);
+
+       h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index);
+       DUK_ASSERT(h != NULL);
+
+       if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
+               DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
+       }
+
+       /* Forget the previous allocation, setting size to 0 and alloc to
+        * NULL.  Caller is responsible for freeing the previous allocation.
+        * Getting the allocation and clearing it is done in the same API
+        * call to avoid any chance of a realloc.
+        */
+       ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
+       sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
+       if (out_size) {
+               *out_size = sz;
+       }
+       DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
+       DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);
+
+       return ptr;
+}
+
+DUK_EXTERNAL void duk_config_buffer(duk_context *ctx, duk_idx_t index, void 
*ptr, duk_size_t len) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_hbuffer_external *h;
+
+       DUK_ASSERT(ctx != NULL);
+
+       h = (duk_hbuffer_external *) duk_require_hbuffer(ctx, index);
+       DUK_ASSERT(h != NULL);
+
+       if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
+               DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
+       }
+       DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
+
+       DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
+       DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_bytecode.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_bytecode.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_bytecode.c
new file mode 100644
index 0000000..bc2a295
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_bytecode.c
@@ -0,0 +1,727 @@
+/*
+ *  Bytecode dump/load
+ *
+ *  The bytecode load primitive is more important performance-wise than the
+ *  dump primitive.
+ *
+ *  Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
+ *  memory safe for invalid arguments - caller beware!  There's little point
+ *  in trying to achieve memory safety unless bytecode instructions are also
+ *  validated which is not easy to do with indirect register references etc.
+ */
+
+#include "duk_internal.h"
+
+#if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
+
+#define DUK__SER_MARKER  0xff
+#define DUK__SER_VERSION 0x00
+#define DUK__SER_STRING  0x00
+#define DUK__SER_NUMBER  0x01
+#define DUK__BYTECODE_INITIAL_ALLOC 256
+
+/*
+ *  Dump/load helpers, xxx_raw() helpers do no buffer checks
+ */
+
+DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_context *ctx, duk_uint8_t *p) {
+       duk_uint32_t len;
+
+       len = DUK_RAW_READ_U32_BE(p);
+       duk_push_lstring(ctx, (const char *) p, len);
+       p += len;
+       return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_context *ctx, duk_uint8_t *p) {
+       duk_uint32_t len;
+       duk_uint8_t *buf;
+
+       len = DUK_RAW_READ_U32_BE(p);
+       buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
+       DUK_ASSERT(buf != NULL);
+       DUK_MEMCPY((void *) buf, (const void *) p, (size_t) len);
+       p += len;
+       return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
+       duk_size_t len;
+       duk_uint32_t tmp32;
+
+       DUK_ASSERT(h != NULL);
+
+       len = DUK_HSTRING_GET_BYTELEN(h);
+       DUK_ASSERT(len <= 0xffffffffUL);  /* string limits */
+       tmp32 = (duk_uint32_t) len;
+       DUK_RAW_WRITE_U32_BE(p, tmp32);
+       DUK_MEMCPY((void *) p,
+                  (const void *) DUK_HSTRING_GET_DATA(h),
+                  len);
+       p += len;
+       return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, 
duk_hbuffer *h) {
+       duk_size_t len;
+       duk_uint32_t tmp32;
+
+       DUK_ASSERT(thr != NULL);
+       DUK_ASSERT(h != NULL);
+       DUK_UNREF(thr);
+
+       len = DUK_HBUFFER_GET_SIZE(h);
+       DUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */
+       tmp32 = (duk_uint32_t) len;
+       DUK_RAW_WRITE_U32_BE(p, tmp32);
+       DUK_MEMCPY((void *) p,
+                  (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
+                  len);
+       p += len;
+       return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_string_prop(duk_hthread *thr, duk_uint8_t *p, 
duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {
+       duk_hstring *h_str;
+       duk_tval *tv;
+
+       tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject 
*) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+       if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
+               h_str = DUK_TVAL_GET_STRING(tv);
+               DUK_ASSERT(h_str != NULL);
+       } else {
+               h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
+               DUK_ASSERT(h_str != NULL);
+       }
+       DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no 
overflow */
+       p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(h_str), 
p);
+       p = duk__dump_hstring_raw(p, h_str);
+       return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_buffer_prop(duk_hthread *thr, duk_uint8_t *p, 
duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {
+       duk_tval *tv;
+
+       tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject 
*) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+       if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
+               duk_hbuffer *h_buf;
+               h_buf = DUK_TVAL_GET_BUFFER(tv);
+               DUK_ASSERT(h_buf != NULL);
+               DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL);  /* 
ensures no overflow */
+               p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + 
DUK_HBUFFER_GET_SIZE(h_buf), p);
+               p = duk__dump_hbuffer_raw(thr, p, h_buf);
+       } else {
+               p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
+               DUK_RAW_WRITE_U32_BE(p, 0);
+       }
+       return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_uint32_prop(duk_hthread *thr, duk_uint8_t *p, 
duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx, 
duk_uint32_t def_value) {
+       duk_tval *tv;
+       duk_uint32_t val;
+
+       tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject 
*) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+       if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
+               val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
+       } else {
+               val = def_value;
+       }
+       p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
+       DUK_RAW_WRITE_U32_BE(p, val);
+       return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, 
duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
+       duk_tval *tv;
+
+       tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject 
*) func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
+       if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
+               duk_hobject *h;
+               duk_uint_fast32_t i;
+
+               h = DUK_TVAL_GET_OBJECT(tv);
+               DUK_ASSERT(h != NULL);
+
+               /* We know _Varmap only has own properties so walk property
+                * table directly.  We also know _Varmap is dense and all
+                * values are numbers; assert for these.  GC and finalizers
+                * shouldn't affect _Varmap so side effects should be fine.
+                */
+               for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); 
i++) {
+                       duk_hstring *key;
+                       duk_tval *tv_val;
+                       duk_uint32_t val;
+
+                       key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
+                       DUK_ASSERT(key != NULL);  /* _Varmap is dense */
+                       DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, 
h, i));
+                       tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, 
i);
+                       DUK_ASSERT(tv_val != NULL);
+                       DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val));  /* known to be 
number; in fact an integer */
+#if defined(DUK_USE_FASTINT)
+                       DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
+                       DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == 
(duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val));  /* known to be 32-bit */
+                       val = DUK_TVAL_GET_FASTINT_U32(tv_val);
+#else
+                       val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
+#endif
+
+                       DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  
/* ensures no overflow */
+                       p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + 
DUK_HSTRING_GET_BYTELEN(key) + 4, p);
+                       p = duk__dump_hstring_raw(p, key);
+                       DUK_RAW_WRITE_U32_BE(p, val);
+               }
+       }
+       p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
+       DUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Varmap */
+       return p;
+}
+
+DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, 
duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
+       duk_tval *tv;
+
+       tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject 
*) func, DUK_HTHREAD_STRING_INT_FORMALS(thr));
+       if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
+               duk_hobject *h;
+               duk_uint_fast32_t i;
+
+               h = DUK_TVAL_GET_OBJECT(tv);
+               DUK_ASSERT(h != NULL);
+
+               /* We know _Formals is dense and all entries will be in the
+                * array part.  GC and finalizers shouldn't affect _Formals
+                * so side effects should be fine.
+                */
+               for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); 
i++) {
+                       duk_tval *tv_val;
+                       duk_hstring *varname;
+
+                       tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i);
+                       DUK_ASSERT(tv_val != NULL);
+                       if (DUK_TVAL_IS_STRING(tv_val)) {
+                               /* Array is dense and contains only strings, 
but ASIZE may
+                                * be larger than used part and there are 
UNUSED entries.
+                                */
+                               varname = DUK_TVAL_GET_STRING(tv_val);
+                               DUK_ASSERT(varname != NULL);
+
+                               DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 
0x7fffffffUL);  /* ensures no overflow */
+                               p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + 
DUK_HSTRING_GET_BYTELEN(varname), p);
+                               p = duk__dump_hstring_raw(p, varname);
+                       }
+               }
+       }
+       p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
+       DUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Formals */
+       return p;
+}
+
+static duk_uint8_t *duk__dump_func(duk_context *ctx, duk_hcompiledfunction 
*func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
+       duk_hthread *thr;
+       duk_tval *tv, *tv_end;
+       duk_instr_t *ins, *ins_end;
+       duk_hobject **fn, **fn_end;
+       duk_hstring *h_str;
+       duk_uint32_t count_instr;
+       duk_uint32_t tmp32;
+       duk_uint16_t tmp16;
+       duk_double_t d;
+
+       thr = (duk_hthread *) ctx;
+       DUK_UNREF(ctx);
+       DUK_UNREF(thr);
+
+       DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
+                          "consts=[%p,%p[ (%ld bytes, %ld items), "
+                          "funcs=[%p,%p[ (%ld bytes, %ld items), "
+                          "code=[%p,%p[ (%ld bytes, %ld items)",
+                          (void *) func,
+                          (void *) p,
+                          (void *) 
DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func),
+                          (void *) 
DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func),
+                          (long) 
DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(thr->heap, func),
+                          (long) 
DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func),
+                          (void *) 
DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func),
+                          (void *) 
DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func),
+                          (long) 
DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(thr->heap, func),
+                          (long) 
DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func),
+                          (void *) 
DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func),
+                          (void *) 
DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func),
+                          (long) 
DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(thr->heap, func),
+                          (long) 
DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func)));
+
+       DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL);  /* ensures no 
overflow */
+       count_instr = (duk_uint32_t) 
DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func);
+       p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3 * 4 + 2 * 2 + 3 * 4 + count_instr 
* 4, p);
+
+       /* Fixed header info. */
+       tmp32 = count_instr;
+       DUK_RAW_WRITE_U32_BE(p, tmp32);
+       tmp32 = (duk_uint32_t) 
DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func);
+       DUK_RAW_WRITE_U32_BE(p, tmp32);
+       tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, 
func);
+       DUK_RAW_WRITE_U32_BE(p, tmp32);
+       tmp16 = func->nregs;
+       DUK_RAW_WRITE_U16_BE(p, tmp16);
+       tmp16 = func->nargs;
+       DUK_RAW_WRITE_U16_BE(p, tmp16);
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+       tmp32 = func->start_line;
+       DUK_RAW_WRITE_U32_BE(p, tmp32);
+       tmp32 = func->end_line;
+       DUK_RAW_WRITE_U32_BE(p, tmp32);
+#else
+       DUK_RAW_WRITE_U32_BE(p, 0);
+       DUK_RAW_WRITE_U32_BE(p, 0);
+#endif
+       tmp32 = ((duk_heaphdr *) func)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK;
+       DUK_RAW_WRITE_U32_BE(p, tmp32);
+
+       /* Bytecode instructions: endian conversion needed unless
+        * platform is big endian.
+        */
+       ins = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func);
+       ins_end = DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func);
+       DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
+#if defined(DUK_USE_INTEGER_BE)
+       DUK_MEMCPY((void *) p, (const void *) ins, (size_t) (ins_end - ins));
+       p += (size_t) (ins_end - ins);
+#else
+       while (ins != ins_end) {
+               tmp32 = (duk_uint32_t) (*ins);
+               DUK_RAW_WRITE_U32_BE(p, tmp32);
+               ins++;
+       }
+#endif
+
+       /* Constants: variable size encoding. */
+       tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func);
+       tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func);
+       while (tv != tv_end) {
+               /* constants are strings or numbers now */
+               DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
+                          DUK_TVAL_IS_NUMBER(tv));
+
+               if (DUK_TVAL_IS_STRING(tv)) {
+                       h_str = DUK_TVAL_GET_STRING(tv);
+                       DUK_ASSERT(h_str != NULL);
+                       DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  
/* ensures no overflow */
+                       p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 4 + 
DUK_HSTRING_GET_BYTELEN(h_str), p),
+                       *p++ = DUK__SER_STRING;
+                       p = duk__dump_hstring_raw(p, h_str);
+               } else {
+                       DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
+                       p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 8, p);
+                       *p++ = DUK__SER_NUMBER;
+                       d = DUK_TVAL_GET_NUMBER(tv);
+                       DUK_RAW_WRITE_DOUBLE_BE(p, d);
+               }
+               tv++;
+       }
+
+       /* Inner functions recursively. */
+       fn = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, 
func);
+       fn_end = (duk_hobject **) 
DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func);
+       while (fn != fn_end) {
+               /* XXX: This causes recursion up to inner function depth
+                * which is normally not an issue, e.g. mark-and-sweep uses
+                * a recursion limiter to avoid C stack issues.  Avoiding
+                * this would mean some sort of a work list or just refusing
+                * to serialize deep functions.
+                */
+               DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(*fn));
+               p = duk__dump_func(ctx, (duk_hcompiledfunction *) *fn, bw_ctx, 
p);
+               fn++;
+       }
+
+       /* Object extra properties.
+        *
+        * There are some difference between function templates and functions.
+        * For example, function templates don't have .length and nargs is
+        * normally used to instantiate the functions.
+        */
+
+       p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, 
DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
+       p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, 
DUK_STRIDX_NAME);
+       p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, 
DUK_STRIDX_FILE_NAME);
+       p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, 
DUK_STRIDX_INT_PC2LINE);
+       p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
+       p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
+
+       DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void 
*) func, (void *) p));
+
+       return p;
+}
+
+/* Load a function from bytecode.  The function object returned here must
+ * match what is created by duk_js_push_closure() with respect to its flags,
+ * properties, etc.
+ *
+ * NOTE: there are intentionally no input buffer length / bound checks.
+ * Adding them would be easy but wouldn't ensure memory safety as untrusted
+ * or broken bytecode is unsafe during execution unless the opcodes themselves
+ * are validated (which is quite complex, especially for indirect opcodes).
+ */
+
+#define DUK__ASSERT_LEFT(n) do { \
+               DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
+       } while (0)
+
+static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, 
duk_uint8_t *p_end) {
+       duk_hthread *thr;
+       duk_hcompiledfunction *h_fun;
+       duk_hbuffer *h_data;
+       duk_size_t data_size;
+       duk_uint32_t count_instr, count_const, count_funcs;
+       duk_uint32_t n;
+       duk_uint32_t tmp32;
+       duk_small_uint_t const_type;
+       duk_uint8_t *fun_data;
+       duk_uint8_t *q;
+       duk_idx_t idx_base;
+       duk_tval *tv1;
+       duk_uarridx_t arr_idx;
+
+       /* XXX: There's some overlap with duk_js_closure() here, but
+        * seems difficult to share code.  Ensure that the final function
+        * looks the same as created by duk_js_closure().
+        */
+
+       DUK_ASSERT(ctx != NULL);
+       thr = (duk_hthread *) ctx;
+
+       DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, 
(void *) p_end));
+
+       DUK__ASSERT_LEFT(3 * 4);
+       count_instr = DUK_RAW_READ_U32_BE(p);
+       count_const = DUK_RAW_READ_U32_BE(p);
+       count_funcs = DUK_RAW_READ_U32_BE(p);
+
+       data_size = sizeof(duk_tval) * count_const +
+                   sizeof(duk_hobject *) * count_funcs +
+                   sizeof(duk_instr_t) * count_instr;
+
+       DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
+                          (long) count_instr, (long) count_const,
+                          (long) count_const, (long) data_size));
+
+       /* Value stack is used to ensure reachability of constants and
+        * inner functions being loaded.  Require enough space to handle
+        * large functions correctly.
+        */
+       duk_require_stack(ctx, 2 + count_const + count_funcs);
+       idx_base = duk_get_top(ctx);
+
+       /* Push function object, init flags etc.  This must match
+        * duk_js_push_closure() quite carefully.
+        */
+       duk_push_compiledfunction(ctx);
+       h_fun = duk_get_hcompiledfunction(ctx, -1);
+       DUK_ASSERT(h_fun != NULL);
+       DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) h_fun));
+       DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, h_fun) == NULL);
+       DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, h_fun) == NULL);
+       DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, h_fun) == 
NULL);
+
+       h_fun->nregs = DUK_RAW_READ_U16_BE(p);
+       h_fun->nargs = DUK_RAW_READ_U16_BE(p);
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+       h_fun->start_line = DUK_RAW_READ_U32_BE(p);
+       h_fun->end_line = DUK_RAW_READ_U32_BE(p);
+#else
+       p += 8;  /* skip line info */
+#endif
+
+       /* duk_hcompiledfunction flags; quite version specific */
+       tmp32 = DUK_RAW_READ_U32_BE(p);
+       DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);
+
+       /* standard prototype */
+       DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, 
thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
+
+       /* assert just a few critical flags */
+       DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == 
DUK_HTYPE_OBJECT);
+       DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&h_fun->obj));
+       DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(&h_fun->obj));
+       DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(&h_fun->obj));
+       DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(&h_fun->obj));
+       DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
+       DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
+       DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
+
+       /* Create function 'data' buffer but don't attach it yet. */
+       fun_data = (duk_uint8_t *) duk_push_fixed_buffer(ctx, data_size);
+       DUK_ASSERT(fun_data != NULL);
+
+       /* Load bytecode instructions. */
+       DUK_ASSERT(sizeof(duk_instr_t) == 4);
+       DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
+#if defined(DUK_USE_INTEGER_BE)
+       q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * 
count_funcs;
+       DUK_MEMCPY((void *) q,
+                  (const void *) p,
+                  sizeof(duk_instr_t) * count_instr);
+       p += sizeof(duk_instr_t) * count_instr;
+#else
+       q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * 
count_funcs;
+       for (n = count_instr; n > 0; n--) {
+               *((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
+               q += sizeof(duk_instr_t);
+       }
+#endif
+
+       /* Load constants onto value stack but don't yet copy to buffer. */
+       for (n = count_const; n > 0; n--) {
+               DUK__ASSERT_LEFT(1);
+               const_type = DUK_RAW_READ_U8(p);
+               switch (const_type) {
+               case DUK__SER_STRING: {
+                       p = duk__load_string_raw(ctx, p);
+                       break;
+               }
+               case DUK__SER_NUMBER: {
+                       /* Important to do a fastint check so that constants are
+                        * properly read back as fastints.
+                        */
+                       duk_tval tv_tmp;
+                       duk_double_t val;
+                       DUK__ASSERT_LEFT(8);
+                       val = DUK_RAW_READ_DOUBLE_BE(p);
+                       DUK_TVAL_SET_NUMBER_CHKFAST(&tv_tmp, val);
+                       duk_push_tval(ctx, &tv_tmp);
+                       break;
+               }
+               default: {
+                       goto format_error;
+               }
+               }
+       }
+
+       /* Load inner functions to value stack, but don't yet copy to buffer. */
+       for (n = count_funcs; n > 0; n--) {
+               p = duk__load_func(ctx, p, p_end);
+               if (p == NULL) {
+                       goto format_error;
+               }
+       }
+
+       /* With constants and inner functions on value stack, we can now
+        * atomically finish the function 'data' buffer, bump refcounts,
+        * etc.
+        *
+        * Here we take advantage of the value stack being just a duk_tval
+        * array: we can just memcpy() the constants as long as we incref
+        * them afterwards.
+        */
+
+       h_data = (duk_hbuffer *) duk_get_hbuffer(ctx, idx_base + 1);
+       DUK_ASSERT(h_data != NULL);
+       DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));
+       DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_fun, h_data);
+       DUK_HBUFFER_INCREF(thr, h_data);
+
+       tv1 = duk_get_tval(ctx, idx_base + 2);  /* may be NULL if no constants 
or inner funcs */
+       DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
+
+       q = fun_data;
+       if (count_const > 0) {
+               /* Explicit zero size check to avoid NULL 'tv1'. */
+               DUK_MEMCPY((void *) q, (const void *) tv1, sizeof(duk_tval) * 
count_const);
+               for (n = count_const; n > 0; n--) {
+                       DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q);  /* 
no side effects */
+                       q += sizeof(duk_tval);
+               }
+               tv1 += count_const;
+       }
+
+       DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) 
(void *) q);
+       for (n = count_funcs; n > 0; n--) {
+               duk_hobject *h_obj;
+
+               DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
+               h_obj = DUK_TVAL_GET_OBJECT(tv1);
+               DUK_ASSERT(h_obj != NULL);
+               tv1++;
+               DUK_HOBJECT_INCREF(thr, h_obj);
+
+               *((duk_hobject **) (void *) q) = h_obj;
+               q += sizeof(duk_hobject *);
+       }
+
+       DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) 
(void *) q);
+
+       /* The function object is now reachable and refcounts are fine,
+        * so we can pop off all the temporaries.
+        */
+       DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", 
duk_get_tval(ctx, idx_base)));
+       duk_set_top(ctx, idx_base + 1);
+
+       /* Setup function properties. */
+       tmp32 = DUK_RAW_READ_U32_BE(p);
+       duk_push_u32(ctx, tmp32);
+       duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, 
DUK_PROPDESC_FLAGS_NONE);
+
+       p = duk__load_string_raw(ctx, p);
+       if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {
+               /* Original function instance/template had NAMEBINDING.
+                * Must create a lexical environment on loading to allow
+                * recursive functions like 'function foo() { foo(); }'.
+                */
+               duk_hobject *proto;
+
+               proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
+               (void) duk_push_object_helper_proto(ctx,
+                                                   DUK_HOBJECT_FLAG_EXTENSIBLE 
|
+                                                   
DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
+                                                   proto);
+               duk_dup(ctx, -2);                                 /* -> [ func 
funcname env funcname ] */
+               duk_dup(ctx, idx_base);                           /* -> [ func 
funcname env funcname func ] */
+               duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE);  /* -> [ func 
funcname env ] */
+               duk_xdef_prop_stridx(ctx, idx_base, DUK_STRIDX_INT_LEXENV, 
DUK_PROPDESC_FLAGS_WC);
+               /* since closure has NEWENV, never define 
DUK_STRIDX_INT_VARENV, as it
+                * will be ignored anyway
+                */
+       }
+       duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
+
+       p = duk__load_string_raw(ctx, p);
+       duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, 
DUK_PROPDESC_FLAGS_WC);
+
+       duk_push_object(ctx);
+       duk_dup(ctx, -2);
+       duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, 
DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */
+       duk_compact(ctx, -1);
+       duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE, 
DUK_PROPDESC_FLAGS_W);
+
+       p = duk__load_buffer_raw(ctx, p);
+       duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_PC2LINE, 
DUK_PROPDESC_FLAGS_WC);
+
+       duk_push_object(ctx);  /* _Varmap */
+       for (;;) {
+               /* XXX: awkward */
+               p = duk__load_string_raw(ctx, p);
+               if (duk_get_length(ctx, -1) == 0) {
+                       duk_pop(ctx);
+                       break;
+               }
+               tmp32 = DUK_RAW_READ_U32_BE(p);
+               duk_push_u32(ctx, tmp32);
+               duk_put_prop(ctx, -3);
+       }
+       duk_compact(ctx, -1);
+       duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VARMAP, 
DUK_PROPDESC_FLAGS_NONE);
+
+       duk_push_array(ctx);  /* _Formals */
+       for (arr_idx = 0; ; arr_idx++) {
+               /* XXX: awkward */
+               p = duk__load_string_raw(ctx, p);
+               if (duk_get_length(ctx, -1) == 0) {
+                       duk_pop(ctx);
+                       break;
+               }
+               duk_put_prop_index(ctx, -2, arr_idx);
+       }
+       duk_compact(ctx, -1);
+       duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_FORMALS, 
DUK_PROPDESC_FLAGS_NONE);
+
+       /* Return with final function pushed on stack top. */
+       DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(ctx, 
-1)));
+       DUK_ASSERT_TOP(ctx, idx_base + 1);
+       return p;
+
+ format_error:
+       return NULL;
+}
+
+DUK_EXTERNAL void duk_dump_function(duk_context *ctx) {
+       duk_hthread *thr;
+       duk_hcompiledfunction *func;
+       duk_bufwriter_ctx bw_ctx_alloc;
+       duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
+       duk_uint8_t *p;
+
+       DUK_ASSERT(ctx != NULL);
+       thr = (duk_hthread *) ctx;
+
+       /* Bound functions don't have all properties so we'd either need to
+        * lookup the non-bound target function or reject bound functions.
+        * For now, bound functions are rejected.
+        */
+       func = duk_require_hcompiledfunction(ctx, -1);
+       DUK_ASSERT(func != NULL);
+       DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&func->obj));
+
+       /* Estimating the result size beforehand would be costly, so
+        * start with a reasonable size and extend as needed.
+        */
+       DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);
+       p = DUK_BW_GET_PTR(thr, bw_ctx);
+       *p++ = DUK__SER_MARKER;
+       *p++ = DUK__SER_VERSION;
+       p = duk__dump_func(ctx, func, bw_ctx, p);
+       DUK_BW_SET_PTR(thr, bw_ctx, p);
+       DUK_BW_COMPACT(thr, bw_ctx);
+
+       DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(ctx, -1)));
+
+       duk_remove(ctx, -2);  /* [ ... func buf ] -> [ ... buf ] */
+}
+
+DUK_EXTERNAL void duk_load_function(duk_context *ctx) {
+       duk_hthread *thr;
+       duk_uint8_t *p_buf, *p, *p_end;
+       duk_size_t sz;
+
+       DUK_ASSERT(ctx != NULL);
+       thr = (duk_hthread *) ctx;
+       DUK_UNREF(ctx);
+
+       p_buf = (duk_uint8_t *) duk_require_buffer(ctx, -1, &sz);
+       DUK_ASSERT(p_buf != NULL);
+
+       /* The caller is responsible for being sure that bytecode being loaded
+        * is valid and trusted.  Invalid bytecode can cause memory unsafe
+        * behavior directly during loading or later during bytecode execution
+        * (instruction validation would be quite complex to implement).
+        *
+        * This signature check is the only sanity check for detecting
+        * accidental invalid inputs.  The initial 0xFF byte ensures no
+        * ordinary string will be accepted by accident.
+        */
+       p = p_buf;
+       p_end = p_buf + sz;
+       if (sz < 2 || p[0] != DUK__SER_MARKER || p[1] != DUK__SER_VERSION) {
+               goto format_error;
+       }
+       p += 2;
+
+       p = duk__load_func(ctx, p, p_end);
+       if (p == NULL) {
+               goto format_error;
+       }
+
+       duk_remove(ctx, -2);  /* [ ... buf func ] -> [ ... func ] */
+       return;
+
+ format_error:
+       DUK_ERROR_TYPE(thr, DUK_STR_DECODE_FAILED);
+}
+
+#undef DUK__SER_MARKER
+#undef DUK__SER_VERSION
+#undef DUK__SER_STRING
+#undef DUK__SER_NUMBER
+#undef DUK__BYTECODE_INITIAL_ALLOC
+
+#else  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
+
+DUK_EXTERNAL void duk_dump_function(duk_context *ctx) {
+       DUK_ERROR_UNSUPPORTED_DEFMSG((duk_hthread *) ctx);
+}
+
+DUK_EXTERNAL void duk_load_function(duk_context *ctx) {
+       DUK_ERROR_UNSUPPORTED_DEFMSG((duk_hthread *) ctx);
+}
+
+#endif  /* DUK_USE_BYTECODE_DUMP_SUPPORT */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_call.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_call.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_call.c
new file mode 100644
index 0000000..25dac14
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_call.c
@@ -0,0 +1,555 @@
+/*
+ *  Calls.
+ *
+ *  Protected variants should avoid ever throwing an error.
+ */
+
+#include "duk_internal.h"
+
+/* Prepare value stack for a method call through an object property.
+ * May currently throw an error e.g. when getting the property.
+ */
+DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t 
normalized_obj_index, duk_idx_t nargs) {
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, 
normalized_obj_index=%ld, nargs=%ld, stacktop=%ld",
+                            (long) normalized_obj_index, (long) nargs, (long) 
duk_get_top(ctx)));
+
+       /* [... key arg1 ... argN] */
+
+       /* duplicate key */
+       duk_dup(ctx, -nargs - 1);  /* Note: -nargs alone would fail for nargs 
== 0, this is OK */
+       duk_get_prop(ctx, normalized_obj_index);
+
+       DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
+
+       /* [... key arg1 ... argN func] */
+
+       duk_replace(ctx, -nargs - 2);
+
+       /* [... func arg1 ... argN] */
+
+       duk_dup(ctx, normalized_obj_index);
+       duk_insert(ctx, -nargs - 1);
+
+       /* [... func this arg1 ... argN] */
+}
+
+DUK_EXTERNAL void duk_call(duk_context *ctx, duk_idx_t nargs) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_small_uint_t call_flags;
+       duk_idx_t idx_func;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+       DUK_ASSERT(thr != NULL);
+
+       idx_func = duk_get_top(ctx) - nargs - 1;
+       if (idx_func < 0 || nargs < 0) {
+               /* note that we can't reliably pop anything here */
+               DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
+       }
+
+       /* XXX: awkward; we assume there is space for this, overwrite
+        * directly instead?
+        */
+       duk_push_undefined(ctx);
+       duk_insert(ctx, idx_func + 1);
+
+       call_flags = 0;  /* not protected, respect reclimit, not constructor */
+
+       duk_handle_call_unprotected(thr,           /* thread */
+                                   nargs,         /* num_stack_args */
+                                   call_flags);   /* call_flags */
+}
+
+DUK_EXTERNAL void duk_call_method(duk_context *ctx, duk_idx_t nargs) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_small_uint_t call_flags;
+       duk_idx_t idx_func;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+       DUK_ASSERT(thr != NULL);
+
+       idx_func = duk_get_top(ctx) - nargs - 2;  /* must work for nargs <= 0 */
+       if (idx_func < 0 || nargs < 0) {
+               /* note that we can't reliably pop anything here */
+               DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
+       }
+
+       call_flags = 0;  /* not protected, respect reclimit, not constructor */
+
+       duk_handle_call_unprotected(thr,           /* thread */
+                                   nargs,         /* num_stack_args */
+                                   call_flags);   /* call_flags */
+}
+
+DUK_EXTERNAL void duk_call_prop(duk_context *ctx, duk_idx_t obj_index, 
duk_idx_t nargs) {
+       /*
+        *  XXX: if duk_handle_call() took values through indices, this could be
+        *  made much more sensible.  However, duk_handle_call() needs to fudge
+        *  the 'this' and 'func' values to handle bound function chains, which
+        *  is now done "in-place", so this is not a trivial change.
+        */
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       obj_index = duk_require_normalize_index(ctx, obj_index);  /* make 
absolute */
+
+       duk__call_prop_prep_stack(ctx, obj_index, nargs);
+
+       duk_call_method(ctx, nargs);
+}
+
+DUK_EXTERNAL duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_small_uint_t call_flags;
+       duk_idx_t idx_func;
+       duk_int_t rc;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+       DUK_ASSERT(thr != NULL);
+
+       idx_func = duk_get_top(ctx) - nargs - 1;  /* must work for nargs <= 0 */
+       if (idx_func < 0 || nargs < 0) {
+               /* We can't reliably pop anything here because the stack input
+                * shape is incorrect.  So we throw an error; if the caller has
+                * no catch point for this, a fatal error will occur.  Another
+                * alternative would be to just return an error.  But then the
+                * stack would be in an unknown state which might cause some
+                * very hard to diagnose problems later on.  Also note that even
+                * if we did not throw an error here, the underlying call 
handler
+                * might STILL throw an out-of-memory error or some other 
internal
+                * fatal error.
+                */
+               DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
+               return DUK_EXEC_ERROR;  /* unreachable */
+       }
+
+       /* awkward; we assume there is space for this */
+       duk_push_undefined(ctx);
+       duk_insert(ctx, idx_func + 1);
+
+       call_flags = 0;  /* respect reclimit, not constructor */
+
+       rc = duk_handle_call_protected(thr,           /* thread */
+                                      nargs,         /* num_stack_args */
+                                      call_flags);   /* call_flags */
+
+       return rc;
+}
+
+DUK_EXTERNAL duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_small_uint_t call_flags;
+       duk_idx_t idx_func;
+       duk_int_t rc;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+       DUK_ASSERT(thr != NULL);
+
+       idx_func = duk_get_top(ctx) - nargs - 2;  /* must work for nargs <= 0 */
+       if (idx_func < 0 || nargs < 0) {
+               /* See comments in duk_pcall(). */
+               DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
+               return DUK_EXEC_ERROR;  /* unreachable */
+       }
+
+       call_flags = 0;  /* respect reclimit, not constructor */
+
+       rc = duk_handle_call_protected(thr,           /* thread */
+                                      nargs,         /* num_stack_args */
+                                      call_flags);   /* call_flags */
+
+       return rc;
+}
+
+DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_context *ctx) {
+       duk_idx_t obj_index;
+       duk_idx_t nargs;
+
+       /* Get the original arguments.  Note that obj_index may be a relative
+        * index so the stack must have the same top when we use it.
+        */
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       obj_index = (duk_idx_t) duk_get_int(ctx, -2);
+       nargs = (duk_idx_t) duk_get_int(ctx, -1);
+       duk_pop_2(ctx);
+
+       obj_index = duk_require_normalize_index(ctx, obj_index);  /* make 
absolute */
+       duk__call_prop_prep_stack(ctx, obj_index, nargs);
+       duk_call_method(ctx, nargs);
+       return 1;
+}
+
+DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_index, 
duk_idx_t nargs) {
+       /*
+        *  Must be careful to catch errors related to value stack manipulation
+        *  and property lookup, not just the call itself.
+        */
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       duk_push_idx(ctx, obj_index);
+       duk_push_idx(ctx, nargs);
+
+       /* Inputs: explicit arguments (nargs), +1 for key, +2 for 
obj_index/nargs passing.
+        * If the value stack does not contain enough args, an error is thrown; 
this matches
+        * behavior of the other protected call API functions.
+        */
+       return duk_safe_call(ctx, duk__pcall_prop_raw, nargs + 1 + 2 /*nargs*/, 
1 /*nrets*/);
+}
+
+DUK_EXTERNAL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function 
func, duk_idx_t nargs, duk_idx_t nrets) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_int_t rc;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+       DUK_ASSERT(thr != NULL);
+
+       if (duk_get_top(ctx) < nargs || nrets < 0) {
+               /* See comments in duk_pcall(). */
+               DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
+               return DUK_EXEC_ERROR;  /* unreachable */
+       }
+
+       rc = duk_handle_safe_call(thr,           /* thread */
+                                 func,          /* func */
+                                 nargs,         /* num_stack_args */
+                                 nrets);        /* num_stack_res */
+
+       return rc;
+}
+
+DUK_EXTERNAL void duk_new(duk_context *ctx, duk_idx_t nargs) {
+       /*
+        *  There are two [[Construct]] operations in the specification:
+        *
+        *    - E5 Section 13.2.2: for Function objects
+        *    - E5 Section 15.3.4.5.2: for "bound" Function objects
+        *
+        *  The chain of bound functions is resolved in Section 15.3.4.5.2,
+        *  with arguments "piling up" until the [[Construct]] internal
+        *  method is called on the final, actual Function object.  Note
+        *  that the "prototype" property is looked up *only* from the
+        *  final object, *before* calling the constructor.
+        *
+        *  Currently we follow the bound function chain here to get the
+        *  "prototype" property value from the final, non-bound function.
+        *  However, we let duk_handle_call() handle the argument "piling"
+        *  when the constructor is called.  The bound function chain is
+        *  thus now processed twice.
+        *
+        *  When constructing new Array instances, an unnecessary object is
+        *  created and discarded now: the standard [[Construct]] creates an
+        *  object, and calls the Array constructor.  The Array constructor
+        *  returns an Array instance, which is used as the result value for
+        *  the "new" operation; the object created before the Array constructor
+        *  call is discarded.
+        *
+        *  This would be easy to fix, e.g. by knowing that the Array 
constructor
+        *  will always create a replacement object and skip creating the 
fallback
+        *  object in that case.
+        *
+        *  Note: functions called via "new" need to know they are called as a
+        *  constructor.  For instance, built-in constructors behave differently
+        *  depending on how they are called.
+        */
+
+       /* XXX: merge this with duk_js_call.c, as this function implements
+        * core semantics (or perhaps merge the two files altogether).
+        */
+
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_hobject *proto;
+       duk_hobject *cons;
+       duk_hobject *fallback;
+       duk_idx_t idx_cons;
+       duk_small_uint_t call_flags;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       /* [... constructor arg1 ... argN] */
+
+       idx_cons = duk_require_normalize_index(ctx, -nargs - 1);
+
+       DUK_DDD(DUK_DDDPRINT("top=%ld, nargs=%ld, idx_cons=%ld",
+                            (long) duk_get_top(ctx), (long) nargs, (long) 
idx_cons));
+
+       /* XXX: code duplication */
+
+       /*
+        *  Figure out the final, non-bound constructor, to get "prototype"
+        *  property.
+        */
+
+       duk_dup(ctx, idx_cons);
+       for (;;) {
+               duk_tval *tv;
+               tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
+               DUK_ASSERT(tv != NULL);
+
+               if (DUK_TVAL_IS_OBJECT(tv)) {
+                       cons = DUK_TVAL_GET_OBJECT(tv);
+                       DUK_ASSERT(cons != NULL);
+                       if (!DUK_HOBJECT_IS_CALLABLE(cons) || 
!DUK_HOBJECT_HAS_CONSTRUCTABLE(cons)) {
+                               /* Checking callability of the immediate target
+                                * is important, same for constructability.
+                                * Checking it for functions down the bound
+                                * function chain is not strictly necessary
+                                * because .bind() should normally reject them.
+                                * But it's good to check anyway because it's
+                                * technically possible to edit the bound 
function
+                                * chain via internal keys.
+                                */
+                               goto not_constructable;
+                       }
+                       if (!DUK_HOBJECT_HAS_BOUND(cons)) {
+                               break;
+                       }
+               } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
+                       /* Lightfuncs cannot be bound. */
+                       break;
+               } else {
+                       /* Anything else is not constructable. */
+                       goto not_constructable;
+               }
+               duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET);  /* -> 
[... cons target] */
+               duk_remove(ctx, -2);                                  /* -> 
[... target] */
+       }
+       DUK_ASSERT(duk_is_callable(ctx, -1));
+       DUK_ASSERT(duk_is_lightfunc(ctx, -1) ||
+                  (duk_get_hobject(ctx, -1) != NULL && 
!DUK_HOBJECT_HAS_BOUND(duk_get_hobject(ctx, -1))));
+
+       /* [... constructor arg1 ... argN final_cons] */
+
+       /*
+        *  Create "fallback" object to be used as the object instance,
+        *  unless the constructor returns a replacement value.
+        *  Its internal prototype needs to be set based on "prototype"
+        *  property of the constructor.
+        */
+
+       duk_push_object(ctx);  /* class Object, extensible */
+
+       /* [... constructor arg1 ... argN final_cons fallback] */
+
+       duk_get_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE);
+       proto = duk_get_hobject(ctx, -1);
+       if (!proto) {
+               DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, 
or value not an object "
+                                    "-> leave standard Object prototype as 
fallback prototype"));
+       } else {
+               DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with 
object value "
+                                    "-> set fallback prototype to that value: 
%!iO", (duk_heaphdr *) proto));
+               fallback = duk_get_hobject(ctx, -2);
+               DUK_ASSERT(fallback != NULL);
+               DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
+       }
+       duk_pop(ctx);
+
+       /* [... constructor arg1 ... argN final_cons fallback] */
+
+       /*
+        *  Manipulate callstack for the call.
+        */
+
+       duk_dup_top(ctx);
+       duk_insert(ctx, idx_cons + 1);  /* use fallback as 'this' value */
+       duk_insert(ctx, idx_cons);      /* also stash it before constructor,
+                                        * in case we need it (as the fallback 
value)
+                                        */
+       duk_pop(ctx);                   /* pop final_cons */
+
+
+       /* [... fallback constructor fallback(this) arg1 ... argN];
+        * Note: idx_cons points to first 'fallback', not 'constructor'.
+        */
+
+       DUK_DDD(DUK_DDDPRINT("before call, idx_cons+1 (constructor) -> %!T, 
idx_cons+2 (fallback/this) -> %!T, "
+                            "nargs=%ld, top=%ld",
+                            (duk_tval *) duk_get_tval(ctx, idx_cons + 1),
+                            (duk_tval *) duk_get_tval(ctx, idx_cons + 2),
+                            (long) nargs,
+                            (long) duk_get_top(ctx)));
+
+       /*
+        *  Call the constructor function (called in "constructor mode").
+        */
+
+       call_flags = DUK_CALL_FLAG_CONSTRUCTOR_CALL;  /* not protected, respect 
reclimit, is a constructor call */
+
+       duk_handle_call_unprotected(thr,           /* thread */
+                                   nargs,         /* num_stack_args */
+                                   call_flags);   /* call_flags */
+
+       /* [... fallback retval] */
+
+       DUK_DDD(DUK_DDDPRINT("constructor call finished, fallback=%!iT, 
retval=%!iT",
+                            (duk_tval *) duk_get_tval(ctx, -2),
+                            (duk_tval *) duk_get_tval(ctx, -1)));
+
+       /*
+        *  Determine whether to use the constructor return value as the created
+        *  object instance or not.
+        */
+
+       if (duk_is_object(ctx, -1)) {
+               duk_remove(ctx, -2);
+       } else {
+               duk_pop(ctx);
+       }
+
+       /*
+        *  Augment created errors upon creation (not when they are thrown or
+        *  rethrown).  __FILE__ and __LINE__ are not desirable here; the call
+        *  stack reflects the caller which is correct.
+        */
+
+#ifdef DUK_USE_AUGMENT_ERROR_CREATE
+       duk_hthread_sync_currpc(thr);
+       duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
+#endif
+
+       /* [... retval] */
+
+       return;
+
+ not_constructable:
+       DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE);
+}
+
+DUK_LOCAL duk_ret_t duk__pnew_helper(duk_context *ctx) {
+       duk_uint_t nargs;
+
+       nargs = duk_to_uint(ctx, -1);
+       duk_pop(ctx);
+
+       duk_new(ctx, nargs);
+       return 1;
+}
+
+DUK_EXTERNAL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs) {
+       duk_int_t rc;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       /* For now, just use duk_safe_call() to wrap duk_new().  We can't
+        * simply use a protected duk_handle_call() because there's post
+        * processing which might throw.  It should be possible to ensure
+        * the post processing never throws (except in internal errors and
+        * out of memory etc which are always allowed) and then remove this
+        * wrapper.
+        */
+
+       duk_push_uint(ctx, nargs);
+       rc = duk_safe_call(ctx, duk__pnew_helper, nargs + 2 /*nargs*/, 1 
/*nrets*/);
+       return rc;
+}
+
+DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_context *ctx) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_activation *act;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+       DUK_ASSERT(thr != NULL);
+       DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
+
+       act = duk_hthread_get_current_activation(thr);
+       DUK_ASSERT(act != NULL);  /* because callstack_top > 0 */
+       return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
+}
+
+DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_context *ctx) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_activation *act;
+
+       /* For user code this could just return 1 (strict) always
+        * because all Duktape/C functions are considered strict,
+        * and strict is also the default when nothing is running.
+        * However, Duktape may call this function internally when
+        * the current activation is an Ecmascript function, so
+        * this cannot be replaced by a 'return 1' without fixing
+        * the internal call sites.
+        */
+
+       DUK_ASSERT_CTX_VALID(ctx);
+       DUK_ASSERT(thr != NULL);
+       DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
+
+       act = duk_hthread_get_current_activation(thr);
+       if (act == NULL) {
+               /* Strict by default. */
+               return 1;
+       }
+       return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
+}
+
+/*
+ *  Duktape/C function magic
+ */
+
+DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_context *ctx) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_activation *act;
+       duk_hobject *func;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+       DUK_ASSERT(thr != NULL);
+       DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
+
+       act = duk_hthread_get_current_activation(thr);
+       if (act) {
+               func = DUK_ACT_GET_FUNC(act);
+               if (!func) {
+                       duk_tval *tv = &act->tv_func;
+                       duk_small_uint_t lf_flags;
+                       lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
+                       return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
+               }
+               DUK_ASSERT(func != NULL);
+
+               if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
+                       duk_hnativefunction *nf = (duk_hnativefunction *) func;
+                       return (duk_int_t) nf->magic;
+               }
+       }
+       return 0;
+}
+
+DUK_EXTERNAL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t index) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       duk_tval *tv;
+       duk_hobject *h;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       tv = duk_require_tval(ctx, index);
+       if (DUK_TVAL_IS_OBJECT(tv)) {
+               h = DUK_TVAL_GET_OBJECT(tv);
+               DUK_ASSERT(h != NULL);
+               if (!DUK_HOBJECT_HAS_NATIVEFUNCTION(h)) {
+                       goto type_error;
+               }
+               return (duk_int_t) ((duk_hnativefunction *) h)->magic;
+       } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
+               duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
+               return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
+       }
+
+       /* fall through */
+ type_error:
+       DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
+       return 0;
+}
+
+DUK_EXTERNAL void duk_set_magic(duk_context *ctx, duk_idx_t index, duk_int_t 
magic) {
+       duk_hnativefunction *nf;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       nf = duk_require_hnativefunction(ctx, index);
+       DUK_ASSERT(nf != NULL);
+       nf->magic = (duk_int16_t) magic;
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_codec.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_codec.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_codec.c
new file mode 100644
index 0000000..5fa0bb8
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/src-separate/duk_api_codec.c
@@ -0,0 +1,638 @@
+/*
+ *  Encoding and decoding basic formats: hex, base64.
+ *
+ *  These are in-place operations which may allow an optimized implementation.
+ *
+ *  Base-64: https://tools.ietf.org/html/rfc4648#section-4
+ */
+
+#include "duk_internal.h"
+
+/* Shared handling for encode/decode argument.  Fast path handling for
+ * buffer and string values because they're the most common.  In particular,
+ * avoid creating a temporary string or buffer when possible.
+ */
+DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_context *ctx, duk_idx_t 
index, duk_size_t *out_len) {
+       DUK_ASSERT(duk_is_valid_index(ctx, index));  /* checked by caller */
+       if (duk_is_buffer(ctx, index)) {
+               return (const duk_uint8_t *) duk_get_buffer(ctx, index, 
out_len);
+       } else {
+               return (const duk_uint8_t *) duk_to_lstring(ctx, index, 
out_len);
+       }
+}
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t 
srclen, duk_uint8_t *dst) {
+       duk_uint_t t;
+       duk_size_t n_full, n_full3, n_final;
+       const duk_uint8_t *src_end_fast;
+
+       n_full = srclen / 3;  /* full 3-byte -> 4-char conversions */
+       n_full3 = n_full * 3;
+       n_final = srclen - n_full3;
+       DUK_ASSERT_DISABLE(n_final >= 0);
+       DUK_ASSERT(n_final <= 2);
+
+       src_end_fast = src + n_full3;
+       while (DUK_UNLIKELY(src != src_end_fast)) {
+               t = (duk_uint_t) (*src++);
+               t = (t << 8) + (duk_uint_t) (*src++);
+               t = (t << 8) + (duk_uint_t) (*src++);
+
+               *dst++ = duk_base64_enctab[t >> 18];
+               *dst++ = duk_base64_enctab[(t >> 12) & 0x3f];
+               *dst++ = duk_base64_enctab[(t >> 6) & 0x3f];
+               *dst++ = duk_base64_enctab[t & 0x3f];
+
+#if 0  /* Tested: not faster on x64 */
+               /* aaaaaabb bbbbcccc ccdddddd */
+               dst[0] = duk_base64_enctab[(src[0] >> 2) & 0x3f];
+               dst[1] = duk_base64_enctab[((src[0] << 4) & 0x30) | ((src[1] >> 
4) & 0x0f)];
+               dst[2] = duk_base64_enctab[((src[1] << 2) & 0x3f) | ((src[2] >> 
6) & 0x03)];
+               dst[3] = duk_base64_enctab[src[2] & 0x3f];
+               src += 3; dst += 4;
+#endif
+       }
+
+       switch (n_final) {
+       /* case 0: nop */
+       case 1: {
+               /* XX== */
+               t = (duk_uint_t) (*src++);
+               *dst++ = duk_base64_enctab[t >> 2];           /* XXXXXX-- */
+               *dst++ = duk_base64_enctab[(t << 4) & 0x3f];  /* ------XX */
+               *dst++ = DUK_ASC_EQUALS;
+               *dst++ = DUK_ASC_EQUALS;
+               break;
+       }
+       case 2: {
+               /* XXX= */
+               t = (duk_uint_t) (*src++);
+               t = (t << 8) + (duk_uint_t) (*src++);
+               *dst++ = duk_base64_enctab[t >> 10];          /* XXXXXX-- 
-------- */
+               *dst++ = duk_base64_enctab[(t >> 4) & 0x3f];  /* ------XX 
XXXX---- */
+               *dst++ = duk_base64_enctab[(t << 2) & 0x3f];  /* -------- 
----XXXX */
+               *dst++ = DUK_ASC_EQUALS;
+               break;
+       }
+       }
+}
+#else  /* DUK_USE_BASE64_FASTPATH */
+DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t 
srclen, duk_uint8_t *dst) {
+       duk_small_uint_t i, snip;
+       duk_uint_t t;
+       duk_uint_fast8_t x, y;
+       const duk_uint8_t *src_end;
+
+       src_end = src + srclen;
+
+       while (src < src_end) {
+               /* read 3 bytes into 't', padded by zero */
+               snip = 4;
+               t = 0;
+               for (i = 0; i < 3; i++) {
+                       t = t << 8;
+                       if (src >= src_end) {
+                               snip--;
+                       } else {
+                               t += (duk_uint_t) (*src++);
+                       }
+               }
+
+               /*
+                *  Missing bytes    snip     base64 example
+                *    0               4         XXXX
+                *    1               3         XXX=
+                *    2               2         XX==
+                */
+
+               DUK_ASSERT(snip >= 2 && snip <= 4);
+
+               for (i = 0; i < 4; i++) {
+                       x = (duk_uint_fast8_t) ((t >> 18) & 0x3f);
+                       t = t << 6;
+
+                       /* A straightforward 64-byte lookup would be faster
+                        * and cleaner, but this is shorter.
+                        */
+                       if (i >= snip) {
+                               y = '=';
+                       } else if (x <= 25) {
+                               y = x + 'A';
+                       } else if (x <= 51) {
+                               y = x - 26 + 'a';
+                       } else if (x <= 61) {
+                               y = x - 52 + '0';
+                       } else if (x == 62) {
+                               y = '+';
+                       } else {
+                               y = '/';
+                       }
+
+                       *dst++ = (duk_uint8_t) y;
+               }
+       }
+}
+#endif  /* DUK_USE_BASE64_FASTPATH */
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, 
duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {
+       duk_int_t x;
+       duk_int_t t;
+       duk_small_uint_t n_equal;
+       duk_small_uint_t n_chars;
+       const duk_uint8_t *src_end;
+       const duk_uint8_t *src_end_safe;
+
+       src_end = src + srclen;
+       src_end_safe = src_end - 4;  /* if 'src < src_end_safe', safe to read 4 
bytes */
+
+       /* Innermost fast path processes 4 valid base-64 characters at a time
+        * but bails out on whitespace, padding chars ('=') and invalid chars.
+        * Once the slow path segment has been processed, we return to the
+        * inner fast path again.  This handles e.g. base64 with newlines
+        * reasonably well because the majority of a line is in the fast path.
+        */
+       for (;;) {
+               /* Fast path, handle units with just actual encoding 
characters. */
+
+               while (src <= src_end_safe) {
+                       /* The lookup byte is intentionally sign extended to 
(at least)
+                        * 32 bits and then ORed.  This ensures that is at 
least 1 byte
+                        * is negative, the highest bit of 't' will be set at 
the end
+                        * and we don't need to check every byte.
+                        */
+                       DUK_DDD(DUK_DDDPRINT("fast loop: src=%p, 
src_end_safe=%p, src_end=%p",
+                                            (const void *) src, (const void *) 
src_end_safe, (const void *) src_end));
+
+                       t = (duk_int_t) duk_base64_dectab[*src++];
+                       t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
+                       t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
+                       t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
+
+                       if (DUK_UNLIKELY(t < 0)) {
+                               DUK_DDD(DUK_DDDPRINT("fast loop unit was not 
clean, process one slow path unit"));
+                               src -= 4;
+                               break;
+                       }
+
+                       DUK_ASSERT(t <= 0xffffffL);
+                       DUK_ASSERT((t >> 24) == 0);
+                       *dst++ = (duk_uint8_t) (t >> 16);
+                       *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
+                       *dst++ = (duk_uint8_t) (t & 0xff);
+               }
+
+               /* Handle one slow path unit (or finish if we're done). */
+
+               n_equal = 0;
+               n_chars = 0;
+               t = 0;
+               for (;;) {
+                       DUK_DDD(DUK_DDDPRINT("slow loop: src=%p, src_end=%p, 
n_chars=%ld, n_equal=%ld, t=%ld",
+                                            (const void *) src, (const void *) 
src_end, (long) n_chars, (long) n_equal, (long) t));
+
+                       if (DUK_UNLIKELY(src >= src_end)) {
+                               goto done;  /* two level break */
+                       }
+
+                       x = duk_base64_dectab[*src++];
+                       if (DUK_UNLIKELY(x < 0)) {
+                               if (x == -2) {
+                                       continue;  /* allowed ascii whitespace 
*/
+                               } else if (x == -3) {
+                                       n_equal++;
+                                       t <<= 6;
+                               } else {
+                                       DUK_ASSERT(x == -1);
+                                       goto error;
+                               }
+                       } else {
+                               DUK_ASSERT(x >= 0 && x <= 63);
+                               if (n_equal > 0) {
+                                       /* Don't allow actual chars after equal 
sign. */
+                                       goto error;
+                               }
+                               t = (t << 6) + x;
+                       }
+
+                       if (DUK_UNLIKELY(n_chars == 3)) {
+                               /* Emit 3 bytes and backtrack if there was 
padding.  There's
+                                * always space for the whole 3 bytes so no 
check needed.
+                                */
+                               DUK_ASSERT(t <= 0xffffffL);
+                               DUK_ASSERT((t >> 24) == 0);
+                               *dst++ = (duk_uint8_t) (t >> 16);
+                               *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
+                               *dst++ = (duk_uint8_t) (t & 0xff);
+
+                               if (DUK_UNLIKELY(n_equal > 0)) {
+                                       DUK_ASSERT(n_equal <= 4);
+
+                                       /* There may be whitespace between the 
equal signs. */
+                                       if (n_equal == 1) {
+                                               /* XXX= */
+                                               dst -= 1;
+                                       } else if (n_equal == 2) {
+                                               /* XX== */
+                                               dst -= 2;
+                                       } else {
+                                               goto error;  /* invalid padding 
*/
+                                       }
+
+                                       /* Continue parsing after padding, 
allows concatenated,
+                                        * padded base64.
+                                        */
+                               }
+                               break;  /* back to fast loop */
+                       } else {
+                               n_chars++;
+                       }
+               }
+       }
+ done:
+       DUK_DDD(DUK_DDDPRINT("done; src=%p, src_end=%p, n_chars=%ld",
+                            (const void *) src, (const void *) src_end, (long) 
n_chars));
+
+       DUK_ASSERT(src == src_end);
+
+       if (n_chars != 0) {
+               /* Here we'd have the option of decoding unpadded base64
+                * (e.g. "xxxxyy" instead of "xxxxyy==".  Currently not
+                * accepted.
+                */
+               goto error;
+       }
+
+       *out_dst_final = dst;
+       return 1;
+
+ error:
+       return 0;
+}
+#else  /* DUK_USE_BASE64_FASTPATH */
+DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, 
duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {
+       duk_uint_t t;
+       duk_uint_fast8_t x, y;
+       duk_small_uint_t group_idx;
+       duk_small_uint_t n_equal;
+       const duk_uint8_t *src_end;
+
+       src_end = src + srclen;
+       t = 0;
+       group_idx = 0;
+       n_equal = 0;
+
+       while (src < src_end) {
+               x = *src++;
+
+               if (x >= 'A' && x <= 'Z') {
+                       y = x - 'A' + 0;
+               } else if (x >= 'a' && x <= 'z') {
+                       y = x - 'a' + 26;
+               } else if (x >= '0' && x <= '9') {
+                       y = x - '0' + 52;
+               } else if (x == '+') {
+                       y = 62;
+               } else if (x == '/') {
+                       y = 63;
+               } else if (x == '=') {
+                       /* We don't check the zero padding bytes here right now
+                        * (that they're actually zero).  This seems to be 
common
+                        * behavior for base-64 decoders.
+                        */
+
+                       n_equal++;
+                       t <<= 6;  /* shift in zeroes */
+                       goto skip_add;
+               } else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) {
+                       /* allow basic ASCII whitespace */
+                       continue;
+               } else {
+                       goto error;
+               }
+
+               if (n_equal > 0) {
+                       /* Don't allow mixed padding and actual chars. */
+                       goto error;
+               }
+               t = (t << 6) + y;
+        skip_add:
+
+               if (group_idx == 3) {
+                       /* output 3 bytes from 't' */
+                       *dst++ = (duk_uint8_t) ((t >> 16) & 0xff);
+                       *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
+                       *dst++ = (duk_uint8_t) (t & 0xff);
+
+                       if (DUK_UNLIKELY(n_equal > 0)) {
+                               /* Backtrack. */
+                               DUK_ASSERT(n_equal <= 4);
+                               if (n_equal == 1) {
+                                       dst -= 1;
+                               } else if (n_equal == 2) {
+                                       dst -= 2;
+                               } else {
+                                       goto error;  /* invalid padding */
+                               }
+
+                               /* Here we can choose either to end parsing and 
ignore
+                                * whatever follows, or to continue parsing in 
case
+                                * multiple (possibly padded) base64 strings 
have been
+                                * concatenated.  Currently, keep on parsing.
+                                */
+                               n_equal = 0;
+                       }
+
+                       t = 0;
+                       group_idx = 0;
+               } else {
+                       group_idx++;
+               }
+       }
+
+       if (group_idx != 0) {
+               /* Here we'd have the option of decoding unpadded base64
+                * (e.g. "xxxxyy" instead of "xxxxyy==".  Currently not
+                * accepted.
+                */
+               goto error;
+       }
+
+       *out_dst_final = dst;
+       return 1;
+
+ error:
+       return 0;
+}
+#endif  /* DUK_USE_BASE64_FASTPATH */
+
+DUK_EXTERNAL const char *duk_base64_encode(duk_context *ctx, duk_idx_t index) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       const duk_uint8_t *src;
+       duk_size_t srclen;
+       duk_size_t dstlen;
+       duk_uint8_t *dst;
+       const char *ret;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       /* XXX: optimize for string inputs: no need to coerce to a buffer
+        * which makes a copy of the input.
+        */
+
+       index = duk_require_normalize_index(ctx, index);
+       src = duk__prep_codec_arg(ctx, index, &srclen);
+       /* Note: for srclen=0, src may be NULL */
+
+       /* Computation must not wrap; this limit works for 32-bit size_t:
+        * >>> srclen = 3221225469
+        * >>> '%x' % ((srclen + 2) / 3 * 4)
+        * 'fffffffc'
+        */
+       if (srclen > 3221225469UL) {
+               goto type_error;
+       }
+       dstlen = (srclen + 2) / 3 * 4;
+       dst = (duk_uint8_t *) duk_push_fixed_buffer(ctx, dstlen);
+
+       duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
+
+       ret = duk_to_string(ctx, -1);
+       duk_replace(ctx, index);
+       return ret;
+
+ type_error:
+       DUK_ERROR_TYPE(thr, DUK_STR_ENCODE_FAILED);
+       return NULL;  /* never here */
+}
+
+DUK_EXTERNAL void duk_base64_decode(duk_context *ctx, duk_idx_t index) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       const duk_uint8_t *src;
+       duk_size_t srclen;
+       duk_size_t dstlen;
+       duk_uint8_t *dst;
+       duk_uint8_t *dst_final;
+       duk_bool_t retval;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       /* XXX: optimize for buffer inputs: no need to coerce to a string
+        * which causes an unnecessary interning.
+        */
+
+       index = duk_require_normalize_index(ctx, index);
+       src = duk__prep_codec_arg(ctx, index, &srclen);
+
+       /* Computation must not wrap, only srclen + 3 is at risk of
+        * wrapping because after that the number gets smaller.
+        * This limit works for 32-bit size_t:
+        * 0x100000000 - 3 - 1 = 4294967292
+        */
+       if (srclen > 4294967292UL) {
+               goto type_error;
+       }
+       dstlen = (srclen + 3) / 4 * 3;  /* upper limit, assuming no whitespace 
etc */
+       dst = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, dstlen);
+       /* Note: for dstlen=0, dst may be NULL */
+
+       retval = duk__base64_decode_helper((const duk_uint8_t *) src, srclen, 
dst, &dst_final);
+       if (!retval) {
+               goto type_error;
+       }
+
+       /* XXX: convert to fixed buffer? */
+       (void) duk_resize_buffer(ctx, -1, (duk_size_t) (dst_final - dst));
+       duk_replace(ctx, index);
+       return;
+
+ type_error:
+       DUK_ERROR_TYPE(thr, DUK_STR_DECODE_FAILED);
+}
+
+DUK_EXTERNAL const char *duk_hex_encode(duk_context *ctx, duk_idx_t index) {
+       const duk_uint8_t *inp;
+       duk_size_t len;
+       duk_size_t i;
+       duk_uint8_t *buf;
+       const char *ret;
+#if defined(DUK_USE_HEX_FASTPATH)
+       duk_size_t len_safe;
+       duk_uint16_t *p16;
+#endif
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       index = duk_require_normalize_index(ctx, index);
+       inp = duk__prep_codec_arg(ctx, index, &len);
+       DUK_ASSERT(inp != NULL || len == 0);
+
+       /* Fixed buffer, no zeroing because we'll fill all the data. */
+       buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len * 2, 
DUK_BUF_FLAG_NOZERO /*flags*/);
+       DUK_ASSERT(buf != NULL);
+
+#if defined(DUK_USE_HEX_FASTPATH)
+       DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0);   /* pointer is aligned, 
guaranteed for fixed buffer */
+       p16 = (duk_uint16_t *) (void *) buf;
+       len_safe = len & ~0x03U;
+       for (i = 0; i < len_safe; i += 4) {
+               p16[0] = duk_hex_enctab[inp[i]];
+               p16[1] = duk_hex_enctab[inp[i + 1]];
+               p16[2] = duk_hex_enctab[inp[i + 2]];
+               p16[3] = duk_hex_enctab[inp[i + 3]];
+               p16 += 4;
+       }
+       for (; i < len; i++) {
+               *p16++ = duk_hex_enctab[inp[i]];
+       }
+#else  /* DUK_USE_HEX_FASTPATH */
+       for (i = 0; i < len; i++) {
+               duk_small_uint_t t;
+               t = (duk_small_uint_t) inp[i];
+               buf[i*2 + 0] = duk_lc_digits[t >> 4];
+               buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
+       }
+#endif  /* DUK_USE_HEX_FASTPATH */
+
+       /* XXX: Using a string return value forces a string intern which is
+        * not always necessary.  As a rough performance measure, hex encode
+        * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
+        * without string coercion.  Change to returning a buffer and let the
+        * caller coerce to string if necessary?
+        */
+
+       ret = duk_to_string(ctx, -1);
+       duk_replace(ctx, index);
+       return ret;
+}
+
+DUK_EXTERNAL void duk_hex_decode(duk_context *ctx, duk_idx_t index) {
+       duk_hthread *thr = (duk_hthread *) ctx;
+       const duk_uint8_t *inp;
+       duk_size_t len;
+       duk_size_t i;
+       duk_int_t t;
+       duk_uint8_t *buf;
+#if defined(DUK_USE_HEX_FASTPATH)
+       duk_int_t chk;
+       duk_uint8_t *p;
+       duk_size_t len_safe;
+#endif
+
+       DUK_ASSERT_CTX_VALID(ctx);
+
+       index = duk_require_normalize_index(ctx, index);
+       inp = duk__prep_codec_arg(ctx, index, &len);
+       DUK_ASSERT(inp != NULL || len == 0);
+
+       if (len & 0x01) {
+               goto type_error;
+       }
+
+       /* Fixed buffer, no zeroing because we'll fill all the data. */
+       buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len / 2, 
DUK_BUF_FLAG_NOZERO /*flags*/);
+       DUK_ASSERT(buf != NULL);
+
+#if defined(DUK_USE_HEX_FASTPATH)
+       p = buf;
+       len_safe = len & ~0x07U;
+       for (i = 0; i < len_safe; i += 8) {
+               t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
+                   ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+               chk = t;
+               p[0] = (duk_uint8_t) t;
+               t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
+                   ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
+               chk |= t;
+               p[1] = (duk_uint8_t) t;
+               t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
+                   ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
+               chk |= t;
+               p[2] = (duk_uint8_t) t;
+               t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
+                   ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
+               chk |= t;
+               p[3] = (duk_uint8_t) t;
+               p += 4;
+
+               /* Check if any lookup above had a negative result. */
+               if (DUK_UNLIKELY(chk < 0)) {
+                       goto type_error;
+               }
+       }
+       for (; i < len; i += 2) {
+               t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
+                   ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+               if (DUK_UNLIKELY(t < 0)) {
+                       goto type_error;
+               }
+               *p++ = (duk_uint8_t) t;
+       }
+#else  /* DUK_USE_HEX_FASTPATH */
+       for (i = 0; i < len; i += 2) {
+               /* For invalid characters the value -1 gets extended to
+                * at least 16 bits.  If either nybble is invalid, the
+                * resulting 't' will be < 0.
+                */
+               t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
+                   ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+               if (DUK_UNLIKELY(t < 0)) {
+                       goto type_error;
+               }
+               buf[i >> 1] = (duk_uint8_t) t;
+       }
+#endif  /* DUK_USE_HEX_FASTPATH */
+
+       duk_replace(ctx, index);
+       return;
+
+ type_error:
+       DUK_ERROR_TYPE(thr, DUK_STR_DECODE_FAILED);
+}
+
+DUK_EXTERNAL const char *duk_json_encode(duk_context *ctx, duk_idx_t index) {
+#ifdef DUK_USE_ASSERTIONS
+       duk_idx_t top_at_entry;
+#endif
+       const char *ret;
+
+       DUK_ASSERT_CTX_VALID(ctx);
+#ifdef DUK_USE_ASSERTIONS
+       top_at_entry = duk_get_top(ctx);
+#endif
+
+       index = duk_require_normalize_index(ctx, index);
+       duk_bi_json_stringify_helper(ctx,
+                                    index /*idx_value*/,
+                                    DUK_INVALID_INDEX /*idx_replacer*/,
+                                    DUK_INVALID_INDEX /*idx_space*/,
+                                    0 /*flags*/);
+       DUK_ASSERT(duk_is_string(ctx, -1));
+       duk_replace(ctx, index);
+       ret = duk_get_string(ctx, index);
+
+       DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
+
+       return ret;
+}
+
+DUK_EXTERNAL void duk_json_decode(duk_context *ctx, duk_idx_t index) {
+#ifdef DUK_USE_ASSERTIONS
+       duk_idx_t top_at_entry;
+#endif
+
+       DUK_ASSERT_CTX_VALID(ctx);
+#ifdef DUK_USE_ASSERTIONS
+       top_at_entry = duk_get_top(ctx);
+#endif
+
+       index = duk_require_normalize_index(ctx, index);
+       duk_bi_json_parse_helper(ctx,
+                                index /*idx_value*/,
+                                DUK_INVALID_INDEX /*idx_reviver*/,
+                                0 /*flags*/);
+       duk_replace(ctx, index);
+
+       DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
+}

Reply via email to