1 /* $NetBSD: prop_number.c,v 1.2 2006/05/18 03:05:19 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_number.h> 40 #include "prop_object_impl.h" 41 42 #if defined(_KERNEL) 43 #include <sys/inttypes.h> 44 #include <sys/systm.h> 45 #elif defined(_STANDALONE) 46 #include <sys/param.h> 47 #include <lib/libkern/libkern.h> 48 #else 49 #include <errno.h> 50 #include <stdlib.h> 51 #include <inttypes.h> 52 #endif 53 54 struct _prop_number { 55 struct _prop_object pn_obj; 56 uintmax_t pn_number; 57 }; 58 59 _PROP_POOL_INIT(_prop_number_pool, sizeof(struct _prop_number), "propnmbr") 60 61 static void _prop_number_free(void *); 62 static boolean_t _prop_number_externalize( 63 struct _prop_object_externalize_context *, 64 void *); 65 static boolean_t _prop_number_equals(void *, void *); 66 67 static const struct _prop_object_type _prop_object_type_number = { 68 .pot_type = PROP_TYPE_NUMBER, 69 .pot_free = _prop_number_free, 70 .pot_extern = _prop_number_externalize, 71 .pot_equals = _prop_number_equals, 72 }; 73 74 #define prop_object_is_number(x) \ 75 ((x)->pn_obj.po_type == &_prop_object_type_number) 76 77 static void 78 _prop_number_free(void *v) 79 { 80 81 _PROP_POOL_PUT(_prop_number_pool, v); 82 } 83 84 static boolean_t 85 _prop_number_externalize(struct _prop_object_externalize_context *ctx, 86 void *v) 87 { 88 prop_number_t pn = v; 89 char tmpstr[32]; 90 91 sprintf(tmpstr, "0x%" PRIxMAX, pn->pn_number); 92 93 if (_prop_object_externalize_start_tag(ctx, "integer") == FALSE || 94 _prop_object_externalize_append_cstring(ctx, tmpstr) == FALSE || 95 _prop_object_externalize_end_tag(ctx, "integer") == FALSE) 96 return (FALSE); 97 98 return (TRUE); 99 } 100 101 static boolean_t 102 _prop_number_equals(void *v1, void *v2) 103 { 104 prop_number_t num1 = v1; 105 prop_number_t num2 = v2; 106 107 _PROP_ASSERT(prop_object_is_number(num1)); 108 _PROP_ASSERT(prop_object_is_number(num2)); 109 return (num1->pn_number == num2->pn_number); 110 } 111 112 static prop_number_t 113 _prop_number_alloc(uintmax_t val) 114 { 115 prop_number_t pn; 116 117 pn = _PROP_POOL_GET(_prop_number_pool); 118 if (pn != NULL) { 119 _prop_object_init(&pn->pn_obj, &_prop_object_type_number); 120 121 pn->pn_number = val; 122 } 123 124 return (pn); 125 } 126 127 /* 128 * prop_number_create_integer -- 129 * Create a prop_number_t and initialize it with the 130 * provided integer value. 131 */ 132 prop_number_t 133 prop_number_create_integer(uintmax_t val) 134 { 135 136 return (_prop_number_alloc(val)); 137 } 138 139 /* 140 * prop_number_copy -- 141 * Copy a prop_number_t. 142 */ 143 prop_number_t 144 prop_number_copy(prop_number_t opn) 145 { 146 147 _PROP_ASSERT(prop_object_is_number(opn)); 148 149 return (_prop_number_alloc(opn->pn_number)); 150 } 151 152 /* 153 * prop_number_size -- 154 * Return the size, in bits, required to hold the value of 155 * the specified number. 156 */ 157 int 158 prop_number_size(prop_number_t pn) 159 { 160 161 _PROP_ASSERT(prop_object_is_number(pn)); 162 if (pn->pn_number > UINT32_MAX) 163 return (64); 164 if (pn->pn_number > UINT16_MAX) 165 return (32); 166 if (pn->pn_number > UINT8_MAX) 167 return (16); 168 return (8); 169 } 170 171 /* 172 * prop_number_integer_value -- 173 * Get the integer value of a prop_number_t. 174 */ 175 uintmax_t 176 prop_number_integer_value(prop_number_t pn) 177 { 178 179 _PROP_ASSERT(prop_object_is_number(pn)); 180 return (pn->pn_number); 181 } 182 183 /* 184 * prop_number_equals -- 185 * Return TRUE if two numbers are equivalent. 186 */ 187 boolean_t 188 prop_number_equals(prop_number_t num1, prop_number_t num2) 189 { 190 191 return (_prop_number_equals(num1, num2)); 192 } 193 194 /* 195 * prop_number_equals_integer -- 196 * Return TRUE if the number is equivalent to the specified integer. 197 */ 198 boolean_t 199 prop_number_equals_integer(prop_number_t pn, uintmax_t val) 200 { 201 202 _PROP_ASSERT(prop_object_is_number(pn)); 203 return (pn->pn_number == val); 204 } 205 206 /* 207 * _prop_number_internalize -- 208 * Parse a <number>...</number> and return the object created from 209 * the external representation. 210 */ 211 prop_object_t 212 _prop_number_internalize(struct _prop_object_internalize_context *ctx) 213 { 214 uintmax_t val = 0; 215 char *cp; 216 217 /* No attributes, no empty elements. */ 218 if (ctx->poic_tagattr != NULL || ctx->poic_is_empty_element) 219 return (NULL); 220 221 #ifndef _KERNEL 222 errno = 0; 223 #endif 224 val = strtoumax(ctx->poic_cp, &cp, 0); 225 #ifndef _KERNEL /* XXX can't check for ERANGE in the kernel */ 226 if (val == UINTMAX_MAX && errno == ERANGE) 227 return (NULL); 228 #endif 229 ctx->poic_cp = cp; 230 231 if (_prop_object_internalize_find_tag(ctx, "integer", 232 _PROP_TAG_TYPE_END) == FALSE) 233 return (NULL); 234 235 return (_prop_number_alloc(val)); 236 } 237