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