prop_number.c revision 1.4 1 /* $NetBSD: prop_number.c,v 1.4 2006/08/21 04:13:28 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 uint64_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%" PRIx64, 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 if (! (prop_object_is_number(num1) &&
108 prop_object_is_number(num2)))
109 return (FALSE);
110
111 return (num1->pn_number == num2->pn_number);
112 }
113
114 static prop_number_t
115 _prop_number_alloc(uint64_t val)
116 {
117 prop_number_t pn;
118
119 pn = _PROP_POOL_GET(_prop_number_pool);
120 if (pn != NULL) {
121 _prop_object_init(&pn->pn_obj, &_prop_object_type_number);
122
123 pn->pn_number = val;
124 }
125
126 return (pn);
127 }
128
129 /*
130 * prop_number_create_integer --
131 * Create a prop_number_t and initialize it with the
132 * provided integer value.
133 */
134 prop_number_t
135 prop_number_create_integer(uint64_t val)
136 {
137
138 return (_prop_number_alloc(val));
139 }
140
141 /*
142 * prop_number_copy --
143 * Copy a prop_number_t.
144 */
145 prop_number_t
146 prop_number_copy(prop_number_t opn)
147 {
148
149 if (! prop_object_is_number(opn))
150 return (NULL);
151
152 return (_prop_number_alloc(opn->pn_number));
153 }
154
155 /*
156 * prop_number_size --
157 * Return the size, in bits, required to hold the value of
158 * the specified number.
159 */
160 int
161 prop_number_size(prop_number_t pn)
162 {
163
164 if (! prop_object_is_number(pn))
165 return (0);
166
167 if (pn->pn_number > UINT32_MAX)
168 return (64);
169 if (pn->pn_number > UINT16_MAX)
170 return (32);
171 if (pn->pn_number > UINT8_MAX)
172 return (16);
173 return (8);
174 }
175
176 /*
177 * prop_number_integer_value --
178 * Get the integer value of a prop_number_t.
179 */
180 uint64_t
181 prop_number_integer_value(prop_number_t pn)
182 {
183
184 /*
185 * XXX Impossible to distinguish between "not a prop_number_t"
186 * XXX and "prop_number_t has a value of 0".
187 */
188 if (! prop_object_is_number(pn))
189 return (0);
190
191 return (pn->pn_number);
192 }
193
194 /*
195 * prop_number_equals --
196 * Return TRUE if two numbers are equivalent.
197 */
198 boolean_t
199 prop_number_equals(prop_number_t num1, prop_number_t num2)
200 {
201
202 return (_prop_number_equals(num1, num2));
203 }
204
205 /*
206 * prop_number_equals_integer --
207 * Return TRUE if the number is equivalent to the specified integer.
208 */
209 boolean_t
210 prop_number_equals_integer(prop_number_t pn, uint64_t val)
211 {
212
213 if (! prop_object_is_number(pn))
214 return (FALSE);
215
216 return (pn->pn_number == val);
217 }
218
219 /*
220 * _prop_number_internalize --
221 * Parse a <number>...</number> and return the object created from
222 * the external representation.
223 */
224 prop_object_t
225 _prop_number_internalize(struct _prop_object_internalize_context *ctx)
226 {
227 uint64_t val = 0;
228 char *cp;
229
230 /* No attributes, no empty elements. */
231 if (ctx->poic_tagattr != NULL || ctx->poic_is_empty_element)
232 return (NULL);
233
234 #ifndef _KERNEL
235 errno = 0;
236 #endif
237 val = strtoumax(ctx->poic_cp, &cp, 0);
238 #ifndef _KERNEL /* XXX can't check for ERANGE in the kernel */
239 if (val == UINTMAX_MAX && errno == ERANGE)
240 return (NULL);
241 #endif
242 ctx->poic_cp = cp;
243
244 if (_prop_object_internalize_find_tag(ctx, "integer",
245 _PROP_TAG_TYPE_END) == FALSE)
246 return (NULL);
247
248 return (_prop_number_alloc(val));
249 }
250