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