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