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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 }