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 <prop/prop_bool.h>
33#include "prop_object_impl.h"
34
35struct _prop_bool {
36	struct _prop_object	pb_obj;
37	bool		pb_value;
38};
39
40static struct _prop_bool _prop_bool_true;
41static struct _prop_bool _prop_bool_false;
42
43static _prop_object_free_rv_t
44		_prop_bool_free(prop_stack_t, prop_object_t *);
45static bool	_prop_bool_externalize(
46				struct _prop_object_externalize_context *,
47				void *);
48static _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
53static 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 */
64static _prop_object_free_rv_t
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
76static bool
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 */
87static _prop_object_equals_rv_t
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
109_PROP_ONCE_DECL(_prop_bool_init_once)
110
111static 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
126static prop_bool_t
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 */
143prop_bool_t
144prop_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 */
154prop_bool_t
155prop_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 */
173bool
174prop_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 */
187bool
188prop_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 */
203bool
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