xref: /netbsd-src/common/lib/libprop/prop_bool.c (revision 1921cb5602567cfc8401cc953be22fe9d74238f2)
1 /*	$NetBSD: prop_bool.c,v 1.6 2006/10/03 15:45:04 thorpej 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 	boolean_t		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 boolean_t	_prop_bool_initialized;
52 
53 static void		_prop_bool_free(void *);
54 static boolean_t	_prop_bool_externalize(
55 				struct _prop_object_externalize_context *,
56 				void *);
57 static boolean_t	_prop_bool_equals(void *, void *);
58 
59 static const struct _prop_object_type _prop_object_type_bool = {
60 	.pot_type	=	PROP_TYPE_BOOL,
61 	.pot_free	=	_prop_bool_free,
62 	.pot_extern	=	_prop_bool_externalize,
63 	.pot_equals	=	_prop_bool_equals,
64 };
65 
66 #define	prop_object_is_bool(x)		\
67 	((x) != NULL && (x)->pb_obj.po_type == &_prop_object_type_bool)
68 
69 static void
70 _prop_bool_free(void *v)
71 {
72 
73 	/*
74 	 * This should never happen as we "leak" our initial reference
75 	 * count.
76 	 */
77 	/* XXX forced assertion failure? */
78 }
79 
80 static boolean_t
81 _prop_bool_externalize(struct _prop_object_externalize_context *ctx,
82 		       void *v)
83 {
84 	prop_bool_t pb = v;
85 
86 	return (_prop_object_externalize_empty_tag(ctx,
87 	    pb->pb_value ? "true" : "false"));
88 }
89 
90 static boolean_t
91 _prop_bool_equals(void *v1, void *v2)
92 {
93 	prop_bool_t b1 = v1;
94 	prop_bool_t b2 = v2;
95 
96 	if (! (prop_object_is_bool(b1) &&
97 	       prop_object_is_bool(b2)))
98 		return (FALSE);
99 
100 	/*
101 	 * Since we only ever allocate one true and one false,
102 	 * save ourselves a couple of memory operations.
103 	 */
104 	return (b1 == b2);
105 }
106 
107 static prop_bool_t
108 _prop_bool_alloc(boolean_t val)
109 {
110 	prop_bool_t pb;
111 
112 	if (! _prop_bool_initialized) {
113 		_PROP_MUTEX_LOCK(_prop_bool_initialized_mutex);
114 		if (! _prop_bool_initialized) {
115 			_prop_object_init(&_prop_bool_true.pb_obj,
116 					  &_prop_object_type_bool);
117 			_prop_bool_true.pb_value = TRUE;
118 
119 			_prop_object_init(&_prop_bool_false.pb_obj,
120 					  &_prop_object_type_bool);
121 			_prop_bool_false.pb_value = FALSE;
122 
123 			_prop_bool_initialized = TRUE;
124 		}
125 		_PROP_MUTEX_UNLOCK(_prop_bool_initialized_mutex);
126 	}
127 
128 	pb = val ? &_prop_bool_true : &_prop_bool_false;
129 	prop_object_retain(pb);
130 
131 	return (pb);
132 }
133 
134 /*
135  * prop_bool_create --
136  *	Create a prop_bool_t and initialize it with the
137  *	provided boolean value.
138  */
139 prop_bool_t
140 prop_bool_create(boolean_t val)
141 {
142 
143 	return (_prop_bool_alloc(val));
144 }
145 
146 /*
147  * prop_bool_copy --
148  *	Copy a prop_bool_t.
149  */
150 prop_bool_t
151 prop_bool_copy(prop_bool_t opb)
152 {
153 
154 	if (! prop_object_is_bool(opb))
155 		return (NULL);
156 
157 	/*
158 	 * Because we only ever allocate one true and one false, this
159 	 * can be reduced to a simple retain operation.
160 	 */
161 	prop_object_retain(opb);
162 	return (opb);
163 }
164 
165 /*
166  * prop_bool_true --
167  *	Get the value of a prop_bool_t.
168  */
169 boolean_t
170 prop_bool_true(prop_bool_t pb)
171 {
172 
173 	if (! prop_object_is_bool(pb))
174 		return (FALSE);
175 
176 	return (pb->pb_value);
177 }
178 
179 /*
180  * prop_bool_equals --
181  *	Return TRUE if the boolean values are equivalent.
182  */
183 boolean_t
184 prop_bool_equals(prop_bool_t b1, prop_bool_t b2)
185 {
186 
187 	return (_prop_bool_equals(b1, b2));
188 }
189 
190 /*
191  * _prop_bool_internalize --
192  *	Parse a <true/> or <false/> and return the object created from
193  *	the external representation.
194  */
195 prop_object_t
196 _prop_bool_internalize(struct _prop_object_internalize_context *ctx)
197 {
198 	boolean_t val;
199 
200 	/* No attributes, and it must be an empty element. */
201 	if (ctx->poic_tagattr != NULL ||
202 	    ctx->poic_is_empty_element == FALSE)
203 	    	return (NULL);
204 
205 	if (_PROP_TAG_MATCH(ctx, "true"))
206 		val = TRUE;
207 	else {
208 		_PROP_ASSERT(_PROP_TAG_MATCH(ctx, "false"));
209 		val = FALSE;
210 	}
211 
212 	return (prop_bool_create(val));
213 }
214