Import proplib-0.6.1.
This commit is contained in:
@@ -1,29 +1,4 @@
|
||||
/* $NetBSD: prop_dictionary.c,v 1.33 2008/11/30 00:17:07 haad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Juan Romero Pardines (zlib/gzip support).
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
/* $NetBSD: prop_dictionary.c,v 1.37 2011/04/20 19:40:00 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
|
||||
@@ -54,12 +29,16 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/proplib.h>
|
||||
#include <prop/prop_array.h>
|
||||
#include <prop/prop_dictionary.h>
|
||||
#include <prop/prop_string.h>
|
||||
#include "prop_object_impl.h"
|
||||
#include "prop_rb_impl.h"
|
||||
|
||||
#if !defined(_KERNEL) && !defined(_STANDALONE)
|
||||
#include <errno.h>
|
||||
#include <zlib.h>
|
||||
#define __unused /* empty */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We implement these like arrays, but we keep them sorted by key.
|
||||
@@ -88,10 +67,6 @@ struct _prop_dictionary_keysym {
|
||||
/* actually variable length */
|
||||
};
|
||||
|
||||
#define RBNODE_TO_PDK(n) \
|
||||
((struct _prop_dictionary_keysym *) \
|
||||
((uintptr_t)n - offsetof(struct _prop_dictionary_keysym, pdk_link)))
|
||||
|
||||
/* pdk_key[1] takes care of the NUL */
|
||||
#define PDK_SIZE_16 (sizeof(struct _prop_dictionary_keysym) + 16)
|
||||
#define PDK_SIZE_32 (sizeof(struct _prop_dictionary_keysym) + 32)
|
||||
@@ -198,35 +173,49 @@ struct _prop_dictionary_iterator {
|
||||
*/
|
||||
|
||||
static int
|
||||
_prop_dict_keysym_rb_compare_nodes(const struct rb_node *n1,
|
||||
const struct rb_node *n2)
|
||||
/*ARGSUSED*/
|
||||
_prop_dict_keysym_rb_compare_nodes(void *ctx __unused,
|
||||
const void *n1, const void *n2)
|
||||
{
|
||||
const prop_dictionary_keysym_t pdk1 = RBNODE_TO_PDK(n1);
|
||||
const prop_dictionary_keysym_t pdk2 = RBNODE_TO_PDK(n2);
|
||||
const struct _prop_dictionary_keysym *pdk1 = n1;
|
||||
const struct _prop_dictionary_keysym *pdk2 = n2;
|
||||
|
||||
return (strcmp(pdk1->pdk_key, pdk2->pdk_key));
|
||||
return strcmp(pdk1->pdk_key, pdk2->pdk_key);
|
||||
}
|
||||
|
||||
static int
|
||||
_prop_dict_keysym_rb_compare_key(const struct rb_node *n,
|
||||
const void *v)
|
||||
/*ARGSUSED*/
|
||||
_prop_dict_keysym_rb_compare_key(void *ctx __unused,
|
||||
const void *n, const void *v)
|
||||
{
|
||||
const prop_dictionary_keysym_t pdk = RBNODE_TO_PDK(n);
|
||||
const struct _prop_dictionary_keysym *pdk = n;
|
||||
const char *cp = v;
|
||||
|
||||
return (strcmp(pdk->pdk_key, cp));
|
||||
return strcmp(pdk->pdk_key, cp);
|
||||
}
|
||||
|
||||
static const struct rb_tree_ops _prop_dict_keysym_rb_tree_ops = {
|
||||
static const rb_tree_ops_t _prop_dict_keysym_rb_tree_ops = {
|
||||
.rbto_compare_nodes = _prop_dict_keysym_rb_compare_nodes,
|
||||
.rbto_compare_key = _prop_dict_keysym_rb_compare_key,
|
||||
.rbto_compare_key = _prop_dict_keysym_rb_compare_key,
|
||||
.rbto_node_offset = offsetof(struct _prop_dictionary_keysym, pdk_link),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
static struct rb_tree _prop_dict_keysym_tree;
|
||||
static bool _prop_dict_keysym_tree_initialized;
|
||||
|
||||
_PROP_ONCE_DECL(_prop_dict_init_once)
|
||||
_PROP_MUTEX_DECL_STATIC(_prop_dict_keysym_tree_mutex)
|
||||
|
||||
static int
|
||||
_prop_dict_init(void)
|
||||
{
|
||||
|
||||
_PROP_MUTEX_INIT(_prop_dict_keysym_tree_mutex);
|
||||
_prop_rb_tree_init(&_prop_dict_keysym_tree,
|
||||
&_prop_dict_keysym_rb_tree_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_dict_keysym_put(prop_dictionary_keysym_t pdk)
|
||||
{
|
||||
@@ -247,7 +236,7 @@ _prop_dict_keysym_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_dictionary_keysym_t pdk = *obj;
|
||||
|
||||
_prop_rb_tree_remove_node(&_prop_dict_keysym_tree, &pdk->pdk_link);
|
||||
_prop_rb_tree_remove_node(&_prop_dict_keysym_tree, pdk);
|
||||
_prop_dict_keysym_put(pdk);
|
||||
|
||||
return _PROP_OBJECT_FREE_DONE;
|
||||
@@ -294,28 +283,21 @@ _prop_dict_keysym_equals(prop_object_t v1, prop_object_t v2,
|
||||
static prop_dictionary_keysym_t
|
||||
_prop_dict_keysym_alloc(const char *key)
|
||||
{
|
||||
prop_dictionary_keysym_t opdk, pdk;
|
||||
const struct rb_node *n;
|
||||
prop_dictionary_keysym_t opdk, pdk, rpdk;
|
||||
size_t size;
|
||||
bool rv;
|
||||
|
||||
_PROP_ONCE_RUN(_prop_dict_init_once, _prop_dict_init);
|
||||
|
||||
/*
|
||||
* Check to see if this already exists in the tree. If it does,
|
||||
* we just retain it and return it.
|
||||
*/
|
||||
_PROP_MUTEX_LOCK(_prop_dict_keysym_tree_mutex);
|
||||
if (! _prop_dict_keysym_tree_initialized) {
|
||||
_prop_rb_tree_init(&_prop_dict_keysym_tree,
|
||||
&_prop_dict_keysym_rb_tree_ops);
|
||||
_prop_dict_keysym_tree_initialized = true;
|
||||
} else {
|
||||
n = _prop_rb_tree_find(&_prop_dict_keysym_tree, key);
|
||||
if (n != NULL) {
|
||||
opdk = RBNODE_TO_PDK(n);
|
||||
prop_object_retain(opdk);
|
||||
_PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
|
||||
return (opdk);
|
||||
}
|
||||
opdk = _prop_rb_tree_find(&_prop_dict_keysym_tree, key);
|
||||
if (opdk != NULL) {
|
||||
prop_object_retain(opdk);
|
||||
_PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
|
||||
return (opdk);
|
||||
}
|
||||
_PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
|
||||
|
||||
@@ -347,16 +329,15 @@ _prop_dict_keysym_alloc(const char *key)
|
||||
* we have to check again if it is in the tree.
|
||||
*/
|
||||
_PROP_MUTEX_LOCK(_prop_dict_keysym_tree_mutex);
|
||||
n = _prop_rb_tree_find(&_prop_dict_keysym_tree, key);
|
||||
if (n != NULL) {
|
||||
opdk = RBNODE_TO_PDK(n);
|
||||
opdk = _prop_rb_tree_find(&_prop_dict_keysym_tree, key);
|
||||
if (opdk != NULL) {
|
||||
prop_object_retain(opdk);
|
||||
_PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
|
||||
_prop_dict_keysym_put(pdk);
|
||||
return (opdk);
|
||||
}
|
||||
rv = _prop_rb_tree_insert_node(&_prop_dict_keysym_tree, &pdk->pdk_link);
|
||||
_PROP_ASSERT(rv == true);
|
||||
rpdk = _prop_rb_tree_insert_node(&_prop_dict_keysym_tree, pdk);
|
||||
_PROP_ASSERT(rpdk == pdk);
|
||||
_PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
|
||||
return (pdk);
|
||||
}
|
||||
@@ -416,6 +397,9 @@ _prop_dictionary_free(prop_stack_t stack, prop_object_t *obj)
|
||||
static void
|
||||
_prop_dictionary_lock(void)
|
||||
{
|
||||
|
||||
/* XXX: once necessary or paranoia? */
|
||||
_PROP_ONCE_RUN(_prop_dict_init_once, _prop_dict_init);
|
||||
_PROP_MUTEX_LOCK(_prop_dict_keysym_tree_mutex);
|
||||
}
|
||||
|
||||
@@ -540,8 +524,8 @@ _prop_dictionary_equals(prop_object_t v1, prop_object_t v2,
|
||||
*stored_pointer1 = (void *)(idx + 1);
|
||||
*stored_pointer2 = (void *)(idx + 1);
|
||||
|
||||
*next_obj1 = &dict1->pd_array[idx].pde_objref;
|
||||
*next_obj2 = &dict2->pd_array[idx].pde_objref;
|
||||
*next_obj1 = dict1->pd_array[idx].pde_objref;
|
||||
*next_obj2 = dict2->pd_array[idx].pde_objref;
|
||||
|
||||
if (!prop_dictionary_keysym_equals(dict1->pd_array[idx].pde_key,
|
||||
dict2->pd_array[idx].pde_key))
|
||||
@@ -645,7 +629,7 @@ static prop_object_t
|
||||
_prop_dictionary_iterator_next_object(void *v)
|
||||
{
|
||||
struct _prop_dictionary_iterator *pdi = v;
|
||||
prop_dictionary_t pd = pdi->pdi_base.pi_obj;
|
||||
prop_dictionary_t pd __unused = pdi->pdi_base.pi_obj;
|
||||
prop_dictionary_keysym_t pdk;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
@@ -672,7 +656,7 @@ static void
|
||||
_prop_dictionary_iterator_reset(void *v)
|
||||
{
|
||||
struct _prop_dictionary_iterator *pdi = v;
|
||||
prop_dictionary_t pd = pdi->pdi_base.pi_obj;
|
||||
prop_dictionary_t pd __unused = pdi->pdi_base.pi_obj;
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pd->pd_rwlock);
|
||||
_prop_dictionary_iterator_reset_locked(pdi);
|
||||
@@ -949,7 +933,10 @@ _prop_dictionary_get(prop_dictionary_t pd, const char *key, bool locked)
|
||||
prop_object_t
|
||||
prop_dictionary_get(prop_dictionary_t pd, const char *key)
|
||||
{
|
||||
prop_object_t po;
|
||||
prop_object_t po = NULL;
|
||||
|
||||
if (! prop_object_is_dictionary(pd))
|
||||
return (NULL);
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pd->pd_rwlock);
|
||||
po = _prop_dictionary_get(pd, key, true);
|
||||
@@ -1388,6 +1375,7 @@ prop_dictionary_internalize(const char *xml)
|
||||
return _prop_generic_internalize(xml, "dict");
|
||||
}
|
||||
|
||||
#if !defined(_KERNEL) && !defined(_STANDALONE)
|
||||
/*
|
||||
* prop_dictionary_externalize_to_file --
|
||||
* Externalize a dictionary to the specified file.
|
||||
@@ -1402,8 +1390,8 @@ prop_dictionary_externalize_to_file(prop_dictionary_t dict, const char *fname)
|
||||
xml = prop_dictionary_externalize(dict);
|
||||
if (xml == NULL)
|
||||
return (false);
|
||||
rv = _prop_object_externalize_write_file(fname, xml,
|
||||
strlen(xml), false);
|
||||
rv = _prop_object_externalize_write_file(fname, xml, strlen(xml),
|
||||
false);
|
||||
if (rv == false)
|
||||
save_errno = errno;
|
||||
_PROP_FREE(xml, M_TEMP);
|
||||
@@ -1413,31 +1401,6 @@ prop_dictionary_externalize_to_file(prop_dictionary_t dict, const char *fname)
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_externalize_to_zfile ---
|
||||
* Externalize a dictionary to the specified file and on the fly
|
||||
* compressing the result with gzip (via zlib).
|
||||
*/
|
||||
bool
|
||||
prop_dictionary_externalize_to_zfile(prop_dictionary_t dict, const char *fname)
|
||||
{
|
||||
char *xml;
|
||||
bool rv;
|
||||
int save_errno = 0;
|
||||
|
||||
xml = prop_dictionary_externalize(dict);
|
||||
if (xml == NULL)
|
||||
return false;
|
||||
rv = _prop_object_externalize_write_file(fname, xml, strlen(xml), true);
|
||||
if (rv == false)
|
||||
save_errno = errno;
|
||||
_PROP_FREE(xml, M_TEMP);
|
||||
if (rv == false)
|
||||
errno = save_errno;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_internalize_from_file --
|
||||
* Internalize a dictionary from a file.
|
||||
@@ -1456,87 +1419,4 @@ prop_dictionary_internalize_from_file(const char *fname)
|
||||
|
||||
return (dict);
|
||||
}
|
||||
|
||||
#define _READ_CHUNK 512
|
||||
/*
|
||||
* prop_dictionary_internalize_from_zfile ---
|
||||
* Internalize a dictionary from a compressed gzip file.
|
||||
*/
|
||||
prop_dictionary_t
|
||||
prop_dictionary_internalize_from_zfile(const char *fname)
|
||||
{
|
||||
struct _prop_object_internalize_mapped_file *mf;
|
||||
prop_dictionary_t dict;
|
||||
z_stream strm;
|
||||
unsigned char out[_READ_CHUNK];
|
||||
char *uncomp_xml = NULL;
|
||||
size_t have;
|
||||
ssize_t totalsize = 0;
|
||||
int rv = 0;
|
||||
|
||||
mf = _prop_object_internalize_map_file(fname);
|
||||
if (mf == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Decompress the mmap'ed buffer with zlib */
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = 0;
|
||||
strm.next_in = Z_NULL;
|
||||
|
||||
/* 15+16 to use gzip method */
|
||||
if (inflateInit2(&strm, 15+16) != Z_OK) {
|
||||
_prop_object_internalize_unmap_file(mf);
|
||||
return NULL;
|
||||
}
|
||||
strm.avail_in = mf->poimf_mapsize;
|
||||
strm.next_in = (unsigned char *)mf->poimf_xml;
|
||||
|
||||
/* Output buffer (uncompressed) */
|
||||
uncomp_xml = _PROP_MALLOC(_READ_CHUNK, M_TEMP);
|
||||
if (uncomp_xml == NULL) {
|
||||
(void)inflateEnd(&strm);
|
||||
_prop_object_internalize_unmap_file(mf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Inflate the input buffer and copy into 'uncomp_xml' */
|
||||
do {
|
||||
strm.avail_out = _READ_CHUNK;
|
||||
strm.next_out = out;
|
||||
rv = inflate(&strm, Z_NO_FLUSH);
|
||||
switch (rv) {
|
||||
case Z_DATA_ERROR:
|
||||
/*
|
||||
* Wrong compressed data or uncompressed, try
|
||||
* normal method as last resort.
|
||||
*/
|
||||
(void)inflateEnd(&strm);
|
||||
_PROP_FREE(uncomp_xml, M_TEMP);
|
||||
dict = prop_dictionary_internalize(mf->poimf_xml);
|
||||
_prop_object_internalize_unmap_file(mf);
|
||||
return dict;
|
||||
case Z_STREAM_ERROR:
|
||||
case Z_NEED_DICT:
|
||||
case Z_MEM_ERROR:
|
||||
(void)inflateEnd(&strm);
|
||||
_PROP_FREE(uncomp_xml, M_TEMP);
|
||||
_prop_object_internalize_unmap_file(mf);
|
||||
errno = rv;
|
||||
return NULL;
|
||||
}
|
||||
have = _READ_CHUNK - strm.avail_out;
|
||||
totalsize += have;
|
||||
uncomp_xml = _PROP_REALLOC(uncomp_xml, totalsize, M_TEMP);
|
||||
memcpy(uncomp_xml + totalsize - have, out, have);
|
||||
} while (strm.avail_out == 0);
|
||||
|
||||
/* we are done */
|
||||
(void)inflateEnd(&strm);
|
||||
dict = prop_dictionary_internalize(uncomp_xml);
|
||||
_PROP_FREE(uncomp_xml, M_TEMP);
|
||||
_prop_object_internalize_unmap_file(mf);
|
||||
|
||||
return dict;
|
||||
}
|
||||
#endif /* !_KERNEL && !_STANDALONE */
|
||||
|
Reference in New Issue
Block a user