prop_bool.c revision 1.10 1 /* $NetBSD: prop_bool.c,v 1.10 2007/08/16 16:28:17 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 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 void _prop_bool_free(void *);
54 static bool _prop_bool_externalize(
55 struct _prop_object_externalize_context *,
56 void *);
57 static bool _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 bool
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 bool
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(bool 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(bool 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 bool
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 bool
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 bool 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