Home | History | Annotate | Line # | Download | only in libprop
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