4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
34 #include "pool_internal.h"
37 * libpool Value Manipulation Routines
39 * pool_value.c implements the value (pool_value_t) functionality for
40 * libpool. The datatypes supported are: uint64_t, int64_t, double,
41 * uchar_t (boolean), const char * (string). Values are used to
42 * represent data stored to and retrieved from the datastore in a
43 * simple discriminated union.
45 * Values are dynamically allocated using pool_value_alloc() and
46 * destroyed using pool_value_free().
48 * Values may be allocated statically for internal use in
49 * libpool. Statically allocated pool_value_t variables must be
50 * initialised with the POOL_VALUE_INITIALIZER macro, otherwise the
51 * results are unpredictable.
53 * A pool_value_t variable can be used to store values in any of the
54 * supported datatypes.
56 * A pool_value_t's name and string value are limited in size to
57 * PV_NAME_MAX_LEN and PV_VALUE_MAX_LEN respectively. Attempting to
58 * store values which are greater than this in length will fail with a
63 * Get the uint64_t data held by the value. If the data type isn't
64 * uint64_t return PO_FAIL and set pool_error to be POE_BAD_PROP_TYPE.
67 pool_value_get_uint64(const pool_value_t
*pv
, uint64_t *result
)
69 if (pv
->pv_class
!= POC_UINT
) {
70 pool_seterror(POE_BAD_PROP_TYPE
);
78 * Get the int64_t data held by the value. If the data type isn't
79 * int64_t return PO_FAIL and set pool_error to be POE_BAD_PROP_TYPE.
82 pool_value_get_int64(const pool_value_t
*pv
, int64_t *result
)
84 if (pv
->pv_class
!= POC_INT
) {
85 pool_seterror(POE_BAD_PROP_TYPE
);
93 * Get the double data held by the value. If the data type isn't
94 * double return PO_FAIL and set pool_error to be POE_BAD_PROP_TYPE.
98 pool_value_get_double(const pool_value_t
*pv
, double *result
)
100 if (pv
->pv_class
!= POC_DOUBLE
) {
101 pool_seterror(POE_BAD_PROP_TYPE
);
104 *result
= pv
->pv_u
.d
;
109 * Get the boolean data held by the value. If the data type isn't
110 * boolean return PO_FAIL and set pool_error to be POE_BAD_PROP_TYPE.
113 pool_value_get_bool(const pool_value_t
*pv
, uchar_t
*result
)
115 if (pv
->pv_class
!= POC_BOOL
) {
116 pool_seterror(POE_BAD_PROP_TYPE
);
119 *result
= pv
->pv_u
.b
;
124 * Get the string data held by the value. If the data type isn't
125 * string return PO_FAIL and set pool_error to be POE_BAD_PROP_TYPE.
128 pool_value_get_string(const pool_value_t
*pv
, const char **result
)
130 if (pv
->pv_class
!= POC_STRING
) {
131 pool_seterror(POE_BAD_PROP_TYPE
);
134 *result
= pv
->pv_u
.s
;
139 * Get the type of the data held by the value. If the value has never
140 * been used to store data, then the type is POC_INVAL.
143 pool_value_get_type(const pool_value_t
*pv
)
145 return (pv
->pv_class
);
149 * Set the value's data to the supplied uint64_t data. Update the type
150 * of the value data to POC_UINT.
153 pool_value_set_uint64(pool_value_t
*pv
, uint64_t val
)
155 if (pv
->pv_class
== POC_STRING
)
156 atom_free(pv
->pv_u
.s
);
157 pv
->pv_class
= POC_UINT
;
162 * Set the value's data to the supplied int64_t data. Update the type
163 * of the value data to POC_INT.
166 pool_value_set_int64(pool_value_t
*pv
, int64_t val
)
168 if (pv
->pv_class
== POC_STRING
)
169 atom_free(pv
->pv_u
.s
);
170 pv
->pv_class
= POC_INT
;
175 * Set the value's data to the supplied double data. Update the type
176 * of the value data to POC_DOUBLE.
180 pool_value_set_double(pool_value_t
*pv
, double val
)
182 if (pv
->pv_class
== POC_STRING
)
183 atom_free(pv
->pv_u
.s
);
184 pv
->pv_class
= POC_DOUBLE
;
189 * Set the value's data to the supplied uchar_t data. Update the type
190 * of the value data to POC_BOOL.
193 pool_value_set_bool(pool_value_t
*pv
, uchar_t val
)
195 if (pv
->pv_class
== POC_STRING
)
196 atom_free(pv
->pv_u
.s
);
197 pv
->pv_class
= POC_BOOL
;
198 pv
->pv_u
.b
= !!val
; /* Lock value at 0 or 1 */
202 * Try to make an internal copy of the val, returning PO_SUCCESS or
203 * PO_FAIL if the copy works or fails.
206 pool_value_set_string(pool_value_t
*pv
, const char *val
)
208 if (pv
->pv_class
== POC_STRING
)
209 atom_free(pv
->pv_u
.s
);
210 pv
->pv_class
= POC_STRING
;
211 if (val
== NULL
|| strlen(val
) >= PV_VALUE_MAX_LEN
) {
212 pool_seterror(POE_BADPARAM
);
215 if ((pv
->pv_u
.s
= atom_string(val
)) == NULL
)
222 * Allocate a pool_value_t structure and initialise it to 0. Set the
223 * type to POC_INVAL and return a pointer to the new pool_value_t. If
224 * memory allocation fails, set POE_SYSTEM and return NULL.
227 pool_value_alloc(void)
231 if ((val
= malloc(sizeof (pool_value_t
))) == NULL
) {
232 pool_seterror(POE_SYSTEM
);
235 (void) memset(val
, 0, sizeof (pool_value_t
));
236 val
->pv_class
= POC_INVAL
;
241 * Free any atoms associated with the value and then free the value
245 pool_value_free(pool_value_t
*pv
)
248 atom_free(pv
->pv_name
);
249 if (pv
->pv_class
== POC_STRING
)
250 atom_free(pv
->pv_u
.s
);
255 * Return a pointer to the name of the value. This may be NULL if the
256 * name has never been set.
259 pool_value_get_name(const pool_value_t
*pv
)
261 return (pv
->pv_name
);
265 * Set the name of the value to the supplied name.
268 pool_value_set_name(pool_value_t
*pv
, const char *name
)
270 if (name
== NULL
|| strlen(name
) >= PV_NAME_MAX_LEN
) {
271 pool_seterror(POE_BADPARAM
);
275 atom_free(pv
->pv_name
);
276 if ((pv
->pv_name
= atom_string(name
)) == NULL
)
283 * Use the supplied nvpair_t to set the name, type and value of the
284 * supplied pool_value_t.
286 * Return: PO_SUCCESS/PO_FAIL
289 pool_value_from_nvpair(pool_value_t
*pv
, nvpair_t
*pn
)
299 if (pool_value_set_name(pv
, nvpair_name(pn
)) != PO_SUCCESS
)
301 switch (nvpair_type(pn
)) {
303 if (nvpair_value_byte(pn
, &bval
) != 0) {
304 pool_seterror(POE_SYSTEM
);
307 pool_value_set_bool(pv
, bval
);
309 case DATA_TYPE_BYTE_ARRAY
:
310 if (nvpair_value_byte_array(pn
, &dval_b
, &nelem
) != 0) {
311 pool_seterror(POE_SYSTEM
);
314 (void) memcpy(&dval
, dval_b
, sizeof (double));
315 pool_value_set_double(pv
, dval
);
317 case DATA_TYPE_INT64
:
318 if (nvpair_value_int64(pn
, &ival
) != 0) {
319 pool_seterror(POE_SYSTEM
);
322 pool_value_set_int64(pv
, ival
);
324 case DATA_TYPE_UINT64
:
325 if (nvpair_value_uint64(pn
, &uval
) != 0) {
326 pool_seterror(POE_SYSTEM
);
329 pool_value_set_uint64(pv
, uval
);
331 case DATA_TYPE_STRING
:
332 if (nvpair_value_string(pn
, &sval
) != 0) {
333 pool_seterror(POE_SYSTEM
);
336 if (pool_value_set_string(pv
, sval
) != PO_SUCCESS
)
340 pool_seterror(POE_SYSTEM
);
347 * Check to see if the values held by two supplied values are
348 * equal. First compare the pointers to see if we are comparing to
349 * ourselves, if we are return PO_TRUE. If not, get the types and
350 * ensure they match, if they don't return PO_FALSE. Then do a type
351 * specific comparison returning PO_TRUE or PO_FALSE accordingly.
354 pool_value_equal(pool_value_t
*pv1
, pool_value_t
*pv2
)
356 uint64_t uval1
, uval2
;
357 int64_t ival1
, ival2
;
359 uchar_t bval1
, bval2
;
360 const char *sval1
, *sval2
;
361 pool_value_class_t type
;
363 if (pv1
== pv2
) /* optimisation */
366 type
= pool_value_get_type(pv1
);
367 if (type
!= pool_value_get_type(pv2
))
372 (void) pool_value_get_uint64(pv1
, &uval1
);
373 (void) pool_value_get_uint64(pv2
, &uval2
);
378 (void) pool_value_get_int64(pv1
, &ival1
);
379 (void) pool_value_get_int64(pv2
, &ival2
);
384 (void) pool_value_get_double(pv1
, &dval1
);
385 (void) pool_value_get_double(pv2
, &dval2
);
390 (void) pool_value_get_bool(pv1
, &bval1
);
391 (void) pool_value_get_bool(pv2
, &bval2
);
396 (void) pool_value_get_string(pv1
, &sval1
);
397 (void) pool_value_get_string(pv2
, &sval2
);
398 if (strcmp(sval1
, sval2
) == 0)
407 * Trace pool_value_t details using dprintf
410 pool_value_dprintf(const pool_value_t
*pv
)
412 const char *class_name
[] = {
420 dprintf("name: %s\n", pv
->pv_name
? pv
->pv_name
: "NULL");
421 if (pv
->pv_class
>= POC_UINT
&& pv
->pv_class
<= POC_STRING
)
422 dprintf("type: %s\n", class_name
[pv
->pv_class
]);
424 dprintf("type: POC_INVAL\n");
425 switch (pv
->pv_class
) {
427 dprintf("value: %llu\n", pv
->pv_u
.u
);
430 dprintf("value: %lld\n", pv
->pv_u
.i
);
433 dprintf("value: %f\n", pv
->pv_u
.d
);
436 dprintf("value: %s\n", pv
->pv_u
.b
? "true" : "false");
439 dprintf("value: %s\n", pv
->pv_u
.s
);
442 dprintf("value: invalid\n");