Home | History | Annotate | Line # | Download | only in libprop
prop_string.c revision 1.10.2.1
      1  1.10.2.1  wrstuden /*	$NetBSD: prop_string.c,v 1.10.2.1 2008/09/18 04:54:19 wrstuden Exp $	*/
      2       1.1   thorpej 
      3       1.1   thorpej /*-
      4       1.1   thorpej  * Copyright (c) 2006 The NetBSD Foundation, Inc.
      5       1.1   thorpej  * All rights reserved.
      6       1.1   thorpej  *
      7       1.1   thorpej  * This code is derived from software contributed to The NetBSD Foundation
      8       1.1   thorpej  * by Jason R. Thorpe.
      9       1.1   thorpej  *
     10       1.1   thorpej  * Redistribution and use in source and binary forms, with or without
     11       1.1   thorpej  * modification, are permitted provided that the following conditions
     12       1.1   thorpej  * are met:
     13       1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     14       1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     15       1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     17       1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     18       1.1   thorpej  *
     19       1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.1   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.1   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.1   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.1   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.1   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.1   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.1   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.1   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.1   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.1   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1   thorpej  */
     31       1.1   thorpej 
     32       1.1   thorpej #include <prop/prop_string.h>
     33       1.1   thorpej #include "prop_object_impl.h"
     34       1.1   thorpej 
     35       1.1   thorpej struct _prop_string {
     36       1.1   thorpej 	struct _prop_object	ps_obj;
     37       1.1   thorpej 	union {
     38       1.1   thorpej 		char *		psu_mutable;
     39       1.1   thorpej 		const char *	psu_immutable;
     40       1.1   thorpej 	} ps_un;
     41       1.1   thorpej #define	ps_mutable		ps_un.psu_mutable
     42       1.1   thorpej #define	ps_immutable		ps_un.psu_immutable
     43       1.1   thorpej 	size_t			ps_size;	/* not including \0 */
     44       1.1   thorpej 	int			ps_flags;
     45       1.1   thorpej };
     46       1.1   thorpej 
     47       1.1   thorpej #define	PS_F_NOCOPY		0x01
     48       1.1   thorpej 
     49       1.1   thorpej _PROP_POOL_INIT(_prop_string_pool, sizeof(struct _prop_string), "propstng")
     50       1.1   thorpej 
     51       1.1   thorpej _PROP_MALLOC_DEFINE(M_PROP_STRING, "prop string",
     52       1.1   thorpej 		    "property string container object")
     53       1.1   thorpej 
     54  1.10.2.1  wrstuden static _prop_object_free_rv_t
     55  1.10.2.1  wrstuden 		_prop_string_free(prop_stack_t, prop_object_t *);
     56       1.7   thorpej static bool	_prop_string_externalize(
     57       1.2   thorpej 				struct _prop_object_externalize_context *,
     58       1.2   thorpej 				void *);
     59  1.10.2.1  wrstuden static _prop_object_equals_rv_t
     60  1.10.2.1  wrstuden 		_prop_string_equals(prop_object_t, prop_object_t,
     61  1.10.2.1  wrstuden 				    void **, void **,
     62  1.10.2.1  wrstuden 				    prop_object_t *, prop_object_t *);
     63       1.2   thorpej 
     64       1.2   thorpej static const struct _prop_object_type _prop_object_type_string = {
     65       1.2   thorpej 	.pot_type	=	PROP_TYPE_STRING,
     66       1.2   thorpej 	.pot_free	=	_prop_string_free,
     67       1.2   thorpej 	.pot_extern	=	_prop_string_externalize,
     68       1.2   thorpej 	.pot_equals	=	_prop_string_equals,
     69       1.2   thorpej };
     70       1.2   thorpej 
     71       1.2   thorpej #define	prop_object_is_string(x)	\
     72       1.4   thorpej 	((x) != NULL && (x)->ps_obj.po_type == &_prop_object_type_string)
     73       1.1   thorpej #define	prop_string_contents(x)  ((x)->ps_immutable ? (x)->ps_immutable : "")
     74       1.1   thorpej 
     75       1.8     joerg /* ARGSUSED */
     76  1.10.2.1  wrstuden static _prop_object_free_rv_t
     77       1.8     joerg _prop_string_free(prop_stack_t stack, prop_object_t *obj)
     78       1.1   thorpej {
     79       1.8     joerg 	prop_string_t ps = *obj;
     80       1.1   thorpej 
     81       1.1   thorpej 	if ((ps->ps_flags & PS_F_NOCOPY) == 0 && ps->ps_mutable != NULL)
     82       1.1   thorpej 	    	_PROP_FREE(ps->ps_mutable, M_PROP_STRING);
     83       1.8     joerg 	_PROP_POOL_PUT(_prop_string_pool, ps);
     84       1.8     joerg 
     85       1.8     joerg 	return (_PROP_OBJECT_FREE_DONE);
     86       1.1   thorpej }
     87       1.1   thorpej 
     88       1.7   thorpej static bool
     89       1.1   thorpej _prop_string_externalize(struct _prop_object_externalize_context *ctx,
     90       1.1   thorpej 			 void *v)
     91       1.1   thorpej {
     92       1.1   thorpej 	prop_string_t ps = v;
     93       1.1   thorpej 
     94       1.1   thorpej 	if (ps->ps_size == 0)
     95       1.1   thorpej 		return (_prop_object_externalize_empty_tag(ctx, "string"));
     96       1.1   thorpej 
     97       1.7   thorpej 	if (_prop_object_externalize_start_tag(ctx, "string") == false ||
     98       1.1   thorpej 	    _prop_object_externalize_append_encoded_cstring(ctx,
     99       1.7   thorpej 	    					ps->ps_immutable) == false ||
    100       1.7   thorpej 	    _prop_object_externalize_end_tag(ctx, "string") == false)
    101       1.7   thorpej 		return (false);
    102       1.1   thorpej 
    103       1.7   thorpej 	return (true);
    104       1.1   thorpej }
    105       1.1   thorpej 
    106       1.9     joerg /* ARGSUSED */
    107  1.10.2.1  wrstuden static _prop_object_equals_rv_t
    108       1.9     joerg _prop_string_equals(prop_object_t v1, prop_object_t v2,
    109       1.9     joerg     void **stored_pointer1, void **stored_pointer2,
    110       1.9     joerg     prop_object_t *next_obj1, prop_object_t *next_obj2)
    111       1.2   thorpej {
    112       1.2   thorpej 	prop_string_t str1 = v1;
    113       1.2   thorpej 	prop_string_t str2 = v2;
    114       1.2   thorpej 
    115       1.2   thorpej 	if (str1 == str2)
    116       1.9     joerg 		return (_PROP_OBJECT_EQUALS_TRUE);
    117       1.2   thorpej 	if (str1->ps_size != str2->ps_size)
    118       1.9     joerg 		return (_PROP_OBJECT_EQUALS_FALSE);
    119       1.9     joerg 	if (strcmp(prop_string_contents(str1), prop_string_contents(str2)))
    120       1.9     joerg 		return (_PROP_OBJECT_EQUALS_FALSE);
    121       1.9     joerg 	else
    122       1.9     joerg 		return (_PROP_OBJECT_EQUALS_TRUE);
    123       1.2   thorpej }
    124       1.2   thorpej 
    125       1.1   thorpej static prop_string_t
    126       1.1   thorpej _prop_string_alloc(void)
    127       1.1   thorpej {
    128       1.1   thorpej 	prop_string_t ps;
    129       1.1   thorpej 
    130       1.1   thorpej 	ps = _PROP_POOL_GET(_prop_string_pool);
    131       1.1   thorpej 	if (ps != NULL) {
    132       1.2   thorpej 		_prop_object_init(&ps->ps_obj, &_prop_object_type_string);
    133       1.1   thorpej 
    134       1.1   thorpej 		ps->ps_mutable = NULL;
    135       1.1   thorpej 		ps->ps_size = 0;
    136       1.1   thorpej 		ps->ps_flags = 0;
    137       1.1   thorpej 	}
    138       1.1   thorpej 
    139       1.1   thorpej 	return (ps);
    140       1.1   thorpej }
    141       1.1   thorpej 
    142       1.1   thorpej /*
    143       1.1   thorpej  * prop_string_create --
    144       1.1   thorpej  *	Create an empty mutable string.
    145       1.1   thorpej  */
    146       1.1   thorpej prop_string_t
    147       1.1   thorpej prop_string_create(void)
    148       1.1   thorpej {
    149       1.1   thorpej 
    150       1.1   thorpej 	return (_prop_string_alloc());
    151       1.1   thorpej }
    152       1.1   thorpej 
    153       1.1   thorpej /*
    154       1.1   thorpej  * prop_string_create_cstring --
    155       1.1   thorpej  *	Create a string that contains a copy of the provided C string.
    156       1.1   thorpej  */
    157       1.1   thorpej prop_string_t
    158       1.1   thorpej prop_string_create_cstring(const char *str)
    159       1.1   thorpej {
    160       1.1   thorpej 	prop_string_t ps;
    161       1.1   thorpej 	char *cp;
    162       1.1   thorpej 	size_t len;
    163       1.1   thorpej 
    164       1.1   thorpej 	ps = _prop_string_alloc();
    165       1.1   thorpej 	if (ps != NULL) {
    166       1.1   thorpej 		len = strlen(str);
    167       1.1   thorpej 		cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
    168       1.1   thorpej 		if (cp == NULL) {
    169       1.8     joerg 			prop_object_release(ps);
    170       1.1   thorpej 			return (NULL);
    171       1.1   thorpej 		}
    172       1.1   thorpej 		strcpy(cp, str);
    173       1.1   thorpej 		ps->ps_mutable = cp;
    174       1.1   thorpej 		ps->ps_size = len;
    175       1.1   thorpej 	}
    176       1.1   thorpej 	return (ps);
    177       1.1   thorpej }
    178       1.1   thorpej 
    179       1.1   thorpej /*
    180       1.1   thorpej  * prop_string_create_cstring_nocopy --
    181       1.1   thorpej  *	Create an immutable string that contains a refrence to the
    182       1.1   thorpej  *	provided C string.
    183       1.1   thorpej  */
    184       1.1   thorpej prop_string_t
    185       1.1   thorpej prop_string_create_cstring_nocopy(const char *str)
    186       1.1   thorpej {
    187       1.1   thorpej 	prop_string_t ps;
    188       1.1   thorpej 
    189       1.1   thorpej 	ps = _prop_string_alloc();
    190       1.1   thorpej 	if (ps != NULL) {
    191       1.1   thorpej 		ps->ps_immutable = str;
    192       1.1   thorpej 		ps->ps_size = strlen(str);
    193       1.1   thorpej 		ps->ps_flags |= PS_F_NOCOPY;
    194       1.1   thorpej 	}
    195       1.1   thorpej 	return (ps);
    196       1.1   thorpej }
    197       1.1   thorpej 
    198       1.1   thorpej /*
    199       1.1   thorpej  * prop_string_copy --
    200       1.1   thorpej  *	Copy a string.  If the original string is immutable, then the
    201       1.1   thorpej  *	copy is also immutable and references the same external data.
    202       1.1   thorpej  */
    203       1.1   thorpej prop_string_t
    204       1.1   thorpej prop_string_copy(prop_string_t ops)
    205       1.1   thorpej {
    206       1.1   thorpej 	prop_string_t ps;
    207       1.1   thorpej 
    208       1.3   thorpej 	if (! prop_object_is_string(ops))
    209       1.3   thorpej 		return (NULL);
    210       1.1   thorpej 
    211       1.1   thorpej 	ps = _prop_string_alloc();
    212       1.1   thorpej 	if (ps != NULL) {
    213       1.1   thorpej 		ps->ps_size = ops->ps_size;
    214       1.1   thorpej 		ps->ps_flags = ops->ps_flags;
    215       1.1   thorpej 		if (ops->ps_flags & PS_F_NOCOPY)
    216       1.1   thorpej 			ps->ps_immutable = ops->ps_immutable;
    217       1.1   thorpej 		else {
    218       1.1   thorpej 			char *cp = _PROP_MALLOC(ps->ps_size + 1, M_PROP_STRING);
    219       1.1   thorpej 			if (cp == NULL) {
    220       1.8     joerg 				prop_object_release(ps);
    221       1.1   thorpej 				return (NULL);
    222       1.1   thorpej 			}
    223       1.1   thorpej 			strcpy(cp, prop_string_contents(ops));
    224       1.1   thorpej 			ps->ps_mutable = cp;
    225       1.1   thorpej 		}
    226       1.1   thorpej 	}
    227       1.1   thorpej 	return (ps);
    228       1.1   thorpej }
    229       1.1   thorpej 
    230       1.1   thorpej /*
    231       1.1   thorpej  * prop_string_copy_mutable --
    232       1.1   thorpej  *	Copy a string, always returning a mutable copy.
    233       1.1   thorpej  */
    234       1.1   thorpej prop_string_t
    235       1.1   thorpej prop_string_copy_mutable(prop_string_t ops)
    236       1.1   thorpej {
    237       1.1   thorpej 	prop_string_t ps;
    238       1.1   thorpej 	char *cp;
    239       1.1   thorpej 
    240       1.3   thorpej 	if (! prop_object_is_string(ops))
    241       1.3   thorpej 		return (NULL);
    242       1.1   thorpej 
    243       1.1   thorpej 	ps = _prop_string_alloc();
    244       1.1   thorpej 	if (ps != NULL) {
    245       1.1   thorpej 		ps->ps_size = ops->ps_size;
    246       1.1   thorpej 		cp = _PROP_MALLOC(ps->ps_size + 1, M_PROP_STRING);
    247       1.1   thorpej 		if (cp == NULL) {
    248       1.8     joerg 			prop_object_release(ps);
    249       1.1   thorpej 			return (NULL);
    250       1.1   thorpej 		}
    251       1.1   thorpej 		strcpy(cp, prop_string_contents(ops));
    252       1.1   thorpej 		ps->ps_mutable = cp;
    253       1.1   thorpej 	}
    254       1.1   thorpej 	return (ps);
    255       1.1   thorpej }
    256       1.1   thorpej 
    257       1.1   thorpej /*
    258       1.1   thorpej  * prop_string_size --
    259       1.3   thorpej  *	Return the size of the string, not including the terminating NUL.
    260       1.1   thorpej  */
    261       1.1   thorpej size_t
    262       1.1   thorpej prop_string_size(prop_string_t ps)
    263       1.1   thorpej {
    264       1.1   thorpej 
    265       1.3   thorpej 	if (! prop_object_is_string(ps))
    266       1.3   thorpej 		return (0);
    267       1.3   thorpej 
    268       1.1   thorpej 	return (ps->ps_size);
    269       1.1   thorpej }
    270       1.1   thorpej 
    271       1.1   thorpej /*
    272       1.1   thorpej  * prop_string_mutable --
    273       1.7   thorpej  *	Return true if the string is a mutable string.
    274       1.1   thorpej  */
    275       1.7   thorpej bool
    276       1.1   thorpej prop_string_mutable(prop_string_t ps)
    277       1.1   thorpej {
    278       1.1   thorpej 
    279       1.3   thorpej 	if (! prop_object_is_string(ps))
    280       1.7   thorpej 		return (false);
    281       1.3   thorpej 
    282       1.1   thorpej 	return ((ps->ps_flags & PS_F_NOCOPY) == 0);
    283       1.1   thorpej }
    284       1.1   thorpej 
    285       1.1   thorpej /*
    286       1.1   thorpej  * prop_string_cstring --
    287       1.1   thorpej  *	Return a copy of the contents of the string as a C string.
    288       1.1   thorpej  *	The string is allocated with the M_TEMP malloc type.
    289       1.1   thorpej  */
    290       1.1   thorpej char *
    291       1.1   thorpej prop_string_cstring(prop_string_t ps)
    292       1.1   thorpej {
    293       1.1   thorpej 	char *cp;
    294       1.1   thorpej 
    295       1.3   thorpej 	if (! prop_object_is_string(ps))
    296       1.3   thorpej 		return (NULL);
    297       1.3   thorpej 
    298       1.1   thorpej 	cp = _PROP_MALLOC(ps->ps_size + 1, M_TEMP);
    299       1.1   thorpej 	if (cp != NULL)
    300       1.1   thorpej 		strcpy(cp, prop_string_contents(ps));
    301       1.1   thorpej 
    302       1.1   thorpej 	return (cp);
    303       1.1   thorpej }
    304       1.1   thorpej 
    305       1.1   thorpej /*
    306       1.1   thorpej  * prop_string_cstring_nocopy --
    307       1.1   thorpej  *	Return an immutable reference to the contents of the string
    308       1.1   thorpej  *	as a C string.
    309       1.1   thorpej  */
    310       1.1   thorpej const char *
    311       1.1   thorpej prop_string_cstring_nocopy(prop_string_t ps)
    312       1.1   thorpej {
    313       1.1   thorpej 
    314       1.3   thorpej 	if (! prop_object_is_string(ps))
    315       1.3   thorpej 		return (NULL);
    316       1.3   thorpej 
    317       1.1   thorpej 	return (prop_string_contents(ps));
    318       1.1   thorpej }
    319       1.1   thorpej 
    320       1.1   thorpej /*
    321       1.1   thorpej  * prop_string_append --
    322       1.7   thorpej  *	Append the contents of one string to another.  Returns true
    323       1.1   thorpej  *	upon success.  The destination string must be mutable.
    324       1.1   thorpej  */
    325       1.7   thorpej bool
    326       1.1   thorpej prop_string_append(prop_string_t dst, prop_string_t src)
    327       1.1   thorpej {
    328       1.1   thorpej 	char *ocp, *cp;
    329       1.1   thorpej 	size_t len;
    330       1.1   thorpej 
    331       1.3   thorpej 	if (! (prop_object_is_string(dst) &&
    332       1.3   thorpej 	       prop_object_is_string(src)))
    333       1.7   thorpej 		return (false);
    334       1.1   thorpej 
    335       1.1   thorpej 	if (dst->ps_flags & PS_F_NOCOPY)
    336       1.7   thorpej 		return (false);
    337       1.1   thorpej 
    338       1.1   thorpej 	len = dst->ps_size + src->ps_size;
    339       1.1   thorpej 	cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
    340       1.1   thorpej 	if (cp == NULL)
    341       1.7   thorpej 		return (false);
    342       1.1   thorpej 	sprintf(cp, "%s%s", prop_string_contents(dst),
    343       1.1   thorpej 		prop_string_contents(src));
    344       1.1   thorpej 	ocp = dst->ps_mutable;
    345       1.1   thorpej 	dst->ps_mutable = cp;
    346       1.1   thorpej 	dst->ps_size = len;
    347       1.1   thorpej 	if (ocp != NULL)
    348       1.1   thorpej 		_PROP_FREE(ocp, M_PROP_STRING);
    349       1.1   thorpej 
    350       1.7   thorpej 	return (true);
    351       1.1   thorpej }
    352       1.1   thorpej 
    353       1.1   thorpej /*
    354       1.1   thorpej  * prop_string_append_cstring --
    355       1.7   thorpej  *	Append a C string to a string.  Returns true upon success.
    356       1.1   thorpej  *	The destination string must be mutable.
    357       1.1   thorpej  */
    358       1.7   thorpej bool
    359       1.1   thorpej prop_string_append_cstring(prop_string_t dst, const char *src)
    360       1.1   thorpej {
    361       1.1   thorpej 	char *ocp, *cp;
    362       1.1   thorpej 	size_t len;
    363       1.1   thorpej 
    364       1.3   thorpej 	if (! prop_object_is_string(dst))
    365       1.7   thorpej 		return (false);
    366       1.3   thorpej 
    367       1.1   thorpej 	_PROP_ASSERT(src != NULL);
    368       1.1   thorpej 
    369       1.1   thorpej 	if (dst->ps_flags & PS_F_NOCOPY)
    370       1.7   thorpej 		return (false);
    371       1.1   thorpej 
    372       1.1   thorpej 	len = dst->ps_size + strlen(src);
    373       1.1   thorpej 	cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
    374       1.1   thorpej 	if (cp == NULL)
    375       1.7   thorpej 		return (false);
    376       1.1   thorpej 	sprintf(cp, "%s%s", prop_string_contents(dst), src);
    377       1.1   thorpej 	ocp = dst->ps_mutable;
    378       1.1   thorpej 	dst->ps_mutable = cp;
    379       1.1   thorpej 	dst->ps_size = len;
    380       1.1   thorpej 	if (ocp != NULL)
    381       1.1   thorpej 		_PROP_FREE(ocp, M_PROP_STRING);
    382       1.1   thorpej 
    383       1.7   thorpej 	return (true);
    384       1.1   thorpej }
    385       1.1   thorpej 
    386       1.1   thorpej /*
    387       1.1   thorpej  * prop_string_equals --
    388       1.7   thorpej  *	Return true if two strings are equivalent.
    389       1.1   thorpej  */
    390       1.7   thorpej bool
    391       1.1   thorpej prop_string_equals(prop_string_t str1, prop_string_t str2)
    392       1.1   thorpej {
    393       1.9     joerg 	if (!prop_object_is_string(str1) || !prop_object_is_string(str2))
    394       1.9     joerg 		return (false);
    395       1.1   thorpej 
    396       1.9     joerg 	return prop_object_equals(str1, str2);
    397       1.1   thorpej }
    398       1.1   thorpej 
    399       1.1   thorpej /*
    400       1.1   thorpej  * prop_string_equals_cstring --
    401       1.7   thorpej  *	Return true if the string is equivalent to the specified
    402       1.1   thorpej  *	C string.
    403       1.1   thorpej  */
    404       1.7   thorpej bool
    405       1.1   thorpej prop_string_equals_cstring(prop_string_t ps, const char *cp)
    406       1.1   thorpej {
    407       1.1   thorpej 
    408       1.3   thorpej 	if (! prop_object_is_string(ps))
    409       1.7   thorpej 		return (false);
    410       1.3   thorpej 
    411       1.1   thorpej 	return (strcmp(prop_string_contents(ps), cp) == 0);
    412       1.1   thorpej }
    413       1.1   thorpej 
    414       1.1   thorpej /*
    415       1.1   thorpej  * _prop_string_internalize --
    416       1.1   thorpej  *	Parse a <string>...</string> and return the object created from the
    417       1.1   thorpej  *	external representation.
    418       1.1   thorpej  */
    419       1.8     joerg /* ARGSUSED */
    420       1.8     joerg bool
    421       1.8     joerg _prop_string_internalize(prop_stack_t stack, prop_object_t *obj,
    422       1.8     joerg     struct _prop_object_internalize_context *ctx)
    423       1.1   thorpej {
    424       1.1   thorpej 	prop_string_t string;
    425       1.1   thorpej 	char *str;
    426       1.1   thorpej 	size_t len, alen;
    427       1.1   thorpej 
    428       1.8     joerg 	if (ctx->poic_is_empty_element) {
    429       1.8     joerg 		*obj = prop_string_create();
    430       1.8     joerg 		return (true);
    431       1.8     joerg 	}
    432       1.1   thorpej 
    433       1.1   thorpej 	/* No attributes recognized here. */
    434       1.1   thorpej 	if (ctx->poic_tagattr != NULL)
    435       1.8     joerg 		return (true);
    436       1.1   thorpej 
    437       1.1   thorpej 	/* Compute the length of the result. */
    438       1.6    martin 	if (_prop_object_internalize_decode_string(ctx, NULL, 0, &len,
    439       1.7   thorpej 						   NULL) == false)
    440       1.8     joerg 		return (true);
    441       1.1   thorpej 
    442       1.1   thorpej 	str = _PROP_MALLOC(len + 1, M_PROP_STRING);
    443       1.1   thorpej 	if (str == NULL)
    444       1.8     joerg 		return (true);
    445       1.1   thorpej 
    446       1.1   thorpej 	if (_prop_object_internalize_decode_string(ctx, str, len, &alen,
    447       1.7   thorpej 						   &ctx->poic_cp) == false ||
    448       1.1   thorpej 	    alen != len) {
    449       1.1   thorpej 		_PROP_FREE(str, M_PROP_STRING);
    450       1.8     joerg 		return (true);
    451       1.1   thorpej 	}
    452       1.1   thorpej 	str[len] = '\0';
    453       1.1   thorpej 
    454       1.1   thorpej 	if (_prop_object_internalize_find_tag(ctx, "string",
    455       1.7   thorpej 					      _PROP_TAG_TYPE_END) == false) {
    456       1.1   thorpej 		_PROP_FREE(str, M_PROP_STRING);
    457       1.8     joerg 		return (true);
    458       1.1   thorpej 	}
    459       1.1   thorpej 
    460       1.1   thorpej 	string = _prop_string_alloc();
    461       1.1   thorpej 	if (string == NULL) {
    462       1.1   thorpej 		_PROP_FREE(str, M_PROP_STRING);
    463       1.8     joerg 		return (true);
    464       1.1   thorpej 	}
    465       1.1   thorpej 
    466       1.1   thorpej 	string->ps_mutable = str;
    467       1.1   thorpej 	string->ps_size = len;
    468       1.8     joerg 	*obj = string;
    469       1.1   thorpej 
    470       1.8     joerg 	return (true);
    471       1.1   thorpej }
    472