1
+ using System . Collections . Generic ;
2
+ using System . IO ;
3
+ using CppSharp . AST ;
4
+ using CppSharp . Generators . C ;
5
+
6
+ namespace CppSharp . Generators . Cpp
7
+ {
8
+ /// <summary>
9
+ /// Generates a common Node N-API C/C++ common files.
10
+ /// N-API documentation: https://nodejs.org/api/n-api.html
11
+ /// </summary>
12
+ public class NAPIHelpers : CppHeaders
13
+ {
14
+ public NAPIHelpers ( BindingContext context )
15
+ : base ( context , null )
16
+ {
17
+ }
18
+
19
+ public override void Process ( )
20
+ {
21
+ GenerateFilePreamble ( CommentKind . BCPL ) ;
22
+
23
+ WriteLine ( "#pragma once" ) ;
24
+ NewLine ( ) ;
25
+
26
+ WriteInclude ( "math.h" , CInclude . IncludeKind . Angled ) ;
27
+ WriteInclude ( "limits.h" , CInclude . IncludeKind . Angled ) ;
28
+ NewLine ( ) ;
29
+
30
+ GenerateHelpers ( ) ;
31
+ return ;
32
+ }
33
+
34
+ private void GenerateHelpers ( )
35
+ {
36
+ WriteLine ( @"#define NAPI_CALL(env, call) \
37
+ do { \
38
+ napi_status status = (call); \
39
+ if (status != napi_ok) { \
40
+ const napi_extended_error_info* error_info = NULL; \
41
+ napi_get_last_error_info((env), &error_info); \
42
+ bool is_pending; \
43
+ napi_is_exception_pending((env), &is_pending); \
44
+ if (!is_pending) { \
45
+ const char* message = (error_info->error_message == NULL) \
46
+ ? ""empty error message"" \
47
+ : error_info->error_message; \
48
+ napi_throw_error((env), NULL, message); \
49
+ return NULL; \
50
+ } \
51
+ } \
52
+ } while(0)" ) ;
53
+ NewLine ( ) ;
54
+
55
+ WriteLine ( @"#define NAPI_CALL_NORET(env, call) \
56
+ do { \
57
+ napi_status status = (call); \
58
+ if (status != napi_ok) { \
59
+ const napi_extended_error_info* error_info = NULL; \
60
+ napi_get_last_error_info((env), &error_info); \
61
+ bool is_pending; \
62
+ napi_is_exception_pending((env), &is_pending); \
63
+ if (!is_pending) { \
64
+ const char* message = (error_info->error_message == NULL) \
65
+ ? ""empty error message"" \
66
+ : error_info->error_message; \
67
+ napi_throw_error((env), NULL, message); \
68
+ return; \
69
+ } \
70
+ } \
71
+ } while(0)" ) ;
72
+ NewLine ( ) ;
73
+
74
+ WriteLine ( @"static int napi_is_int32(napi_env env, napi_value value, int* integer) {
75
+ double temp = 0;
76
+ if (
77
+ // We get the value as a double so we can check for NaN, Infinity and float:
78
+ // https://github.com/nodejs/node/issues/26323
79
+ napi_get_value_double(env, value, &temp) != napi_ok ||
80
+ // Reject NaN:
81
+ isnan(temp) ||
82
+ // Reject Infinity and avoid undefined behavior when casting double to int:
83
+ // https://groups.google.com/forum/#!topic/comp.lang.c/rhPzd4bgKJk
84
+ temp < INT_MIN ||
85
+ temp > INT_MAX ||
86
+ // Reject float by casting double to int:
87
+ (double) ((int) temp) != temp
88
+ ) {
89
+ //napi_throw_error(env, NULL, ""argument must be an integer"");
90
+ return 0;
91
+ }
92
+ if (integer)
93
+ *integer = (int) temp;
94
+ return 1;
95
+ }" ) ;
96
+ NewLine ( ) ;
97
+
98
+ WriteLine ( @"static int napi_is_uint32(napi_env env, napi_value value, int* integer) {
99
+ double temp = 0;
100
+ if (
101
+ // We get the value as a double so we can check for NaN, Infinity and float:
102
+ // https://github.com/nodejs/node/issues/26323
103
+ napi_get_value_double(env, value, &temp) != napi_ok ||
104
+ // Reject NaN:
105
+ isnan(temp) ||
106
+ // Reject Infinity and avoid undefined behavior when casting double to int:
107
+ // https://groups.google.com/forum/#!topic/comp.lang.c/rhPzd4bgKJk
108
+ temp < 0 ||
109
+ temp > ULONG_MAX ||
110
+ // Reject float by casting double to int:
111
+ (double) ((unsigned long) temp) != temp
112
+ ) {
113
+ //napi_throw_error(env, NULL, ""argument must be an integer"");
114
+ return 0;
115
+ }
116
+ if (integer)
117
+ *integer = (int) temp;
118
+ return 1;
119
+ }" ) ;
120
+ NewLine ( ) ;
121
+
122
+ WriteLine ( @"#define NAPI_IS_BOOL(valuetype) (valuetype == napi_boolean)" ) ;
123
+ WriteLine ( @"#define NAPI_IS_NULL(valuetype) (valuetype == napi_null)" ) ;
124
+ WriteLine ( @"#define NAPI_IS_NUMBER(valuetype) (valuetype == napi_number)" ) ;
125
+ WriteLine ( @"#define NAPI_IS_BIGINT(valuetype) (valuetype == napi_bigint)" ) ;
126
+ WriteLine ( @"#define NAPI_IS_INT32(valuetype, value) (NAPI_IS_NUMBER(valuetype) && napi_is_int32(env, value, nullptr))" ) ;
127
+ WriteLine ( @"#define NAPI_IS_UINT32(valuetype, value) (NAPI_IS_NUMBER(valuetype) && napi_is_uint32(env, value, nullptr))" ) ;
128
+ WriteLine ( @"#define NAPI_IS_INT64(valuetype, value) (NAPI_IS_BIGINT(valuetype))" ) ;
129
+ WriteLine ( @"#define NAPI_IS_UINT64(valuetype, value) (NAPI_IS_BIGINT(valuetype))" ) ;
130
+ NewLine ( ) ;
131
+ }
132
+ }
133
+ }
0 commit comments