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
;