msgpackr-extract 2.1.1 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,10 @@
2
2
 
3
3
  const { dirname } = require('path');
4
4
  const { fileURLToPath } = require('url');
5
+ const { exec } = require('child_process');
6
+
5
7
  process.chdir(dirname(__dirname));
6
- process.argv[2] = 'download';
7
- require('prebuildify-ci');
8
+ exec('prebuildify-ci download', (error, stdout, stderr) => {
9
+ console.error(stderr);
10
+ console.log(stdout);
11
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "msgpackr-extract",
3
3
  "author": "Kris Zyp",
4
- "version": "2.1.1",
4
+ "version": "2.1.2",
5
5
  "description": "Node addon for string extraction for msgpackr",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -34,12 +34,12 @@
34
34
  "download-msgpackr-prebuilds": "./bin/download-prebuilds.js"
35
35
  },
36
36
  "optionalDependencies": {
37
- "@msgpackr-extract/msgpackr-extract-darwin-arm64": "2.1.1",
38
- "@msgpackr-extract/msgpackr-extract-darwin-x64": "2.1.1",
39
- "@msgpackr-extract/msgpackr-extract-linux-arm": "2.1.1",
40
- "@msgpackr-extract/msgpackr-extract-linux-arm64": "2.1.1",
41
- "@msgpackr-extract/msgpackr-extract-linux-x64": "2.1.1",
42
- "@msgpackr-extract/msgpackr-extract-win32-x64": "2.1.1"
37
+ "@msgpackr-extract/msgpackr-extract-darwin-arm64": "2.1.2",
38
+ "@msgpackr-extract/msgpackr-extract-darwin-x64": "2.1.2",
39
+ "@msgpackr-extract/msgpackr-extract-linux-arm": "2.1.2",
40
+ "@msgpackr-extract/msgpackr-extract-linux-arm64": "2.1.2",
41
+ "@msgpackr-extract/msgpackr-extract-linux-x64": "2.1.2",
42
+ "@msgpackr-extract/msgpackr-extract-win32-x64": "2.1.2"
43
43
  },
44
44
  "devDependencies": {
45
45
  "prebuildify-platform-packages": "5.0.0",
@@ -0,0 +1,3 @@
1
+ {
2
+ "CurrentProjectSetting": "No Configurations"
3
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "ExpandedNodes": [
3
+ ""
4
+ ],
5
+ "SelectedNode": "\\extract.cpp",
6
+ "PreviewInSolutionExplorer": false
7
+ }
Binary file
Binary file
Binary file
Binary file
File without changes
package/src/extract.cpp CHANGED
@@ -1,272 +1,272 @@
1
- /*
2
- This is responsible for extracting the strings, in bulk, from a MessagePack buffer. Creating strings from buffers can
3
- be one of the biggest performance bottlenecks of parsing, but creating an array of extracting strings all at once
4
- provides much better performance. This will parse and produce up to 256 strings at once .The JS parser can call this multiple
5
- times as necessary to get more strings. This must be partially capable of parsing MessagePack so it can know where to
6
- find the string tokens and determine their position and length. All strings are decoded as UTF-8.
7
- */
8
- #include <node_api.h>
9
- #if ENABLE_V8_API
10
- #include <v8.h>
11
- #endif
12
-
13
- #ifndef thread_local
14
- #ifdef __GNUC__
15
- # define thread_local __thread
16
- #elif __STDC_VERSION__ >= 201112L
17
- # define thread_local _Thread_local
18
- #elif defined(_MSC_VER)
19
- # define thread_local __declspec(thread)
20
- #else
21
- # define thread_local
22
- #endif
23
- #endif
24
-
25
- const int MAX_TARGET_SIZE = 255;
26
- typedef int (*token_handler)(uint8_t* source, int position, int size);
27
- token_handler tokenTable[256] = {};
28
- napi_value unexpectedEnd(napi_env env) {
29
- napi_value returnValue;
30
- napi_get_undefined(env, &returnValue);
31
- napi_throw_type_error(env, NULL, "Unexpected end of buffer reading string");
32
- return returnValue;
33
- }
34
-
35
- class Extractor {
36
- public:
37
- // napi_ref targetArray; // could consider reenabling this optimization for napi
38
- bool hasTargetArray = false;
39
- uint8_t* source;
40
- int position = 0;
41
- int writePosition = 0;
42
- int stringStart = 0;
43
- int lastStringEnd = 0;
44
-
45
- void readString(napi_env env, int length, bool allowStringBlocks, napi_value* target) {
46
- int start = position;
47
- int end = position + length;
48
- if (allowStringBlocks) { // for larger strings, we don't bother to check every character for being latin, and just go right to creating a new string
49
- while(position < end) {
50
- if (source[position] < 0x80) // ensure we character is latin and can be decoded as one byte
51
- position++;
52
- else {
53
- break;
54
- }
55
- }
56
- }
57
- if (position < end) {
58
- // non-latin character
59
- if (lastStringEnd) {
60
- napi_value value;
61
- napi_create_string_latin1(env, (const char*) source + stringStart, lastStringEnd - stringStart, &value);
62
- target[writePosition++] = value;
63
- lastStringEnd = 0;
64
- }
65
- // use standard utf-8 conversion
66
- napi_value value;
67
- napi_create_string_utf8(env, (const char*) source + start, (int) length, &value);
68
- target[writePosition++] = value;
69
- position = end;
70
- return;
71
- }
72
-
73
- if (lastStringEnd) {
74
- if (start - lastStringEnd > 40 || end - stringStart > 6000) {
75
- napi_value value;
76
- napi_create_string_latin1(env, (const char*) source + stringStart, lastStringEnd - stringStart, &value);
77
- target[writePosition++] = value;
78
- stringStart = start;
79
- }
80
- } else {
81
- stringStart = start;
82
- }
83
- lastStringEnd = end;
84
- }
85
-
86
- napi_value extractStrings(napi_env env, int startingPosition, int size, uint8_t* inputSource) {
87
- napi_value target[MAX_TARGET_SIZE + 1]; // leave one for the queued string
88
- writePosition = 0;
89
- lastStringEnd = 0;
90
- position = startingPosition;
91
- source = inputSource;
92
- while (position < size) {
93
- uint8_t token = source[position++];
94
- if (token < 0xa0) {
95
- // all one byte tokens
96
- } else if (token < 0xc0) {
97
- // fixstr, we want to convert this
98
- token -= 0xa0;
99
- if (token + position > size) {
100
- return unexpectedEnd(env);
101
- }
102
- readString(env, token, true, target);
103
- if (writePosition >= MAX_TARGET_SIZE)
104
- break;
105
- } else if (token <= 0xdb && token >= 0xd9) {
106
- if (token == 0xd9) { //str 8
107
- if (position >= size) {
108
- return unexpectedEnd(env);
109
- }
110
- int length = source[position++];
111
- if (length + position > size) {
112
- return unexpectedEnd(env);
113
- }
114
- readString(env,length, true, target);
115
- } else if (token == 0xda) { //str 16
116
- if (2 + position > size) {
117
- return unexpectedEnd(env);
118
- }
119
- int length = source[position++] << 8;
120
- length += source[position++];
121
- if (length + position > size) {
122
- return unexpectedEnd(env);
123
- }
124
- readString(env,length, false, target);
125
- } else { //str 32
126
- if (4 + position > size) {
127
- return unexpectedEnd(env);
128
- }
129
- int length = source[position++] << 24;
130
- length += source[position++] << 16;
131
- length += source[position++] << 8;
132
- length += source[position++];
133
- if (length + position > size) {
134
- return unexpectedEnd(env);
135
- }
136
- readString(env, length, false, target);
137
- }
138
- if (writePosition >= MAX_TARGET_SIZE)
139
- break;
140
- } else {
141
- auto handle = tokenTable[token];
142
- if ((size_t ) handle < 20) {
143
- position += (size_t ) handle;
144
- } else {
145
- position = tokenTable[token](source, position, size);
146
- if (position < 0) {
147
- return unexpectedEnd(env);
148
- }
149
- }
150
- }
151
- }
152
-
153
- if (lastStringEnd) {
154
- napi_value value;
155
- napi_create_string_latin1(env, (const char*) source + stringStart, lastStringEnd - stringStart, &value);
156
- if (writePosition == 0) {
157
- return value;
158
- }
159
- target[writePosition++] = value;
160
- } else if (writePosition == 1) {
161
- return target[0];
162
- }
163
- napi_value array;
164
- #if ENABLE_V8_API
165
- v8::Local<v8::Array> v8Array = v8::Array::New(v8::Isolate::GetCurrent(), (v8::Local<v8::Value>*) target, writePosition);
166
- memcpy(&array, &v8Array, sizeof(array));
167
- #else
168
- napi_create_array_with_length(env, writePosition, &array);
169
- for (int i = 0; i < writePosition; i++) {
170
- napi_set_element(env, array, i, target[i]);
171
- }
172
- #endif
173
- return array;
174
- }
175
- };
176
-
177
- void setupTokenTable() {
178
- for (int i = 0; i < 256; i++) {
179
- tokenTable[i] = nullptr;
180
- }
181
- // uint8, int8
182
- tokenTable[0xcc] = tokenTable[0xd0] = (token_handler) 1;
183
- // uint16, int16, array 16, map 16, fixext 1
184
- tokenTable[0xcd] = tokenTable[0xd1] = tokenTable[0xdc] = tokenTable[0xde] = tokenTable[0xd4] = (token_handler) 2;
185
- // fixext 16
186
- tokenTable[0xd5] = (token_handler) 3;
187
- // uint32, int32, float32, array 32, map 32
188
- tokenTable[0xce] = tokenTable[0xd2] = tokenTable[0xca] = tokenTable[0xdd] = tokenTable[0xdf] = (token_handler) 4;
189
- // fixext 4
190
- tokenTable[0xd6] = (token_handler) 5;
191
- // uint64, int64, float64, fixext 8
192
- tokenTable[0xcf] = tokenTable[0xd3] = tokenTable[0xcb] = (token_handler) 8;
193
- // fixext 8
194
- tokenTable[0xd7] = (token_handler) 9;
195
- // fixext 16
196
- tokenTable[0xd8] = (token_handler) 17;
197
- // bin 8
198
- tokenTable[0xc4] = ([](uint8_t* source, int position, int size) -> int {
199
- if (position >= size) {
200
- return -1;
201
- }
202
- int length = source[position++];
203
- return position + length;
204
- });
205
- // bin 16
206
- tokenTable[0xc5] = ([](uint8_t* source, int position, int size) -> int {
207
- if (position + 2 > size) {
208
- return -1;
209
- }
210
- int length = source[position++] << 8;
211
- length += source[position++];
212
- return position + length;
213
- });
214
- // bin 32
215
- tokenTable[0xc6] = ([](uint8_t* source, int position, int size) -> int {
216
- if (position + 4 > size)
217
- return -1;
218
- int length = source[position++] << 24;
219
- length += source[position++] << 16;
220
- length += source[position++] << 8;
221
- length += source[position++];
222
- return position + length;
223
- });
224
- // ext 8
225
- tokenTable[0xc7] = ([](uint8_t* source, int position, int size) -> int {
226
- if (position >= size)
227
- return -1;
228
- int length = source[position++];
229
- position++;
230
- return position + length;
231
- });
232
- // ext 16
233
- tokenTable[0xc8] = ([](uint8_t* source, int position, int size) -> int {
234
- if (position + 2 > size)
235
- return -1;
236
- int length = source[position++] << 8;
237
- length += source[position++];
238
- position++;
239
- return position + length;
240
- });
241
- // ext 32
242
- tokenTable[0xc9] = ([](uint8_t* source, int position, int size) -> int {
243
- if (position + 4 > size)
244
- return -1;
245
- int length = source[position++] << 24;
246
- length += source[position++] << 16;
247
- length += source[position++] << 8;
248
- length += source[position++];
249
- position++;
250
- return position + length;
251
- });
252
- }
253
- static thread_local Extractor* extractor;
254
- napi_value extractStrings(napi_env env, napi_callback_info info) {
255
- size_t argc = 3;
256
- napi_value args[3];
257
- napi_get_cb_info(env, info, &argc, args, NULL, NULL);
258
- uint32_t position;
259
- uint32_t size;
260
- napi_get_value_uint32(env, args[0], &position);
261
- napi_get_value_uint32(env, args[1], &size);
262
- uint8_t* source;
263
- napi_get_typedarray_info(env, args[2], NULL, NULL, (void**) &source, NULL, NULL);
264
- return extractor->extractStrings(env, position, size, source);
265
- }
266
- #define EXPORT_NAPI_FUNCTION(name, func) { napi_property_descriptor desc = { name, 0, func, 0, 0, 0, (napi_property_attributes) (napi_writable | napi_configurable), 0 }; napi_define_properties(env, exports, 1, &desc); }
267
- NAPI_MODULE_INIT() {
268
- extractor = new Extractor(); // create our thread-local extractor
269
- setupTokenTable();
270
- EXPORT_NAPI_FUNCTION("extractStrings", extractStrings);
271
- return exports;
272
- }
1
+ /*
2
+ This is responsible for extracting the strings, in bulk, from a MessagePack buffer. Creating strings from buffers can
3
+ be one of the biggest performance bottlenecks of parsing, but creating an array of extracting strings all at once
4
+ provides much better performance. This will parse and produce up to 256 strings at once .The JS parser can call this multiple
5
+ times as necessary to get more strings. This must be partially capable of parsing MessagePack so it can know where to
6
+ find the string tokens and determine their position and length. All strings are decoded as UTF-8.
7
+ */
8
+ #include <node_api.h>
9
+ #if ENABLE_V8_API
10
+ #include <v8.h>
11
+ #endif
12
+
13
+ #ifndef thread_local
14
+ #ifdef __GNUC__
15
+ # define thread_local __thread
16
+ #elif __STDC_VERSION__ >= 201112L
17
+ # define thread_local _Thread_local
18
+ #elif defined(_MSC_VER)
19
+ # define thread_local __declspec(thread)
20
+ #else
21
+ # define thread_local
22
+ #endif
23
+ #endif
24
+
25
+ const int MAX_TARGET_SIZE = 255;
26
+ typedef int (*token_handler)(uint8_t* source, int position, int size);
27
+ token_handler tokenTable[256] = {};
28
+ napi_value unexpectedEnd(napi_env env) {
29
+ napi_value returnValue;
30
+ napi_get_undefined(env, &returnValue);
31
+ napi_throw_type_error(env, NULL, "Unexpected end of buffer reading string");
32
+ return returnValue;
33
+ }
34
+
35
+ class Extractor {
36
+ public:
37
+ // napi_ref targetArray; // could consider reenabling this optimization for napi
38
+ bool hasTargetArray = false;
39
+ uint8_t* source;
40
+ int position = 0;
41
+ int writePosition = 0;
42
+ int stringStart = 0;
43
+ int lastStringEnd = 0;
44
+
45
+ void readString(napi_env env, int length, bool allowStringBlocks, napi_value* target) {
46
+ int start = position;
47
+ int end = position + length;
48
+ if (allowStringBlocks) { // for larger strings, we don't bother to check every character for being latin, and just go right to creating a new string
49
+ while(position < end) {
50
+ if (source[position] < 0x80) // ensure we character is latin and can be decoded as one byte
51
+ position++;
52
+ else {
53
+ break;
54
+ }
55
+ }
56
+ }
57
+ if (position < end) {
58
+ // non-latin character
59
+ if (lastStringEnd) {
60
+ napi_value value;
61
+ napi_create_string_latin1(env, (const char*) source + stringStart, lastStringEnd - stringStart, &value);
62
+ target[writePosition++] = value;
63
+ lastStringEnd = 0;
64
+ }
65
+ // use standard utf-8 conversion
66
+ napi_value value;
67
+ napi_create_string_utf8(env, (const char*) source + start, (int) length, &value);
68
+ target[writePosition++] = value;
69
+ position = end;
70
+ return;
71
+ }
72
+
73
+ if (lastStringEnd) {
74
+ if (start - lastStringEnd > 40 || end - stringStart > 6000) {
75
+ napi_value value;
76
+ napi_create_string_latin1(env, (const char*) source + stringStart, lastStringEnd - stringStart, &value);
77
+ target[writePosition++] = value;
78
+ stringStart = start;
79
+ }
80
+ } else {
81
+ stringStart = start;
82
+ }
83
+ lastStringEnd = end;
84
+ }
85
+
86
+ napi_value extractStrings(napi_env env, int startingPosition, int size, uint8_t* inputSource) {
87
+ napi_value target[MAX_TARGET_SIZE + 1]; // leave one for the queued string
88
+ writePosition = 0;
89
+ lastStringEnd = 0;
90
+ position = startingPosition;
91
+ source = inputSource;
92
+ while (position < size) {
93
+ uint8_t token = source[position++];
94
+ if (token < 0xa0) {
95
+ // all one byte tokens
96
+ } else if (token < 0xc0) {
97
+ // fixstr, we want to convert this
98
+ token -= 0xa0;
99
+ if (token + position > size) {
100
+ return unexpectedEnd(env);
101
+ }
102
+ readString(env, token, true, target);
103
+ if (writePosition >= MAX_TARGET_SIZE)
104
+ break;
105
+ } else if (token <= 0xdb && token >= 0xd9) {
106
+ if (token == 0xd9) { //str 8
107
+ if (position >= size) {
108
+ return unexpectedEnd(env);
109
+ }
110
+ int length = source[position++];
111
+ if (length + position > size) {
112
+ return unexpectedEnd(env);
113
+ }
114
+ readString(env,length, true, target);
115
+ } else if (token == 0xda) { //str 16
116
+ if (2 + position > size) {
117
+ return unexpectedEnd(env);
118
+ }
119
+ int length = source[position++] << 8;
120
+ length += source[position++];
121
+ if (length + position > size) {
122
+ return unexpectedEnd(env);
123
+ }
124
+ readString(env,length, false, target);
125
+ } else { //str 32
126
+ if (4 + position > size) {
127
+ return unexpectedEnd(env);
128
+ }
129
+ int length = source[position++] << 24;
130
+ length += source[position++] << 16;
131
+ length += source[position++] << 8;
132
+ length += source[position++];
133
+ if (length + position > size) {
134
+ return unexpectedEnd(env);
135
+ }
136
+ readString(env, length, false, target);
137
+ }
138
+ if (writePosition >= MAX_TARGET_SIZE)
139
+ break;
140
+ } else {
141
+ auto handle = tokenTable[token];
142
+ if ((size_t ) handle < 20) {
143
+ position += (size_t ) handle;
144
+ } else {
145
+ position = tokenTable[token](source, position, size);
146
+ if (position < 0) {
147
+ return unexpectedEnd(env);
148
+ }
149
+ }
150
+ }
151
+ }
152
+
153
+ if (lastStringEnd) {
154
+ napi_value value;
155
+ napi_create_string_latin1(env, (const char*) source + stringStart, lastStringEnd - stringStart, &value);
156
+ if (writePosition == 0) {
157
+ return value;
158
+ }
159
+ target[writePosition++] = value;
160
+ } else if (writePosition == 1) {
161
+ return target[0];
162
+ }
163
+ napi_value array;
164
+ #if ENABLE_V8_API
165
+ v8::Local<v8::Array> v8Array = v8::Array::New(v8::Isolate::GetCurrent(), (v8::Local<v8::Value>*) target, writePosition);
166
+ memcpy(&array, &v8Array, sizeof(array));
167
+ #else
168
+ napi_create_array_with_length(env, writePosition, &array);
169
+ for (int i = 0; i < writePosition; i++) {
170
+ napi_set_element(env, array, i, target[i]);
171
+ }
172
+ #endif
173
+ return array;
174
+ }
175
+ };
176
+
177
+ void setupTokenTable() {
178
+ for (int i = 0; i < 256; i++) {
179
+ tokenTable[i] = nullptr;
180
+ }
181
+ // uint8, int8
182
+ tokenTable[0xcc] = tokenTable[0xd0] = (token_handler) 1;
183
+ // uint16, int16, array 16, map 16, fixext 1
184
+ tokenTable[0xcd] = tokenTable[0xd1] = tokenTable[0xdc] = tokenTable[0xde] = tokenTable[0xd4] = (token_handler) 2;
185
+ // fixext 16
186
+ tokenTable[0xd5] = (token_handler) 3;
187
+ // uint32, int32, float32, array 32, map 32
188
+ tokenTable[0xce] = tokenTable[0xd2] = tokenTable[0xca] = tokenTable[0xdd] = tokenTable[0xdf] = (token_handler) 4;
189
+ // fixext 4
190
+ tokenTable[0xd6] = (token_handler) 5;
191
+ // uint64, int64, float64, fixext 8
192
+ tokenTable[0xcf] = tokenTable[0xd3] = tokenTable[0xcb] = (token_handler) 8;
193
+ // fixext 8
194
+ tokenTable[0xd7] = (token_handler) 9;
195
+ // fixext 16
196
+ tokenTable[0xd8] = (token_handler) 17;
197
+ // bin 8
198
+ tokenTable[0xc4] = ([](uint8_t* source, int position, int size) -> int {
199
+ if (position >= size) {
200
+ return -1;
201
+ }
202
+ int length = source[position++];
203
+ return position + length;
204
+ });
205
+ // bin 16
206
+ tokenTable[0xc5] = ([](uint8_t* source, int position, int size) -> int {
207
+ if (position + 2 > size) {
208
+ return -1;
209
+ }
210
+ int length = source[position++] << 8;
211
+ length += source[position++];
212
+ return position + length;
213
+ });
214
+ // bin 32
215
+ tokenTable[0xc6] = ([](uint8_t* source, int position, int size) -> int {
216
+ if (position + 4 > size)
217
+ return -1;
218
+ int length = source[position++] << 24;
219
+ length += source[position++] << 16;
220
+ length += source[position++] << 8;
221
+ length += source[position++];
222
+ return position + length;
223
+ });
224
+ // ext 8
225
+ tokenTable[0xc7] = ([](uint8_t* source, int position, int size) -> int {
226
+ if (position >= size)
227
+ return -1;
228
+ int length = source[position++];
229
+ position++;
230
+ return position + length;
231
+ });
232
+ // ext 16
233
+ tokenTable[0xc8] = ([](uint8_t* source, int position, int size) -> int {
234
+ if (position + 2 > size)
235
+ return -1;
236
+ int length = source[position++] << 8;
237
+ length += source[position++];
238
+ position++;
239
+ return position + length;
240
+ });
241
+ // ext 32
242
+ tokenTable[0xc9] = ([](uint8_t* source, int position, int size) -> int {
243
+ if (position + 4 > size)
244
+ return -1;
245
+ int length = source[position++] << 24;
246
+ length += source[position++] << 16;
247
+ length += source[position++] << 8;
248
+ length += source[position++];
249
+ position++;
250
+ return position + length;
251
+ });
252
+ }
253
+ static thread_local Extractor* extractor;
254
+ napi_value extractStrings(napi_env env, napi_callback_info info) {
255
+ size_t argc = 3;
256
+ napi_value args[3];
257
+ napi_get_cb_info(env, info, &argc, args, NULL, NULL);
258
+ uint32_t position;
259
+ uint32_t size;
260
+ napi_get_value_uint32(env, args[0], &position);
261
+ napi_get_value_uint32(env, args[1], &size);
262
+ uint8_t* source;
263
+ napi_get_typedarray_info(env, args[2], NULL, NULL, (void**) &source, NULL, NULL);
264
+ return extractor->extractStrings(env, position, size, source);
265
+ }
266
+ #define EXPORT_NAPI_FUNCTION(name, func) { napi_property_descriptor desc = { name, 0, func, 0, 0, 0, (napi_property_attributes) (napi_writable | napi_configurable), 0 }; napi_define_properties(env, exports, 1, &desc); }
267
+ NAPI_MODULE_INIT() {
268
+ extractor = new Extractor(); // create our thread-local extractor
269
+ setupTokenTable();
270
+ EXPORT_NAPI_FUNCTION("extractStrings", extractStrings);
271
+ return exports;
272
+ }