1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "napi/native_api.h"
17 #include <cerrno>
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 #include <ctime>
22 #include <js_native_api.h>
23 #include <malloc.h>
24 #include <node_api.h>
25 #include <search.h>
26 #include <string>
27 #include <unistd.h>
28 #include <vector>
29
30 #define PARAM_0 0
31 #define PARAM_5 5
32 #define PARAM_27 27
33 #define PARAM_1 1
34 #define PARAM_3 3
35 #define PARAM_123 123
36 #define PARAM_456 456
37 #define PARAM_2 2
38 #define PARAM_8 8
39 #define PARAM_UNNORMAL (-1)
40 #define ERRON_0 0
41 #define TWICE 12
42 #define ARRAY_SIZE (10)
43 #define FAIL (-1)
44 #define NOERR 0
45 #define VALUE_ONE 1
46 #define VALUE_TWO 1
47 #define BUFFERSIZE 128
48 #define LOOPNUM 12
49
Hcreate(napi_env env,napi_callback_info info)50 static napi_value Hcreate(napi_env env, napi_callback_info info)
51 {
52 size_t argc = PARAM_1;
53 napi_value args[1] = {nullptr};
54 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
55 int param;
56 napi_get_value_int32(env, args[0], ¶m);
57
58 int ret = FAIL;
59 if (param == PARAM_0) {
60 ret = hcreate(PARAM_8);
61 hdestroy();
62 }
63 if (ret > PARAM_0) {
64 ret = NOERR;
65 } else {
66 ret = FAIL;
67 }
68
69 napi_value result = nullptr;
70 napi_create_int32(env, ret, &result);
71 return result;
72 }
73
HcreateR(napi_env env,napi_callback_info info)74 static napi_value HcreateR(napi_env env, napi_callback_info info)
75 {
76 size_t argc = PARAM_1;
77 napi_value args[1] = {nullptr};
78 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
79 int param;
80 napi_get_value_int32(env, args[0], ¶m);
81
82 int ret = FAIL;
83 errno = PARAM_0;
84 struct hsearch_data data;
85 if (param == PARAM_0) {
86 ret = hcreate_r(PARAM_8, &data);
87 hdestroy_r(&data);
88 }
89 if (ret > PARAM_0) {
90 ret = NOERR;
91 } else {
92 ret = FAIL;
93 }
94
95 napi_value result = nullptr;
96 napi_create_int32(env, ret, &result);
97 return result;
98 }
99
Hdestroy(napi_env env,napi_callback_info info)100 static napi_value Hdestroy(napi_env env, napi_callback_info info)
101 {
102 size_t argc = PARAM_1;
103 napi_value args[1] = {nullptr};
104 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
105 int param;
106 napi_get_value_int32(env, args[0], ¶m);
107
108 int ret = FAIL;
109 if (param == PARAM_0) {
110 hcreate(PARAM_8);
111 errno = ERRON_0;
112 hdestroy();
113 }
114 if (errno == ERRON_0) {
115 ret = NOERR;
116 }
117
118 napi_value result = nullptr;
119 napi_create_int32(env, ret, &result);
120 return result;
121 }
122
HdestroyR(napi_env env,napi_callback_info info)123 static napi_value HdestroyR(napi_env env, napi_callback_info info)
124 {
125 size_t argc = PARAM_1;
126 napi_value args[1] = {nullptr};
127 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
128 int param;
129 napi_get_value_int32(env, args[0], ¶m);
130
131 int ret = FAIL;
132 struct hsearch_data data;
133 if (param == PARAM_0) {
134 hcreate_r(PARAM_8, &data);
135 errno = ERRON_0;
136 hdestroy_r(&data);
137 }
138 if (errno == ERRON_0) {
139 ret = NOERR;
140 }
141
142 napi_value result = nullptr;
143 napi_create_int32(env, ret, &result);
144 return result;
145 }
146
147 static char data[][30] = {"test_search_1", "test_search_2"};
148
Hsearch(napi_env env,napi_callback_info info)149 static napi_value Hsearch(napi_env env, napi_callback_info info)
150 {
151 size_t argc = PARAM_1;
152 napi_value args[1] = {nullptr};
153 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
154 int param;
155 napi_get_value_int32(env, args[0], ¶m);
156
157 int ret;
158 ENTRY e;
159 ENTRY *ep;
160 int i;
161 hcreate(PARAM_2);
162 for (i = PARAM_0; i < PARAM_2; i++) {
163 e.key = data[i];
164 e.data = (void *)i;
165 ep = hsearch(e, ENTER);
166 if (ep == nullptr) {
167 ret = FAIL;
168 goto exit;
169 }
170 }
171
172 if (param == PARAM_0) {
173 for (i = PARAM_0; i < PARAM_2; i++) {
174 e.key = data[i];
175 ep = hsearch(e, FIND);
176 if (ep == nullptr) {
177 ret = FAIL;
178 goto exit;
179 }
180 }
181 ret = NOERR;
182 } else {
183 char key[] = "test_search_null";
184 e.key = key;
185 ep = hsearch(e, FIND);
186 if (ep == nullptr) {
187 ret = FAIL;
188 } else {
189 ret = NOERR;
190 }
191 }
192
193 exit:
194 hdestroy();
195 napi_value result = nullptr;
196 napi_create_int32(env, ret, &result);
197 return result;
198 }
199
HsearchR(napi_env env,napi_callback_info info)200 static napi_value HsearchR(napi_env env, napi_callback_info info)
201 {
202 size_t argc = PARAM_1;
203 napi_value args[1] = {nullptr};
204 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
205 int param;
206 napi_get_value_int32(env, args[0], ¶m);
207
208 int ret;
209 struct hsearch_data hdata = {};
210 ENTRY e;
211 ENTRY *ep;
212 hcreate_r(PARAM_2, &hdata);
213 for (int i = PARAM_0; i < PARAM_2; i++) {
214 e.key = data[i];
215 e.data = (void *)i;
216 ret = hsearch_r(e, ENTER, &ep, &hdata);
217 if (ret == PARAM_0) {
218 ret = FAIL;
219 goto exit;
220 }
221 }
222 if (param == PARAM_0) {
223 for (int i = PARAM_0; i < PARAM_2; i++) {
224 e.key = data[i];
225 ret = hsearch_r(e, FIND, &ep, &hdata);
226 if (ret == PARAM_0) {
227 ret = FAIL;
228 goto exit;
229 }
230 }
231 ret = NOERR;
232 } else {
233 char key[] = "test_search_null";
234 e.key = key;
235 ret = hsearch_r(e, FIND, &ep, &hdata);
236 if (ret == PARAM_0) {
237 ret = FAIL;
238 } else {
239 ret = NOERR;
240 }
241 }
242
243 exit:
244 hdestroy_r(&hdata);
245 napi_value result = nullptr;
246 napi_create_int32(env, ret, &result);
247 return result;
248 }
249
250 struct element {
251 struct element *prev;
252 struct element *next;
253 int i;
254 };
255
new_element(int i)256 static struct element *new_element(int i)
257 {
258 struct element *e = (struct element *)malloc(sizeof(struct element));
259 e->i = i;
260 return e;
261 }
262
Insque(napi_env env,napi_callback_info info)263 static napi_value Insque(napi_env env, napi_callback_info info)
264 {
265 int ret = NOERR;
266 int i;
267 struct element *elem = new_element(PARAM_0);
268 insque(elem, PARAM_0);
269 for (i = PARAM_1; i < PARAM_3; i++) {
270 insque(new_element(i), elem);
271 elem = elem->prev;
272 }
273 while (elem) {
274 if (elem->i != --i) {
275 ret = FAIL;
276 }
277 elem = elem->next;
278 }
279
280 napi_value result = nullptr;
281 napi_create_int32(env, ret, &result);
282 return result;
283 }
284
compare(const void * pa,const void * pb)285 static int compare(const void *pa, const void *pb)
286 {
287 if (*static_cast<const int *>(pa)< *static_cast<const int *>(pb))
288 return PARAM_UNNORMAL;
289 if (*static_cast<const int *>(pa)> *static_cast<const int *>(pb))
290 return PARAM_1;
291 return PARAM_0;
292 }
293
Lfind(napi_env env,napi_callback_info info)294 static napi_value Lfind(napi_env env, napi_callback_info info)
295 {
296 size_t argc = PARAM_1;
297 napi_value args[1] = {nullptr};
298 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
299 int param;
300 napi_get_value_int32(env, args[0], ¶m);
301
302 int *ret;
303 int key;
304 int array[5] = {1, 2, 3, 4, 5};
305 size_t nlength = PARAM_5;
306 if (param == PARAM_0) {
307 key = PARAM_5;
308 } else {
309 key = PARAM_0;
310 }
311 ret = static_cast<int*>(lfind(&key, array, &nlength, sizeof(int), compare));
312
313 napi_value result = nullptr;
314 if (!ret) {
315 napi_create_int32(env, FAIL, &result);
316 } else {
317 napi_create_int32(env, NOERR, &result);
318 }
319 return result;
320 }
321
LSearch(napi_env env,napi_callback_info info)322 static napi_value LSearch(napi_env env, napi_callback_info info)
323 {
324 size_t argc = PARAM_1;
325 napi_value args[1] = {nullptr};
326 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
327 int param;
328 napi_get_value_int32(env, args[0], ¶m);
329
330 int *ret = nullptr;
331 int key = PARAM_5;
332 int array[5] = {1, 2, 3, 4, 5};
333 size_t nlength = PARAM_5;
334 if (param == PARAM_0) {
335 ret = static_cast<int*>(lsearch(&key, array, &nlength, sizeof(int), compare));
336 }
337
338 napi_value result = nullptr;
339 if (!ret) {
340 napi_create_int32(env, FAIL, &result);
341 } else {
342 napi_create_int32(env, NOERR, &result);
343 }
344 return result;
345 }
346
Remque(napi_env env,napi_callback_info info)347 static napi_value Remque(napi_env env, napi_callback_info info)
348 {
349 int ret = NOERR;
350 int i;
351 struct element *elem = new_element(PARAM_0);
352 insque(elem, PARAM_0);
353 for (i = PARAM_1; i < PARAM_5; i++) {
354 insque(new_element(i), elem);
355 elem = elem->prev;
356 }
357 remque(elem->next);
358 if (elem->next->i != elem->i - PARAM_2) {
359 ret = FAIL;
360 }
361 if (elem->next->prev->i != elem->i) {
362 ret = FAIL;
363 }
364
365 napi_value result = nullptr;
366 napi_create_int32(env, ret, &result);
367 return result;
368 }
369
370 struct PodNode {
PodNodePodNode371 explicit PodNode(int i) : i(i) {}
372 int i;
373 };
PodNode_cmp(const void * lhs,const void * rhs)374 static int PodNode_cmp(const void *lhs, const void *rhs)
375 {
376 return reinterpret_cast<const PodNode *>(rhs)->i - reinterpret_cast<const PodNode *>(lhs)->i;
377 }
378
Tdelete(napi_env env,napi_callback_info info)379 static napi_value Tdelete(napi_env env, napi_callback_info info)
380 {
381 size_t argc = PARAM_1;
382 napi_value args[1] = {nullptr};
383 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
384 int param;
385 napi_get_value_int32(env, args[0], ¶m);
386
387 int ret = NOERR;
388 void *root = nullptr;
389 PodNode n1(PARAM_123);
390 tsearch(&n1, &root, PodNode_cmp);
391 if (param == PARAM_0) {
392 if (tdelete(&n1, &root, PodNode_cmp) == nullptr) {
393 ret = FAIL;
394 }
395 } else {
396 PodNode not_there(PARAM_456);
397 if (tdelete(¬_there, &root, PodNode_cmp) == nullptr) {
398 ret = FAIL;
399 }
400 }
401
402 napi_value result = nullptr;
403 napi_create_int32(env, ret, &result);
404 return result;
405 }
406
407 struct Node {
NodeNode408 explicit Node(const char *s) : s(strdup(s)) {}
409 char *s;
410 };
NodeCmp(const void * lhs,const void * rhs)411 static int NodeCmp(const void *lhs, const void *rhs)
412 {
413 return strcmp(reinterpret_cast<const Node *>(lhs)->s, reinterpret_cast<const Node *>(rhs)->s);
414 }
415 static size_t g_freeCalls;
node_free(void * p)416 static void node_free(void *p)
417 {
418 Node *n = reinterpret_cast<Node *>(p);
419 free(n->s);
420 ++g_freeCalls;
421 }
Tdestroy(napi_env env,napi_callback_info info)422 static napi_value Tdestroy(napi_env env, napi_callback_info info)
423 {
424 int ret = FAIL;
425 void *root = nullptr;
426 Node n1("z");
427 Node n2("a");
428 Node n3("m");
429 tsearch(&n1, &root, NodeCmp);
430 tsearch(&n2, &root, NodeCmp);
431 tsearch(&n3, &root, NodeCmp);
432 g_freeCalls = PARAM_0;
433 tdestroy(root, node_free);
434 if (g_freeCalls == 3U) {
435 ret = NOERR;
436 }
437 g_freeCalls = PARAM_0;
438
439 napi_value result = nullptr;
440 napi_create_int32(env, ret, &result);
441 return result;
442 }
443
Tfind(napi_env env,napi_callback_info info)444 static napi_value Tfind(napi_env env, napi_callback_info info)
445 {
446 size_t argc = PARAM_1;
447 napi_value args[1] = {nullptr};
448 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
449 int param;
450 napi_get_value_int32(env, args[0], ¶m);
451
452 int ret = NOERR;
453 void *root = nullptr;
454 Node n1("z");
455 if (param == PARAM_0) {
456 void *i1 = tsearch(&n1, &root, NodeCmp);
457 if (tfind(&n1, &root, NodeCmp) != i1) {
458 ret = FAIL;
459 }
460 } else {
461 if (tfind(&n1, &root, NodeCmp) == nullptr) {
462 ret = FAIL;
463 }
464 }
465 tdestroy(root, node_free);
466 g_freeCalls = PARAM_0;
467 napi_value result = nullptr;
468 napi_create_int32(env, ret, &result);
469 return result;
470 }
471
Tsearch(napi_env env,napi_callback_info info)472 static napi_value Tsearch(napi_env env, napi_callback_info info)
473 {
474 int ret = NOERR;
475 void *root = nullptr;
476 Node n1("z");
477 void *i1 = tsearch(&n1, &root, NodeCmp);
478 if (i1 == nullptr) {
479 ret = FAIL;
480 }
481 tdestroy(root, node_free);
482 g_freeCalls = PARAM_0;
483
484 napi_value result = nullptr;
485 napi_create_int32(env, ret, &result);
486 return result;
487 }
488
489 static std::vector<std::string> g_nodes;
NodeWalk(const void * p,VISIT order,int)490 static void NodeWalk(const void *p, VISIT order, int)
491 {
492 const Node *n = *reinterpret_cast<const Node *const *>(p);
493 if (order == postorder || order == leaf) {
494 g_nodes.push_back(n->s);
495 }
496 }
Twalk(napi_env env,napi_callback_info info)497 static napi_value Twalk(napi_env env, napi_callback_info info)
498 {
499 int ret = FAIL;
500 void *root = nullptr;
501
502 Node n1("z");
503 Node n2("a");
504 Node n3("m");
505 tsearch(&n1, &root, NodeCmp);
506 tsearch(&n2, &root, NodeCmp);
507 tsearch(&n3, &root, NodeCmp);
508
509 g_nodes.clear();
510 twalk(root, NodeWalk);
511 if (g_nodes.size() == 3U) {
512 ret = NOERR;
513 }
514
515 tdestroy(root, node_free);
516 g_freeCalls = PARAM_0;
517 napi_value result = nullptr;
518 napi_create_int32(env, ret, &result);
519 return result;
520 }
521
522 EXTERN_C_START
Init(napi_env env,napi_value exports)523 static napi_value Init(napi_env env, napi_value exports)
524 {
525 napi_property_descriptor desc[] = {
526 {"hcreate", nullptr, Hcreate, nullptr, nullptr, nullptr, napi_default, nullptr},
527 {"hcreateR", nullptr, HcreateR, nullptr, nullptr, nullptr, napi_default, nullptr},
528 {"hdestroy", nullptr, Hdestroy, nullptr, nullptr, nullptr, napi_default, nullptr},
529 {"hdestroyR", nullptr, HdestroyR, nullptr, nullptr, nullptr, napi_default, nullptr},
530 {"hsearch", nullptr, Hsearch, nullptr, nullptr, nullptr, napi_default, nullptr},
531 {"hsearchR", nullptr, HsearchR, nullptr, nullptr, nullptr, napi_default, nullptr},
532 {"insque", nullptr, Insque, nullptr, nullptr, nullptr, napi_default, nullptr},
533 {"lfind", nullptr, Lfind, nullptr, nullptr, nullptr, napi_default, nullptr},
534 {"lSearch", nullptr, LSearch, nullptr, nullptr, nullptr, napi_default, nullptr},
535 {"remque", nullptr, Remque, nullptr, nullptr, nullptr, napi_default, nullptr},
536 {"tdelete", nullptr, Tdelete, nullptr, nullptr, nullptr, napi_default, nullptr},
537 {"tdestroy", nullptr, Tdestroy, nullptr, nullptr, nullptr, napi_default, nullptr},
538 {"tfind", nullptr, Tfind, nullptr, nullptr, nullptr, napi_default, nullptr},
539 {"tsearch", nullptr, Tsearch, nullptr, nullptr, nullptr, napi_default, nullptr},
540 {"twalk", nullptr, Twalk, nullptr, nullptr, nullptr, napi_default, nullptr},
541 };
542 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
543 return exports;
544 }
545
546 EXTERN_C_END
547
548 static napi_module demoModule = {
549 .nm_version = 1,
550 .nm_flags = 0,
551 .nm_filename = "searchndk1",
552 .nm_register_func = Init,
553 .nm_modname = "libsearchndk1",
554 .nm_priv = ((void *)0),
555 .reserved = {0},
556 };
557
RegisterEntryModule(void)558 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
559