xref: /php-src/ext/dom/lexbor/lexbor/core/shs.c (revision bffab33a)
1 /*
2  * Copyright (C) 2018-2019 Alexander Borisov
3  *
4  * Author: Alexander Borisov <borisov@lexbor.com>
5  */
6 
7 #include "lexbor/core/shs.h"
8 #include "lexbor/core/str.h"
9 
10 #define LEXBOR_STR_RES_MAP_LOWERCASE
11 #define LEXBOR_STR_RES_MAP_UPPERCASE
12 #include "lexbor/core/str_res.h"
13 
14 
15 #define lexbor_shs_make_id_m(key, size, table_size)                            \
16     (((((key[0] * key[size - 1]) * key[0]) + size) % table_size) + 0x01)
17 
18 #define lexbor_shs_make_id_lower_m(key, size, table_size)                      \
19     (((((lexbor_str_res_map_lowercase[key[0]]                                  \
20      * lexbor_str_res_map_lowercase[key[size - 1]])                            \
21      * lexbor_str_res_map_lowercase[key[0]])                                   \
22      + size)                                                                   \
23      % table_size) + 0x01)
24 
25 #define lexbor_shs_make_id_upper_m(key, size, table_size)                      \
26     (((((lexbor_str_res_map_uppercase[key[0]]                                  \
27      * lexbor_str_res_map_uppercase[key[size - 1]])                            \
28      * lexbor_str_res_map_uppercase[key[0]])                                   \
29      + size)                                                                   \
30      % table_size) + 0x01)
31 
32 
33 const lexbor_shs_entry_t *
lexbor_shs_entry_get_static(const lexbor_shs_entry_t * root,const lxb_char_t * key,size_t key_len)34 lexbor_shs_entry_get_static(const lexbor_shs_entry_t *root,
35                             const lxb_char_t *key, size_t key_len)
36 {
37     const lexbor_shs_entry_t *entry;
38     entry = root + lexbor_shs_make_id_m(key, key_len, root->key_len);
39 
40     while (entry->key != NULL)
41     {
42         if (entry->key_len == key_len) {
43             if (lexbor_str_data_ncmp((const lxb_char_t *) entry->key,
44                                      key, key_len))
45             {
46                 return entry;
47             }
48 
49             entry = &root[entry->next];
50         }
51         else if (entry->key_len > key_len) {
52             return NULL;
53         }
54         else {
55             entry = &root[entry->next];
56         }
57     }
58 
59     return NULL;
60 }
61 
62 const lexbor_shs_entry_t *
lexbor_shs_entry_get_lower_static(const lexbor_shs_entry_t * root,const lxb_char_t * key,size_t key_len)63 lexbor_shs_entry_get_lower_static(const lexbor_shs_entry_t *root,
64                                   const lxb_char_t *key, size_t key_len)
65 {
66     const lexbor_shs_entry_t *entry;
67     entry = root + lexbor_shs_make_id_lower_m(key, key_len, root->key_len);
68 
69     while (entry->key != NULL)
70     {
71         if (entry->key_len == key_len) {
72             if (lexbor_str_data_nlocmp_right((const lxb_char_t *) entry->key,
73                                              key, key_len))
74             {
75                 return entry;
76             }
77 
78             entry = &root[entry->next];
79         }
80         else if (entry->key_len > key_len) {
81             return NULL;
82         }
83         else {
84             entry = &root[entry->next];
85         }
86     }
87 
88     return NULL;
89 }
90 
91 const lexbor_shs_entry_t *
lexbor_shs_entry_get_upper_static(const lexbor_shs_entry_t * root,const lxb_char_t * key,size_t key_len)92 lexbor_shs_entry_get_upper_static(const lexbor_shs_entry_t *root,
93                                   const lxb_char_t *key, size_t key_len)
94 {
95     const lexbor_shs_entry_t *entry;
96     entry = root + lexbor_shs_make_id_upper_m(key, key_len, root->key_len);
97 
98     while (entry->key != NULL)
99     {
100         if (entry->key_len == key_len) {
101             if (lexbor_str_data_nupcmp_right((const lxb_char_t *) entry->key,
102                                              key, key_len))
103             {
104                 return entry;
105             }
106 
107             entry = &root[entry->next];
108         }
109         else if (entry->key_len > key_len) {
110             return NULL;
111         }
112         else {
113             entry = &root[entry->next];
114         }
115     }
116 
117     return NULL;
118 }
119