1 /*
2 * Copyright (C) 2018-2023 Alexander Borisov
3 *
4 * Author: Alexander Borisov <borisov@lexbor.com>
5 */
6
7 #ifndef LEXBOR_STR_H
8 #define LEXBOR_STR_H
9
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13
14 #include "lexbor/core/base.h"
15 #include "lexbor/core/mraw.h"
16 #include "lexbor/core/utils.h"
17
18
19 #define lexbor_str_get(str, attr) str->attr
20 #define lexbor_str_set(str, attr) lexbor_str_get(str, attr)
21 #define lexbor_str_len(str) lexbor_str_get(str, length)
22 #define lexbor_str(p) {.data = (lxb_char_t *) (p), sizeof(p) - 1}
23
24
25 #define lexbor_str_check_size_arg_m(str, size, mraw, plus_len, return_fail) \
26 do { \
27 void *tmp; \
28 \
29 if (str->length > (SIZE_MAX - (plus_len))) \
30 return (return_fail); \
31 \
32 if ((str->length + (plus_len)) > (size)) { \
33 tmp = lexbor_mraw_realloc(mraw, str->data, \
34 (str->length + plus_len)); \
35 \
36 if (tmp == NULL) { \
37 return (return_fail); \
38 } \
39 \
40 str->data = (lxb_char_t *) tmp; \
41 } \
42 } \
43 while (0)
44
45
46 typedef struct {
47 lxb_char_t *data;
48 size_t length;
49 }
50 lexbor_str_t;
51
52
53 LXB_API lexbor_str_t *
54 lexbor_str_create(void);
55
56 LXB_API lxb_char_t *
57 lexbor_str_init(lexbor_str_t *str, lexbor_mraw_t *mraw, size_t size);
58
59 LXB_API lxb_char_t *
60 lexbor_str_init_append(lexbor_str_t *str, lexbor_mraw_t *mraw,
61 const lxb_char_t *data, size_t length);
62
63 LXB_API void
64 lexbor_str_clean(lexbor_str_t *str);
65
66 LXB_API void
67 lexbor_str_clean_all(lexbor_str_t *str);
68
69 LXB_API lexbor_str_t *
70 lexbor_str_destroy(lexbor_str_t *str, lexbor_mraw_t *mraw, bool destroy_obj);
71
72
73 LXB_API lxb_char_t *
74 lexbor_str_realloc(lexbor_str_t *str, lexbor_mraw_t *mraw, size_t new_size);
75
76 LXB_API lxb_char_t *
77 lexbor_str_check_size(lexbor_str_t *str, lexbor_mraw_t *mraw, size_t plus_len);
78
79 /* Append */
80 LXB_API lxb_char_t *
81 lexbor_str_append(lexbor_str_t *str, lexbor_mraw_t *mraw,
82 const lxb_char_t *data, size_t length);
83
84 LXB_API lxb_char_t *
85 lexbor_str_append_before(lexbor_str_t *str, lexbor_mraw_t *mraw,
86 const lxb_char_t *buff, size_t length);
87
88 LXB_API lxb_char_t *
89 lexbor_str_append_one(lexbor_str_t *str, lexbor_mraw_t *mraw,
90 const lxb_char_t data);
91
92 LXB_API lxb_char_t *
93 lexbor_str_append_lowercase(lexbor_str_t *str, lexbor_mraw_t *mraw,
94 const lxb_char_t *data, size_t length);
95
96 LXB_API lxb_char_t *
97 lexbor_str_append_with_rep_null_chars(lexbor_str_t *str, lexbor_mraw_t *mraw,
98 const lxb_char_t *buff, size_t length);
99
100 /* Other functions */
101 LXB_API lxb_char_t *
102 lexbor_str_copy(lexbor_str_t *dest, const lexbor_str_t *target,
103 lexbor_mraw_t *mraw);
104
105 LXB_API void
106 lexbor_str_stay_only_whitespace(lexbor_str_t *target);
107
108 LXB_API void
109 lexbor_str_strip_collapse_whitespace(lexbor_str_t *target);
110
111 LXB_API size_t
112 lexbor_str_crop_whitespace_from_begin(lexbor_str_t *target);
113
114 LXB_API size_t
115 lexbor_str_whitespace_from_begin(lexbor_str_t *target);
116
117 LXB_API size_t
118 lexbor_str_whitespace_from_end(lexbor_str_t *target);
119
120
121 /* Data utils */
122 /*
123 * [in] first: must be null-terminated
124 * [in] sec: no matter what data
125 * [in] sec_size: size of the 'sec' buffer
126 *
127 * Function compare two lxb_char_t data until find '\0' in first arg.
128 * Successfully if the function returned a pointer starting with '\0',
129 * otherwise, if the data of the second buffer is insufficient function returned
130 * position in first buffer.
131 * If function returns NULL, the data are not equal.
132 */
133 LXB_API const lxb_char_t *
134 lexbor_str_data_ncasecmp_first(const lxb_char_t *first, const lxb_char_t *sec,
135 size_t sec_size);
136 LXB_API bool
137 lexbor_str_data_ncasecmp_end(const lxb_char_t *first, const lxb_char_t *sec,
138 size_t size);
139 LXB_API bool
140 lexbor_str_data_ncasecmp_contain(const lxb_char_t *where, size_t where_size,
141 const lxb_char_t *what, size_t what_size);
142 LXB_API bool
143 lexbor_str_data_ncasecmp(const lxb_char_t *first, const lxb_char_t *sec,
144 size_t size);
145 LXB_API bool
146 lexbor_str_data_nlocmp_right(const lxb_char_t *first, const lxb_char_t *sec,
147 size_t size);
148 LXB_API bool
149 lexbor_str_data_nupcmp_right(const lxb_char_t *first, const lxb_char_t *sec,
150 size_t size);
151 LXB_API bool
152 lexbor_str_data_casecmp(const lxb_char_t *first, const lxb_char_t *sec);
153
154 LXB_API bool
155 lexbor_str_data_ncmp_end(const lxb_char_t *first, const lxb_char_t *sec,
156 size_t size);
157 LXB_API bool
158 lexbor_str_data_ncmp_contain(const lxb_char_t *where, size_t where_size,
159 const lxb_char_t *what, size_t what_size);
160 LXB_API bool
161 lexbor_str_data_ncmp(const lxb_char_t *first, const lxb_char_t *sec,
162 size_t size);
163
164 LXB_API bool
165 lexbor_str_data_cmp(const lxb_char_t *first, const lxb_char_t *sec);
166
167 LXB_API bool
168 lexbor_str_data_cmp_ws(const lxb_char_t *first, const lxb_char_t *sec);
169
170 LXB_API void
171 lexbor_str_data_to_lowercase(lxb_char_t *to, const lxb_char_t *from, size_t len);
172
173 LXB_API void
174 lexbor_str_data_to_uppercase(lxb_char_t *to, const lxb_char_t *from, size_t len);
175
176 LXB_API const lxb_char_t *
177 lexbor_str_data_find_lowercase(const lxb_char_t *data, size_t len);
178
179 LXB_API const lxb_char_t *
180 lexbor_str_data_find_uppercase(const lxb_char_t *data, size_t len);
181
182
183 /*
184 * Inline functions
185 */
186 lxb_inline lxb_char_t *
lexbor_str_data(lexbor_str_t * str)187 lexbor_str_data(lexbor_str_t *str)
188 {
189 return str->data;
190 }
191
192 lxb_inline size_t
lexbor_str_length(lexbor_str_t * str)193 lexbor_str_length(lexbor_str_t *str)
194 {
195 return str->length;
196 }
197
198 lxb_inline size_t
lexbor_str_size(lexbor_str_t * str)199 lexbor_str_size(lexbor_str_t *str)
200 {
201 return lexbor_mraw_data_size(str->data);
202 }
203
204 lxb_inline void
lexbor_str_data_set(lexbor_str_t * str,lxb_char_t * data)205 lexbor_str_data_set(lexbor_str_t *str, lxb_char_t *data)
206 {
207 str->data = data;
208 }
209
210 lxb_inline lxb_char_t *
lexbor_str_length_set(lexbor_str_t * str,lexbor_mraw_t * mraw,size_t length)211 lexbor_str_length_set(lexbor_str_t *str, lexbor_mraw_t *mraw, size_t length)
212 {
213 if (length >= lexbor_str_size(str)) {
214 lxb_char_t *tmp;
215
216 tmp = lexbor_str_realloc(str, mraw, length + 1);
217 if (tmp == NULL) {
218 return NULL;
219 }
220 }
221
222 str->length = length;
223 str->data[length] = 0x00;
224
225 return str->data;
226 }
227
228 /*
229 * No inline functions for ABI.
230 */
231 LXB_API lxb_char_t *
232 lexbor_str_data_noi(lexbor_str_t *str);
233
234 LXB_API size_t
235 lexbor_str_length_noi(lexbor_str_t *str);
236
237 LXB_API size_t
238 lexbor_str_size_noi(lexbor_str_t *str);
239
240 LXB_API void
241 lexbor_str_data_set_noi(lexbor_str_t *str, lxb_char_t *data);
242
243 LXB_API lxb_char_t *
244 lexbor_str_length_set_noi(lexbor_str_t *str, lexbor_mraw_t *mraw,
245 size_t length);
246
247
248 #ifdef __cplusplus
249 } /* extern "C" */
250 #endif
251
252 #endif /* LEXBOR_STR_H */
253