Home | History | Annotate | Download | only in common
      1  0  stevel /*
      2  0  stevel  * CDDL HEADER START
      3  0  stevel  *
      4  0  stevel  * The contents of this file are subject to the terms of the
      5  0  stevel  * Common Development and Distribution License, Version 1.0 only
      6  0  stevel  * (the "License").  You may not use this file except in compliance
      7  0  stevel  * with the License.
      8  0  stevel  *
      9  0  stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  0  stevel  * or http://www.opensolaris.org/os/licensing.
     11  0  stevel  * See the License for the specific language governing permissions
     12  0  stevel  * and limitations under the License.
     13  0  stevel  *
     14  0  stevel  * When distributing Covered Code, include this CDDL HEADER in each
     15  0  stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  0  stevel  * If applicable, add the following below this CDDL HEADER, with the
     17  0  stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     18  0  stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  0  stevel  *
     20  0  stevel  * CDDL HEADER END
     21  0  stevel  */
     22  0  stevel /*
     23  0  stevel  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
     24  0  stevel  * Use is subject to license terms.
     25  0  stevel  */
     26  0  stevel 
     27  0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28  0  stevel 
     29  0  stevel #include <stdio.h>
     30  0  stevel #include <stdlib.h>
     31  0  stevel #include <string.h>
     32  0  stevel #include <strings.h>
     33  0  stevel #include <pool.h>
     34  0  stevel #include "pool_internal.h"
     35  0  stevel 
     36  0  stevel /*
     37  0  stevel  * libpool Value Manipulation Routines
     38  0  stevel  *
     39  0  stevel  * pool_value.c implements the value (pool_value_t) functionality for
     40  0  stevel  * libpool. The datatypes supported are: uint64_t, int64_t, double,
     41  0  stevel  * uchar_t (boolean), const char * (string). Values are used to
     42  0  stevel  * represent data stored to and retrieved from the datastore in a
     43  0  stevel  * simple discriminated union.
     44  0  stevel  *
     45  0  stevel  * Values are dynamically allocated using pool_value_alloc() and
     46  0  stevel  * destroyed using pool_value_free().
     47  0  stevel  *
     48  0  stevel  * Values may be allocated statically for internal use in
     49  0  stevel  * libpool. Statically allocated pool_value_t variables must be
     50  0  stevel  * initialised with the POOL_VALUE_INITIALIZER macro, otherwise the
     51  0  stevel  * results are unpredictable.
     52  0  stevel  *
     53  0  stevel  * A pool_value_t variable can be used to store values in any of the
     54  0  stevel  * supported datatypes.
     55  0  stevel  *
     56  0  stevel  * A pool_value_t's name and string value are limited in size to
     57  0  stevel  * PV_NAME_MAX_LEN and PV_VALUE_MAX_LEN respectively. Attempting to
     58  0  stevel  * store values which are greater than this in length will fail with a
     59  0  stevel  * POE_BADPARAM error.
     60  0  stevel  */
     61  0  stevel 
     62  0  stevel /*
     63  0  stevel  * Get the uint64_t data held by the value. If the data type isn't
     64  0  stevel  * uint64_t return PO_FAIL and set pool_error to be POE_BAD_PROP_TYPE.
     65  0  stevel  */
     66  0  stevel int
     67  0  stevel pool_value_get_uint64(const pool_value_t *pv, uint64_t *result)
     68  0  stevel {
     69  0  stevel 	if (pv->pv_class != POC_UINT) {
     70  0  stevel 		pool_seterror(POE_BAD_PROP_TYPE);
     71  0  stevel 		return (PO_FAIL);
     72  0  stevel 	}
     73  0  stevel 	*result = pv->pv_u.u;
     74  0  stevel 	return (PO_SUCCESS);
     75  0  stevel }
     76  0  stevel 
     77  0  stevel /*
     78  0  stevel  * Get the int64_t data held by the value. If the data type isn't
     79  0  stevel  * int64_t return PO_FAIL and set pool_error to be POE_BAD_PROP_TYPE.
     80  0  stevel  */
     81  0  stevel int
     82  0  stevel pool_value_get_int64(const pool_value_t *pv, int64_t *result)
     83  0  stevel {
     84  0  stevel 	if (pv->pv_class != POC_INT) {
     85  0  stevel 		pool_seterror(POE_BAD_PROP_TYPE);
     86  0  stevel 		return (PO_FAIL);
     87  0  stevel 	}
     88  0  stevel 	*result = pv->pv_u.i;
     89  0  stevel 	return (PO_SUCCESS);
     90  0  stevel }
     91  0  stevel 
     92  0  stevel /*
     93  0  stevel  * Get the double data held by the value. If the data type isn't
     94  0  stevel  * double return PO_FAIL and set pool_error to be POE_BAD_PROP_TYPE.
     95  0  stevel  */
     96  0  stevel 
     97  0  stevel int
     98  0  stevel pool_value_get_double(const pool_value_t *pv, double *result)
     99  0  stevel {
    100  0  stevel 	if (pv->pv_class != POC_DOUBLE) {
    101  0  stevel 		pool_seterror(POE_BAD_PROP_TYPE);
    102  0  stevel 		return (PO_FAIL);
    103  0  stevel 	}
    104  0  stevel 	*result = pv->pv_u.d;
    105  0  stevel 	return (PO_SUCCESS);
    106  0  stevel }
    107  0  stevel 
    108  0  stevel /*
    109  0  stevel  * Get the boolean data held by the value. If the data type isn't
    110  0  stevel  * boolean return PO_FAIL and set pool_error to be POE_BAD_PROP_TYPE.
    111  0  stevel  */
    112  0  stevel int
    113  0  stevel pool_value_get_bool(const pool_value_t *pv, uchar_t *result)
    114  0  stevel {
    115  0  stevel 	if (pv->pv_class != POC_BOOL) {
    116  0  stevel 		pool_seterror(POE_BAD_PROP_TYPE);
    117  0  stevel 		return (PO_FAIL);
    118  0  stevel 	}
    119  0  stevel 	*result = pv->pv_u.b;
    120  0  stevel 	return (PO_SUCCESS);
    121  0  stevel }
    122  0  stevel 
    123  0  stevel /*
    124  0  stevel  * Get the string data held by the value. If the data type isn't
    125  0  stevel  * string return PO_FAIL and set pool_error to be POE_BAD_PROP_TYPE.
    126  0  stevel  */
    127  0  stevel int
    128  0  stevel pool_value_get_string(const pool_value_t *pv, const char **result)
    129  0  stevel {
    130  0  stevel 	if (pv->pv_class != POC_STRING) {
    131  0  stevel 		pool_seterror(POE_BAD_PROP_TYPE);
    132  0  stevel 		return (PO_FAIL);
    133  0  stevel 	}
    134  0  stevel 	*result = pv->pv_u.s;
    135  0  stevel 	return (PO_SUCCESS);
    136  0  stevel }
    137  0  stevel 
    138  0  stevel /*
    139  0  stevel  * Get the type of the data held by the value. If the value has never
    140  0  stevel  * been used to store data, then the type is POC_INVAL.
    141  0  stevel  */
    142  0  stevel pool_value_class_t
    143  0  stevel pool_value_get_type(const pool_value_t *pv)
    144  0  stevel {
    145  0  stevel 	return (pv->pv_class);
    146  0  stevel }
    147  0  stevel 
    148  0  stevel /*
    149  0  stevel  * Set the value's data to the supplied uint64_t data. Update the type
    150  0  stevel  * of the value data to POC_UINT.
    151  0  stevel  */
    152  0  stevel void
    153  0  stevel pool_value_set_uint64(pool_value_t *pv, uint64_t val)
    154  0  stevel {
    155  0  stevel 	if (pv->pv_class == POC_STRING)
    156  0  stevel 		atom_free(pv->pv_u.s);
    157  0  stevel 	pv->pv_class = POC_UINT;
    158  0  stevel 	pv->pv_u.u = val;
    159  0  stevel }
    160  0  stevel 
    161  0  stevel /*
    162  0  stevel  * Set the value's data to the supplied int64_t data. Update the type
    163  0  stevel  * of the value data to POC_INT.
    164  0  stevel  */
    165  0  stevel void
    166  0  stevel pool_value_set_int64(pool_value_t *pv, int64_t val)
    167  0  stevel {
    168  0  stevel 	if (pv->pv_class == POC_STRING)
    169  0  stevel 		atom_free(pv->pv_u.s);
    170  0  stevel 	pv->pv_class = POC_INT;
    171  0  stevel 	pv->pv_u.i = val;
    172  0  stevel }
    173  0  stevel 
    174  0  stevel /*
    175  0  stevel  * Set the value's data to the supplied double data. Update the type
    176  0  stevel  * of the value data to POC_DOUBLE.
    177  0  stevel  */
    178  0  stevel 
    179  0  stevel void
    180  0  stevel pool_value_set_double(pool_value_t *pv, double val)
    181  0  stevel {
    182  0  stevel 	if (pv->pv_class == POC_STRING)
    183  0  stevel 		atom_free(pv->pv_u.s);
    184  0  stevel 	pv->pv_class = POC_DOUBLE;
    185  0  stevel 	pv->pv_u.d = val;
    186  0  stevel }
    187  0  stevel 
    188  0  stevel /*
    189  0  stevel  * Set the value's data to the supplied uchar_t data. Update the type
    190  0  stevel  * of the value data to POC_BOOL.
    191  0  stevel  */
    192  0  stevel void
    193  0  stevel pool_value_set_bool(pool_value_t *pv, uchar_t val)
    194  0  stevel {
    195  0  stevel 	if (pv->pv_class == POC_STRING)
    196  0  stevel 		atom_free(pv->pv_u.s);
    197  0  stevel 	pv->pv_class = POC_BOOL;
    198  0  stevel 	pv->pv_u.b = !!val;	/* Lock value at 0 or 1 */
    199  0  stevel }
    200  0  stevel 
    201  0  stevel /*
    202  0  stevel  * Try to make an internal copy of the val, returning PO_SUCCESS or
    203  0  stevel  * PO_FAIL if the copy works or fails.
    204  0  stevel  */
    205  0  stevel int
    206  0  stevel pool_value_set_string(pool_value_t *pv, const char *val)
    207  0  stevel {
    208  0  stevel 	if (pv->pv_class == POC_STRING)
    209  0  stevel 		atom_free(pv->pv_u.s);
    210  0  stevel 	pv->pv_class = POC_STRING;
    211  0  stevel 	if (val == NULL || strlen(val) >= PV_VALUE_MAX_LEN) {
    212  0  stevel 		pool_seterror(POE_BADPARAM);
    213  0  stevel 		return (PO_FAIL);
    214  0  stevel 	} else {
    215  0  stevel 		if ((pv->pv_u.s = atom_string(val)) == NULL)
    216  0  stevel 			return (PO_FAIL);
    217  0  stevel 	}
    218  0  stevel 	return (PO_SUCCESS);
    219  0  stevel }
    220  0  stevel 
    221  0  stevel /*
    222  0  stevel  * Allocate a pool_value_t structure and initialise it to 0. Set the
    223  0  stevel  * type to POC_INVAL and return a pointer to the new pool_value_t. If
    224  0  stevel  * memory allocation fails, set POE_SYSTEM and return NULL.
    225  0  stevel  */
    226  0  stevel pool_value_t *
    227  0  stevel pool_value_alloc(void)
    228  0  stevel {
    229  0  stevel 	pool_value_t *val;
    230  0  stevel 
    231  0  stevel 	if ((val = malloc(sizeof (pool_value_t))) == NULL) {
    232  0  stevel 		pool_seterror(POE_SYSTEM);
    233  0  stevel 		return (NULL);
    234  0  stevel 	}
    235  0  stevel 	(void) memset(val, 0, sizeof (pool_value_t));
    236  0  stevel 	val->pv_class = POC_INVAL;
    237  0  stevel 	return (val);
    238  0  stevel }
    239  0  stevel 
    240  0  stevel /*
    241  0  stevel  * Free any atoms associated with the value and then free the value
    242  0  stevel  * itself.
    243  0  stevel  */
    244  0  stevel void
    245  0  stevel pool_value_free(pool_value_t *pv)
    246  0  stevel {
    247  0  stevel 	if (pv->pv_name)
    248  0  stevel 		atom_free(pv->pv_name);
    249  0  stevel 	if (pv->pv_class == POC_STRING)
    250  0  stevel 		atom_free(pv->pv_u.s);
    251  0  stevel 	free(pv);
    252  0  stevel }
    253  0  stevel 
    254  0  stevel /*
    255  0  stevel  * Return a pointer to the name of the value. This may be NULL if the
    256  0  stevel  * name has never been set.
    257  0  stevel  */
    258  0  stevel const char *
    259  0  stevel pool_value_get_name(const pool_value_t *pv)
    260  0  stevel {
    261  0  stevel 	return (pv->pv_name);
    262  0  stevel }
    263  0  stevel 
    264  0  stevel /*
    265  0  stevel  * Set the name of the value to the supplied name.
    266  0  stevel  */
    267  0  stevel int
    268  0  stevel pool_value_set_name(pool_value_t *pv, const char *name)
    269  0  stevel {
    270  0  stevel 	if (name == NULL || strlen(name) >= PV_NAME_MAX_LEN) {
    271  0  stevel 		pool_seterror(POE_BADPARAM);
    272  0  stevel 		return (PO_FAIL);
    273  0  stevel 	} else {
    274  0  stevel 		if (pv->pv_name)
    275  0  stevel 			atom_free(pv->pv_name);
    276  0  stevel 		if ((pv->pv_name = atom_string(name)) == NULL)
    277  0  stevel 			return (PO_FAIL);
    278  0  stevel 	}
    279  0  stevel 	return (PO_SUCCESS);
    280  0  stevel }
    281  0  stevel 
    282  0  stevel /*
    283  0  stevel  * Use the supplied nvpair_t to set the name, type and value of the
    284  0  stevel  * supplied pool_value_t.
    285  0  stevel  *
    286  0  stevel  * Return: PO_SUCCESS/PO_FAIL
    287  0  stevel  */
    288  0  stevel int
    289  0  stevel pool_value_from_nvpair(pool_value_t *pv, nvpair_t *pn)
    290  0  stevel {
    291  0  stevel 	uchar_t bval;
    292  0  stevel 	uint64_t uval;
    293  0  stevel 	int64_t ival;
    294  0  stevel 	double dval;
    295  0  stevel 	uint_t nelem;
    296  0  stevel 	uchar_t *dval_b;
    297  0  stevel 	char *sval;
    298  0  stevel 
    299  0  stevel 	if (pool_value_set_name(pv, nvpair_name(pn)) != PO_SUCCESS)
    300  0  stevel 		return (PO_FAIL);
    301  0  stevel 	switch (nvpair_type(pn)) {
    302  0  stevel 	case DATA_TYPE_BYTE:
    303  0  stevel 		if (nvpair_value_byte(pn, &bval) != 0) {
    304  0  stevel 			pool_seterror(POE_SYSTEM);
    305  0  stevel 			return (PO_FAIL);
    306  0  stevel 		}
    307  0  stevel 		pool_value_set_bool(pv, bval);
    308  0  stevel 		break;
    309  0  stevel 	case DATA_TYPE_BYTE_ARRAY:
    310  0  stevel 		if (nvpair_value_byte_array(pn, &dval_b, &nelem) != 0) {
    311  0  stevel 			pool_seterror(POE_SYSTEM);
    312  0  stevel 			return (PO_FAIL);
    313  0  stevel 		}
    314  0  stevel 		(void) memcpy(&dval, dval_b, sizeof (double));
    315  0  stevel 		pool_value_set_double(pv, dval);
    316  0  stevel 		break;
    317  0  stevel 	case DATA_TYPE_INT64:
    318  0  stevel 		if (nvpair_value_int64(pn, &ival) != 0) {
    319  0  stevel 			pool_seterror(POE_SYSTEM);
    320  0  stevel 			return (PO_FAIL);
    321  0  stevel 		}
    322  0  stevel 		pool_value_set_int64(pv, ival);
    323  0  stevel 		break;
    324  0  stevel 	case DATA_TYPE_UINT64:
    325  0  stevel 		if (nvpair_value_uint64(pn, &uval) != 0) {
    326  0  stevel 			pool_seterror(POE_SYSTEM);
    327  0  stevel 			return (PO_FAIL);
    328  0  stevel 		}
    329  0  stevel 		pool_value_set_uint64(pv, uval);
    330  0  stevel 		break;
    331  0  stevel 	case DATA_TYPE_STRING:
    332  0  stevel 		if (nvpair_value_string(pn, &sval) != 0) {
    333  0  stevel 			pool_seterror(POE_SYSTEM);
    334  0  stevel 			return (PO_FAIL);
    335  0  stevel 		}
    336  0  stevel 		if (pool_value_set_string(pv, sval) != PO_SUCCESS)
    337  0  stevel 			return (PO_FAIL);
    338  0  stevel 		break;
    339  0  stevel 	default:
    340  0  stevel 		pool_seterror(POE_SYSTEM);
    341  0  stevel 		return (PO_FAIL);
    342  0  stevel 	}
    343  0  stevel 	return (PO_SUCCESS);
    344  0  stevel }
    345  0  stevel 
    346  0  stevel /*
    347  0  stevel  * Check to see if the values held by two supplied values are
    348  0  stevel  * equal. First compare the pointers to see if we are comparing to
    349  0  stevel  * ourselves, if we are return PO_TRUE. If not, get the types and
    350  0  stevel  * ensure they match, if they don't return PO_FALSE. Then do a type
    351  0  stevel  * specific comparison returning PO_TRUE or PO_FALSE accordingly.
    352  0  stevel  */
    353  0  stevel int
    354  0  stevel pool_value_equal(pool_value_t *pv1, pool_value_t *pv2)
    355  0  stevel {
    356  0  stevel 	uint64_t uval1, uval2;
    357  0  stevel 	int64_t ival1, ival2;
    358  0  stevel 	double dval1, dval2;
    359  0  stevel 	uchar_t bval1, bval2;
    360  0  stevel 	const char *sval1, *sval2;
    361  0  stevel 	pool_value_class_t type;
    362  0  stevel 
    363  0  stevel 	if (pv1 == pv2) /* optimisation */
    364  0  stevel 		return (PO_TRUE);
    365  0  stevel 
    366  0  stevel 	type = pool_value_get_type(pv1);
    367  0  stevel 	if (type != pool_value_get_type(pv2))
    368  0  stevel 	    return (PO_FALSE);
    369  0  stevel 
    370  0  stevel 	switch (type) {
    371  0  stevel 		case POC_UINT:
    372  0  stevel 			(void) pool_value_get_uint64(pv1, &uval1);
    373  0  stevel 			(void) pool_value_get_uint64(pv2, &uval2);
    374  0  stevel 			if (uval1 == uval2)
    375  0  stevel 				return (PO_TRUE);
    376  0  stevel 			break;
    377  0  stevel 		case POC_INT:
    378  0  stevel 			(void) pool_value_get_int64(pv1, &ival1);
    379  0  stevel 			(void) pool_value_get_int64(pv2, &ival2);
    380  0  stevel 			if (ival1 == ival2)
    381  0  stevel 				return (PO_TRUE);
    382  0  stevel 			break;
    383  0  stevel 		case POC_DOUBLE:
    384  0  stevel 			(void) pool_value_get_double(pv1, &dval1);
    385  0  stevel 			(void) pool_value_get_double(pv2, &dval2);
    386  0  stevel 			if (dval1 == dval2)
    387  0  stevel 				return (PO_TRUE);
    388  0  stevel 			break;
    389  0  stevel 		case POC_BOOL:
    390  0  stevel 			(void) pool_value_get_bool(pv1, &bval1);
    391  0  stevel 			(void) pool_value_get_bool(pv2, &bval2);
    392  0  stevel 			if (bval1 == bval2)
    393  0  stevel 				return (PO_TRUE);
    394  0  stevel 			break;
    395  0  stevel 		case POC_STRING:
    396  0  stevel 			(void) pool_value_get_string(pv1, &sval1);
    397  0  stevel 			(void) pool_value_get_string(pv2, &sval2);
    398  0  stevel 			if (strcmp(sval1, sval2) == 0)
    399  0  stevel 				return (PO_TRUE);
    400  0  stevel 			break;
    401  0  stevel 	}
    402  0  stevel 	return (PO_FALSE);
    403  0  stevel }
    404  0  stevel 
    405  0  stevel #ifdef DEBUG
    406  0  stevel /*
    407  0  stevel  * Trace pool_value_t details using dprintf
    408  0  stevel  */
    409  0  stevel void
    410  0  stevel pool_value_dprintf(const pool_value_t *pv)
    411  0  stevel {
    412  0  stevel 	const char *class_name[] = {
    413  0  stevel 		"POC_UINT",
    414  0  stevel 		"POC_INT",
    415  0  stevel 		"POC_DOUBLE",
    416  0  stevel 		"POC_BOOL",
    417  0  stevel 		"POC_STRING"
    418  0  stevel 	};
    419  0  stevel 
    420  0  stevel 	dprintf("name: %s\n", pv->pv_name ? pv->pv_name : "NULL");
    421  0  stevel 	if (pv->pv_class >= POC_UINT && pv->pv_class <= POC_STRING)
    422  0  stevel 		dprintf("type: %s\n", class_name[pv->pv_class]);
    423  0  stevel 	else
    424  0  stevel 		dprintf("type: POC_INVAL\n");
    425  0  stevel 	switch (pv->pv_class) {
    426  0  stevel 	case POC_UINT:
    427  0  stevel 		dprintf("value: %llu\n", pv->pv_u.u);
    428  0  stevel 		break;
    429  0  stevel 	case POC_INT:
    430  0  stevel 		dprintf("value: %lld\n", pv->pv_u.i);
    431  0  stevel 		break;
    432  0  stevel 	case POC_DOUBLE:
    433  0  stevel 		dprintf("value: %f\n", pv->pv_u.d);
    434  0  stevel 		break;
    435  0  stevel 	case POC_BOOL:
    436  0  stevel 		dprintf("value: %s\n", pv->pv_u.b ? "true" : "false");
    437  0  stevel 		break;
    438  0  stevel 	case POC_STRING:
    439  0  stevel 		dprintf("value: %s\n", pv->pv_u.s);
    440  0  stevel 		break;
    441  0  stevel 	default:
    442  0  stevel 		dprintf("value: invalid\n");
    443  0  stevel 		break;
    444  0  stevel 	}
    445  0  stevel }
    446  0  stevel #endif	/* DEBUG */
    447