1 /* $NetBSD: prop_string.c,v 1.11 2008/08/03 04:00:12 thorpej Exp $ */
4 * Copyright (c) 2006 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <prop/prop_string.h>
33 #include "prop_object_impl.h"
36 struct _prop_object ps_obj;
39 const char * psu_immutable;
41 #define ps_mutable ps_un.psu_mutable
42 #define ps_immutable ps_un.psu_immutable
43 size_t ps_size; /* not including \0 */
47 #define PS_F_NOCOPY 0x01
49 _PROP_POOL_INIT(_prop_string_pool, sizeof(struct _prop_string), "propstng")
51 _PROP_MALLOC_DEFINE(M_PROP_STRING, "prop string",
52 "property string container object")
54 static _prop_object_free_rv_t
55 _prop_string_free(prop_stack_t, prop_object_t *);
56 static bool _prop_string_externalize(
57 struct _prop_object_externalize_context *,
59 static _prop_object_equals_rv_t
60 _prop_string_equals(prop_object_t, prop_object_t,
62 prop_object_t *, prop_object_t *);
64 static const struct _prop_object_type _prop_object_type_string = {
65 .pot_type = PROP_TYPE_STRING,
66 .pot_free = _prop_string_free,
67 .pot_extern = _prop_string_externalize,
68 .pot_equals = _prop_string_equals,
71 #define prop_object_is_string(x) \
72 ((x) != NULL && (x)->ps_obj.po_type == &_prop_object_type_string)
73 #define prop_string_contents(x) ((x)->ps_immutable ? (x)->ps_immutable : "")
76 static _prop_object_free_rv_t
77 _prop_string_free(prop_stack_t stack, prop_object_t *obj)
79 prop_string_t ps = *obj;
81 if ((ps->ps_flags & PS_F_NOCOPY) == 0 && ps->ps_mutable != NULL)
82 _PROP_FREE(ps->ps_mutable, M_PROP_STRING);
83 _PROP_POOL_PUT(_prop_string_pool, ps);
85 return (_PROP_OBJECT_FREE_DONE);
89 _prop_string_externalize(struct _prop_object_externalize_context *ctx,
95 return (_prop_object_externalize_empty_tag(ctx, "string"));
97 if (_prop_object_externalize_start_tag(ctx, "string") == false ||
98 _prop_object_externalize_append_encoded_cstring(ctx,
99 ps->ps_immutable) == false ||
100 _prop_object_externalize_end_tag(ctx, "string") == false)
107 static _prop_object_equals_rv_t
108 _prop_string_equals(prop_object_t v1, prop_object_t v2,
109 void **stored_pointer1, void **stored_pointer2,
110 prop_object_t *next_obj1, prop_object_t *next_obj2)
112 prop_string_t str1 = v1;
113 prop_string_t str2 = v2;
116 return (_PROP_OBJECT_EQUALS_TRUE);
117 if (str1->ps_size != str2->ps_size)
118 return (_PROP_OBJECT_EQUALS_FALSE);
119 if (strcmp(prop_string_contents(str1), prop_string_contents(str2)))
120 return (_PROP_OBJECT_EQUALS_FALSE);
122 return (_PROP_OBJECT_EQUALS_TRUE);
126 _prop_string_alloc(void)
130 ps = _PROP_POOL_GET(_prop_string_pool);
132 _prop_object_init(&ps->ps_obj, &_prop_object_type_string);
134 ps->ps_mutable = NULL;
143 * prop_string_create --
144 * Create an empty mutable string.
147 prop_string_create(void)
150 return (_prop_string_alloc());
154 * prop_string_create_cstring --
155 * Create a string that contains a copy of the provided C string.
158 prop_string_create_cstring(const char *str)
164 ps = _prop_string_alloc();
167 cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
169 prop_object_release(ps);
180 * prop_string_create_cstring_nocopy --
181 * Create an immutable string that contains a refrence to the
185 prop_string_create_cstring_nocopy(const char *str)
189 ps = _prop_string_alloc();
191 ps->ps_immutable = str;
192 ps->ps_size = strlen(str);
193 ps->ps_flags |= PS_F_NOCOPY;
199 * prop_string_copy --
200 * Copy a string. If the original string is immutable, then the
201 * copy is also immutable and references the same external data.
204 prop_string_copy(prop_string_t ops)
208 if (! prop_object_is_string(ops))
211 ps = _prop_string_alloc();
213 ps->ps_size = ops->ps_size;
214 ps->ps_flags = ops->ps_flags;
215 if (ops->ps_flags & PS_F_NOCOPY)
216 ps->ps_immutable = ops->ps_immutable;
218 char *cp = _PROP_MALLOC(ps->ps_size + 1, M_PROP_STRING);
220 prop_object_release(ps);
223 strcpy(cp, prop_string_contents(ops));
231 * prop_string_copy_mutable --
232 * Copy a string, always returning a mutable copy.
235 prop_string_copy_mutable(prop_string_t ops)
240 if (! prop_object_is_string(ops))
243 ps = _prop_string_alloc();
245 ps->ps_size = ops->ps_size;
246 cp = _PROP_MALLOC(ps->ps_size + 1, M_PROP_STRING);
248 prop_object_release(ps);
251 strcpy(cp, prop_string_contents(ops));
258 * prop_string_size --
259 * Return the size of the string, not including the terminating NUL.
262 prop_string_size(prop_string_t ps)
265 if (! prop_object_is_string(ps))
268 return (ps->ps_size);
272 * prop_string_mutable --
273 * Return true if the string is a mutable string.
276 prop_string_mutable(prop_string_t ps)
279 if (! prop_object_is_string(ps))
282 return ((ps->ps_flags & PS_F_NOCOPY) == 0);
286 * prop_string_cstring --
287 * Return a copy of the contents of the string as a C string.
288 * The string is allocated with the M_TEMP malloc type.
291 prop_string_cstring(prop_string_t ps)
295 if (! prop_object_is_string(ps))
298 cp = _PROP_MALLOC(ps->ps_size + 1, M_TEMP);
300 strcpy(cp, prop_string_contents(ps));
306 * prop_string_cstring_nocopy --
307 * Return an immutable reference to the contents of the string
311 prop_string_cstring_nocopy(prop_string_t ps)
314 if (! prop_object_is_string(ps))
317 return (prop_string_contents(ps));
321 * prop_string_append --
322 * Append the contents of one string to another. Returns true
323 * upon success. The destination string must be mutable.
326 prop_string_append(prop_string_t dst, prop_string_t src)
331 if (! (prop_object_is_string(dst) &&
332 prop_object_is_string(src)))
335 if (dst->ps_flags & PS_F_NOCOPY)
338 len = dst->ps_size + src->ps_size;
339 cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
342 sprintf(cp, "%s%s", prop_string_contents(dst),
343 prop_string_contents(src));
344 ocp = dst->ps_mutable;
345 dst->ps_mutable = cp;
348 _PROP_FREE(ocp, M_PROP_STRING);
354 * prop_string_append_cstring --
355 * Append a C string to a string. Returns true upon success.
356 * The destination string must be mutable.
359 prop_string_append_cstring(prop_string_t dst, const char *src)
364 if (! prop_object_is_string(dst))
367 _PROP_ASSERT(src != NULL);
369 if (dst->ps_flags & PS_F_NOCOPY)
372 len = dst->ps_size + strlen(src);
373 cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
376 sprintf(cp, "%s%s", prop_string_contents(dst), src);
377 ocp = dst->ps_mutable;
378 dst->ps_mutable = cp;
381 _PROP_FREE(ocp, M_PROP_STRING);
387 * prop_string_equals --
388 * Return true if two strings are equivalent.
391 prop_string_equals(prop_string_t str1, prop_string_t str2)
393 if (!prop_object_is_string(str1) || !prop_object_is_string(str2))
396 return prop_object_equals(str1, str2);
400 * prop_string_equals_cstring --
401 * Return true if the string is equivalent to the specified
405 prop_string_equals_cstring(prop_string_t ps, const char *cp)
408 if (! prop_object_is_string(ps))
411 return (strcmp(prop_string_contents(ps), cp) == 0);
415 * _prop_string_internalize --
416 * Parse a <string>...</string> and return the object created from the
417 * external representation.
421 _prop_string_internalize(prop_stack_t stack, prop_object_t *obj,
422 struct _prop_object_internalize_context *ctx)
424 prop_string_t string;
428 if (ctx->poic_is_empty_element) {
429 *obj = prop_string_create();
433 /* No attributes recognized here. */
434 if (ctx->poic_tagattr != NULL)
437 /* Compute the length of the result. */
438 if (_prop_object_internalize_decode_string(ctx, NULL, 0, &len,
442 str = _PROP_MALLOC(len + 1, M_PROP_STRING);
446 if (_prop_object_internalize_decode_string(ctx, str, len, &alen,
447 &ctx->poic_cp) == false ||
449 _PROP_FREE(str, M_PROP_STRING);
454 if (_prop_object_internalize_find_tag(ctx, "string",
455 _PROP_TAG_TYPE_END) == false) {
456 _PROP_FREE(str, M_PROP_STRING);
460 string = _prop_string_alloc();
461 if (string == NULL) {
462 _PROP_FREE(str, M_PROP_STRING);
466 string->ps_mutable = str;
467 string->ps_size = len;