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