Home | History | Annotate | Line # | Download | only in libprop
prop_string.c revision 1.12.26.1
      1  1.12.26.1  christos /*	$NetBSD: prop_string.c,v 1.12.26.1 2019/06/10 21:41:08 christos 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_object_impl.h"
     33  1.12.26.1  christos #include <prop/prop_string.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.11   thorpej static _prop_object_free_rv_t
     55       1.11   thorpej 		_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.11   thorpej static _prop_object_equals_rv_t
     60       1.11   thorpej 		_prop_string_equals(prop_object_t, prop_object_t,
     61       1.11   thorpej 				    void **, void **,
     62       1.11   thorpej 				    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.11   thorpej 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.11   thorpej 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.12  christos 	snprintf(cp, len + 1, "%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.12  christos 	snprintf(cp, len + 1, "%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