1#include <assert.h>
2#define NAPI_EXPERIMENTAL
3#include <node_api.h>
4
5#define NAPI_CALL(call)                                                        \
6  do {                                                                         \
7    napi_status status = call;                                                 \
8    assert(status == napi_ok && #call " failed");                              \
9  } while (0);
10
11#define EXPORT_FUNC(env, exports, name, func)                                  \
12  do {                                                                         \
13    napi_value js_func;                                                        \
14    NAPI_CALL(napi_create_function(                                            \
15        (env), (name), NAPI_AUTO_LENGTH, (func), NULL, &js_func));             \
16    NAPI_CALL(napi_set_named_property((env), (exports), (name), js_func));     \
17  } while (0);
18
19const char* one_byte_string = "The Quick Brown Fox Jumped Over The Lazy Dog.";
20const char16_t* two_byte_string =
21    u"The Quick Brown Fox Jumped Over The Lazy Dog.";
22
23#define DECLARE_BINDING(CapName, lowercase_name, var_name)                     \
24  static napi_value CreateString##CapName(napi_env env,                        \
25                                          napi_callback_info info) {           \
26    size_t argc = 4;                                                           \
27    napi_value argv[4];                                                        \
28    uint32_t n;                                                                \
29    uint32_t index;                                                            \
30    napi_handle_scope scope;                                                   \
31    napi_value js_string;                                                      \
32                                                                               \
33    NAPI_CALL(napi_get_cb_info(env, info, &argc, argv, NULL, NULL));           \
34    NAPI_CALL(napi_get_value_uint32(env, argv[0], &n));                        \
35    NAPI_CALL(napi_open_handle_scope(env, &scope));                            \
36    NAPI_CALL(napi_call_function(env, argv[1], argv[2], 0, NULL, NULL));       \
37    for (index = 0; index < n; index++) {                                      \
38      NAPI_CALL(napi_create_string_##lowercase_name(                           \
39          env, (var_name), NAPI_AUTO_LENGTH, &js_string));                     \
40    }                                                                          \
41    NAPI_CALL(napi_call_function(env, argv[1], argv[3], 1, &argv[0], NULL));   \
42    NAPI_CALL(napi_close_handle_scope(env, scope));                            \
43                                                                               \
44    return NULL;                                                               \
45  }
46
47DECLARE_BINDING(Latin1, latin1, one_byte_string)
48DECLARE_BINDING(Utf8, utf8, one_byte_string)
49DECLARE_BINDING(Utf16, utf16, two_byte_string)
50
51NAPI_MODULE_INIT() {
52  EXPORT_FUNC(env, exports, "createStringLatin1", CreateStringLatin1);
53  EXPORT_FUNC(env, exports, "createStringUtf8", CreateStringUtf8);
54  EXPORT_FUNC(env, exports, "createStringUtf16", CreateStringUtf16);
55  return exports;
56}
57