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