xref: /netbsd-src/common/lib/libprop/prop_number.c (revision fad4c9f71477ae11cea2ee75ec82151ac770a534)
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