You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A heap-allocated growable array of SVs. Returned by `sv_split`. Always call `sva_free` when done.
205
+
206
+
`SVArray sva_new(void)` — Creates an empty array. Does not allocate until first push.
207
+
208
+
`void sva_push(SVArray *arr, SV sv)` — Appends an SV to the array. Grows automatically.
209
+
210
+
`SV sva_get(SVArray *arr, size_t i)` — Returns the SV at index i. Aborts with an error message if i is out of bounds.
211
+
212
+
`void sva_free(SVArray *arr)` — Frees the backing array and zeroes the struct. Safe to call on an already-freed `SVArray`. Does not free the individual SVs — they are views and do not own memory.
`SV sv_chop_by_delim(SV *sv, char delim)` — Returns everything before the first `delim` and advances `sv` past it. If not found, returns the full view and leaves `sv` empty.
223
243
244
+
`bool sv_is_empty(SV sv)` — Returns true if sv has zero length.
245
+
246
+
`bool sv_is_whitespace(SV sv)` — Returns true if every byte is whitespace. Returns false on empty.
247
+
248
+
`bool sv_is_alpha(SV sv)` — Returns true if every byte is an alphabetic character. Returns false on empty.
249
+
250
+
`bool sv_is_numeric(SV sv)` — Returns true if every byte is a decimal digit. Returns false on empty.
251
+
252
+
`bool sv_is_alphanumeric(SV sv)` — Returns true if every byte is alphabetic or a decimal digit. Returns false on empty.
253
+
254
+
`bool sv_is_upper(SV sv)` — Returns true if every byte is an uppercase letter. Returns false on empty.
255
+
256
+
`bool sv_is_lower(SV sv)` — Returns true if every byte is a lowercase letter. Returns false on empty.
257
+
258
+
`size_t sv_count_sv(SV sv, SV needle, bool overlapping)` — Counts occurrences of needle in sv. If overlapping is false, matches do not overlap — `sv_count("aaa", "aa", false)` returns 1. If overlapping is true, every position is checked — `sv_count("aaa", "aa", true)` returns 2. Returns 0 if needle is empty or longer than sv.
259
+
260
+
`bool sv_parse_int(SV sv, int *out)` — Parses sv as a decimal integer into `*out`. Returns true on success, false if the input is not a valid integer or overflows the type. If out is NULL, validates without storing. All sv_parse_* variants follow this same contract.
261
+
262
+
`bool sv_parse_long(SV sv, long *out)` — Parses as `long`.
263
+
264
+
`bool sv_parse_longlong(SV sv, long long *out)` — Parses as `long long`.
265
+
266
+
`bool sv_parse_int8(SV sv, int8_t *out)` — Parses as `int8_t`.
267
+
268
+
`bool sv_parse_int16(SV sv, int16_t *out)` — Parses as `int16_t`.
269
+
270
+
`bool sv_parse_int32(SV sv, int32_t *out)` — Parses as `int32_t`.
271
+
272
+
`bool sv_parse_int64(SV sv, int64_t *out)` — Parses as `int64_t`.
273
+
274
+
`bool sv_parse_uint8(SV sv, uint8_t *out)` — Parses as `uint8_t`.
275
+
276
+
`bool sv_parse_uint16(SV sv, uint16_t *out)` — Parses as `uint16_t`.
277
+
278
+
`bool sv_parse_uint32(SV sv, uint32_t *out)` — Parses as `uint32_t`.
279
+
280
+
`bool sv_parse_uint64(SV sv, uint64_t *out)` — Parses as `uint64_t`.
281
+
282
+
`bool sv_parse_float(SV sv, float *out)` — Parses as `float`.
283
+
284
+
`bool sv_parse_double(SV sv, double *out)` — Parses as `double`.
285
+
286
+
`SVArray sv_split_char(SV sv, char delim, size_t maxsplit)` — Splits sv on every occurrence of delim. If maxsplit is non-zero, stops after that many splits and puts the remainder in the final element. Empty segments are preserved. Caller must call `sva_free` on the result.
287
+
288
+
`SVArray sv_split_sv(SV sv, SV delim, size_t maxsplit)` — Same as `sv_split_char` but splits on a multi-character delimiter. If delim is empty, returns sv unsplit as a single element.
289
+
224
290
**Macros:**
225
291
226
292
`NEW_SV(s)` — Converts `SV`, `char *`, or `const char *` into an `SV` at compile time via `_Generic`. No copy.
227
293
228
294
`sv_eq(a, b)`, `sv_cmp(a, b)`, `sv_starts_with(a, b)`, `sv_ends_with(a, b)`, `sv_contains(a, b)`, `sv_find(a, b)` — Type-coercing wrappers around their `_sv` counterparts. Accept any mix of `SV`, `char *`, or `const char *` as arguments.
229
295
296
+
`sv_count(a, b)` — Counts non-overlapping occurrences of b in a. Accepts any mix of SV, `char *`, or `const char *`.
297
+
298
+
`sv_count_overlapping(a, b)` — Counts overlapping occurrences of b in a. Accepts any mix of SV, `char *`, or `const char *`.
299
+
300
+
`sv_split(sv, delim, maxsplit)` — Splits sv on delim, dispatching to `sv_split_char` or `sv_split_sv` based on the type of delim at compile time. Accepts char, SV, `char *`, or `const char *` as delimiter. Pass 0 for maxsplit to split everything.
301
+
230
302
`SV_FMT`, `SV_ARGS(sv)` — Use with printf-style functions to print an SV without null-termination:
231
303
```c
232
304
printf(SV_FMT "\n", SV_ARGS(my_sv));
@@ -354,6 +426,16 @@ str_free(&a);
354
426
str_free(&b);
355
427
```
356
428
429
+
### `SVArray` views into freed memory
430
+
431
+
The SVs inside an `SVArray` returned by `sv_split` are views into the original string's memory. Freeing or modifying the source string while still using the array will leave all the views dangling:
432
+
```c
433
+
SVArray parts = sv_split(sv_from_cstr(get_temp_string()), ',', 0); // imagine get_temp_string() is a fn that returns temp string
434
+
// if get_temp_string()'s memory is gone, parts.data[i] are all dangling
435
+
sva_free(&parts);
436
+
```
437
+
Make sure the source string outlives the `SVArray`.
438
+
357
439
### `SB_AUTO` / `STR_AUTO` are no-ops on unknown compilers
358
440
359
441
On compilers without `__attribute__((cleanup))`, both macros expand to nothing and no warning is emitted at the point of use — only at the point `compat.h` is processed. Variables marked `SB_AUTO` or `STR_AUTO` will not be freed automatically. You will leak memory silently.
0 commit comments