1 /*
2 * Copyright (C) 2018-2021 Alexander Borisov
3 *
4 * Author: Alexander Borisov <borisov@lexbor.com>
5 */
6
7 #ifndef LEXBOR_DOM_ATTR_H
8 #define LEXBOR_DOM_ATTR_H
9
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13
14 #include "lexbor/core/hash.h"
15 #include "lexbor/core/str.h"
16
17 #include "lexbor/ns/ns.h"
18
19 #include "lexbor/dom/interface.h"
20 #include "lexbor/dom/interfaces/node.h"
21 #include "lexbor/dom/interfaces/attr_const.h"
22 #include "lexbor/dom/interfaces/document.h"
23
24
25 typedef struct {
26 lexbor_hash_entry_t entry;
27 lxb_dom_attr_id_t attr_id;
28 size_t ref_count;
29 bool read_only;
30 }
31 lxb_dom_attr_data_t;
32
33 /* More memory to God of memory! */
34 struct lxb_dom_attr {
35 lxb_dom_node_t node;
36
37 /* For example: <LalAla:DiV Fix:Me="value"> */
38
39 lxb_dom_attr_id_t upper_name; /* uppercase, with prefix: FIX:ME */
40 lxb_dom_attr_id_t qualified_name; /* original, with prefix: Fix:Me */
41
42 lexbor_str_t *value;
43
44 lxb_dom_element_t *owner;
45
46 lxb_dom_attr_t *next;
47 lxb_dom_attr_t *prev;
48 };
49
50
51 LXB_API lxb_dom_attr_t *
52 lxb_dom_attr_interface_create(lxb_dom_document_t *document);
53
54 LXB_API lxb_dom_attr_t *
55 lxb_dom_attr_interface_clone(lxb_dom_document_t *document,
56 const lxb_dom_attr_t *attr);
57
58 LXB_API lxb_dom_attr_t *
59 lxb_dom_attr_interface_destroy(lxb_dom_attr_t *attr);
60
61 LXB_API lxb_status_t
62 lxb_dom_attr_set_name(lxb_dom_attr_t *attr, const lxb_char_t *local_name,
63 size_t local_name_len, bool to_lowercase);
64
65 LXB_API lxb_status_t
66 lxb_dom_attr_set_value(lxb_dom_attr_t *attr,
67 const lxb_char_t *value, size_t value_len);
68
69 LXB_API lxb_status_t
70 lxb_dom_attr_set_value_wo_copy(lxb_dom_attr_t *attr,
71 lxb_char_t *value, size_t value_len);
72
73 LXB_API lxb_status_t
74 lxb_dom_attr_set_existing_value(lxb_dom_attr_t *attr,
75 const lxb_char_t *value, size_t value_len);
76
77 LXB_API lxb_status_t
78 lxb_dom_attr_clone_name_value(lxb_dom_attr_t *attr_from,
79 lxb_dom_attr_t *attr_to);
80
81 LXB_API bool
82 lxb_dom_attr_compare(lxb_dom_attr_t *first, lxb_dom_attr_t *second);
83
84 LXB_API void
85 lxb_dom_attr_remove(lxb_dom_attr_t *attr);
86
87 LXB_API const lxb_dom_attr_data_t *
88 lxb_dom_attr_data_undef(void);
89
90 LXB_API const lxb_dom_attr_data_t *
91 lxb_dom_attr_data_by_id(lexbor_hash_t *hash, lxb_dom_attr_id_t attr_id);
92
93 LXB_API const lxb_dom_attr_data_t *
94 lxb_dom_attr_data_by_local_name(lexbor_hash_t *hash,
95 const lxb_char_t *name, size_t length);
96
97 LXB_API const lxb_dom_attr_data_t *
98 lxb_dom_attr_data_by_qualified_name(lexbor_hash_t *hash,
99 const lxb_char_t *name, size_t length);
100
101 LXB_API const lxb_char_t *
102 lxb_dom_attr_qualified_name(lxb_dom_attr_t *attr, size_t *len);
103
104
105 /*
106 * Inline functions
107 */
108 lxb_inline const lxb_char_t *
lxb_dom_attr_local_name(lxb_dom_attr_t * attr,size_t * len)109 lxb_dom_attr_local_name(lxb_dom_attr_t *attr, size_t *len)
110 {
111 const lxb_dom_attr_data_t *data;
112
113 data = lxb_dom_attr_data_by_id(attr->node.owner_document->attrs,
114 attr->node.local_name);
115
116 if (len != NULL) {
117 *len = data->entry.length;
118 }
119
120 return lexbor_hash_entry_str(&data->entry);
121 }
122
123 lxb_inline const lxb_char_t *
lxb_dom_attr_value(lxb_dom_attr_t * attr,size_t * len)124 lxb_dom_attr_value(lxb_dom_attr_t *attr, size_t *len)
125 {
126 if (attr->value == NULL) {
127 if (len != NULL) {
128 *len = 0;
129 }
130
131 return NULL;
132 }
133
134 if (len != NULL) {
135 *len = attr->value->length;
136 }
137
138 return attr->value->data;
139 }
140
141 /*
142 * No inline functions for ABI.
143 */
144 LXB_API const lxb_char_t *
145 lxb_dom_attr_local_name_noi(lxb_dom_attr_t *attr, size_t *len);
146
147 LXB_API const lxb_char_t *
148 lxb_dom_attr_value_noi(lxb_dom_attr_t *attr, size_t *len);
149
150
151 #ifdef __cplusplus
152 } /* extern "C" */
153 #endif
154
155 #endif /* LEXBOR_DOM_ATTR_H */
156