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