1 /*
2  * Copyright (C) 2021 Alexander Borisov
3  *
4  * Author: Alexander Borisov <borisov@lexbor.com>
5  */
6 
7 #ifndef LEXBOR_CSS_SELECTORS_SELECTOR_H
8 #define LEXBOR_CSS_SELECTORS_SELECTOR_H
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #include "lexbor/core/str.h"
15 #include "lexbor/css/selectors/base.h"
16 #include "lexbor/css/syntax/anb.h"
17 
18 
19 typedef enum {
20     LXB_CSS_SELECTOR_TYPE__UNDEF = 0x00,
21     LXB_CSS_SELECTOR_TYPE_ANY,
22     LXB_CSS_SELECTOR_TYPE_ELEMENT,                 /* div, tag name <div> */
23     LXB_CSS_SELECTOR_TYPE_ID,                      /* #hash */
24     LXB_CSS_SELECTOR_TYPE_CLASS,                   /* .class */
25     LXB_CSS_SELECTOR_TYPE_ATTRIBUTE,               /* [key=val], <... key="val"> */
26     LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS,            /* :pseudo */
27     LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS_FUNCTION,   /* :function(...) */
28     LXB_CSS_SELECTOR_TYPE_PSEUDO_ELEMENT,          /* ::pseudo */
29     LXB_CSS_SELECTOR_TYPE_PSEUDO_ELEMENT_FUNCTION, /* ::function(...) */
30     LXB_CSS_SELECTOR_TYPE__LAST_ENTRY
31 }
32 lxb_css_selector_type_t;
33 
34 typedef enum {
35     LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT = 0x00, /* WHITESPACE */
36     LXB_CSS_SELECTOR_COMBINATOR_CLOSE,             /* two compound selectors [key=val].foo */
37     LXB_CSS_SELECTOR_COMBINATOR_CHILD,             /* '>' */
38     LXB_CSS_SELECTOR_COMBINATOR_SIBLING,           /* '+' */
39     LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING,         /* '~' */
40     LXB_CSS_SELECTOR_COMBINATOR_CELL,              /* '||' */
41     LXB_CSS_SELECTOR_COMBINATOR__LAST_ENTRY
42 }
43 lxb_css_selector_combinator_t;
44 
45 typedef enum {
46     LXB_CSS_SELECTOR_MATCH_EQUAL = 0x00,  /*  = */
47     LXB_CSS_SELECTOR_MATCH_INCLUDE,       /* ~= */
48     LXB_CSS_SELECTOR_MATCH_DASH,          /* |= */
49     LXB_CSS_SELECTOR_MATCH_PREFIX,        /* ^= */
50     LXB_CSS_SELECTOR_MATCH_SUFFIX,        /* $= */
51     LXB_CSS_SELECTOR_MATCH_SUBSTRING,     /* *= */
52     LXB_CSS_SELECTOR_MATCH__LAST_ENTRY
53 }
54 lxb_css_selector_match_t;
55 
56 typedef enum {
57     LXB_CSS_SELECTOR_MODIFIER_UNSET = 0x00,
58     LXB_CSS_SELECTOR_MODIFIER_I,
59     LXB_CSS_SELECTOR_MODIFIER_S,
60     LXB_CSS_SELECTOR_MODIFIER__LAST_ENTRY
61 }
62 lxb_css_selector_modifier_t;
63 
64 typedef struct {
65     lxb_css_selector_match_t    match;
66     lxb_css_selector_modifier_t modifier;
67     lexbor_str_t                value;
68 }
69 lxb_css_selector_attribute_t;
70 
71 typedef struct {
72     unsigned type;
73     void     *data;
74 }
75 lxb_css_selector_pseudo_t;
76 
77 typedef struct {
78     lxb_css_syntax_anb_t          anb;
79     lxb_css_selector_list_t       *of;
80 }
81 lxb_css_selector_anb_of_t;
82 
83 struct lxb_css_selector {
84     lxb_css_selector_type_t       type;
85     lxb_css_selector_combinator_t combinator;
86 
87     lexbor_str_t                  name;
88     lexbor_str_t                  ns;
89 
90     union lxb_css_selector_u {
91         lxb_css_selector_attribute_t attribute;
92         lxb_css_selector_pseudo_t    pseudo;
93     }
94     u;
95 
96     lxb_css_selector_t            *next;
97     lxb_css_selector_t            *prev;
98 
99     lxb_css_selector_list_t       *list;
100 };
101 
102 
103 /*
104  *   I       S       A       B       C
105  * 1 bit | 1 bit | 9 bit | 9 bit | 9 bit
106  */
107 typedef uint32_t lxb_css_selector_specificity_t;
108 
109 #define LXB_CSS_SELECTOR_SPECIFICITY_MASK_N(sp, n)                            \
110     ((sp) & ~((((uint32_t) 1 << 9) - 1) << (n)))
111 
112 #define LXB_CSS_SELECTOR_SPECIFICITY_MASK                                     \
113     ((((uint32_t) 1 << 31) - 1) << (9))
114 
115 #define lxb_css_selector_sp_i(sp)  ((sp) >> 28)
116 
117 #define lxb_css_selector_sp_s(sp)                                             \
118     (((sp) >> 27) & ~((((uint32_t) 1 << 31) - 1) << (1)))
119 
120 #define lxb_css_selector_sp_a(sp)                                             \
121     (((sp) >> 18) & ~LXB_CSS_SELECTOR_SPECIFICITY_MASK)
122 
123 #define lxb_css_selector_sp_b(sp)                                             \
124     (((sp) >> 9) & ~LXB_CSS_SELECTOR_SPECIFICITY_MASK)
125 
126 #define lxb_css_selector_sp_c(sp)                                             \
127     ((sp) & ~LXB_CSS_SELECTOR_SPECIFICITY_MASK)
128 
129 #define lxb_css_selector_sp_set_i(sp, num)                                    \
130     sp = (LXB_CSS_SELECTOR_SPECIFICITY_MASK_N((sp), 28) | ((num) << 28))
131 
132 #define lxb_css_selector_sp_set_s(sp, num)                                    \
133     sp = (LXB_CSS_SELECTOR_SPECIFICITY_MASK_N((sp), 27) | ((num) << 27))
134 
135 #define lxb_css_selector_sp_set_a(sp, num)                                    \
136     sp = (LXB_CSS_SELECTOR_SPECIFICITY_MASK_N((sp), 18) | ((num) << 18))
137 
138 #define lxb_css_selector_sp_set_b(sp, num)                                    \
139     sp = (LXB_CSS_SELECTOR_SPECIFICITY_MASK_N((sp), 9) | ((num) << 9))
140 
141 #define lxb_css_selector_sp_set_c(sp, num)                                    \
142     sp = (LXB_CSS_SELECTOR_SPECIFICITY_MASK_N((sp), 0) | (num))
143 
144 #define lxb_css_selector_sp_add_s(sp, num)                                   \
145     (lxb_css_selector_sp_set_s((sp), lxb_css_selector_sp_s(sp) + num))
146 
147 #define lxb_css_selector_sp_add_a(sp, num)                                   \
148     (lxb_css_selector_sp_set_a((sp), lxb_css_selector_sp_a(sp) + num))
149 
150 #define lxb_css_selector_sp_add_b(sp, num)                                   \
151     (lxb_css_selector_sp_set_b((sp), lxb_css_selector_sp_b(sp) + num))
152 
153 #define lxb_css_selector_sp_add_c(sp, num)                                   \
154     (lxb_css_selector_sp_set_c((sp), lxb_css_selector_sp_c(sp) + num))
155 
156 #define lxb_css_selector_sp_up_i(num)  (num | (1 << 28))
157 #define lxb_css_selector_sp_up_s(num)  (num | (1 << 27))
158 
159 #define LXB_CSS_SELECTOR_SP_S_MAX  ((1 << 28) - 1)
160 #define LXB_CSS_SELECTOR_SP_A_MAX  ((1 << 27) - 1)
161 #define LXB_CSS_SELECTOR_SP_B_MAX  ((1 << 18) - 1)
162 #define LXB_CSS_SELECTOR_SP_C_MAX  ((1 <<  9) - 1)
163 
164 
165 struct lxb_css_selector_list {
166     lxb_css_selector_t             *first;
167     lxb_css_selector_t             *last;
168 
169     lxb_css_selector_t             *parent;
170 
171     lxb_css_selector_list_t        *next;
172     lxb_css_selector_list_t        *prev;
173 
174     lxb_css_memory_t               *memory;
175 
176     lxb_css_selector_specificity_t specificity;
177 };
178 
179 
180 LXB_API lxb_css_selector_t *
181 lxb_css_selector_create(lxb_css_selector_list_t *list);
182 
183 LXB_API void
184 lxb_css_selector_destroy(lxb_css_selector_t *selector);
185 
186 LXB_API void
187 lxb_css_selector_destroy_chain(lxb_css_selector_t *selector);
188 
189 LXB_API void
190 lxb_css_selector_remove(lxb_css_selector_t *selector);
191 
192 LXB_API lxb_css_selector_list_t *
193 lxb_css_selector_list_create(lxb_css_memory_t *mem);
194 
195 LXB_API void
196 lxb_css_selector_list_remove(lxb_css_selector_list_t *list);
197 
198 LXB_API void
199 lxb_css_selector_list_selectors_remove(lxb_css_selectors_t *selectors,
200                                        lxb_css_selector_list_t *list);
201 
202 LXB_API void
203 lxb_css_selector_list_destroy(lxb_css_selector_list_t *list);
204 
205 LXB_API void
206 lxb_css_selector_list_destroy_chain(lxb_css_selector_list_t *list);
207 
208 LXB_API void
209 lxb_css_selector_list_destroy_memory(lxb_css_selector_list_t *list);
210 
211 LXB_API lxb_status_t
212 lxb_css_selector_serialize(lxb_css_selector_t *selector,
213                            lexbor_serialize_cb_f cb, void *ctx);
214 
215 LXB_API lxb_status_t
216 lxb_css_selector_serialize_chain(lxb_css_selector_t *selector,
217                                  lexbor_serialize_cb_f cb, void *ctx);
218 
219 LXB_API lxb_char_t *
220 lxb_css_selector_serialize_chain_char(lxb_css_selector_t *selector,
221                                       size_t *out_length);
222 
223 LXB_API lxb_status_t
224 lxb_css_selector_serialize_list(lxb_css_selector_list_t *list,
225                                     lexbor_serialize_cb_f cb, void *ctx);
226 
227 LXB_API lxb_status_t
228 lxb_css_selector_serialize_list_chain(lxb_css_selector_list_t *list,
229                                       lexbor_serialize_cb_f cb, void *ctx);
230 
231 LXB_API lxb_char_t *
232 lxb_css_selector_serialize_list_chain_char(lxb_css_selector_list_t *list,
233                                            size_t *out_length);
234 
235 LXB_API lxb_status_t
236 lxb_css_selector_serialize_anb_of(lxb_css_selector_anb_of_t *anbof,
237                                   lexbor_serialize_cb_f cb, void *ctx);
238 
239 LXB_API lxb_char_t *
240 lxb_css_selector_combinator(lxb_css_selector_t *selector, size_t *out_length);
241 
242 LXB_API void
243 lxb_css_selector_list_append(lxb_css_selector_list_t *list,
244                              lxb_css_selector_t *selector);
245 
246 LXB_API void
247 lxb_css_selector_list_append_next(lxb_css_selector_list_t *dist,
248                                   lxb_css_selector_list_t *src);
249 
250 LXB_API void
251 lxb_css_selector_append_next(lxb_css_selector_t *dist, lxb_css_selector_t *src);
252 
253 
254 #ifdef __cplusplus
255 } /* extern "C" */
256 #endif
257 
258 #endif /* LEXBOR_CSS_SELECTORS_SELECTOR_H */
259