Home | History | Annotate | Line # | Download | only in libprop
      1 /*	$NetBSD: prop_bool.c,v 1.24 2025/05/14 03:25:45 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2006, 2025 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     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.
     18  *
     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.
     30  */
     31 
     32 #include "prop_object_impl.h"
     33 #include <prop/prop_bool.h>
     34 
     35 struct _prop_bool {
     36 	struct _prop_object	pb_obj;
     37 	bool			pb_value;
     38 };
     39 
     40 static struct _prop_bool _prop_bool_true;
     41 static struct _prop_bool _prop_bool_false;
     42 
     43 static const char truestr[] = "true";
     44 static const char falsestr[] = "false";
     45 
     46 static const struct _prop_object_type_tags _prop_bool_true_type_tags = {
     47 	.xml_tag	=	truestr,
     48 	.json_open_tag	=	truestr,
     49 };
     50 static const struct _prop_object_type_tags _prop_bool_false_type_tags = {
     51 	.xml_tag	=	falsestr,
     52 	.json_open_tag	=	falsestr,
     53 };
     54 
     55 static _prop_object_free_rv_t
     56 		_prop_bool_free(prop_stack_t, prop_object_t *);
     57 static bool	_prop_bool_externalize(
     58 				struct _prop_object_externalize_context *,
     59 				void *);
     60 static _prop_object_equals_rv_t
     61 		_prop_bool_equals(prop_object_t, prop_object_t,
     62 				  void **, void **,
     63 				  prop_object_t *, prop_object_t *);
     64 
     65 static const struct _prop_object_type _prop_object_type_bool = {
     66 	.pot_type	=	PROP_TYPE_BOOL,
     67 	.pot_free	=	_prop_bool_free,
     68 	.pot_extern	=	_prop_bool_externalize,
     69 	.pot_equals	=	_prop_bool_equals,
     70 };
     71 
     72 #define	prop_object_is_bool(x)		\
     73 	((x) != NULL && (x)->pb_obj.po_type == &_prop_object_type_bool)
     74 
     75 /* ARGSUSED */
     76 static _prop_object_free_rv_t
     77 _prop_bool_free(prop_stack_t stack, prop_object_t *obj)
     78 {
     79 	/*
     80 	 * This should never happen as we "leak" our initial reference
     81 	 * count.
     82 	 */
     83 
     84 	/* XXX forced assertion failure? */
     85 	return (_PROP_OBJECT_FREE_DONE);
     86 }
     87 
     88 static bool
     89 _prop_bool_externalize(struct _prop_object_externalize_context *ctx,
     90 		       void *v)
     91 {
     92 	prop_bool_t pb = v;
     93 	const struct _prop_object_type_tags *tags =
     94 	    pb->pb_value ? &_prop_bool_true_type_tags
     95 			 : &_prop_bool_false_type_tags;
     96 
     97 	return _prop_extern_append_empty_tag(ctx, tags);
     98 }
     99 
    100 /* ARGSUSED */
    101 static _prop_object_equals_rv_t
    102 _prop_bool_equals(prop_object_t v1, prop_object_t v2,
    103     void **stored_pointer1, void **stored_pointer2,
    104     prop_object_t *next_obj1, prop_object_t *next_obj2)
    105 {
    106 	prop_bool_t b1 = v1;
    107 	prop_bool_t b2 = v2;
    108 
    109 	if (! (prop_object_is_bool(b1) &&
    110 	       prop_object_is_bool(b2)))
    111 		return (_PROP_OBJECT_EQUALS_FALSE);
    112 
    113 	/*
    114 	 * Since we only ever allocate one true and one false,
    115 	 * save ourselves a couple of memory operations.
    116 	 */
    117 	if (b1 == b2)
    118 		return (_PROP_OBJECT_EQUALS_TRUE);
    119 	else
    120 		return (_PROP_OBJECT_EQUALS_FALSE);
    121 }
    122 
    123 _PROP_ONCE_DECL(_prop_bool_init_once)
    124 
    125 static int
    126 _prop_bool_init(void)
    127 {
    128 
    129 	_prop_object_init(&_prop_bool_true.pb_obj,
    130 	    &_prop_object_type_bool);
    131 	_prop_bool_true.pb_value = true;
    132 
    133 	_prop_object_init(&_prop_bool_false.pb_obj,
    134 	    &_prop_object_type_bool);
    135 	_prop_bool_false.pb_value = false;
    136 
    137 	return 0;
    138 }
    139 
    140 static prop_bool_t
    141 _prop_bool_alloc(bool val)
    142 {
    143 	prop_bool_t pb;
    144 
    145 	_PROP_ONCE_RUN(_prop_bool_init_once, _prop_bool_init);
    146 	pb = val ? &_prop_bool_true : &_prop_bool_false;
    147 	prop_object_retain(pb);
    148 
    149 	return (pb);
    150 }
    151 
    152 /*
    153  * prop_bool_create --
    154  *	Create a prop_bool_t and initialize it with the
    155  *	provided boolean value.
    156  */
    157 _PROP_EXPORT prop_bool_t
    158 prop_bool_create(bool val)
    159 {
    160 
    161 	return (_prop_bool_alloc(val));
    162 }
    163 
    164 /*
    165  * prop_bool_copy --
    166  *	Copy a prop_bool_t.
    167  */
    168 _PROP_EXPORT prop_bool_t
    169 prop_bool_copy(prop_bool_t opb)
    170 {
    171 
    172 	if (! prop_object_is_bool(opb))
    173 		return (NULL);
    174 
    175 	/*
    176 	 * Because we only ever allocate one true and one false, this
    177 	 * can be reduced to a simple retain operation.
    178 	 */
    179 	prop_object_retain(opb);
    180 	return (opb);
    181 }
    182 
    183 /*
    184  * prop_bool_value --
    185  *	Get the value of a prop_bool_t.
    186  */
    187 _PROP_EXPORT bool
    188 prop_bool_value(prop_bool_t pb)
    189 {
    190 
    191 	if (! prop_object_is_bool(pb))
    192 		return (false);
    193 
    194 	return (pb->pb_value);
    195 }
    196 
    197 /*
    198  * prop_bool_true --
    199  *	Historical alias for prop_bool_value().
    200  */
    201 _PROP_EXPORT bool
    202 prop_bool_true(prop_bool_t pb)
    203 {
    204 	return prop_bool_value(pb);
    205 }
    206 
    207 /*
    208  * prop_bool_equals --
    209  *	Return true if the boolean values are equivalent.
    210  */
    211 _PROP_EXPORT bool
    212 prop_bool_equals(prop_bool_t b1, prop_bool_t b2)
    213 {
    214 	if (!prop_object_is_bool(b1) || !prop_object_is_bool(b2))
    215 		return (false);
    216 
    217 	return (prop_object_equals(b1, b2));
    218 }
    219 
    220 /*
    221  * _prop_bool_internalize --
    222  *	Parse a <true/> or <false/> and return the object created from
    223  *	the external representation.
    224  */
    225 
    226 /* ARGSUSED */
    227 bool
    228 _prop_bool_internalize(prop_stack_t stack, prop_object_t *obj,
    229     struct _prop_object_internalize_context *ctx)
    230 {
    231 	bool val;
    232 
    233 	/*
    234 	 * N.B. For internalizing JSON, the layer above us has
    235 	 * made it look like XML for this object type.
    236 	 */
    237 
    238 	/* No attributes, and it must be an empty element. */
    239 	if (ctx->poic_tagattr != NULL ||
    240 	    ctx->poic_is_empty_element == false)
    241 	    	return (true);
    242 
    243 	if (_PROP_TAG_MATCH(ctx, truestr))
    244 		val = true;
    245 	else {
    246 		_PROP_ASSERT(_PROP_TAG_MATCH(ctx, falsestr));
    247 		val = false;
    248 	}
    249 	*obj = prop_bool_create(val);
    250 	return (true);
    251 }
    252