Print this page
Address Robert's feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libsysdemangle/common/str.c
+++ new/usr/src/lib/libsysdemangle/common/str.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright 2017 Jason King
14 14 */
15 15 #include <sys/debug.h>
16 16 #include <sys/sysmacros.h>
17 17 #include <string.h>
18 18 #include "str.h"
19 19 #include "sysdemangle_int.h"
20 20
21 21 #define STR_CHUNK_SZ (64U)
22 22
23 23 /* are we storing a reference vs. a dynamically allocated copy? */
24 24 #define IS_REF(s) ((s)->str_s != NULL && (s)->str_size == 0)
25 25
26 26 /*
27 27 * Dynamically resizeable strings, with lazy allocation when initialized
28 28 * with a constant string value
29 29 *
30 30 * NOTE: these are not necessairly 0-terminated
31 31 *
32 32 * Additionally, these can store references instead of copies of strings
33 33 * (as indicated by the IS_REF() macro. However mutation may cause a
34 34 * string to convert from a refence to a dynamically allocated copy.
35 35 */
36 36
37 37 void
38 38 str_init(str_t *restrict s, sysdem_ops_t *restrict ops)
39 39 {
40 40 (void) memset(s, 0, sizeof (*s));
41 41 s->str_ops = (ops != NULL) ? ops : sysdem_ops_default;
42 42 }
43 43
44 44 void
45 45 str_fini(str_t *s)
46 46 {
47 47 if (s == NULL)
48 48 return;
49 49 if (!IS_REF(s))
50 50 xfree(s->str_ops, s->str_s, s->str_size);
51 51 (void) memset(s, 0, sizeof (*s));
52 52 }
53 53
54 54 size_t
55 55 str_length(const str_t *s)
56 56 {
57 57 return (s->str_len);
58 58 }
59 59
60 60 /*
61 61 * store as a reference instead of a copy
62 62 * if len == 0, means store entire copy of 0 terminated string
63 63 */
64 64 void
65 65 str_set(str_t *s, const char *cstr, size_t len)
66 66 {
67 67 sysdem_ops_t *ops = s->str_ops;
68 68
69 69 str_fini(s);
70 70 s->str_ops = ops;
71 71 s->str_s = (char *)cstr;
72 72 s->str_len = (len == 0 && cstr != NULL) ? strlen(cstr) : len;
73 73 }
74 74
75 75 boolean_t
76 76 str_copy(const str_t *src, str_t *dest)
77 77 {
78 78 str_fini(dest);
79 79 str_init(dest, src->str_ops);
80 80
81 81 if (src->str_len == 0)
82 82 return (B_TRUE);
83 83
84 84 size_t len = roundup(src->str_len, STR_CHUNK_SZ);
85 85 dest->str_s = zalloc(src->str_ops, len);
86 86 if (dest->str_s == NULL)
87 87 return (B_FALSE);
88 88
89 89 (void) memcpy(dest->str_s, src->str_s, src->str_len);
90 90 dest->str_len = src->str_len;
91 91 dest->str_size = len;
92 92
93 93 return (B_TRUE);
↓ open down ↓ |
93 lines elided |
↑ open up ↑ |
94 94 }
95 95
96 96 /*
97 97 * ensure s has at least amt bytes free, resizing if necessary
98 98 */
99 99 static boolean_t
100 100 str_reserve(str_t *s, size_t amt)
101 101 {
102 102 size_t newlen = s->str_len + amt;
103 103
104 + /* overflow check */
105 + if (newlen < s->str_len || newlen < amt)
106 + return (B_FALSE);
107 +
104 108 if ((amt > 0) && (s->str_len + amt <= s->str_size))
105 109 return (B_TRUE);
106 110
107 111 size_t newsize = roundup(newlen, STR_CHUNK_SZ);
108 112 void *temp;
109 113
110 114 if (IS_REF(s)) {
111 115 temp = zalloc(s->str_ops, newsize);
112 116 if (temp == NULL)
113 117 return (B_FALSE);
114 118
115 119 (void) memcpy(temp, s->str_s, s->str_len);
116 120 } else {
117 121 temp = xrealloc(s->str_ops, s->str_s, s->str_size, newsize);
118 122 if (temp == NULL)
119 123 return (B_FALSE);
120 124 }
121 125
122 126 s->str_s = temp;
123 127 s->str_size = newsize;
124 128
125 129 return (B_TRUE);
126 130 }
127 131
128 132 /* append to s, cstrlen == 0 means entire length of string */
129 133 boolean_t
130 134 str_append(str_t *s, const char *cstr, size_t cstrlen)
131 135 {
132 136 if (cstr != NULL && cstrlen == 0)
133 137 cstrlen = strlen(cstr);
134 138
135 139 const str_t src = {
136 140 .str_s = (char *)cstr,
137 141 .str_len = cstrlen,
138 142 .str_ops = s->str_ops
139 143 };
140 144
141 145 return (str_append_str(s, &src));
142 146 }
143 147
144 148 boolean_t
145 149 str_append_str(str_t *dest, const str_t *src)
146 150 {
147 151 /* empty string is a noop */
148 152 if (src->str_s == NULL || src->str_len == 0)
149 153 return (B_TRUE);
150 154
151 155 /* if src is a reference, we can just copy that */
152 156 if (dest->str_s == NULL && IS_REF(src)) {
153 157 *dest = *src;
154 158 return (B_TRUE);
155 159 }
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
156 160
157 161 if (!str_reserve(dest, src->str_len))
158 162 return (B_FALSE);
159 163
160 164 (void) memcpy(dest->str_s + dest->str_len, src->str_s, src->str_len);
161 165 dest->str_len += src->str_len;
162 166 return (B_TRUE);
163 167 }
164 168
165 169 boolean_t
166 -str_append_c(str_t *s, int c)
170 +str_append_c(str_t *s, char c)
167 171 {
168 172 if (!str_reserve(s, 1))
169 173 return (B_FALSE);
170 174
171 175 s->str_s[s->str_len++] = c;
172 176 return (B_TRUE);
173 177 }
174 178
175 179 boolean_t
176 180 str_insert(str_t *s, size_t idx, const char *cstr, size_t cstrlen)
177 181 {
178 182 if (cstr == NULL)
179 183 return (B_TRUE);
180 184
181 185 if (cstrlen == 0)
182 186 cstrlen = strlen(cstr);
183 187
184 188 str_t src = {
185 189 .str_s = (char *)cstr,
186 190 .str_len = cstrlen,
187 191 .str_ops = s->str_ops,
188 192 .str_size = 0
189 193 };
190 194
191 195 return (str_insert_str(s, idx, &src));
192 196 }
193 197
194 198 boolean_t
195 199 str_insert_str(str_t *dest, size_t idx, const str_t *src)
196 200 {
197 201 ASSERT3U(idx, <=, dest->str_len);
198 202
199 203 if (idx == dest->str_len)
200 204 return (str_append_str(dest, src));
201 205
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
202 206 if (idx == 0 && dest->str_s == NULL && IS_REF(src)) {
203 207 sysdem_ops_t *ops = dest->str_ops;
204 208 *dest = *src;
205 209 dest->str_ops = ops;
206 210 return (B_TRUE);
207 211 }
208 212
209 213 if (!str_reserve(dest, src->str_len))
210 214 return (B_FALSE);
211 215
212 - /* Unlike some programmers, *I* can read manpages. */
216 + /*
217 + * Shift the contents of dest over at the insertion point. Since
218 + * src and dest ranges will overlap, and unlike some programmers,
219 + * *I* can read man pages - memmove() is the appropriate function
220 + * to this.
221 + */
213 222 (void) memmove(dest->str_s + idx + src->str_len, dest->str_s + idx,
214 223 dest->str_len - idx);
224 +
225 + /*
226 + * However the content to insert does not overlap with the destination
227 + * so memcpy() is fine here.
228 + */
215 229 (void) memcpy(dest->str_s + idx, src->str_s, src->str_len);
216 230 dest->str_len += src->str_len;
217 231
218 232 return (B_TRUE);
219 233 }
220 234
221 235 boolean_t
222 236 str_erase(str_t *s, size_t pos, size_t len)
223 237 {
224 238 ASSERT3U(pos, <, s->str_len);
225 239 ASSERT3U(pos + len, <=, s->str_len);
226 240
227 241 if (IS_REF(s)) {
228 242 if (!str_reserve(s, 0))
229 243 return (B_FALSE);
230 244 }
231 245
232 246 (void) memmove(s->str_s + pos, s->str_s + pos + len, s->str_len - len);
233 247 s->str_len -= len;
234 248 return (B_TRUE);
235 249 }
236 250
237 251 str_pair_t *
238 252 str_pair_init(str_pair_t *sp, sysdem_ops_t *ops)
239 253 {
240 254 (void) memset(sp, 0, sizeof (*sp));
241 255 str_init(&sp->strp_l, ops);
242 256 str_init(&sp->strp_r, ops);
243 257 return (sp);
244 258 }
245 259
246 260 void
247 261 str_pair_fini(str_pair_t *sp)
248 262 {
249 263 str_fini(&sp->strp_l);
250 264 str_fini(&sp->strp_r);
251 265 }
252 266
253 267 /* combine left and right parts and put result into left part */
254 268 boolean_t
255 269 str_pair_merge(str_pair_t *sp)
256 270 {
257 271 /* if right side is empty, don't need to do anything */
258 272 if (str_length(&sp->strp_r) == 0)
259 273 return (B_TRUE);
260 274
261 275 /* if left side is empty, just move right to left */
262 276 if (str_length(&sp->strp_l) == 0) {
263 277 str_fini(&sp->strp_l);
264 278 sp->strp_l = sp->strp_r;
265 279 sp->strp_r.str_s = NULL;
266 280 sp->strp_r.str_len = sp->strp_r.str_size = 0;
267 281 return (B_TRUE);
268 282 }
269 283
270 284 if (!str_append_str(&sp->strp_l, &sp->strp_r))
271 285 return (B_FALSE);
272 286
273 287 str_fini(&sp->strp_r);
274 288 str_init(&sp->strp_r, sp->strp_l.str_ops);
275 289 return (B_TRUE);
276 290 }
277 291
278 292 boolean_t
279 293 str_pair_copy(const str_pair_t *src, str_pair_t *dest)
280 294 {
281 295 boolean_t ok = B_TRUE;
282 296
283 297 ok &= str_copy(&src->strp_l, &dest->strp_l);
284 298 ok &= str_copy(&src->strp_r, &dest->strp_r);
285 299
286 300 if (!ok) {
287 301 str_fini(&dest->strp_l);
288 302 str_fini(&dest->strp_r);
289 303 return (B_FALSE);
290 304 }
291 305
292 306 return (B_TRUE);
293 307 }
294 308
295 309 size_t
296 310 str_pair_len(const str_pair_t *sp)
297 311 {
298 312 return (str_length(&sp->strp_l) + str_length(&sp->strp_r));
299 313 }
↓ open down ↓ |
75 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX