prop_number.c revision 1.2 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