Mercurial > libjeffpc
annotate str.c @ 794:d018af7c979c
slab: make struct mem_cache private
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Sun, 15 Mar 2020 15:52:09 +0200 |
parents | 955644dda096 |
children |
rev | line source |
---|---|
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
1 /* |
155
a68a3c91f9b6
str: use the generic getref/putref generator macros
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
120
diff
changeset
|
2 * Copyright (c) 2014-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
3 * |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
4 * Permission is hereby granted, free of charge, to any person obtaining a copy |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
5 * of this software and associated documentation files (the "Software"), to deal |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
6 * in the Software without restriction, including without limitation the rights |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
8 * copies of the Software, and to permit persons to whom the Software is |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
9 * furnished to do so, subject to the following conditions: |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
10 * |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
11 * The above copyright notice and this permission notice shall be included in |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
12 * all copies or substantial portions of the Software. |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
13 * |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
20 * SOFTWARE. |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
21 */ |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
22 |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
23 #include <stdlib.h> |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
24 #include <stdbool.h> |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
25 |
159
59d3f2a362a9
str: use the libjeffpc slab allocator API instead of libumem
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
155
diff
changeset
|
26 #include <jeffpc/mem.h> |
19
017a4abcfe3d
init: add a single initialize-the-library function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
12
diff
changeset
|
27 #include <jeffpc/jeffpc.h> |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
28 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
29 #include "val_impl.h" |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
30 |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
31 /* check that STR_INLINE_LEN is used properly in the struct definition */ |
460
876176e8a855
val: move string related fields into a substruct
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
361
diff
changeset
|
32 STATIC_ASSERT(STR_INLINE_LEN + 1 == sizeof(((struct str *) NULL)->val.str.inline_str)); |
312
15d4201c0f1b
str: sanity check that ->inline_str is using STR_INLINE_LEN properly
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
311
diff
changeset
|
33 |
311
a5771ab42602
str: assert at compile time that we aren't being wasteful with inline strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
295
diff
changeset
|
34 /* check that STR_INLINE_LEN is not undersized */ |
a5771ab42602
str: assert at compile time that we aren't being wasteful with inline strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
295
diff
changeset
|
35 STATIC_ASSERT(STR_INLINE_LEN + 1 >= sizeof(char *)); |
a5771ab42602
str: assert at compile time that we aren't being wasteful with inline strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
295
diff
changeset
|
36 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
37 /* check that struct str is just a type alias for struct val */ |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
38 STATIC_ASSERT(sizeof(struct str) == sizeof(struct val)); |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
39 STATIC_ASSERT(offsetof(struct str, val) == 0); |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
40 |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
41 /* same as above but for struct sym */ |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
42 STATIC_ASSERT(sizeof(struct sym) == sizeof(struct val)); |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
43 STATIC_ASSERT(offsetof(struct sym, val) == 0); |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
44 |
295
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
45 #define USE_STRLEN ((size_t) ~0ul) |
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
46 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
47 static struct str empty_string = _STATIC_STR_INITIALIZER(VT_STR, ""); |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
48 static struct sym empty_symbol = _STATIC_STR_INITIALIZER(VT_SYM, ""); |
230
6c9d77cf8c1e
str: preallocate more single-char strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
228
diff
changeset
|
49 |
358
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
50 /* one 7-bit ASCII character long strings */ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
51 static struct str one_char[128] = { |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
52 #define STATIC_CHAR1(start) \ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
53 [start] = STR_STATIC_CHAR_INITIALIZER(start) |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
54 #define STATIC_CHAR2(start) \ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
55 STATIC_CHAR1(start), STATIC_CHAR1(start + 1) |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
56 #define STATIC_CHAR4(start) \ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
57 STATIC_CHAR2(start), STATIC_CHAR2(start + 2) |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
58 #define STATIC_CHAR8(start) \ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
59 STATIC_CHAR4(start), STATIC_CHAR4(start + 4) |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
60 #define STATIC_CHAR16(start) \ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
61 STATIC_CHAR8(start), STATIC_CHAR8(start + 8) |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
62 #define STATIC_CHAR32(start) \ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
63 STATIC_CHAR16(start), STATIC_CHAR16(start + 16) |
230
6c9d77cf8c1e
str: preallocate more single-char strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
228
diff
changeset
|
64 |
358
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
65 /* Note: 0 is not initialized */ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
66 STATIC_CHAR1(1), /* 1 */ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
67 STATIC_CHAR2(2), /* 2....3 */ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
68 STATIC_CHAR4(4), /* 4....7 */ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
69 STATIC_CHAR8(8), /* 8...15 */ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
70 STATIC_CHAR16(16), /* 16...31 */ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
71 STATIC_CHAR32(32), /* 32...63 */ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
72 STATIC_CHAR32(64), /* 64...95 */ |
2c746904eba3
str: generate one-char strings using the preprocessor
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
354
diff
changeset
|
73 STATIC_CHAR32(96) /* 96..127 */ |
192
94c9db63f1c3
str: preallocate " " string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
191
diff
changeset
|
74 }; |
191
626a2d545bbe
str: allow simple static preallocation of one-char long strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
190
diff
changeset
|
75 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
76 static inline size_t get_len(const struct val *val) |
320
1fa790d3c6a5
str: str_len and str_cat should make use of the stored string length
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
319
diff
changeset
|
77 { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
78 return strlen(val_cstr(val)); |
320
1fa790d3c6a5
str: str_len and str_cat should make use of the stored string length
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
319
diff
changeset
|
79 } |
1fa790d3c6a5
str: str_len and str_cat should make use of the stored string length
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
319
diff
changeset
|
80 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
81 static inline void set_len(struct val *str, size_t len) |
322
8b974e84641b
str: save newly allocated string's length
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
321
diff
changeset
|
82 { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
83 /* TODO: stash length in struct val if possible */ |
322
8b974e84641b
str: save newly allocated string's length
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
321
diff
changeset
|
84 } |
8b974e84641b
str: save newly allocated string's length
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
321
diff
changeset
|
85 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
86 static struct val *__get_preallocated(enum val_type type, const char *s, |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
87 size_t len) |
224
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
88 { |
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
89 unsigned char first_char; |
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
90 |
295
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
91 /* NULL or non-nul terminated & zero length */ |
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
92 if (!s || !len) |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
93 return (type == VT_STR) ? &empty_string.val : &empty_symbol.val; |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
94 |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
95 if (type != VT_STR) |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
96 return NULL; |
295
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
97 |
224
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
98 first_char = s[0]; |
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
99 |
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
100 /* preallocated one-char long strings of 7-bit ASCII */ |
321
5e57bb7042a9
str: simplify heap string allocation
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
320
diff
changeset
|
101 if ((len == 1) && |
5e57bb7042a9
str: simplify heap string allocation
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
320
diff
changeset
|
102 (first_char > '\0') && (first_char < '\x7f') && |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
103 one_char[first_char].val.static_struct) |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
104 return &one_char[first_char].val; |
224
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
105 |
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
106 /* nothing pre-allocated */ |
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
107 return NULL; |
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
108 } |
eabb98107cba
str: move preallocation lookups into a helper function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
198
diff
changeset
|
109 |
321
5e57bb7042a9
str: simplify heap string allocation
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
320
diff
changeset
|
110 static bool __inlinable(size_t len) |
293
88f777a374ad
str: abstract away inlinablity checking
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
257
diff
changeset
|
111 { |
321
5e57bb7042a9
str: simplify heap string allocation
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
320
diff
changeset
|
112 return (len <= STR_INLINE_LEN); |
293
88f777a374ad
str: abstract away inlinablity checking
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
257
diff
changeset
|
113 } |
88f777a374ad
str: abstract away inlinablity checking
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
257
diff
changeset
|
114 |
329
ed0aebd109c9
str: factor out initialization string copying code
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
328
diff
changeset
|
115 static inline void __copy(char *dest, const char *s, size_t len) |
295
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
116 { |
329
ed0aebd109c9
str: factor out initialization string copying code
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
328
diff
changeset
|
117 memcpy(dest, s, len); |
ed0aebd109c9
str: factor out initialization string copying code
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
328
diff
changeset
|
118 dest[len] = '\0'; |
295
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
119 } |
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
120 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
121 static struct val *__alloc(enum val_type type, const char *s, size_t len, |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
122 bool heapalloc, bool mustdup) |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
123 { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
124 struct val *val; |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
125 bool copy; |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
126 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
127 ASSERT((type == VT_STR) || (type == VT_SYM)); |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
128 |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
129 /* sanity check */ |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
130 if (mustdup) |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
131 ASSERT(!heapalloc); |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
132 |
321
5e57bb7042a9
str: simplify heap string allocation
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
320
diff
changeset
|
133 /* determine the real length of the string */ |
323
d52894dc2c80
str: use strnlen to determine string length
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
322
diff
changeset
|
134 len = s ? strnlen(s, len) : 0; |
321
5e57bb7042a9
str: simplify heap string allocation
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
320
diff
changeset
|
135 |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
136 /* check preallocated strings */ |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
137 val = __get_preallocated(type, s, len); |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
138 if (val) |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
139 goto out; |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
140 |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
141 /* can we inline it? */ |
321
5e57bb7042a9
str: simplify heap string allocation
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
320
diff
changeset
|
142 copy = __inlinable(len); |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
143 |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
144 /* we'll be storing a pointer - strdup as necessary */ |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
145 if (!copy && mustdup) { |
329
ed0aebd109c9
str: factor out initialization string copying code
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
328
diff
changeset
|
146 char *tmp; |
ed0aebd109c9
str: factor out initialization string copying code
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
328
diff
changeset
|
147 |
ed0aebd109c9
str: factor out initialization string copying code
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
328
diff
changeset
|
148 tmp = malloc(len + 1); |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
149 if (!tmp) { |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
150 val = ERR_PTR(-ENOMEM); |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
151 goto out; |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
152 } |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
153 |
329
ed0aebd109c9
str: factor out initialization string copying code
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
328
diff
changeset
|
154 __copy(tmp, s, len); |
ed0aebd109c9
str: factor out initialization string copying code
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
328
diff
changeset
|
155 |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
156 /* we're now using the heap */ |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
157 heapalloc = true; |
329
ed0aebd109c9
str: factor out initialization string copying code
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
328
diff
changeset
|
158 s = tmp; |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
159 } |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
160 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
161 val = __val_alloc(type); |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
162 if (IS_ERR(val)) |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
163 goto out; |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
164 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
165 val->static_alloc = copy || !heapalloc; |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
166 val->inline_alloc = copy; |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
167 set_len(val, len); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
168 |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
169 if (copy) { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
170 __copy(val->_set_str_inline, s, len); |
295
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
171 |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
172 if (heapalloc) |
328
ad58b69a6a54
str: constify the internal allocator function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
326
diff
changeset
|
173 free((char *) s); |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
174 } else { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
175 val->_set_str_ptr = s; |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
176 } |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
177 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
178 return val; |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
179 |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
180 out: |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
181 if (heapalloc) |
328
ad58b69a6a54
str: constify the internal allocator function
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
326
diff
changeset
|
182 free((char *) s); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
183 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
184 return val; |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
185 } |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
186 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
187 struct val *_strsym_dup(const char *s, enum val_type type) |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
188 { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
189 return __alloc(type, s, USE_STRLEN, false, true); |
295
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
190 } |
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
191 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
192 struct val *_strsym_dup_len(const char *s, size_t len, enum val_type type) |
295
842d49f888f3
str: add a str_dup variant that doesn't assume the input is nul-terminated
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
294
diff
changeset
|
193 { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
194 return __alloc(type, s, len, false, true); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
195 } |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
196 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
197 struct val *_strsym_alloc(char *s, enum val_type type) |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
198 { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
199 return __alloc(type, s, USE_STRLEN, true, false); |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
200 } |
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
201 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
202 struct val *_strsym_alloc_static(const char *s, enum val_type type) |
228
2ffb2b971149
str: add support for static strings
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
227
diff
changeset
|
203 { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
204 return __alloc(type, s, USE_STRLEN, false, false); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
205 } |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
206 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
207 size_t _strsym_len(const struct val *s) |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
208 { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
209 return get_len(s); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
210 } |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
211 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
212 int _strsym_cmp(const struct val *a, const struct val *b) |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
213 { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
214 return strcmp(val_cstr(a), val_cstr(b)); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
215 } |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
216 |
232
7b1c311a77e4
str: the number of strings passed to str_cat() should be a size_t
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
230
diff
changeset
|
217 struct str *str_cat(size_t n, ...) |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
218 { |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
219 size_t totallen; |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
220 char *buf, *out; |
360
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
221 struct val **vals; |
41
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
222 size_t *len; |
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
223 va_list ap; |
232
7b1c311a77e4
str: the number of strings passed to str_cat() should be a size_t
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
230
diff
changeset
|
224 size_t i; |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
225 |
360
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
226 if (!n) |
361
2a460efe5d40
str: return empty string instead of NULL
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
360
diff
changeset
|
227 return &empty_string; |
41
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
228 |
360
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
229 if (n == 1) { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
230 struct val *val; |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
231 struct str *ret; |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
232 |
41
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
233 va_start(ap, n); |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
234 val = va_arg(ap, struct val *); |
41
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
235 va_end(ap); |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
236 |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
237 if (val->type == VT_STR) |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
238 return val_cast_to_str(val); |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
239 |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
240 ret = STR_DUP(val_cstr(val)); |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
241 val_putref(val); |
41
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
242 return ret; |
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
243 } |
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
244 |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
245 totallen = 0; |
41
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
246 len = alloca(sizeof(size_t) * n); |
360
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
247 vals = alloca(sizeof(struct val *) * n); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
248 |
41
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
249 va_start(ap, n); |
360
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
250 for (i = 0; i < n; i++) { |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
251 struct val *val = va_arg(ap, struct val *); |
41
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
252 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
253 if (!val) { |
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
254 len[i] = 0; |
360
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
255 vals[i] = NULL; |
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
256 } else { |
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
257 len[i] = get_len(val); |
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
258 vals[i] = val; |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
259 |
360
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
260 totallen += len[i]; |
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
261 } |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
262 } |
41
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
263 va_end(ap); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
264 |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
265 buf = malloc(totallen + 1); |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
266 ASSERT(buf); |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
267 |
330
d7f0dde260ee
str: fix str_cat issues found by the clang static analyzer
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
329
diff
changeset
|
268 buf[0] = '\0'; |
d7f0dde260ee
str: fix str_cat issues found by the clang static analyzer
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
329
diff
changeset
|
269 |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
270 out = buf; |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
271 |
360
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
272 for (i = 0; i < n; i++) { |
d3db42f6c3d5
str: str_cat should iterate through va list only once
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
359
diff
changeset
|
273 struct val *val = vals[i]; |
41
ce17740b7bf2
str: str_cat should handle unlimited number of arguments
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
19
diff
changeset
|
274 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
275 if (!val) |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
276 continue; |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
277 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
278 strcpy(out, val_cstr(val)); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
279 |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
280 out += len[i]; |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
281 |
359
7544e9990bc1
str: implement struct str in terms of struct val
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
358
diff
changeset
|
282 val_putref(val); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
283 } |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
284 |
353
f9eadf52ec6d
str: don't open-code STR_ALLOC
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
338
diff
changeset
|
285 return STR_ALLOC(buf); |
6
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
286 } |
4317d47b267f
str: a reference counted string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff
changeset
|
287 |
120
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
288 struct str *str_vprintf(const char *fmt, va_list args) |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
289 { |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
290 char *tmp; |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
291 int ret; |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
292 |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
293 ret = vasprintf(&tmp, fmt, args); |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
294 if (ret < 0) |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
295 return ERR_PTR(-errno); |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
296 if (ret == 0) |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
297 return NULL; |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
298 |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
299 return STR_ALLOC(tmp); |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
300 } |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
301 |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
302 struct str *str_printf(const char *fmt, ...) |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
303 { |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
304 struct str *ret; |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
305 va_list args; |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
306 |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
307 va_start(args, fmt); |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
308 ret = str_vprintf(fmt, args); |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
309 va_end(args); |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
310 |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
311 return ret; |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
312 } |
b43b8fc87c0b
str: introduce str_printf and str_vprintf
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
67
diff
changeset
|
313 |
354
e79153a1f42f
str: make it easy to get an empty string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
353
diff
changeset
|
314 struct str *str_empty_string(void) |
e79153a1f42f
str: make it easy to get an empty string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
353
diff
changeset
|
315 { |
e79153a1f42f
str: make it easy to get an empty string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
353
diff
changeset
|
316 return &empty_string; |
e79153a1f42f
str: make it easy to get an empty string
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
353
diff
changeset
|
317 } |