• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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], &param);
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(&not_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], &param);
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