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