2 * Copyright (c) 2014-2016 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 #include <jeffpc/str.h>
29 #include <jeffpc/jeffpc.h>
31 static umem_cache_t
*str_cache
;
33 void init_str_subsys(void)
35 str_cache
= umem_cache_create("str-cache", sizeof(struct str
),
36 0, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
40 static struct str
*__alloc(char *s
, bool copy
)
44 str
= umem_cache_alloc(str_cache
, 0);
48 refcnt_init(&str
->refcnt
, 1);
52 strcpy(str
->inline_str
, s
);
53 str
->str
= str
->inline_str
;
61 struct str
*str_dup(const char *s
)
64 return __alloc("", true);
66 if (strlen(s
) <= STR_INLINE_LEN
)
67 return __alloc((char *) s
, true);
69 return str_alloc(strdup(s
));
72 struct str
*str_alloc(char *s
)
74 return __alloc(s
, false);
77 size_t str_len(const struct str
*s
)
79 return strlen(s
->str
);
82 int str_cmp(const struct str
*a
, const struct str
*b
)
84 return strcmp(a
->str
, b
->str
);
87 struct str
*str_cat(int n
, ...)
101 ret
= va_arg(ap
, struct str
*);
107 len
= alloca(sizeof(size_t) * n
);
110 for (i
= 0; i
< n
; i
++) {
111 struct str
*str
= va_arg(ap
, struct str
*);
116 len
[i
] = strlen(str
->str
);
122 buf
= malloc(totallen
+ 1);
128 for (i
= 0; i
< n
; i
++) {
129 struct str
*str
= va_arg(ap
, struct str
*);
134 strcpy(out
, str
->str
);
142 ret
= str_alloc(buf
);
148 void str_free(struct str
*str
)
153 ASSERT3U(refcnt_read(&str
->refcnt
), ==, 0);
155 if (str
->str
!= str
->inline_str
)
157 umem_cache_free(str_cache
, str
);
161 * We are not using REFCNT_FXNS() here because we want to support statically
164 struct str
*str_getref(struct str
*x
)
169 if (!(x
->flags
& STR_FLAG_STATIC
)) {
170 ASSERT3U(refcnt_read(&x
->refcnt
), >=, 1);
172 __refcnt_inc(&x
->refcnt
);
178 void str_putref(struct str
*x
)
183 if (x
->flags
& STR_FLAG_STATIC
)
186 ASSERT3S(refcnt_read(&x
->refcnt
), >=, 1);
188 if (!__refcnt_dec(&x
->refcnt
))