xref: /netbsd-src/common/lib/libprop/prop_bool.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: prop_bool.c,v 1.12 2007/08/30 12:23:54 joerg Exp $	*/
2 
3 /*-
4  * Copyright (c) 2006 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  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the NetBSD
21  *      Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <prop/prop_bool.h>
40 #include "prop_object_impl.h"
41 
42 struct _prop_bool {
43 	struct _prop_object	pb_obj;
44 	bool		pb_value;
45 };
46 
47 static struct _prop_bool _prop_bool_true;
48 static struct _prop_bool _prop_bool_false;
49 
50 _PROP_MUTEX_DECL_STATIC(_prop_bool_initialized_mutex)
51 static bool	_prop_bool_initialized;
52 
53 static int		_prop_bool_free(prop_stack_t, prop_object_t *);
54 static bool	_prop_bool_externalize(
55 				struct _prop_object_externalize_context *,
56 				void *);
57 static bool	_prop_bool_equals(prop_object_t, prop_object_t,
58 				  void **, void **,
59 				  prop_object_t *, prop_object_t *);
60 
61 static const struct _prop_object_type _prop_object_type_bool = {
62 	.pot_type	=	PROP_TYPE_BOOL,
63 	.pot_free	=	_prop_bool_free,
64 	.pot_extern	=	_prop_bool_externalize,
65 	.pot_equals	=	_prop_bool_equals,
66 };
67 
68 #define	prop_object_is_bool(x)		\
69 	((x) != NULL && (x)->pb_obj.po_type == &_prop_object_type_bool)
70 
71 /* ARGSUSED */
72 static int
73 _prop_bool_free(prop_stack_t stack, prop_object_t *obj)
74 {
75 	/*
76 	 * This should never happen as we "leak" our initial reference
77 	 * count.
78 	 */
79 
80 	/* XXX forced assertion failure? */
81 	return (_PROP_OBJECT_FREE_DONE);
82 }
83 
84 static bool
85 _prop_bool_externalize(struct _prop_object_externalize_context *ctx,
86 		       void *v)
87 {
88 	prop_bool_t pb = v;
89 
90 	return (_prop_object_externalize_empty_tag(ctx,
91 	    pb->pb_value ? "true" : "false"));
92 }
93 
94 /* ARGSUSED */
95 static bool
96 _prop_bool_equals(prop_object_t v1, prop_object_t v2,
97     void **stored_pointer1, void **stored_pointer2,
98     prop_object_t *next_obj1, prop_object_t *next_obj2)
99 {
100 	prop_bool_t b1 = v1;
101 	prop_bool_t b2 = v2;
102 
103 	if (! (prop_object_is_bool(b1) &&
104 	       prop_object_is_bool(b2)))
105 		return (_PROP_OBJECT_EQUALS_FALSE);
106 
107 	/*
108 	 * Since we only ever allocate one true and one false,
109 	 * save ourselves a couple of memory operations.
110 	 */
111 	if (b1 == b2)
112 		return (_PROP_OBJECT_EQUALS_TRUE);
113 	else
114 		return (_PROP_OBJECT_EQUALS_FALSE);
115 }
116 
117 static prop_bool_t
118 _prop_bool_alloc(bool val)
119 {
120 	prop_bool_t pb;
121 
122 	if (! _prop_bool_initialized) {
123 		_PROP_MUTEX_LOCK(_prop_bool_initialized_mutex);
124 		if (! _prop_bool_initialized) {
125 			_prop_object_init(&_prop_bool_true.pb_obj,
126 					  &_prop_object_type_bool);
127 			_prop_bool_true.pb_value = true;
128 
129 			_prop_object_init(&_prop_bool_false.pb_obj,
130 					  &_prop_object_type_bool);
131 			_prop_bool_false.pb_value = false;
132 
133 			_prop_bool_initialized = true;
134 		}
135 		_PROP_MUTEX_UNLOCK(_prop_bool_initialized_mutex);
136 	}
137 
138 	pb = val ? &_prop_bool_true : &_prop_bool_false;
139 	prop_object_retain(pb);
140 
141 	return (pb);
142 }
143 
144 /*
145  * prop_bool_create --
146  *	Create a prop_bool_t and initialize it with the
147  *	provided boolean value.
148  */
149 prop_bool_t
150 prop_bool_create(bool val)
151 {
152 
153 	return (_prop_bool_alloc(val));
154 }
155 
156 /*
157  * prop_bool_copy --
158  *	Copy a prop_bool_t.
159  */
160 prop_bool_t
161 prop_bool_copy(prop_bool_t opb)
162 {
163 
164 	if (! prop_object_is_bool(opb))
165 		return (NULL);
166 
167 	/*
168 	 * Because we only ever allocate one true and one false, this
169 	 * can be reduced to a simple retain operation.
170 	 */
171 	prop_object_retain(opb);
172 	return (opb);
173 }
174 
175 /*
176  * prop_bool_true --
177  *	Get the value of a prop_bool_t.
178  */
179 bool
180 prop_bool_true(prop_bool_t pb)
181 {
182 
183 	if (! prop_object_is_bool(pb))
184 		return (false);
185 
186 	return (pb->pb_value);
187 }
188 
189 /*
190  * prop_bool_equals --
191  *	Return true if the boolean values are equivalent.
192  */
193 bool
194 prop_bool_equals(prop_bool_t b1, prop_bool_t b2)
195 {
196 	if (!prop_object_is_bool(b1) || !prop_object_is_bool(b2))
197 		return (false);
198 
199 	return (prop_object_equals(b1, b2));
200 }
201 
202 /*
203  * _prop_bool_internalize --
204  *	Parse a <true/> or <false/> and return the object created from
205  *	the external representation.
206  */
207 
208 /* ARGSUSED */
209 bool
210 _prop_bool_internalize(prop_stack_t stack, prop_object_t *obj,
211     struct _prop_object_internalize_context *ctx)
212 {
213 	bool val;
214 
215 	/* No attributes, and it must be an empty element. */
216 	if (ctx->poic_tagattr != NULL ||
217 	    ctx->poic_is_empty_element == false)
218 	    	return (true);
219 
220 	if (_PROP_TAG_MATCH(ctx, "true"))
221 		val = true;
222 	else {
223 		_PROP_ASSERT(_PROP_TAG_MATCH(ctx, "false"));
224 		val = false;
225 	}
226 	*obj = prop_bool_create(val);
227 	return (true);
228 }
229