/* $NetBSD: prop_data.c,v 1.6 2007/03/04 22:31:43 dillo Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include "prop_object_impl.h" #if defined(_KERNEL) #include #elif defined(_STANDALONE) #include #include #else #include #include #include #endif _PROP_POOL_INIT(_prop_data_pool, sizeof(struct _prop_data), "propdata") _PROP_MALLOC_DEFINE(M_PROP_DATA, "prop data", "property data container object") static void _prop_data_free(void *); static boolean_t _prop_data_equals(void *, void *); static const struct _prop_object_type _prop_object_type_data = { .pot_type = PROP_TYPE_DATA, .pot_free = _prop_data_free, .pot_equals = _prop_data_equals, }; #define prop_object_is_data(x) \ ((x) != NULL && (x)->pd_obj.po_type == &_prop_object_type_data) static void _prop_data_free(void *v) { prop_data_t pd = v; if ((pd->pd_flags & PD_F_NOCOPY) == 0 && pd->pd_mutable != NULL) _PROP_FREE(pd->pd_mutable, M_PROP_DATA); _PROP_POOL_PUT(_prop_data_pool, v); } static boolean_t _prop_data_equals(void *v1, void *v2) { prop_data_t pd1 = v1; prop_data_t pd2 = v2; if (! (prop_object_is_data(pd1) && prop_object_is_data(pd2))) return (FALSE); if (pd1 == pd2) return (TRUE); if (pd1->pd_size != pd2->pd_size) return (FALSE); if (pd1->pd_size == 0) { _PROP_ASSERT(pd1->pd_immutable == NULL); _PROP_ASSERT(pd2->pd_immutable == NULL); return (TRUE); } return (memcmp(pd1->pd_immutable, pd2->pd_immutable, pd1->pd_size) == 0); } prop_data_t _prop_data_alloc(void) { prop_data_t pd; pd = _PROP_POOL_GET(_prop_data_pool); if (pd != NULL) { _prop_object_init(&pd->pd_obj, &_prop_object_type_data); pd->pd_mutable = NULL; pd->pd_size = 0; pd->pd_flags = 0; } return (pd); } /* * prop_data_create_data -- * Create a data container that contains a copy of the data. */ prop_data_t prop_data_create_data(const void *v, size_t size) { prop_data_t pd; void *nv; pd = _prop_data_alloc(); if (pd != NULL) { nv = _PROP_MALLOC(size, M_PROP_DATA); if (nv == NULL) { _prop_data_free(pd); return (NULL); } memcpy(nv, v, size); pd->pd_mutable = nv; pd->pd_size = size; } return (pd); } /* * prop_data_create_data_nocopy -- * Create an immutable data container that contains a refrence to the * provided external data. */ prop_data_t prop_data_create_data_nocopy(const void *v, size_t size) { prop_data_t pd; pd = _prop_data_alloc(); if (pd != NULL) { pd->pd_immutable = v; pd->pd_size = size; pd->pd_flags |= PD_F_NOCOPY; } return (pd); } /* * prop_data_copy -- * Copy a data container. If the original data is external, then * the copy is also references the same external data. */ prop_data_t prop_data_copy(prop_data_t opd) { prop_data_t pd; if (! prop_object_is_data(opd)) return (NULL); pd = _prop_data_alloc(); if (pd != NULL) { pd->pd_size = opd->pd_size; pd->pd_flags = opd->pd_flags; if (opd->pd_flags & PD_F_NOCOPY) pd->pd_immutable = opd->pd_immutable; else if (opd->pd_size != 0) { void *nv = _PROP_MALLOC(pd->pd_size, M_PROP_DATA); if (nv == NULL) { _prop_data_free(pd); return (NULL); } memcpy(nv, opd->pd_immutable, opd->pd_size); pd->pd_mutable = nv; } } return (pd); } /* * prop_data_size -- * Return the size of the data. */ size_t prop_data_size(prop_data_t pd) { if (! prop_object_is_data(pd)) return (0); return (pd->pd_size); } /* * prop_data_data -- * Return a copy of the contents of the data container. * The data is allocated with the M_TEMP malloc type. * If the data container is empty, NULL is returned. */ void * prop_data_data(prop_data_t pd) { void *v; if (! prop_object_is_data(pd)) return (NULL); if (pd->pd_size == 0) { _PROP_ASSERT(pd->pd_immutable == NULL); return (NULL); } _PROP_ASSERT(pd->pd_immutable != NULL); v = _PROP_MALLOC(pd->pd_size, M_TEMP); if (v != NULL) memcpy(v, pd->pd_immutable, pd->pd_size); return (v); } /* * prop_data_data_nocopy -- * Return an immutable reference to the contents of the data * container. */ const void * prop_data_data_nocopy(prop_data_t pd) { if (! prop_object_is_data(pd)) return (NULL); _PROP_ASSERT((pd->pd_size == 0 && pd->pd_immutable == NULL) || (pd->pd_size != 0 && pd->pd_immutable != NULL)); return (pd->pd_immutable); } /* * prop_data_equals -- * Return TRUE if two strings are equivalent. */ boolean_t prop_data_equals(prop_data_t pd1, prop_data_t pd2) { return (_prop_data_equals(pd1, pd2)); } /* * prop_data_equals_data -- * Return TRUE if the contained data is equivalent to the specified * external data. */ boolean_t prop_data_equals_data(prop_data_t pd, const void *v, size_t size) { if (! prop_object_is_data(pd)) return (FALSE); if (pd->pd_size != size) return (FALSE); return (memcmp(pd->pd_immutable, v, size) == 0); }