Revert "Move all external code to lib/external."
This reverts commit 9effec0c4e
.
This commit is contained in:
152
lib/portableproplib/prop/prop_array.h
Normal file
152
lib/portableproplib/prop/prop_array.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/* $NetBSD: prop_array.h,v 1.8 2008/09/11 13:15:13 haad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 Juan Romero Pardines.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_ARRAY_H_
|
||||
#define _PROPLIB_PROP_ARRAY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_array *prop_array_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_array_t prop_array_create(void);
|
||||
prop_array_t prop_array_create_with_capacity(unsigned int);
|
||||
|
||||
prop_array_t prop_array_copy(prop_array_t);
|
||||
prop_array_t prop_array_copy_mutable(prop_array_t);
|
||||
|
||||
unsigned int prop_array_capacity(prop_array_t);
|
||||
unsigned int prop_array_count(prop_array_t);
|
||||
bool prop_array_ensure_capacity(prop_array_t, unsigned int);
|
||||
|
||||
void prop_array_make_immutable(prop_array_t);
|
||||
bool prop_array_mutable(prop_array_t);
|
||||
|
||||
prop_object_iterator_t prop_array_iterator(prop_array_t);
|
||||
|
||||
prop_object_t prop_array_get(prop_array_t, unsigned int);
|
||||
bool prop_array_set(prop_array_t, unsigned int, prop_object_t);
|
||||
bool prop_array_add(prop_array_t, prop_object_t);
|
||||
bool prop_array_add_first(prop_array_t, prop_object_t);
|
||||
void prop_array_remove(prop_array_t, unsigned int);
|
||||
|
||||
bool prop_array_equals(prop_array_t, prop_array_t);
|
||||
|
||||
char * prop_array_externalize(prop_array_t);
|
||||
prop_array_t prop_array_internalize(const char *);
|
||||
|
||||
bool prop_array_externalize_to_file(prop_array_t, const char *);
|
||||
bool prop_array_externalize_to_zfile(prop_array_t, const char *);
|
||||
prop_array_t prop_array_internalize_from_file(const char *);
|
||||
prop_array_t prop_array_internalize_from_zfile(const char *);
|
||||
|
||||
/*
|
||||
* Utility routines to make it more convenient to work with values
|
||||
* stored in dictionaries.
|
||||
*/
|
||||
bool prop_array_get_bool(prop_array_t, unsigned int,
|
||||
bool *);
|
||||
bool prop_array_set_bool(prop_array_t, unsigned int,
|
||||
bool);
|
||||
|
||||
bool prop_array_get_int8(prop_array_t, unsigned int,
|
||||
int8_t *);
|
||||
bool prop_array_get_uint8(prop_array_t, unsigned int,
|
||||
uint8_t *);
|
||||
bool prop_array_set_int8(prop_array_t, unsigned int,
|
||||
int8_t);
|
||||
bool prop_array_set_uint8(prop_array_t, unsigned int,
|
||||
uint8_t);
|
||||
|
||||
bool prop_array_get_int16(prop_array_t, unsigned int,
|
||||
int16_t *);
|
||||
bool prop_array_get_uint16(prop_array_t, unsigned int,
|
||||
uint16_t *);
|
||||
bool prop_array_set_int16(prop_array_t, unsigned int,
|
||||
int16_t);
|
||||
bool prop_array_set_uint16(prop_array_t, unsigned int,
|
||||
uint16_t);
|
||||
|
||||
bool prop_array_get_int32(prop_array_t, unsigned int,
|
||||
int32_t *);
|
||||
bool prop_array_get_uint32(prop_array_t, unsigned int,
|
||||
uint32_t *);
|
||||
bool prop_array_set_int32(prop_array_t, unsigned int,
|
||||
int32_t);
|
||||
bool prop_array_set_uint32(prop_array_t, unsigned int,
|
||||
uint32_t);
|
||||
|
||||
bool prop_array_get_int64(prop_array_t, unsigned int,
|
||||
int64_t *);
|
||||
bool prop_array_get_uint64(prop_array_t, unsigned int,
|
||||
uint64_t *);
|
||||
bool prop_array_set_int64(prop_array_t, unsigned int,
|
||||
int64_t);
|
||||
bool prop_array_set_uint64(prop_array_t, unsigned int,
|
||||
uint64_t);
|
||||
|
||||
bool prop_array_add_int8(prop_array_t, int8_t);
|
||||
bool prop_array_add_uint8(prop_array_t, uint8_t);
|
||||
|
||||
bool prop_array_add_int16(prop_array_t, int16_t);
|
||||
bool prop_array_add_uint16(prop_array_t, uint16_t);
|
||||
|
||||
bool prop_array_add_int32(prop_array_t, int32_t);
|
||||
bool prop_array_add_uint32(prop_array_t, uint32_t);
|
||||
|
||||
bool prop_array_add_int64(prop_array_t, int64_t);
|
||||
bool prop_array_add_uint64(prop_array_t, uint64_t);
|
||||
|
||||
bool prop_array_get_cstring(prop_array_t, unsigned int,
|
||||
char **);
|
||||
bool prop_array_set_cstring(prop_array_t, unsigned int,
|
||||
const char *);
|
||||
bool prop_array_add_cstring(prop_array_t, const char *);
|
||||
bool prop_array_add_cstring_nocopy(prop_array_t,
|
||||
const char *);
|
||||
bool prop_array_get_cstring_nocopy(prop_array_t,
|
||||
unsigned int,
|
||||
const char **);
|
||||
bool prop_array_set_cstring_nocopy(prop_array_t,
|
||||
unsigned int,
|
||||
const char *);
|
||||
bool prop_array_add_and_rel(prop_array_t, prop_object_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_ARRAY_H_ */
|
55
lib/portableproplib/prop/prop_bool.h
Normal file
55
lib/portableproplib/prop/prop_bool.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* $NetBSD: prop_bool.h,v 1.4 2008/04/28 20:22:51 martin 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_BOOL_H_
|
||||
#define _PROPLIB_PROP_BOOL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_bool *prop_bool_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_bool_t prop_bool_create(bool);
|
||||
prop_bool_t prop_bool_copy(prop_bool_t);
|
||||
|
||||
bool prop_bool_true(prop_bool_t);
|
||||
|
||||
bool prop_bool_equals(prop_bool_t, prop_bool_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_BOOL_H_ */
|
62
lib/portableproplib/prop/prop_data.h
Normal file
62
lib/portableproplib/prop/prop_data.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* $NetBSD: prop_data.h,v 1.3 2008/04/28 20:22:51 martin 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_DATA_H_
|
||||
#define _PROPLIB_PROP_DATA_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <prop/prop_object.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct _prop_data *prop_data_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_data_t prop_data_create_data(const void *, size_t);
|
||||
prop_data_t prop_data_create_data_nocopy(const void *, size_t);
|
||||
|
||||
prop_data_t prop_data_copy(prop_data_t);
|
||||
|
||||
size_t prop_data_size(prop_data_t);
|
||||
|
||||
void * prop_data_data(prop_data_t);
|
||||
const void * prop_data_data_nocopy(prop_data_t);
|
||||
|
||||
bool prop_data_equals(prop_data_t, prop_data_t);
|
||||
bool prop_data_equals_data(prop_data_t, const void *, size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_DATA_H_ */
|
158
lib/portableproplib/prop/prop_dictionary.h
Normal file
158
lib/portableproplib/prop/prop_dictionary.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/* $NetBSD: prop_dictionary.h,v 1.9 2008/04/28 20:22:51 martin 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_DICTIONARY_H_
|
||||
#define _PROPLIB_PROP_DICTIONARY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <prop/prop_object.h>
|
||||
#include <prop/prop_array.h>
|
||||
|
||||
typedef struct _prop_dictionary *prop_dictionary_t;
|
||||
typedef struct _prop_dictionary_keysym *prop_dictionary_keysym_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_dictionary_t prop_dictionary_create(void);
|
||||
prop_dictionary_t prop_dictionary_create_with_capacity(unsigned int);
|
||||
|
||||
prop_dictionary_t prop_dictionary_copy(prop_dictionary_t);
|
||||
prop_dictionary_t prop_dictionary_copy_mutable(prop_dictionary_t);
|
||||
|
||||
unsigned int prop_dictionary_count(prop_dictionary_t);
|
||||
bool prop_dictionary_ensure_capacity(prop_dictionary_t,
|
||||
unsigned int);
|
||||
|
||||
void prop_dictionary_make_immutable(prop_dictionary_t);
|
||||
bool prop_dictionary_mutable(prop_dictionary_t);
|
||||
|
||||
prop_object_iterator_t prop_dictionary_iterator(prop_dictionary_t);
|
||||
prop_array_t prop_dictionary_all_keys(prop_dictionary_t);
|
||||
|
||||
prop_object_t prop_dictionary_get(prop_dictionary_t, const char *);
|
||||
bool prop_dictionary_set(prop_dictionary_t, const char *,
|
||||
prop_object_t);
|
||||
void prop_dictionary_remove(prop_dictionary_t, const char *);
|
||||
|
||||
prop_object_t prop_dictionary_get_keysym(prop_dictionary_t,
|
||||
prop_dictionary_keysym_t);
|
||||
bool prop_dictionary_set_keysym(prop_dictionary_t,
|
||||
prop_dictionary_keysym_t,
|
||||
prop_object_t);
|
||||
void prop_dictionary_remove_keysym(prop_dictionary_t,
|
||||
prop_dictionary_keysym_t);
|
||||
|
||||
bool prop_dictionary_equals(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
char * prop_dictionary_externalize(prop_dictionary_t);
|
||||
prop_dictionary_t prop_dictionary_internalize(const char *);
|
||||
|
||||
bool prop_dictionary_externalize_to_file(prop_dictionary_t,
|
||||
const char *);
|
||||
bool prop_dictionary_externalize_to_zfile(prop_dictionary_t,
|
||||
const char *);
|
||||
prop_dictionary_t prop_dictionary_internalize_from_file(const char *);
|
||||
prop_dictionary_t prop_dictionary_internalize_from_zfile(const char *);
|
||||
|
||||
const char * prop_dictionary_keysym_cstring_nocopy(prop_dictionary_keysym_t);
|
||||
|
||||
bool prop_dictionary_keysym_equals(prop_dictionary_keysym_t,
|
||||
prop_dictionary_keysym_t);
|
||||
|
||||
/*
|
||||
* Utility routines to make it more convenient to work with values
|
||||
* stored in dictionaries.
|
||||
*/
|
||||
bool prop_dictionary_get_dict(prop_dictionary_t, const char *,
|
||||
prop_dictionary_t *);
|
||||
bool prop_dictionary_get_bool(prop_dictionary_t, const char *,
|
||||
bool *);
|
||||
bool prop_dictionary_set_bool(prop_dictionary_t, const char *,
|
||||
bool);
|
||||
|
||||
bool prop_dictionary_get_int8(prop_dictionary_t, const char *,
|
||||
int8_t *);
|
||||
bool prop_dictionary_get_uint8(prop_dictionary_t, const char *,
|
||||
uint8_t *);
|
||||
bool prop_dictionary_set_int8(prop_dictionary_t, const char *,
|
||||
int8_t);
|
||||
bool prop_dictionary_set_uint8(prop_dictionary_t, const char *,
|
||||
uint8_t);
|
||||
|
||||
bool prop_dictionary_get_int16(prop_dictionary_t, const char *,
|
||||
int16_t *);
|
||||
bool prop_dictionary_get_uint16(prop_dictionary_t, const char *,
|
||||
uint16_t *);
|
||||
bool prop_dictionary_set_int16(prop_dictionary_t, const char *,
|
||||
int16_t);
|
||||
bool prop_dictionary_set_uint16(prop_dictionary_t, const char *,
|
||||
uint16_t);
|
||||
|
||||
bool prop_dictionary_get_int32(prop_dictionary_t, const char *,
|
||||
int32_t *);
|
||||
bool prop_dictionary_get_uint32(prop_dictionary_t, const char *,
|
||||
uint32_t *);
|
||||
bool prop_dictionary_set_int32(prop_dictionary_t, const char *,
|
||||
int32_t);
|
||||
bool prop_dictionary_set_uint32(prop_dictionary_t, const char *,
|
||||
uint32_t);
|
||||
|
||||
bool prop_dictionary_get_int64(prop_dictionary_t, const char *,
|
||||
int64_t *);
|
||||
bool prop_dictionary_get_uint64(prop_dictionary_t, const char *,
|
||||
uint64_t *);
|
||||
bool prop_dictionary_set_int64(prop_dictionary_t, const char *,
|
||||
int64_t);
|
||||
bool prop_dictionary_set_uint64(prop_dictionary_t, const char *,
|
||||
uint64_t);
|
||||
|
||||
bool prop_dictionary_get_cstring(prop_dictionary_t, const char *,
|
||||
char **);
|
||||
bool prop_dictionary_set_cstring(prop_dictionary_t, const char *,
|
||||
const char *);
|
||||
|
||||
bool prop_dictionary_get_cstring_nocopy(prop_dictionary_t,
|
||||
const char *,
|
||||
const char **);
|
||||
bool prop_dictionary_set_cstring_nocopy(prop_dictionary_t,
|
||||
const char *,
|
||||
const char *);
|
||||
bool prop_dictionary_set_and_rel(prop_dictionary_t,
|
||||
const char *,
|
||||
prop_object_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_DICTIONARY_H_ */
|
96
lib/portableproplib/prop/prop_ingest.h
Normal file
96
lib/portableproplib/prop/prop_ingest.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* $NetBSD: prop_ingest.h,v 1.3 2008/04/28 20:22:51 martin 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_INGEST_H_
|
||||
#define _PROPLIB_PROP_INGEST_H_
|
||||
|
||||
#include <prop/prop_object.h>
|
||||
#include <prop/prop_dictionary.h>
|
||||
|
||||
typedef enum {
|
||||
PROP_INGEST_ERROR_NO_ERROR = 0,
|
||||
PROP_INGEST_ERROR_NO_KEY = 1,
|
||||
PROP_INGEST_ERROR_WRONG_TYPE = 2,
|
||||
PROP_INGEST_ERROR_HANDLER_FAILED = 3
|
||||
} prop_ingest_error_t;
|
||||
|
||||
typedef enum {
|
||||
PROP_INGEST_FLAG_OPTIONAL = 0x01
|
||||
} prop_ingest_flag_t;
|
||||
|
||||
typedef struct _prop_ingest_context *prop_ingest_context_t;
|
||||
|
||||
typedef bool (*prop_ingest_handler_t)(prop_ingest_context_t, prop_object_t);
|
||||
|
||||
typedef struct {
|
||||
const char *pite_key;
|
||||
prop_type_t pite_type;
|
||||
unsigned int pite_flags;
|
||||
prop_ingest_handler_t pite_handler;
|
||||
} prop_ingest_table_entry;
|
||||
|
||||
#define PROP_INGEST(key_, type_, handler_) \
|
||||
{ .pite_key = key_ , \
|
||||
.pite_type = type_ , \
|
||||
.pite_flags = 0 , \
|
||||
.pite_handler = handler_ }
|
||||
|
||||
#define PROP_INGEST_OPTIONAL(key_, type_, handler_) \
|
||||
{ .pite_key = key_ , \
|
||||
.pite_type = type_ , \
|
||||
.pite_flags = PROP_INGEST_FLAG_OPTIONAL , \
|
||||
.pite_handler = handler_ }
|
||||
|
||||
#define PROP_INGEST_END \
|
||||
{ .pite_key = NULL }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_ingest_context_t
|
||||
prop_ingest_context_alloc(void *);
|
||||
void prop_ingest_context_free(prop_ingest_context_t);
|
||||
|
||||
prop_ingest_error_t
|
||||
prop_ingest_context_error(prop_ingest_context_t);
|
||||
prop_type_t prop_ingest_context_type(prop_ingest_context_t);
|
||||
const char * prop_ingest_context_key(prop_ingest_context_t);
|
||||
void * prop_ingest_context_private(prop_ingest_context_t);
|
||||
|
||||
bool prop_dictionary_ingest(prop_dictionary_t,
|
||||
const prop_ingest_table_entry[],
|
||||
prop_ingest_context_t);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_INGEST_H_ */
|
63
lib/portableproplib/prop/prop_number.h
Normal file
63
lib/portableproplib/prop/prop_number.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* $NetBSD: prop_number.h,v 1.6 2008/04/28 20:22:51 martin 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_NUMBER_H_
|
||||
#define _PROPLIB_PROP_NUMBER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_number *prop_number_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_number_t prop_number_create_integer(int64_t);
|
||||
prop_number_t prop_number_create_unsigned_integer(uint64_t);
|
||||
|
||||
prop_number_t prop_number_copy(prop_number_t);
|
||||
|
||||
int prop_number_size(prop_number_t);
|
||||
bool prop_number_unsigned(prop_number_t);
|
||||
|
||||
int64_t prop_number_integer_value(prop_number_t);
|
||||
uint64_t prop_number_unsigned_integer_value(prop_number_t);
|
||||
|
||||
bool prop_number_equals(prop_number_t, prop_number_t);
|
||||
bool prop_number_equals_integer(prop_number_t, int64_t);
|
||||
bool prop_number_equals_unsigned_integer(prop_number_t, uint64_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_NUMBER_H_ */
|
73
lib/portableproplib/prop/prop_object.h
Normal file
73
lib/portableproplib/prop/prop_object.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* $NetBSD: prop_object.h,v 1.7 2008/04/28 20:22:51 martin 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_OBJECT_H_
|
||||
#define _PROPLIB_PROP_OBJECT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef void *prop_object_t;
|
||||
|
||||
typedef enum {
|
||||
PROP_TYPE_UNKNOWN = 0x00000000,
|
||||
PROP_TYPE_BOOL = 0x626f6f6c, /* 'bool' */
|
||||
PROP_TYPE_NUMBER = 0x6e6d6272, /* 'nmbr' */
|
||||
PROP_TYPE_STRING = 0x73746e67, /* 'stng' */
|
||||
PROP_TYPE_DATA = 0x64617461, /* 'data' */
|
||||
PROP_TYPE_ARRAY = 0x61726179, /* 'aray' */
|
||||
PROP_TYPE_DICTIONARY = 0x64696374, /* 'dict' */
|
||||
PROP_TYPE_DICT_KEYSYM = 0x646b6579 /* 'dkey' */
|
||||
} prop_type_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void prop_object_retain(prop_object_t);
|
||||
void prop_object_release(prop_object_t);
|
||||
|
||||
prop_type_t prop_object_type(prop_object_t);
|
||||
|
||||
bool prop_object_equals(prop_object_t, prop_object_t);
|
||||
bool prop_object_equals_with_error(prop_object_t, prop_object_t, bool *);
|
||||
|
||||
typedef struct _prop_object_iterator *prop_object_iterator_t;
|
||||
|
||||
prop_object_t prop_object_iterator_next(prop_object_iterator_t);
|
||||
void prop_object_iterator_reset(prop_object_iterator_t);
|
||||
void prop_object_iterator_release(prop_object_iterator_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_OBJECT_H_ */
|
68
lib/portableproplib/prop/prop_string.h
Normal file
68
lib/portableproplib/prop/prop_string.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* $NetBSD: prop_string.h,v 1.3 2008/04/28 20:22:51 martin 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_STRING_H_
|
||||
#define _PROPLIB_PROP_STRING_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <prop/prop_object.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct _prop_string *prop_string_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
prop_string_t prop_string_create(void);
|
||||
prop_string_t prop_string_create_cstring(const char *);
|
||||
prop_string_t prop_string_create_cstring_nocopy(const char *);
|
||||
|
||||
prop_string_t prop_string_copy(prop_string_t);
|
||||
prop_string_t prop_string_copy_mutable(prop_string_t);
|
||||
|
||||
size_t prop_string_size(prop_string_t);
|
||||
bool prop_string_mutable(prop_string_t);
|
||||
|
||||
char * prop_string_cstring(prop_string_t);
|
||||
const char * prop_string_cstring_nocopy(prop_string_t);
|
||||
|
||||
bool prop_string_append(prop_string_t, prop_string_t);
|
||||
bool prop_string_append_cstring(prop_string_t, const char *);
|
||||
|
||||
bool prop_string_equals(prop_string_t, prop_string_t);
|
||||
bool prop_string_equals_cstring(prop_string_t, const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PROPLIB_PROP_STRING_H_ */
|
45
lib/portableproplib/prop/proplib.h
Normal file
45
lib/portableproplib/prop/proplib.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* $NetBSD: proplib.h,v 1.6 2008/04/28 20:22:51 martin 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROPLIB_H_
|
||||
#define _PROPLIB_PROPLIB_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <prop/prop_array.h>
|
||||
#include <prop/prop_bool.h>
|
||||
#include <prop/prop_data.h>
|
||||
#include <prop/prop_dictionary.h>
|
||||
#include <prop/prop_number.h>
|
||||
#include <prop/prop_string.h>
|
||||
#include <prop/prop_ingest.h>
|
||||
|
||||
#endif /* _PROPLIB_PROPLIB_H_ */
|
222
lib/portableproplib/prop/rbtree.h
Normal file
222
lib/portableproplib/prop/rbtree.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/* $NetBSD: rbtree.h,v 1.1 2010/09/25 01:42:40 matt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Matt Thomas <matt@3am-software.com>.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_RBTREE_H_
|
||||
#define _SYS_RBTREE_H_
|
||||
|
||||
#if defined(_KERNEL) || defined(_STANDALONE)
|
||||
#include <sys/types.h>
|
||||
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include <queue.h>
|
||||
|
||||
/* GCC version checking borrowed from glibc. */
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define __GNUC_PREREQ(maj,min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
# define __GNUC_PREREQ(maj,min) 0
|
||||
#endif
|
||||
|
||||
#if __GNUC_PREREQ(2, 96)
|
||||
# ifndef __predict_true
|
||||
# define __predict_true(exp) __builtin_expect((exp), 1)
|
||||
# endif
|
||||
# ifndef __predict_false
|
||||
# define __predict_false(exp) __builtin_expect((exp), 0)
|
||||
# endif
|
||||
#else
|
||||
# ifndef __predict_true
|
||||
# define __predict_true(exp) (exp)
|
||||
# endif
|
||||
# ifndef __predict_false
|
||||
# define __predict_false(exp) (exp)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct rb_node {
|
||||
struct rb_node *rb_nodes[2];
|
||||
#define RB_DIR_LEFT 0
|
||||
#define RB_DIR_RIGHT 1
|
||||
#define RB_DIR_OTHER 1
|
||||
#define rb_left rb_nodes[RB_DIR_LEFT]
|
||||
#define rb_right rb_nodes[RB_DIR_RIGHT]
|
||||
|
||||
/*
|
||||
* rb_info contains the two flags and the parent back pointer.
|
||||
* We put the two flags in the low two bits since we know that
|
||||
* rb_node will have an alignment of 4 or 8 bytes.
|
||||
*/
|
||||
uintptr_t rb_info;
|
||||
#define RB_FLAG_POSITION 0x2
|
||||
#define RB_FLAG_RED 0x1
|
||||
#define RB_FLAG_MASK (RB_FLAG_POSITION|RB_FLAG_RED)
|
||||
#define RB_FATHER(rb) \
|
||||
((struct rb_node *)((rb)->rb_info & ~RB_FLAG_MASK))
|
||||
#define RB_SET_FATHER(rb, father) \
|
||||
((void)((rb)->rb_info = (uintptr_t)(father)|((rb)->rb_info & RB_FLAG_MASK)))
|
||||
|
||||
#define RB_SENTINEL_P(rb) ((rb) == NULL)
|
||||
#define RB_LEFT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_left)
|
||||
#define RB_RIGHT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_right)
|
||||
#define RB_FATHER_SENTINEL_P(rb) RB_SENTINEL_P(RB_FATHER((rb)))
|
||||
#define RB_CHILDLESS_P(rb) \
|
||||
(RB_SENTINEL_P(rb) || (RB_LEFT_SENTINEL_P(rb) && RB_RIGHT_SENTINEL_P(rb)))
|
||||
#define RB_TWOCHILDREN_P(rb) \
|
||||
(!RB_SENTINEL_P(rb) && !RB_LEFT_SENTINEL_P(rb) && !RB_RIGHT_SENTINEL_P(rb))
|
||||
|
||||
#define RB_POSITION(rb) \
|
||||
(((rb)->rb_info & RB_FLAG_POSITION) ? RB_DIR_RIGHT : RB_DIR_LEFT)
|
||||
#define RB_RIGHT_P(rb) (RB_POSITION(rb) == RB_DIR_RIGHT)
|
||||
#define RB_LEFT_P(rb) (RB_POSITION(rb) == RB_DIR_LEFT)
|
||||
#define RB_RED_P(rb) (!RB_SENTINEL_P(rb) && ((rb)->rb_info & RB_FLAG_RED) != 0)
|
||||
#define RB_BLACK_P(rb) (RB_SENTINEL_P(rb) || ((rb)->rb_info & RB_FLAG_RED) == 0)
|
||||
#define RB_MARK_RED(rb) ((void)((rb)->rb_info |= RB_FLAG_RED))
|
||||
#define RB_MARK_BLACK(rb) ((void)((rb)->rb_info &= ~RB_FLAG_RED))
|
||||
#define RB_INVERT_COLOR(rb) ((void)((rb)->rb_info ^= RB_FLAG_RED))
|
||||
#define RB_ROOT_P(rbt, rb) ((rbt)->rbt_root == (rb))
|
||||
#define RB_SET_POSITION(rb, position) \
|
||||
((void)((position) ? ((rb)->rb_info |= RB_FLAG_POSITION) : \
|
||||
((rb)->rb_info &= ~RB_FLAG_POSITION)))
|
||||
#define RB_ZERO_PROPERTIES(rb) ((void)((rb)->rb_info &= ~RB_FLAG_MASK))
|
||||
#define RB_COPY_PROPERTIES(dst, src) \
|
||||
((void)((dst)->rb_info ^= ((dst)->rb_info ^ (src)->rb_info) & RB_FLAG_MASK))
|
||||
#define RB_SWAP_PROPERTIES(a, b) do { \
|
||||
uintptr_t xorinfo = ((a)->rb_info ^ (b)->rb_info) & RB_FLAG_MASK; \
|
||||
(a)->rb_info ^= xorinfo; \
|
||||
(b)->rb_info ^= xorinfo; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
#ifdef RBDEBUG
|
||||
TAILQ_ENTRY(rb_node) rb_link;
|
||||
#endif
|
||||
} rb_node_t;
|
||||
|
||||
#define RB_TREE_MIN(T) rb_tree_iterate((T), NULL, RB_DIR_LEFT)
|
||||
#define RB_TREE_MAX(T) rb_tree_iterate((T), NULL, RB_DIR_RIGHT)
|
||||
#define RB_TREE_FOREACH(N, T) \
|
||||
for ((N) = RB_TREE_MIN(T); (N); \
|
||||
(N) = rb_tree_iterate((T), (N), RB_DIR_RIGHT))
|
||||
#define RB_TREE_FOREACH_REVERSE(N, T) \
|
||||
for ((N) = RB_TREE_MAX(T); (N); \
|
||||
(N) = rb_tree_iterate((T), (N), RB_DIR_LEFT))
|
||||
|
||||
#ifdef RBDEBUG
|
||||
TAILQ_HEAD(rb_node_qh, rb_node);
|
||||
|
||||
#define RB_TAILQ_REMOVE(a, b, c) TAILQ_REMOVE(a, b, c)
|
||||
#define RB_TAILQ_INIT(a) TAILQ_INIT(a)
|
||||
#define RB_TAILQ_INSERT_HEAD(a, b, c) TAILQ_INSERT_HEAD(a, b, c)
|
||||
#define RB_TAILQ_INSERT_BEFORE(a, b, c) TAILQ_INSERT_BEFORE(a, b, c)
|
||||
#define RB_TAILQ_INSERT_AFTER(a, b, c, d) TAILQ_INSERT_AFTER(a, b, c, d)
|
||||
#else
|
||||
#define RB_TAILQ_REMOVE(a, b, c) do { } while (/*CONSTCOND*/0)
|
||||
#define RB_TAILQ_INIT(a) do { } while (/*CONSTCOND*/0)
|
||||
#define RB_TAILQ_INSERT_HEAD(a, b, c) do { } while (/*CONSTCOND*/0)
|
||||
#define RB_TAILQ_INSERT_BEFORE(a, b, c) do { } while (/*CONSTCOND*/0)
|
||||
#define RB_TAILQ_INSERT_AFTER(a, b, c, d) do { } while (/*CONSTCOND*/0)
|
||||
#endif /* RBDEBUG */
|
||||
|
||||
/*
|
||||
* rbto_compare_nodes_fn:
|
||||
* return a positive value if the first node > the second node.
|
||||
* return a negative value if the first node < the second node.
|
||||
* return 0 if they are considered same.
|
||||
*
|
||||
* rbto_compare_key_fn:
|
||||
* return a positive value if the node > the key.
|
||||
* return a negative value if the node < the key.
|
||||
* return 0 if they are considered same.
|
||||
*/
|
||||
|
||||
typedef signed int (*const rbto_compare_nodes_fn)(void *,
|
||||
const void *, const void *);
|
||||
typedef signed int (*const rbto_compare_key_fn)(void *,
|
||||
const void *, const void *);
|
||||
|
||||
typedef struct {
|
||||
rbto_compare_nodes_fn rbto_compare_nodes;
|
||||
rbto_compare_key_fn rbto_compare_key;
|
||||
size_t rbto_node_offset;
|
||||
void *rbto_context;
|
||||
} rb_tree_ops_t;
|
||||
|
||||
typedef struct rb_tree {
|
||||
struct rb_node *rbt_root;
|
||||
const rb_tree_ops_t *rbt_ops;
|
||||
struct rb_node *rbt_minmax[2];
|
||||
#ifdef RBDEBUG
|
||||
struct rb_node_qh rbt_nodes;
|
||||
#endif
|
||||
#ifdef RBSTATS
|
||||
unsigned int rbt_count;
|
||||
unsigned int rbt_insertions;
|
||||
unsigned int rbt_removals;
|
||||
unsigned int rbt_insertion_rebalance_calls;
|
||||
unsigned int rbt_insertion_rebalance_passes;
|
||||
unsigned int rbt_removal_rebalance_calls;
|
||||
unsigned int rbt_removal_rebalance_passes;
|
||||
#endif
|
||||
} rb_tree_t;
|
||||
|
||||
#ifdef RBSTATS
|
||||
#define RBSTAT_INC(v) ((void)((v)++))
|
||||
#define RBSTAT_DEC(v) ((void)((v)--))
|
||||
#else
|
||||
#define RBSTAT_INC(v) do { } while (/*CONSTCOND*/0)
|
||||
#define RBSTAT_DEC(v) do { } while (/*CONSTCOND*/0)
|
||||
#endif
|
||||
|
||||
void rb_tree_init(rb_tree_t *, const rb_tree_ops_t *);
|
||||
void * rb_tree_insert_node(rb_tree_t *, void *);
|
||||
void * rb_tree_find_node(rb_tree_t *, const void *);
|
||||
void * rb_tree_find_node_geq(rb_tree_t *, const void *);
|
||||
void * rb_tree_find_node_leq(rb_tree_t *, const void *);
|
||||
void rb_tree_remove_node(rb_tree_t *, void *);
|
||||
void * rb_tree_iterate(rb_tree_t *, void *, const unsigned int);
|
||||
#ifdef RBDEBUG
|
||||
void rb_tree_check(const rb_tree_t *, bool);
|
||||
#endif
|
||||
#ifdef RBSTATS
|
||||
void rb_tree_depths(const rb_tree_t *, size_t *);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_RBTREE_H_*/
|
962
lib/portableproplib/prop_array.c
Normal file
962
lib/portableproplib/prop_array.c
Normal file
@@ -0,0 +1,962 @@
|
||||
/* $NetBSD: prop_array.c,v 1.21 2012/07/27 09:10:59 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007 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.
|
||||
*
|
||||
* 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 "prop_object_impl.h"
|
||||
#include <prop/prop_array.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
struct _prop_array {
|
||||
struct _prop_object pa_obj;
|
||||
_PROP_RWLOCK_DECL(pa_rwlock)
|
||||
prop_object_t * pa_array;
|
||||
unsigned int pa_capacity;
|
||||
unsigned int pa_count;
|
||||
int pa_flags;
|
||||
|
||||
uint32_t pa_version;
|
||||
};
|
||||
|
||||
#define PA_F_IMMUTABLE 0x01 /* array is immutable */
|
||||
|
||||
_PROP_POOL_INIT(_prop_array_pool, sizeof(struct _prop_array), "proparay")
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_array_free(prop_stack_t, prop_object_t *);
|
||||
static void _prop_array_emergency_free(prop_object_t);
|
||||
static bool _prop_array_externalize(
|
||||
struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_array_equals(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
static void _prop_array_equals_finish(prop_object_t, prop_object_t);
|
||||
static prop_object_iterator_t
|
||||
_prop_array_iterator_locked(prop_array_t);
|
||||
static prop_object_t
|
||||
_prop_array_iterator_next_object_locked(void *);
|
||||
static void _prop_array_iterator_reset_locked(void *);
|
||||
|
||||
static const struct _prop_object_type _prop_object_type_array = {
|
||||
.pot_type = PROP_TYPE_ARRAY,
|
||||
.pot_free = _prop_array_free,
|
||||
.pot_emergency_free = _prop_array_emergency_free,
|
||||
.pot_extern = _prop_array_externalize,
|
||||
.pot_equals = _prop_array_equals,
|
||||
.pot_equals_finish = _prop_array_equals_finish,
|
||||
};
|
||||
|
||||
#define prop_object_is_array(x) \
|
||||
((x) != NULL && (x)->pa_obj.po_type == &_prop_object_type_array)
|
||||
|
||||
#define prop_array_is_immutable(x) (((x)->pa_flags & PA_F_IMMUTABLE) != 0)
|
||||
|
||||
struct _prop_array_iterator {
|
||||
struct _prop_object_iterator pai_base;
|
||||
unsigned int pai_index;
|
||||
};
|
||||
|
||||
#define EXPAND_STEP 16
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_array_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_array_t pa = *obj;
|
||||
prop_object_t po;
|
||||
|
||||
_PROP_ASSERT(pa->pa_count <= pa->pa_capacity);
|
||||
_PROP_ASSERT((pa->pa_capacity == 0 && pa->pa_array == NULL) ||
|
||||
(pa->pa_capacity != 0 && pa->pa_array != NULL));
|
||||
|
||||
/* The easy case is an empty array, just free and return. */
|
||||
if (pa->pa_count == 0) {
|
||||
if (pa->pa_array != NULL)
|
||||
_PROP_FREE(pa->pa_array, M_PROP_ARRAY);
|
||||
|
||||
_PROP_RWLOCK_DESTROY(pa->pa_rwlock);
|
||||
|
||||
_PROP_POOL_PUT(_prop_array_pool, pa);
|
||||
|
||||
return (_PROP_OBJECT_FREE_DONE);
|
||||
}
|
||||
|
||||
po = pa->pa_array[pa->pa_count - 1];
|
||||
_PROP_ASSERT(po != NULL);
|
||||
|
||||
if (stack == NULL) {
|
||||
/*
|
||||
* If we are in emergency release mode,
|
||||
* just let caller recurse down.
|
||||
*/
|
||||
*obj = po;
|
||||
return (_PROP_OBJECT_FREE_FAILED);
|
||||
}
|
||||
|
||||
/* Otherwise, try to push the current object on the stack. */
|
||||
if (!_prop_stack_push(stack, pa, NULL, NULL, NULL)) {
|
||||
/* Push failed, entering emergency release mode. */
|
||||
return (_PROP_OBJECT_FREE_FAILED);
|
||||
}
|
||||
/* Object pushed on stack, caller will release it. */
|
||||
--pa->pa_count;
|
||||
*obj = po;
|
||||
return (_PROP_OBJECT_FREE_RECURSE);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_array_emergency_free(prop_object_t obj)
|
||||
{
|
||||
prop_array_t pa = obj;
|
||||
|
||||
_PROP_ASSERT(pa->pa_count != 0);
|
||||
--pa->pa_count;
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_array_t pa = v;
|
||||
struct _prop_object *po;
|
||||
prop_object_iterator_t pi;
|
||||
unsigned int i;
|
||||
bool rv = false;
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
|
||||
if (pa->pa_count == 0) {
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (_prop_object_externalize_empty_tag(ctx, "array"));
|
||||
}
|
||||
|
||||
/* XXXJRT Hint "count" for the internalize step? */
|
||||
if (_prop_object_externalize_start_tag(ctx, "array") == false ||
|
||||
_prop_object_externalize_append_char(ctx, '\n') == false)
|
||||
goto out;
|
||||
|
||||
pi = _prop_array_iterator_locked(pa);
|
||||
if (pi == NULL)
|
||||
goto out;
|
||||
|
||||
ctx->poec_depth++;
|
||||
_PROP_ASSERT(ctx->poec_depth != 0);
|
||||
|
||||
while ((po = _prop_array_iterator_next_object_locked(pi)) != NULL) {
|
||||
if ((*po->po_type->pot_extern)(ctx, po) == false) {
|
||||
prop_object_iterator_release(pi);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
prop_object_iterator_release(pi);
|
||||
|
||||
ctx->poec_depth--;
|
||||
for (i = 0; i < ctx->poec_depth; i++) {
|
||||
if (_prop_object_externalize_append_char(ctx, '\t') == false)
|
||||
goto out;
|
||||
}
|
||||
if (_prop_object_externalize_end_tag(ctx, "array") == false)
|
||||
goto out;
|
||||
|
||||
rv = true;
|
||||
|
||||
out:
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_array_equals(prop_object_t v1, prop_object_t v2,
|
||||
void **stored_pointer1, void **stored_pointer2,
|
||||
prop_object_t *next_obj1, prop_object_t *next_obj2)
|
||||
{
|
||||
prop_array_t array1 = v1;
|
||||
prop_array_t array2 = v2;
|
||||
uintptr_t idx;
|
||||
_prop_object_equals_rv_t rv = _PROP_OBJECT_EQUALS_FALSE;
|
||||
|
||||
if (array1 == array2)
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
|
||||
_PROP_ASSERT(*stored_pointer1 == *stored_pointer2);
|
||||
idx = (uintptr_t)*stored_pointer1;
|
||||
|
||||
/* For the first iteration, lock the objects. */
|
||||
if (idx == 0) {
|
||||
if ((uintptr_t)array1 < (uintptr_t)array2) {
|
||||
_PROP_RWLOCK_RDLOCK(array1->pa_rwlock);
|
||||
_PROP_RWLOCK_RDLOCK(array2->pa_rwlock);
|
||||
} else {
|
||||
_PROP_RWLOCK_RDLOCK(array2->pa_rwlock);
|
||||
_PROP_RWLOCK_RDLOCK(array1->pa_rwlock);
|
||||
}
|
||||
}
|
||||
|
||||
if (array1->pa_count != array2->pa_count)
|
||||
goto out;
|
||||
if (idx == array1->pa_count) {
|
||||
rv = _PROP_OBJECT_EQUALS_TRUE;
|
||||
goto out;
|
||||
}
|
||||
_PROP_ASSERT(idx < array1->pa_count);
|
||||
|
||||
*stored_pointer1 = (void *)(idx + 1);
|
||||
*stored_pointer2 = (void *)(idx + 1);
|
||||
|
||||
*next_obj1 = array1->pa_array[idx];
|
||||
*next_obj2 = array2->pa_array[idx];
|
||||
|
||||
return (_PROP_OBJECT_EQUALS_RECURSE);
|
||||
|
||||
out:
|
||||
_PROP_RWLOCK_UNLOCK(array1->pa_rwlock);
|
||||
_PROP_RWLOCK_UNLOCK(array2->pa_rwlock);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_array_equals_finish(prop_object_t v1, prop_object_t v2)
|
||||
{
|
||||
_PROP_RWLOCK_UNLOCK(((prop_array_t)v1)->pa_rwlock);
|
||||
_PROP_RWLOCK_UNLOCK(((prop_array_t)v2)->pa_rwlock);
|
||||
}
|
||||
|
||||
static prop_array_t
|
||||
_prop_array_alloc(unsigned int capacity)
|
||||
{
|
||||
prop_array_t pa;
|
||||
prop_object_t *array;
|
||||
|
||||
if (capacity != 0) {
|
||||
array = _PROP_CALLOC(capacity * sizeof(prop_object_t),
|
||||
M_PROP_ARRAY);
|
||||
if (array == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
array = NULL;
|
||||
|
||||
pa = _PROP_POOL_GET(_prop_array_pool);
|
||||
if (pa != NULL) {
|
||||
_prop_object_init(&pa->pa_obj, &_prop_object_type_array);
|
||||
pa->pa_obj.po_type = &_prop_object_type_array;
|
||||
|
||||
_PROP_RWLOCK_INIT(pa->pa_rwlock);
|
||||
pa->pa_array = array;
|
||||
pa->pa_capacity = capacity;
|
||||
pa->pa_count = 0;
|
||||
pa->pa_flags = 0;
|
||||
|
||||
pa->pa_version = 0;
|
||||
} else if (array != NULL)
|
||||
_PROP_FREE(array, M_PROP_ARRAY);
|
||||
|
||||
return (pa);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_expand(prop_array_t pa, unsigned int capacity)
|
||||
{
|
||||
prop_object_t *array, *oarray;
|
||||
|
||||
/*
|
||||
* Array must be WRITE-LOCKED.
|
||||
*/
|
||||
|
||||
oarray = pa->pa_array;
|
||||
|
||||
array = _PROP_CALLOC(capacity * sizeof(*array), M_PROP_ARRAY);
|
||||
if (array == NULL)
|
||||
return (false);
|
||||
if (oarray != NULL)
|
||||
memcpy(array, oarray, pa->pa_capacity * sizeof(*array));
|
||||
pa->pa_array = array;
|
||||
pa->pa_capacity = capacity;
|
||||
|
||||
if (oarray != NULL)
|
||||
_PROP_FREE(oarray, M_PROP_ARRAY);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static prop_object_t
|
||||
_prop_array_iterator_next_object_locked(void *v)
|
||||
{
|
||||
struct _prop_array_iterator *pai = v;
|
||||
prop_array_t pa = pai->pai_base.pi_obj;
|
||||
prop_object_t po = NULL;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
if (pa->pa_version != pai->pai_base.pi_version)
|
||||
goto out; /* array changed during iteration */
|
||||
|
||||
_PROP_ASSERT(pai->pai_index <= pa->pa_count);
|
||||
|
||||
if (pai->pai_index == pa->pa_count)
|
||||
goto out; /* we've iterated all objects */
|
||||
|
||||
po = pa->pa_array[pai->pai_index];
|
||||
pai->pai_index++;
|
||||
|
||||
out:
|
||||
return (po);
|
||||
}
|
||||
|
||||
static prop_object_t
|
||||
_prop_array_iterator_next_object(void *v)
|
||||
{
|
||||
struct _prop_array_iterator *pai = v;
|
||||
prop_array_t pa _PROP_ARG_UNUSED = pai->pai_base.pi_obj;
|
||||
prop_object_t po;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
po = _prop_array_iterator_next_object_locked(pai);
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (po);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_array_iterator_reset_locked(void *v)
|
||||
{
|
||||
struct _prop_array_iterator *pai = v;
|
||||
prop_array_t pa = pai->pai_base.pi_obj;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
pai->pai_index = 0;
|
||||
pai->pai_base.pi_version = pa->pa_version;
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_array_iterator_reset(void *v)
|
||||
{
|
||||
struct _prop_array_iterator *pai = v;
|
||||
prop_array_t pa _PROP_ARG_UNUSED = pai->pai_base.pi_obj;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
_prop_array_iterator_reset_locked(pai);
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_create --
|
||||
* Create an empty array.
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_create(void)
|
||||
{
|
||||
|
||||
return (_prop_array_alloc(0));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_create_with_capacity --
|
||||
* Create an array with the capacity to store N objects.
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_create_with_capacity(unsigned int capacity)
|
||||
{
|
||||
|
||||
return (_prop_array_alloc(capacity));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_copy --
|
||||
* Copy an array. The new array has an initial capacity equal to
|
||||
* the number of objects stored in the original array. The new
|
||||
* array contains references to the original array's objects, not
|
||||
* copies of those objects (i.e. a shallow copy).
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_copy(prop_array_t opa)
|
||||
{
|
||||
prop_array_t pa;
|
||||
prop_object_t po;
|
||||
unsigned int idx;
|
||||
|
||||
if (! prop_object_is_array(opa))
|
||||
return (NULL);
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(opa->pa_rwlock);
|
||||
|
||||
pa = _prop_array_alloc(opa->pa_count);
|
||||
if (pa != NULL) {
|
||||
for (idx = 0; idx < opa->pa_count; idx++) {
|
||||
po = opa->pa_array[idx];
|
||||
prop_object_retain(po);
|
||||
pa->pa_array[idx] = po;
|
||||
}
|
||||
pa->pa_count = opa->pa_count;
|
||||
pa->pa_flags = opa->pa_flags;
|
||||
}
|
||||
_PROP_RWLOCK_UNLOCK(opa->pa_rwlock);
|
||||
return (pa);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_copy_mutable --
|
||||
* Like prop_array_copy(), but the resulting array is mutable.
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_copy_mutable(prop_array_t opa)
|
||||
{
|
||||
prop_array_t pa;
|
||||
|
||||
pa = prop_array_copy(opa);
|
||||
if (pa != NULL)
|
||||
pa->pa_flags &= ~PA_F_IMMUTABLE;
|
||||
|
||||
return (pa);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_capacity --
|
||||
* Return the capacity of the array.
|
||||
*/
|
||||
unsigned int
|
||||
prop_array_capacity(prop_array_t pa)
|
||||
{
|
||||
unsigned int rv;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (0);
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
rv = pa->pa_capacity;
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_count --
|
||||
* Return the number of objects stored in the array.
|
||||
*/
|
||||
unsigned int
|
||||
prop_array_count(prop_array_t pa)
|
||||
{
|
||||
unsigned int rv;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (0);
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
rv = pa->pa_count;
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_ensure_capacity --
|
||||
* Ensure that the array has the capacity to store the specified
|
||||
* total number of objects (inluding the objects already stored
|
||||
* in the array).
|
||||
*/
|
||||
bool
|
||||
prop_array_ensure_capacity(prop_array_t pa, unsigned int capacity)
|
||||
{
|
||||
bool rv;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (false);
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
if (capacity > pa->pa_capacity)
|
||||
rv = _prop_array_expand(pa, capacity);
|
||||
else
|
||||
rv = true;
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static prop_object_iterator_t
|
||||
_prop_array_iterator_locked(prop_array_t pa)
|
||||
{
|
||||
struct _prop_array_iterator *pai;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (NULL);
|
||||
|
||||
pai = _PROP_CALLOC(sizeof(*pai), M_TEMP);
|
||||
if (pai == NULL)
|
||||
return (NULL);
|
||||
pai->pai_base.pi_next_object = _prop_array_iterator_next_object;
|
||||
pai->pai_base.pi_reset = _prop_array_iterator_reset;
|
||||
prop_object_retain(pa);
|
||||
pai->pai_base.pi_obj = pa;
|
||||
_prop_array_iterator_reset_locked(pai);
|
||||
|
||||
return (&pai->pai_base);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_iterator --
|
||||
* Return an iterator for the array. The array is retained by
|
||||
* the iterator.
|
||||
*/
|
||||
prop_object_iterator_t
|
||||
prop_array_iterator(prop_array_t pa)
|
||||
{
|
||||
prop_object_iterator_t pi;
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
pi = _prop_array_iterator_locked(pa);
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (pi);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_make_immutable --
|
||||
* Make the array immutable.
|
||||
*/
|
||||
void
|
||||
prop_array_make_immutable(prop_array_t pa)
|
||||
{
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
if (prop_array_is_immutable(pa) == false)
|
||||
pa->pa_flags |= PA_F_IMMUTABLE;
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_mutable --
|
||||
* Returns true if the array is mutable.
|
||||
*/
|
||||
bool
|
||||
prop_array_mutable(prop_array_t pa)
|
||||
{
|
||||
bool rv;
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
rv = prop_array_is_immutable(pa) == false;
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_get --
|
||||
* Return the object stored at the specified array index.
|
||||
*/
|
||||
prop_object_t
|
||||
prop_array_get(prop_array_t pa, unsigned int idx)
|
||||
{
|
||||
prop_object_t po = NULL;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (NULL);
|
||||
|
||||
_PROP_RWLOCK_RDLOCK(pa->pa_rwlock);
|
||||
if (idx >= pa->pa_count)
|
||||
goto out;
|
||||
po = pa->pa_array[idx];
|
||||
_PROP_ASSERT(po != NULL);
|
||||
out:
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (po);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_add(prop_array_t pa, prop_object_t po)
|
||||
{
|
||||
|
||||
/*
|
||||
* Array must be WRITE-LOCKED.
|
||||
*/
|
||||
|
||||
_PROP_ASSERT(pa->pa_count <= pa->pa_capacity);
|
||||
|
||||
if (prop_array_is_immutable(pa) ||
|
||||
(pa->pa_count == pa->pa_capacity &&
|
||||
_prop_array_expand(pa, pa->pa_capacity + EXPAND_STEP) == false))
|
||||
return (false);
|
||||
|
||||
prop_object_retain(po);
|
||||
pa->pa_array[pa->pa_count++] = po;
|
||||
pa->pa_version++;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_add_first(prop_array_t pa, prop_object_t po)
|
||||
{
|
||||
unsigned int cnt;
|
||||
/*
|
||||
* Array must be WRITE-LOCKED.
|
||||
*/
|
||||
|
||||
_PROP_ASSERT(pa->pa_count <= pa->pa_capacity);
|
||||
|
||||
if (prop_array_is_immutable(pa) ||
|
||||
(pa->pa_count == pa->pa_capacity &&
|
||||
_prop_array_expand(pa, pa->pa_capacity + EXPAND_STEP) == false))
|
||||
return false;
|
||||
|
||||
prop_object_retain(po);
|
||||
if (pa->pa_count) {
|
||||
cnt = pa->pa_count+1;
|
||||
/* move all stored elements to the right */
|
||||
while (--cnt) {
|
||||
prop_object_t opo = pa->pa_array[cnt-1];
|
||||
_PROP_ASSERT(opo != NULL);
|
||||
prop_object_retain(opo);
|
||||
pa->pa_array[cnt] = opo;
|
||||
prop_object_release(opo);
|
||||
}
|
||||
/* passed in object is now the first element */
|
||||
pa->pa_array[0] = po;
|
||||
pa->pa_version++;
|
||||
pa->pa_count++;
|
||||
} else {
|
||||
pa->pa_array[pa->pa_count++] = po;
|
||||
pa->pa_version++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_set --
|
||||
* Store a reference to an object at the specified array index.
|
||||
* This method is not allowed to create holes in the array; the
|
||||
* caller must either be setting the object just beyond the existing
|
||||
* count or replacing an already existing object reference.
|
||||
*/
|
||||
bool
|
||||
prop_array_set(prop_array_t pa, unsigned int idx, prop_object_t po)
|
||||
{
|
||||
prop_object_t opo;
|
||||
bool rv = false;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (false);
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
|
||||
if (prop_array_is_immutable(pa))
|
||||
goto out;
|
||||
|
||||
if (idx == pa->pa_count) {
|
||||
rv = _prop_array_add(pa, po);
|
||||
goto out;
|
||||
}
|
||||
|
||||
_PROP_ASSERT(idx < pa->pa_count);
|
||||
|
||||
opo = pa->pa_array[idx];
|
||||
_PROP_ASSERT(opo != NULL);
|
||||
|
||||
prop_object_retain(po);
|
||||
pa->pa_array[idx] = po;
|
||||
pa->pa_version++;
|
||||
|
||||
prop_object_release(opo);
|
||||
|
||||
rv = true;
|
||||
|
||||
out:
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_add --
|
||||
* Add a reference to an object to the specified array, appending
|
||||
* to the end and growing the array's capacity, if necessary.
|
||||
*/
|
||||
bool
|
||||
prop_array_add(prop_array_t pa, prop_object_t po)
|
||||
{
|
||||
bool rv;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (false);
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
rv = _prop_array_add(pa, po);
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_add_first --
|
||||
* Add a reference to an object to the specified array, inserting it
|
||||
* as first element, moving all objects to the right and growing the
|
||||
* array's capacity, if necessary.
|
||||
*/
|
||||
bool
|
||||
prop_array_add_first(prop_array_t pa, prop_object_t po)
|
||||
{
|
||||
bool rv;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return (false);
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
rv = _prop_array_add_first(pa, po);
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
/*
|
||||
* prop_array_remove --
|
||||
* Remove the reference to an object from an array at the specified
|
||||
* index. The array will be compacted following the removal.
|
||||
*/
|
||||
void
|
||||
prop_array_remove(prop_array_t pa, unsigned int idx)
|
||||
{
|
||||
prop_object_t po;
|
||||
|
||||
if (! prop_object_is_array(pa))
|
||||
return;
|
||||
|
||||
_PROP_RWLOCK_WRLOCK(pa->pa_rwlock);
|
||||
|
||||
_PROP_ASSERT(idx < pa->pa_count);
|
||||
|
||||
/* XXX Should this be a _PROP_ASSERT()? */
|
||||
if (prop_array_is_immutable(pa)) {
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
return;
|
||||
}
|
||||
|
||||
po = pa->pa_array[idx];
|
||||
_PROP_ASSERT(po != NULL);
|
||||
|
||||
for (++idx; idx < pa->pa_count; idx++)
|
||||
pa->pa_array[idx - 1] = pa->pa_array[idx];
|
||||
pa->pa_count--;
|
||||
pa->pa_version++;
|
||||
|
||||
_PROP_RWLOCK_UNLOCK(pa->pa_rwlock);
|
||||
|
||||
prop_object_release(po);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_equals --
|
||||
* Return true if the two arrays are equivalent. Note we do a
|
||||
* by-value comparison of the objects in the array.
|
||||
*/
|
||||
bool
|
||||
prop_array_equals(prop_array_t array1, prop_array_t array2)
|
||||
{
|
||||
if (!prop_object_is_array(array1) || !prop_object_is_array(array2))
|
||||
return (false);
|
||||
|
||||
return (prop_object_equals(array1, array2));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_externalize --
|
||||
* Externalize an array, return a NUL-terminated buffer
|
||||
* containing the XML-style representation. The buffer is allocated
|
||||
* with the M_TEMP memory type.
|
||||
*/
|
||||
char *
|
||||
prop_array_externalize(prop_array_t pa)
|
||||
{
|
||||
struct _prop_object_externalize_context *ctx;
|
||||
char *cp;
|
||||
|
||||
ctx = _prop_object_externalize_context_alloc();
|
||||
if (ctx == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (_prop_object_externalize_header(ctx) == false ||
|
||||
(*pa->pa_obj.po_type->pot_extern)(ctx, pa) == false ||
|
||||
_prop_object_externalize_footer(ctx) == false) {
|
||||
/* We are responsible for releasing the buffer. */
|
||||
_PROP_FREE(ctx->poec_buf, M_TEMP);
|
||||
_prop_object_externalize_context_free(ctx);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
cp = ctx->poec_buf;
|
||||
_prop_object_externalize_context_free(ctx);
|
||||
|
||||
return (cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_array_internalize --
|
||||
* Parse an <array>...</array> and return the object created from the
|
||||
* external representation.
|
||||
*/
|
||||
static bool _prop_array_internalize_body(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
|
||||
bool
|
||||
_prop_array_internalize(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
/* We don't currently understand any attributes. */
|
||||
if (ctx->poic_tagattr != NULL)
|
||||
return (true);
|
||||
|
||||
*obj = prop_array_create();
|
||||
/*
|
||||
* We are done if the create failed or no child elements exist.
|
||||
*/
|
||||
if (*obj == NULL || ctx->poic_is_empty_element)
|
||||
return (true);
|
||||
|
||||
/*
|
||||
* Opening tag is found, now continue to the first element.
|
||||
*/
|
||||
return (_prop_array_internalize_body(stack, obj, ctx));
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_internalize_continue(prop_stack_t stack,
|
||||
prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx,
|
||||
void *data, prop_object_t child)
|
||||
{
|
||||
prop_array_t array;
|
||||
|
||||
_PROP_ASSERT(data == NULL);
|
||||
|
||||
if (child == NULL)
|
||||
goto bad; /* Element could not be parsed. */
|
||||
|
||||
array = *obj;
|
||||
|
||||
if (prop_array_add(array, child) == false) {
|
||||
prop_object_release(child);
|
||||
goto bad;
|
||||
}
|
||||
prop_object_release(child);
|
||||
|
||||
/*
|
||||
* Current element is processed and added, look for next.
|
||||
*/
|
||||
return (_prop_array_internalize_body(stack, obj, ctx));
|
||||
|
||||
bad:
|
||||
prop_object_release(*obj);
|
||||
*obj = NULL;
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_array_internalize_body(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
prop_array_t array = *obj;
|
||||
|
||||
_PROP_ASSERT(array != NULL);
|
||||
|
||||
/* Fetch the next tag. */
|
||||
if (_prop_object_internalize_find_tag(ctx, NULL,
|
||||
_PROP_TAG_TYPE_EITHER) == false)
|
||||
goto bad;
|
||||
|
||||
/* Check to see if this is the end of the array. */
|
||||
if (_PROP_TAG_MATCH(ctx, "array") &&
|
||||
ctx->poic_tag_type == _PROP_TAG_TYPE_END) {
|
||||
/* It is, so don't iterate any further. */
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (_prop_stack_push(stack, array,
|
||||
_prop_array_internalize_continue, NULL, NULL))
|
||||
return (false);
|
||||
|
||||
bad:
|
||||
prop_object_release(array);
|
||||
*obj = NULL;
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_internalize --
|
||||
* Create an array by parsing the XML-style representation.
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_internalize(const char *xml)
|
||||
{
|
||||
return _prop_generic_internalize(xml, "array");
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_externalize_to_file --
|
||||
* Externalize an array to the specified file.
|
||||
*/
|
||||
bool
|
||||
prop_array_externalize_to_file(prop_array_t array, const char *fname)
|
||||
{
|
||||
char *xml;
|
||||
bool rv;
|
||||
int save_errno = 0; /* XXXGCC -Wuninitialized [mips, ...] */
|
||||
|
||||
xml = prop_array_externalize(array);
|
||||
if (xml == NULL)
|
||||
return (false);
|
||||
rv = _prop_object_externalize_write_file(fname, xml, strlen(xml), false);
|
||||
if (rv == false)
|
||||
save_errno = errno;
|
||||
_PROP_FREE(xml, M_TEMP);
|
||||
if (rv == false)
|
||||
errno = save_errno;
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_internalize_from_file --
|
||||
* Internalize an array from a file.
|
||||
*/
|
||||
prop_array_t
|
||||
prop_array_internalize_from_file(const char *fname)
|
||||
{
|
||||
struct _prop_object_internalize_mapped_file *mf;
|
||||
prop_array_t array;
|
||||
|
||||
mf = _prop_object_internalize_map_file(fname);
|
||||
if (mf == NULL)
|
||||
return (NULL);
|
||||
array = prop_array_internalize(mf->poimf_xml);
|
||||
_prop_object_internalize_unmap_file(mf);
|
||||
|
||||
return (array);
|
||||
}
|
266
lib/portableproplib/prop_array_util.c
Normal file
266
lib/portableproplib/prop_array_util.c
Normal file
@@ -0,0 +1,266 @@
|
||||
/* $NetBSD: prop_array_util.c,v 1.4 2012/07/27 09:10:59 pooka 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Utility routines to make it more convenient to work with values
|
||||
* stored in array.
|
||||
*
|
||||
* Note: There is no special magic going on here. We use the standard
|
||||
* proplib(3) APIs to do all of this work. Any application could do
|
||||
* exactly what we're doing here.
|
||||
*/
|
||||
|
||||
#include "prop_object_impl.h" /* hide kernel vs. not-kernel vs. standalone */
|
||||
#include <prop/proplib.h>
|
||||
|
||||
bool
|
||||
prop_array_get_bool(prop_array_t array,
|
||||
unsigned int indx,
|
||||
bool *valp)
|
||||
{
|
||||
prop_bool_t b;
|
||||
|
||||
b = prop_array_get(array, indx);
|
||||
if (prop_object_type(b) != PROP_TYPE_BOOL)
|
||||
return (false);
|
||||
|
||||
*valp = prop_bool_true(b);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
prop_array_set_bool(prop_array_t array,
|
||||
unsigned int indx,
|
||||
bool val)
|
||||
{
|
||||
prop_bool_t b;
|
||||
int rv;
|
||||
|
||||
b = prop_bool_create(val);
|
||||
if (b == NULL)
|
||||
return (false);
|
||||
rv = prop_array_set(array, indx, b);
|
||||
prop_object_release(b);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
#define TEMPLATE(size) \
|
||||
bool \
|
||||
prop_array_get_int ## size (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
int ## size ## _t *valp) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
\
|
||||
num = prop_array_get(array, indx); \
|
||||
if (prop_object_type(num) != PROP_TYPE_NUMBER) \
|
||||
return (false); \
|
||||
\
|
||||
if (prop_number_unsigned(num) && \
|
||||
prop_number_unsigned_integer_value(num) > \
|
||||
/*CONSTCOND*/((size) == 8 ? INT8_MAX : \
|
||||
(size) == 16 ? INT16_MAX : \
|
||||
(size) == 32 ? INT32_MAX : INT64_MAX)) { \
|
||||
return (false); \
|
||||
} \
|
||||
\
|
||||
if (prop_number_size(num) > (size)) \
|
||||
return (false); \
|
||||
\
|
||||
*valp = (int ## size ## _t) prop_number_integer_value(num); \
|
||||
\
|
||||
return (true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_get_uint ## size (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
uint ## size ## _t *valp) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
\
|
||||
num = prop_array_get(array, indx); \
|
||||
if (prop_object_type(num) != PROP_TYPE_NUMBER) \
|
||||
return (false); \
|
||||
\
|
||||
if (prop_number_unsigned(num) == false && \
|
||||
prop_number_integer_value(num) < 0) { \
|
||||
return (false); \
|
||||
} \
|
||||
\
|
||||
if (prop_number_size(num) > (size)) \
|
||||
return (false); \
|
||||
\
|
||||
*valp = (uint ## size ## _t) \
|
||||
prop_number_unsigned_integer_value(num); \
|
||||
\
|
||||
return (true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_set_int ## size (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
int ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_integer((int64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_array_set(array, indx, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_set_uint ## size (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
uint ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_unsigned_integer((uint64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_array_set(array, indx, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_add_int ## size (prop_array_t array, \
|
||||
int ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_integer((int64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_array_add(array, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_add_uint ## size (prop_array_t array, \
|
||||
uint ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_integer((int64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_array_add(array, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
}
|
||||
|
||||
TEMPLATE(8)
|
||||
TEMPLATE(16)
|
||||
TEMPLATE(32)
|
||||
TEMPLATE(64)
|
||||
|
||||
#undef TEMPLATE
|
||||
|
||||
#define TEMPLATE(variant, qualifier) \
|
||||
bool \
|
||||
prop_array_get_cstring ## variant (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
qualifier char **cpp) \
|
||||
{ \
|
||||
prop_string_t str; \
|
||||
\
|
||||
str = prop_array_get(array, indx); \
|
||||
if (prop_object_type(str) != PROP_TYPE_STRING) \
|
||||
return (false); \
|
||||
\
|
||||
*cpp = prop_string_cstring ## variant (str); \
|
||||
\
|
||||
return (*cpp == NULL ? false : true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_add_cstring ## variant (prop_array_t array, \
|
||||
const char *cp) \
|
||||
{ \
|
||||
prop_string_t str; \
|
||||
bool rv; \
|
||||
\
|
||||
str = prop_string_create_cstring ## variant (cp); \
|
||||
if (str == NULL) \
|
||||
return false; \
|
||||
rv = prop_array_add(array, str); \
|
||||
prop_object_release(str); \
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_array_set_cstring ## variant (prop_array_t array, \
|
||||
unsigned int indx, \
|
||||
const char *cp) \
|
||||
{ \
|
||||
prop_string_t str; \
|
||||
int rv; \
|
||||
\
|
||||
str = prop_string_create_cstring ## variant (cp); \
|
||||
if (str == NULL) \
|
||||
return (false); \
|
||||
rv = prop_array_set(array, indx, str); \
|
||||
prop_object_release(str); \
|
||||
\
|
||||
return (rv); \
|
||||
}
|
||||
|
||||
TEMPLATE(,)
|
||||
TEMPLATE(_nocopy,const)
|
||||
|
||||
#undef TEMPLATE
|
||||
|
||||
bool
|
||||
prop_array_add_and_rel(prop_array_t array, prop_object_t po)
|
||||
{
|
||||
bool ret;
|
||||
if (po == NULL)
|
||||
return false;
|
||||
ret = prop_array_add(array, po);
|
||||
prop_object_release(po);
|
||||
return ret;
|
||||
}
|
222
lib/portableproplib/prop_bool.c
Normal file
222
lib/portableproplib/prop_bool.c
Normal file
@@ -0,0 +1,222 @@
|
||||
/* $NetBSD: prop_bool.c,v 1.17 2009/01/03 18:31:33 pooka 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.
|
||||
*
|
||||
* 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 <prop/prop_bool.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
struct _prop_bool {
|
||||
struct _prop_object pb_obj;
|
||||
bool pb_value;
|
||||
};
|
||||
|
||||
static struct _prop_bool _prop_bool_true;
|
||||
static struct _prop_bool _prop_bool_false;
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_bool_free(prop_stack_t, prop_object_t *);
|
||||
static bool _prop_bool_externalize(
|
||||
struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_bool_equals(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
|
||||
static const struct _prop_object_type _prop_object_type_bool = {
|
||||
.pot_type = PROP_TYPE_BOOL,
|
||||
.pot_free = _prop_bool_free,
|
||||
.pot_extern = _prop_bool_externalize,
|
||||
.pot_equals = _prop_bool_equals,
|
||||
};
|
||||
|
||||
#define prop_object_is_bool(x) \
|
||||
((x) != NULL && (x)->pb_obj.po_type == &_prop_object_type_bool)
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_free_rv_t
|
||||
_prop_bool_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
/*
|
||||
* This should never happen as we "leak" our initial reference
|
||||
* count.
|
||||
*/
|
||||
|
||||
/* XXX forced assertion failure? */
|
||||
return (_PROP_OBJECT_FREE_DONE);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_bool_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_bool_t pb = v;
|
||||
|
||||
return (_prop_object_externalize_empty_tag(ctx,
|
||||
pb->pb_value ? "true" : "false"));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_bool_equals(prop_object_t v1, prop_object_t v2,
|
||||
void **stored_pointer1, void **stored_pointer2,
|
||||
prop_object_t *next_obj1, prop_object_t *next_obj2)
|
||||
{
|
||||
prop_bool_t b1 = v1;
|
||||
prop_bool_t b2 = v2;
|
||||
|
||||
if (! (prop_object_is_bool(b1) &&
|
||||
prop_object_is_bool(b2)))
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
|
||||
/*
|
||||
* Since we only ever allocate one true and one false,
|
||||
* save ourselves a couple of memory operations.
|
||||
*/
|
||||
if (b1 == b2)
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
else
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
}
|
||||
|
||||
_PROP_ONCE_DECL(_prop_bool_init_once)
|
||||
|
||||
static int
|
||||
_prop_bool_init(void)
|
||||
{
|
||||
|
||||
_prop_object_init(&_prop_bool_true.pb_obj,
|
||||
&_prop_object_type_bool);
|
||||
_prop_bool_true.pb_value = true;
|
||||
|
||||
_prop_object_init(&_prop_bool_false.pb_obj,
|
||||
&_prop_object_type_bool);
|
||||
_prop_bool_false.pb_value = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static prop_bool_t
|
||||
_prop_bool_alloc(bool val)
|
||||
{
|
||||
prop_bool_t pb;
|
||||
|
||||
_PROP_ONCE_RUN(_prop_bool_init_once, _prop_bool_init);
|
||||
pb = val ? &_prop_bool_true : &_prop_bool_false;
|
||||
prop_object_retain(pb);
|
||||
|
||||
return (pb);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_create --
|
||||
* Create a prop_bool_t and initialize it with the
|
||||
* provided boolean value.
|
||||
*/
|
||||
prop_bool_t
|
||||
prop_bool_create(bool val)
|
||||
{
|
||||
|
||||
return (_prop_bool_alloc(val));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_copy --
|
||||
* Copy a prop_bool_t.
|
||||
*/
|
||||
prop_bool_t
|
||||
prop_bool_copy(prop_bool_t opb)
|
||||
{
|
||||
|
||||
if (! prop_object_is_bool(opb))
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Because we only ever allocate one true and one false, this
|
||||
* can be reduced to a simple retain operation.
|
||||
*/
|
||||
prop_object_retain(opb);
|
||||
return (opb);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_true --
|
||||
* Get the value of a prop_bool_t.
|
||||
*/
|
||||
bool
|
||||
prop_bool_true(prop_bool_t pb)
|
||||
{
|
||||
|
||||
if (! prop_object_is_bool(pb))
|
||||
return (false);
|
||||
|
||||
return (pb->pb_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_equals --
|
||||
* Return true if the boolean values are equivalent.
|
||||
*/
|
||||
bool
|
||||
prop_bool_equals(prop_bool_t b1, prop_bool_t b2)
|
||||
{
|
||||
if (!prop_object_is_bool(b1) || !prop_object_is_bool(b2))
|
||||
return (false);
|
||||
|
||||
return (prop_object_equals(b1, b2));
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_bool_internalize --
|
||||
* Parse a <true/> or <false/> and return the object created from
|
||||
* the external representation.
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
bool
|
||||
_prop_bool_internalize(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
bool val;
|
||||
|
||||
/* No attributes, and it must be an empty element. */
|
||||
if (ctx->poic_tagattr != NULL ||
|
||||
ctx->poic_is_empty_element == false)
|
||||
return (true);
|
||||
|
||||
if (_PROP_TAG_MATCH(ctx, "true"))
|
||||
val = true;
|
||||
else {
|
||||
_PROP_ASSERT(_PROP_TAG_MATCH(ctx, "false"));
|
||||
val = false;
|
||||
}
|
||||
*obj = prop_bool_create(val);
|
||||
return (true);
|
||||
}
|
614
lib/portableproplib/prop_data.c
Normal file
614
lib/portableproplib/prop_data.c
Normal file
@@ -0,0 +1,614 @@
|
||||
/* $NetBSD: prop_data.c,v 1.13 2008/08/03 04:00:12 thorpej 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.
|
||||
*
|
||||
* 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 <prop/prop_data.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct _prop_data {
|
||||
struct _prop_object pd_obj;
|
||||
union {
|
||||
void * pdu_mutable;
|
||||
const void * pdu_immutable;
|
||||
} pd_un;
|
||||
#define pd_mutable pd_un.pdu_mutable
|
||||
#define pd_immutable pd_un.pdu_immutable
|
||||
size_t pd_size;
|
||||
int pd_flags;
|
||||
};
|
||||
|
||||
#define PD_F_NOCOPY 0x01
|
||||
|
||||
_PROP_POOL_INIT(_prop_data_pool, sizeof(struct _prop_data), "propdata")
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_data_free(prop_stack_t, prop_object_t *);
|
||||
static bool _prop_data_externalize(
|
||||
struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_data_equals(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
|
||||
static const struct _prop_object_type _prop_object_type_data = {
|
||||
.pot_type = PROP_TYPE_DATA,
|
||||
.pot_free = _prop_data_free,
|
||||
.pot_extern = _prop_data_externalize,
|
||||
.pot_equals = _prop_data_equals,
|
||||
};
|
||||
|
||||
#define prop_object_is_data(x) \
|
||||
((x) != NULL && (x)->pd_obj.po_type == &_prop_object_type_data)
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_free_rv_t
|
||||
_prop_data_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_data_t pd = *obj;
|
||||
|
||||
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, pd);
|
||||
|
||||
return (_PROP_OBJECT_FREE_DONE);
|
||||
}
|
||||
|
||||
static const char _prop_data_base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char _prop_data_pad64 = '=';
|
||||
|
||||
static bool
|
||||
_prop_data_externalize(struct _prop_object_externalize_context *ctx, void *v)
|
||||
{
|
||||
prop_data_t pd = v;
|
||||
size_t i, srclen;
|
||||
const uint8_t *src;
|
||||
uint8_t output[4];
|
||||
uint8_t input[3];
|
||||
|
||||
if (pd->pd_size == 0)
|
||||
return (_prop_object_externalize_empty_tag(ctx, "data"));
|
||||
|
||||
if (_prop_object_externalize_start_tag(ctx, "data") == false)
|
||||
return (false);
|
||||
|
||||
for (src = pd->pd_immutable, srclen = pd->pd_size;
|
||||
srclen > 2; srclen -= 3) {
|
||||
input[0] = *src++;
|
||||
input[1] = *src++;
|
||||
input[2] = *src++;
|
||||
|
||||
output[0] = (uint32_t)input[0] >> 2;
|
||||
output[1] = ((uint32_t)(input[0] & 0x03) << 4) +
|
||||
((uint32_t)input[1] >> 4);
|
||||
output[2] = ((uint32_t)(input[1] & 0x0f) << 2) +
|
||||
((uint32_t)input[2] >> 6);
|
||||
output[3] = input[2] & 0x3f;
|
||||
_PROP_ASSERT(output[0] < 64);
|
||||
_PROP_ASSERT(output[1] < 64);
|
||||
_PROP_ASSERT(output[2] < 64);
|
||||
_PROP_ASSERT(output[3] < 64);
|
||||
|
||||
if (_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[0]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[1]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[2]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[3]]) == false)
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (srclen != 0) {
|
||||
input[0] = input[1] = input[2] = '\0';
|
||||
for (i = 0; i < srclen; i++)
|
||||
input[i] = *src++;
|
||||
|
||||
output[0] = (uint32_t)input[0] >> 2;
|
||||
output[1] = ((uint32_t)(input[0] & 0x03) << 4) +
|
||||
((uint32_t)input[1] >> 4);
|
||||
output[2] = ((uint32_t)(input[1] & 0x0f) << 2) +
|
||||
((uint32_t)input[2] >> 6);
|
||||
_PROP_ASSERT(output[0] < 64);
|
||||
_PROP_ASSERT(output[1] < 64);
|
||||
_PROP_ASSERT(output[2] < 64);
|
||||
|
||||
if (_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[0]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_base64[output[1]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
srclen == 1 ? _prop_data_pad64
|
||||
: _prop_data_base64[output[2]]) == false ||
|
||||
_prop_object_externalize_append_char(ctx,
|
||||
_prop_data_pad64) == false)
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (_prop_object_externalize_end_tag(ctx, "data") == false)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_data_equals(prop_object_t v1, prop_object_t v2,
|
||||
void **stored_pointer1, void **stored_pointer2,
|
||||
prop_object_t *next_obj1, prop_object_t *next_obj2)
|
||||
{
|
||||
prop_data_t pd1 = v1;
|
||||
prop_data_t pd2 = v2;
|
||||
|
||||
if (pd1 == pd2)
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
if (pd1->pd_size != pd2->pd_size)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
if (pd1->pd_size == 0) {
|
||||
_PROP_ASSERT(pd1->pd_immutable == NULL);
|
||||
_PROP_ASSERT(pd2->pd_immutable == NULL);
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
}
|
||||
if (memcmp(pd1->pd_immutable, pd2->pd_immutable, pd1->pd_size) == 0)
|
||||
return _PROP_OBJECT_EQUALS_TRUE;
|
||||
else
|
||||
return _PROP_OBJECT_EQUALS_FALSE;
|
||||
}
|
||||
|
||||
static 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 && size != 0) {
|
||||
nv = _PROP_MALLOC(size, M_PROP_DATA);
|
||||
if (nv == NULL) {
|
||||
prop_object_release(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_object_release(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.
|
||||
*/
|
||||
bool
|
||||
prop_data_equals(prop_data_t pd1, prop_data_t pd2)
|
||||
{
|
||||
if (!prop_object_is_data(pd1) || !prop_object_is_data(pd2))
|
||||
return (false);
|
||||
|
||||
return (prop_object_equals(pd1, pd2));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_equals_data --
|
||||
* Return true if the contained data is equivalent to the specified
|
||||
* external data.
|
||||
*/
|
||||
bool
|
||||
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);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_data_internalize_decode(struct _prop_object_internalize_context *ctx,
|
||||
uint8_t *target, size_t targsize, size_t *sizep,
|
||||
const char **cpp)
|
||||
{
|
||||
const char *src;
|
||||
size_t tarindex;
|
||||
int state, ch;
|
||||
const char *pos;
|
||||
|
||||
state = 0;
|
||||
tarindex = 0;
|
||||
src = ctx->poic_cp;
|
||||
|
||||
for (;;) {
|
||||
ch = (unsigned char) *src++;
|
||||
if (_PROP_EOF(ch))
|
||||
return (false);
|
||||
if (_PROP_ISSPACE(ch))
|
||||
continue;
|
||||
if (ch == '<') {
|
||||
src--;
|
||||
break;
|
||||
}
|
||||
if (ch == _prop_data_pad64)
|
||||
break;
|
||||
|
||||
pos = strchr(_prop_data_base64, ch);
|
||||
if (pos == NULL)
|
||||
return (false);
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (target) {
|
||||
if (tarindex >= targsize)
|
||||
return (false);
|
||||
target[tarindex] =
|
||||
(uint8_t)((pos - _prop_data_base64) << 2);
|
||||
}
|
||||
state = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (target) {
|
||||
if (tarindex + 1 >= targsize)
|
||||
return (false);
|
||||
target[tarindex] |=
|
||||
(uint32_t)(pos - _prop_data_base64) >> 4;
|
||||
target[tarindex + 1] =
|
||||
(uint8_t)(((pos - _prop_data_base64) & 0xf)
|
||||
<< 4);
|
||||
}
|
||||
tarindex++;
|
||||
state = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (target) {
|
||||
if (tarindex + 1 >= targsize)
|
||||
return (false);
|
||||
target[tarindex] |=
|
||||
(uint32_t)(pos - _prop_data_base64) >> 2;
|
||||
target[tarindex + 1] =
|
||||
(uint8_t)(((pos - _prop_data_base64)
|
||||
& 0x3) << 6);
|
||||
}
|
||||
tarindex++;
|
||||
state = 3;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (target) {
|
||||
if (tarindex >= targsize)
|
||||
return (false);
|
||||
target[tarindex] |= (uint8_t)
|
||||
(pos - _prop_data_base64);
|
||||
}
|
||||
tarindex++;
|
||||
state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
_PROP_ASSERT(/*CONSTCOND*/0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We are done decoding the Base64 characters. Let's see if we
|
||||
* ended up on a byte boundary and/or with unrecognized trailing
|
||||
* characters.
|
||||
*/
|
||||
if (ch == _prop_data_pad64) {
|
||||
ch = (unsigned char) *src; /* src already advanced */
|
||||
if (_PROP_EOF(ch))
|
||||
return (false);
|
||||
switch (state) {
|
||||
case 0: /* Invalid = in first position */
|
||||
case 1: /* Invalid = in second position */
|
||||
return (false);
|
||||
|
||||
case 2: /* Valid, one byte of info */
|
||||
/* Skip whitespace */
|
||||
for (ch = (unsigned char) *src++;
|
||||
ch != '<'; ch = (unsigned char) *src++) {
|
||||
if (_PROP_EOF(ch))
|
||||
return (false);
|
||||
if (!_PROP_ISSPACE(ch))
|
||||
break;
|
||||
}
|
||||
/* Make sure there is another trailing = */
|
||||
if (ch != _prop_data_pad64)
|
||||
return (false);
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 3: /* Valid, two bytes of info */
|
||||
/*
|
||||
* We know this char is a =. Is there anything but
|
||||
* whitespace after it?
|
||||
*/
|
||||
for (ch = (unsigned char) *src++;
|
||||
ch != '<'; ch = (unsigned char) *src++) {
|
||||
if (_PROP_EOF(ch))
|
||||
return (false);
|
||||
if (!_PROP_ISSPACE(ch))
|
||||
return (false);
|
||||
}
|
||||
/* back up to '<' */
|
||||
src--;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We ended by seeing the end of the Base64 string. Make
|
||||
* sure there are no partial bytes lying around.
|
||||
*/
|
||||
if (state != 0)
|
||||
return (false);
|
||||
}
|
||||
|
||||
_PROP_ASSERT(*src == '<');
|
||||
if (sizep != NULL)
|
||||
*sizep = tarindex;
|
||||
if (cpp != NULL)
|
||||
*cpp = src;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_data_internalize --
|
||||
* Parse a <data>...</data> and return the object created from the
|
||||
* external representation.
|
||||
*/
|
||||
|
||||
/* strtoul is used for parsing, enforce. */
|
||||
typedef int PROP_DATA_ASSERT[/* CONSTCOND */sizeof(size_t) == sizeof(unsigned long) ? 1 : -1];
|
||||
|
||||
/* ARGSUSED */
|
||||
bool
|
||||
_prop_data_internalize(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
prop_data_t data;
|
||||
uint8_t *buf;
|
||||
size_t len, alen;
|
||||
|
||||
/*
|
||||
* We don't accept empty elements.
|
||||
* This actually only checks for the node to be <data/>
|
||||
* (Which actually causes another error if found.)
|
||||
*/
|
||||
if (ctx->poic_is_empty_element)
|
||||
return (true);
|
||||
|
||||
/*
|
||||
* If we got a "size" attribute, get the size of the data blob
|
||||
* from that. Otherwise, we have to figure it out from the base64.
|
||||
*/
|
||||
if (ctx->poic_tagattr != NULL) {
|
||||
char *cp;
|
||||
|
||||
if (!_PROP_TAGATTR_MATCH(ctx, "size") ||
|
||||
ctx->poic_tagattrval_len == 0)
|
||||
return (true);
|
||||
|
||||
errno = 0;
|
||||
len = strtoul(ctx->poic_tagattrval, &cp, 0);
|
||||
if (len == ULONG_MAX && errno == ERANGE)
|
||||
return (true);
|
||||
if (cp != ctx->poic_tagattrval + ctx->poic_tagattrval_len)
|
||||
return (true);
|
||||
_PROP_ASSERT(*cp == '\"');
|
||||
} else if (_prop_data_internalize_decode(ctx, NULL, 0, &len,
|
||||
NULL) == false)
|
||||
return (true);
|
||||
|
||||
if (len >= SIZE_MAX)
|
||||
len = 1;
|
||||
/*
|
||||
* Always allocate one extra in case we don't land on an even byte
|
||||
* boundary during the decode.
|
||||
*/
|
||||
buf = _PROP_MALLOC(len + 1, M_PROP_DATA);
|
||||
if (buf == NULL)
|
||||
return (true);
|
||||
|
||||
if (_prop_data_internalize_decode(ctx, buf, len + 1, &alen,
|
||||
&ctx->poic_cp) == false) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (true);
|
||||
}
|
||||
if (alen != len) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (_prop_object_internalize_find_tag(ctx, "data",
|
||||
_PROP_TAG_TYPE_END) == false) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (true);
|
||||
}
|
||||
|
||||
data = _prop_data_alloc();
|
||||
if (data == NULL) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle alternate type of empty node.
|
||||
* XML document could contain open/close tags, yet still be empty.
|
||||
*/
|
||||
if (alen == 0) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
data->pd_mutable = NULL;
|
||||
} else {
|
||||
data->pd_mutable = buf;
|
||||
}
|
||||
data->pd_size = len;
|
||||
|
||||
*obj = data;
|
||||
return (true);
|
||||
}
|
1414
lib/portableproplib/prop_dictionary.c
Normal file
1414
lib/portableproplib/prop_dictionary.c
Normal file
File diff suppressed because it is too large
Load Diff
232
lib/portableproplib/prop_dictionary_util.c
Normal file
232
lib/portableproplib/prop_dictionary_util.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/* $NetBSD: prop_dictionary_util.c,v 1.4 2011/03/24 17:05:39 bouyer 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Utility routines to make it more convenient to work with values
|
||||
* stored in dictionaries.
|
||||
*
|
||||
* Note: There is no special magic going on here. We use the standard
|
||||
* proplib(3) APIs to do all of this work. Any application could do
|
||||
* exactly what we're doing here.
|
||||
*/
|
||||
|
||||
#include <prop/proplib.h>
|
||||
#include "prop_object_impl.h" /* only to hide kernel vs. not-kernel */
|
||||
|
||||
bool
|
||||
prop_dictionary_get_dict(prop_dictionary_t dict, const char *key, prop_dictionary_t *dp)
|
||||
{
|
||||
prop_object_t o;
|
||||
o = prop_dictionary_get(dict, key);
|
||||
if (o == NULL || prop_object_type(o) != PROP_TYPE_DICTIONARY)
|
||||
return false;
|
||||
*dp = o;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
prop_dictionary_get_bool(prop_dictionary_t dict,
|
||||
const char *key,
|
||||
bool *valp)
|
||||
{
|
||||
prop_bool_t b;
|
||||
|
||||
b = prop_dictionary_get(dict, key);
|
||||
if (prop_object_type(b) != PROP_TYPE_BOOL)
|
||||
return (false);
|
||||
|
||||
*valp = prop_bool_true(b);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
prop_dictionary_set_bool(prop_dictionary_t dict,
|
||||
const char *key,
|
||||
bool val)
|
||||
{
|
||||
prop_bool_t b;
|
||||
int rv;
|
||||
|
||||
b = prop_bool_create(val);
|
||||
if (b == NULL)
|
||||
return (false);
|
||||
rv = prop_dictionary_set(dict, key, b);
|
||||
prop_object_release(b);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
#define TEMPLATE(size) \
|
||||
bool \
|
||||
prop_dictionary_get_int ## size (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
int ## size ## _t *valp) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
\
|
||||
num = prop_dictionary_get(dict, key); \
|
||||
if (prop_object_type(num) != PROP_TYPE_NUMBER) \
|
||||
return (false); \
|
||||
\
|
||||
if (prop_number_unsigned(num) && \
|
||||
prop_number_unsigned_integer_value(num) > \
|
||||
/*CONSTCOND*/((size) == 8 ? INT8_MAX : \
|
||||
(size) == 16 ? INT16_MAX : \
|
||||
(size) == 32 ? INT32_MAX : INT64_MAX)) { \
|
||||
return (false); \
|
||||
} \
|
||||
\
|
||||
if (prop_number_size(num) > (size)) \
|
||||
return (false); \
|
||||
\
|
||||
*valp = (int ## size ## _t) prop_number_integer_value(num); \
|
||||
\
|
||||
return (true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_dictionary_get_uint ## size (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
uint ## size ## _t *valp) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
\
|
||||
num = prop_dictionary_get(dict, key); \
|
||||
if (prop_object_type(num) != PROP_TYPE_NUMBER) \
|
||||
return (false); \
|
||||
\
|
||||
if (prop_number_unsigned(num) == false && \
|
||||
prop_number_integer_value(num) < 0) { \
|
||||
return (false); \
|
||||
} \
|
||||
\
|
||||
if (prop_number_size(num) > (size)) \
|
||||
return (false); \
|
||||
\
|
||||
*valp = (uint ## size ## _t) \
|
||||
prop_number_unsigned_integer_value(num); \
|
||||
\
|
||||
return (true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_dictionary_set_int ## size (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
int ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_integer((int64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_dictionary_set(dict, key, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_dictionary_set_uint ## size (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
uint ## size ## _t val) \
|
||||
{ \
|
||||
prop_number_t num; \
|
||||
int rv; \
|
||||
\
|
||||
num = prop_number_create_unsigned_integer((uint64_t) val); \
|
||||
if (num == NULL) \
|
||||
return (false); \
|
||||
rv = prop_dictionary_set(dict, key, num); \
|
||||
prop_object_release(num); \
|
||||
\
|
||||
return (rv); \
|
||||
}
|
||||
|
||||
TEMPLATE(8)
|
||||
TEMPLATE(16)
|
||||
TEMPLATE(32)
|
||||
TEMPLATE(64)
|
||||
|
||||
#undef TEMPLATE
|
||||
|
||||
#define TEMPLATE(variant, qualifier) \
|
||||
bool \
|
||||
prop_dictionary_get_cstring ## variant (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
qualifier char **cpp) \
|
||||
{ \
|
||||
prop_string_t str; \
|
||||
\
|
||||
str = prop_dictionary_get(dict, key); \
|
||||
if (prop_object_type(str) != PROP_TYPE_STRING) \
|
||||
return (false); \
|
||||
\
|
||||
*cpp = prop_string_cstring ## variant (str); \
|
||||
\
|
||||
return (*cpp == NULL ? false : true); \
|
||||
} \
|
||||
\
|
||||
bool \
|
||||
prop_dictionary_set_cstring ## variant (prop_dictionary_t dict, \
|
||||
const char *key, \
|
||||
const char *cp) \
|
||||
{ \
|
||||
prop_string_t str; \
|
||||
int rv; \
|
||||
\
|
||||
str = prop_string_create_cstring ## variant (cp); \
|
||||
if (str == NULL) \
|
||||
return (false); \
|
||||
rv = prop_dictionary_set(dict, key, str); \
|
||||
prop_object_release(str); \
|
||||
\
|
||||
return (rv); \
|
||||
}
|
||||
|
||||
TEMPLATE(,)
|
||||
TEMPLATE(_nocopy,const)
|
||||
|
||||
#undef TEMPLATE
|
||||
|
||||
bool
|
||||
prop_dictionary_set_and_rel(prop_dictionary_t dict, const char *key,
|
||||
prop_object_t po)
|
||||
{
|
||||
bool ret;
|
||||
if (po == NULL)
|
||||
return false;
|
||||
ret = prop_dictionary_set(dict, key, po);
|
||||
prop_object_release(po);
|
||||
return ret;
|
||||
}
|
159
lib/portableproplib/prop_ingest.c
Normal file
159
lib/portableproplib/prop_ingest.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/* $NetBSD: prop_ingest.c,v 1.5 2014/09/05 05:19:24 matt 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.
|
||||
*
|
||||
* 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 "prop_object_impl.h"
|
||||
#include <prop/proplib.h>
|
||||
|
||||
struct _prop_ingest_context {
|
||||
prop_ingest_error_t pic_error;
|
||||
prop_type_t pic_type;
|
||||
const char * pic_key;
|
||||
void * pic_private;
|
||||
};
|
||||
|
||||
/*
|
||||
* prop_ingest_context_alloc --
|
||||
* Allocate and initialize an ingest context.
|
||||
*/
|
||||
prop_ingest_context_t
|
||||
prop_ingest_context_alloc(void *xprivate)
|
||||
{
|
||||
prop_ingest_context_t ctx;
|
||||
|
||||
ctx = _PROP_MALLOC(sizeof(*ctx), M_TEMP);
|
||||
if (ctx != NULL) {
|
||||
ctx->pic_error = PROP_INGEST_ERROR_NO_ERROR;
|
||||
ctx->pic_type = PROP_TYPE_UNKNOWN;
|
||||
ctx->pic_key = NULL;
|
||||
ctx->pic_private = xprivate;
|
||||
}
|
||||
return (ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_ingest_context_free --
|
||||
* Free an ingest context.
|
||||
*/
|
||||
void
|
||||
prop_ingest_context_free(prop_ingest_context_t ctx)
|
||||
{
|
||||
|
||||
_PROP_FREE(ctx, M_TEMP);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_ingest_context_error --
|
||||
* Get the error code from an ingest context.
|
||||
*/
|
||||
prop_ingest_error_t
|
||||
prop_ingest_context_error(prop_ingest_context_t ctx)
|
||||
{
|
||||
|
||||
return (ctx->pic_error);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_ingest_context_type --
|
||||
* Return the type of last object visisted by an ingest context.
|
||||
*/
|
||||
prop_type_t
|
||||
prop_ingest_context_type(prop_ingest_context_t ctx)
|
||||
{
|
||||
|
||||
return (ctx->pic_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_ingest_context_key --
|
||||
* Return the last key looked up by an ingest context.
|
||||
*/
|
||||
const char *
|
||||
prop_ingest_context_key(prop_ingest_context_t ctx)
|
||||
{
|
||||
|
||||
return (ctx->pic_key);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_ingest_context_private --
|
||||
* Return the caller-private data associated with an ingest context.
|
||||
*/
|
||||
void *
|
||||
prop_ingest_context_private(prop_ingest_context_t ctx)
|
||||
{
|
||||
|
||||
return (ctx->pic_private);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_ingest --
|
||||
* Ingest a dictionary using handlers for each object to translate
|
||||
* into an arbitrary binary format.
|
||||
*/
|
||||
bool
|
||||
prop_dictionary_ingest(prop_dictionary_t dict,
|
||||
const prop_ingest_table_entry rules[],
|
||||
prop_ingest_context_t ctx)
|
||||
{
|
||||
const prop_ingest_table_entry *pite;
|
||||
prop_object_t obj;
|
||||
|
||||
ctx->pic_error = PROP_INGEST_ERROR_NO_ERROR;
|
||||
|
||||
for (pite = rules; pite->pite_key != NULL; pite++) {
|
||||
ctx->pic_key = pite->pite_key;
|
||||
obj = prop_dictionary_get(dict, pite->pite_key);
|
||||
ctx->pic_type = prop_object_type(obj);
|
||||
if (obj == NULL) {
|
||||
if (pite->pite_flags & PROP_INGEST_FLAG_OPTIONAL) {
|
||||
if ((*pite->pite_handler)(ctx, NULL) == false) {
|
||||
ctx->pic_error =
|
||||
PROP_INGEST_ERROR_HANDLER_FAILED;
|
||||
return (false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ctx->pic_error = PROP_INGEST_ERROR_NO_KEY;
|
||||
return (false);
|
||||
}
|
||||
if (ctx->pic_type != pite->pite_type &&
|
||||
pite->pite_type != PROP_TYPE_UNKNOWN) {
|
||||
ctx->pic_error = PROP_INGEST_ERROR_WRONG_TYPE;
|
||||
return (false);
|
||||
}
|
||||
if ((*pite->pite_handler)(ctx, obj) == false) {
|
||||
ctx->pic_error = PROP_INGEST_ERROR_HANDLER_FAILED;
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
584
lib/portableproplib/prop_number.c
Normal file
584
lib/portableproplib/prop_number.c
Normal file
@@ -0,0 +1,584 @@
|
||||
/* $NetBSD: prop_number.c,v 1.27 2014/09/05 05:19:24 matt 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.
|
||||
*
|
||||
* 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 <prop/prop_number.h>
|
||||
#include "prop_object_impl.h"
|
||||
#include "prop_rb_impl.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct _prop_number_value {
|
||||
union {
|
||||
int64_t pnu_signed;
|
||||
uint64_t pnu_unsigned;
|
||||
} pnv_un;
|
||||
#define pnv_signed pnv_un.pnu_signed
|
||||
#define pnv_unsigned pnv_un.pnu_unsigned
|
||||
unsigned int pnv_is_unsigned :1,
|
||||
:31;
|
||||
};
|
||||
|
||||
struct _prop_number {
|
||||
struct _prop_object pn_obj;
|
||||
struct rb_node pn_link;
|
||||
struct _prop_number_value pn_value;
|
||||
};
|
||||
|
||||
_PROP_POOL_INIT(_prop_number_pool, sizeof(struct _prop_number), "propnmbr")
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_number_free(prop_stack_t, prop_object_t *);
|
||||
static bool _prop_number_externalize(
|
||||
struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_number_equals(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
|
||||
static void _prop_number_lock(void);
|
||||
static void _prop_number_unlock(void);
|
||||
|
||||
static const struct _prop_object_type _prop_object_type_number = {
|
||||
.pot_type = PROP_TYPE_NUMBER,
|
||||
.pot_free = _prop_number_free,
|
||||
.pot_extern = _prop_number_externalize,
|
||||
.pot_equals = _prop_number_equals,
|
||||
.pot_lock = _prop_number_lock,
|
||||
.pot_unlock = _prop_number_unlock,
|
||||
};
|
||||
|
||||
#define prop_object_is_number(x) \
|
||||
((x) != NULL && (x)->pn_obj.po_type == &_prop_object_type_number)
|
||||
|
||||
/*
|
||||
* Number objects are immutable, and we are likely to have many number
|
||||
* objects that have the same value. So, to save memory, we unique'ify
|
||||
* numbers so we only have one copy of each.
|
||||
*/
|
||||
|
||||
static int
|
||||
_prop_number_compare_values(const struct _prop_number_value *pnv1,
|
||||
const struct _prop_number_value *pnv2)
|
||||
{
|
||||
|
||||
/* Signed numbers are sorted before unsigned numbers. */
|
||||
|
||||
if (pnv1->pnv_is_unsigned) {
|
||||
if (! pnv2->pnv_is_unsigned)
|
||||
return (1);
|
||||
if (pnv1->pnv_unsigned < pnv2->pnv_unsigned)
|
||||
return (-1);
|
||||
if (pnv1->pnv_unsigned > pnv2->pnv_unsigned)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (pnv2->pnv_is_unsigned)
|
||||
return (-1);
|
||||
if (pnv1->pnv_signed < pnv2->pnv_signed)
|
||||
return (-1);
|
||||
if (pnv1->pnv_signed > pnv2->pnv_signed)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
/*ARGSUSED*/
|
||||
_prop_number_rb_compare_nodes(void *ctx _PROP_ARG_UNUSED,
|
||||
const void *n1, const void *n2)
|
||||
{
|
||||
const struct _prop_number *pn1 = n1;
|
||||
const struct _prop_number *pn2 = n2;
|
||||
|
||||
return _prop_number_compare_values(&pn1->pn_value, &pn2->pn_value);
|
||||
}
|
||||
|
||||
static int
|
||||
/*ARGSUSED*/
|
||||
_prop_number_rb_compare_key(void *ctx _PROP_ARG_UNUSED,
|
||||
const void *n, const void *v)
|
||||
{
|
||||
const struct _prop_number *pn = n;
|
||||
const struct _prop_number_value *pnv = v;
|
||||
|
||||
return _prop_number_compare_values(&pn->pn_value, pnv);
|
||||
}
|
||||
|
||||
static const rb_tree_ops_t _prop_number_rb_tree_ops = {
|
||||
.rbto_compare_nodes = _prop_number_rb_compare_nodes,
|
||||
.rbto_compare_key = _prop_number_rb_compare_key,
|
||||
.rbto_node_offset = offsetof(struct _prop_number, pn_link),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
static struct rb_tree _prop_number_tree;
|
||||
_PROP_MUTEX_DECL_STATIC(_prop_number_tree_mutex)
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_free_rv_t
|
||||
_prop_number_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_number_t pn = *obj;
|
||||
|
||||
_prop_rb_tree_remove_node(&_prop_number_tree, pn);
|
||||
|
||||
_PROP_POOL_PUT(_prop_number_pool, pn);
|
||||
|
||||
return (_PROP_OBJECT_FREE_DONE);
|
||||
}
|
||||
|
||||
_PROP_ONCE_DECL(_prop_number_init_once)
|
||||
|
||||
static int
|
||||
_prop_number_init(void)
|
||||
{
|
||||
|
||||
_PROP_MUTEX_INIT(_prop_number_tree_mutex);
|
||||
_prop_rb_tree_init(&_prop_number_tree, &_prop_number_rb_tree_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_number_lock(void)
|
||||
{
|
||||
/* XXX: init necessary? */
|
||||
_PROP_ONCE_RUN(_prop_number_init_once, _prop_number_init);
|
||||
_PROP_MUTEX_LOCK(_prop_number_tree_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_number_unlock(void)
|
||||
{
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_number_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_number_t pn = v;
|
||||
char tmpstr[32];
|
||||
|
||||
/*
|
||||
* For unsigned numbers, we output in hex. For signed numbers,
|
||||
* we output in decimal.
|
||||
*/
|
||||
if (pn->pn_value.pnv_is_unsigned)
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%" PRIu64,
|
||||
pn->pn_value.pnv_unsigned);
|
||||
else
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%" PRIi64,
|
||||
pn->pn_value.pnv_signed);
|
||||
|
||||
if (_prop_object_externalize_start_tag(ctx, "integer") == false ||
|
||||
_prop_object_externalize_append_cstring(ctx, tmpstr) == false ||
|
||||
_prop_object_externalize_end_tag(ctx, "integer") == false)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_number_equals(prop_object_t v1, prop_object_t v2,
|
||||
void **stored_pointer1, void **stored_pointer2,
|
||||
prop_object_t *next_obj1, prop_object_t *next_obj2)
|
||||
{
|
||||
prop_number_t num1 = v1;
|
||||
prop_number_t num2 = v2;
|
||||
|
||||
/*
|
||||
* There is only ever one copy of a number object at any given
|
||||
* time, so we can reduce this to a simple pointer equality check
|
||||
* in the common case.
|
||||
*/
|
||||
if (num1 == num2)
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
|
||||
/*
|
||||
* If the numbers are the same signed-ness, then we know they
|
||||
* cannot be equal because they would have had pointer equality.
|
||||
*/
|
||||
if (num1->pn_value.pnv_is_unsigned == num2->pn_value.pnv_is_unsigned)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
|
||||
/*
|
||||
* We now have one signed value and one unsigned value. We can
|
||||
* compare them iff:
|
||||
* - The unsigned value is not larger than the signed value
|
||||
* can represent.
|
||||
* - The signed value is not smaller than the unsigned value
|
||||
* can represent.
|
||||
*/
|
||||
if (num1->pn_value.pnv_is_unsigned) {
|
||||
/*
|
||||
* num1 is unsigned and num2 is signed.
|
||||
*/
|
||||
if (num1->pn_value.pnv_unsigned > INT64_MAX)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
if (num2->pn_value.pnv_signed < 0)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
} else {
|
||||
/*
|
||||
* num1 is signed and num2 is unsigned.
|
||||
*/
|
||||
if (num1->pn_value.pnv_signed < 0)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
if (num2->pn_value.pnv_unsigned > INT64_MAX)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
}
|
||||
|
||||
if (num1->pn_value.pnv_signed == num2->pn_value.pnv_signed)
|
||||
return _PROP_OBJECT_EQUALS_TRUE;
|
||||
else
|
||||
return _PROP_OBJECT_EQUALS_FALSE;
|
||||
}
|
||||
|
||||
static prop_number_t
|
||||
_prop_number_alloc(const struct _prop_number_value *pnv)
|
||||
{
|
||||
prop_number_t opn, pn, rpn;
|
||||
|
||||
_PROP_ONCE_RUN(_prop_number_init_once, _prop_number_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_number_tree_mutex);
|
||||
opn = _prop_rb_tree_find(&_prop_number_tree, pnv);
|
||||
if (opn != NULL) {
|
||||
prop_object_retain(opn);
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
return (opn);
|
||||
}
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
|
||||
/*
|
||||
* Not in the tree. Create it now.
|
||||
*/
|
||||
|
||||
pn = _PROP_POOL_GET(_prop_number_pool);
|
||||
if (pn == NULL)
|
||||
return (NULL);
|
||||
|
||||
_prop_object_init(&pn->pn_obj, &_prop_object_type_number);
|
||||
|
||||
pn->pn_value = *pnv;
|
||||
|
||||
/*
|
||||
* We dropped the mutex when we allocated the new object, so
|
||||
* we have to check again if it is in the tree.
|
||||
*/
|
||||
_PROP_MUTEX_LOCK(_prop_number_tree_mutex);
|
||||
opn = _prop_rb_tree_find(&_prop_number_tree, pnv);
|
||||
if (opn != NULL) {
|
||||
prop_object_retain(opn);
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
_PROP_POOL_PUT(_prop_number_pool, pn);
|
||||
return (opn);
|
||||
}
|
||||
rpn = _prop_rb_tree_insert_node(&_prop_number_tree, pn);
|
||||
_PROP_ASSERT(rpn == pn);
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
return (rpn);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_create_integer --
|
||||
* Create a prop_number_t and initialize it with the
|
||||
* provided integer value.
|
||||
*/
|
||||
prop_number_t
|
||||
prop_number_create_integer(int64_t val)
|
||||
{
|
||||
struct _prop_number_value pnv;
|
||||
|
||||
memset(&pnv, 0, sizeof(pnv));
|
||||
pnv.pnv_signed = val;
|
||||
pnv.pnv_is_unsigned = false;
|
||||
|
||||
return (_prop_number_alloc(&pnv));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_create_unsigned_integer --
|
||||
* Create a prop_number_t and initialize it with the
|
||||
* provided unsigned integer value.
|
||||
*/
|
||||
prop_number_t
|
||||
prop_number_create_unsigned_integer(uint64_t val)
|
||||
{
|
||||
struct _prop_number_value pnv;
|
||||
|
||||
memset(&pnv, 0, sizeof(pnv));
|
||||
pnv.pnv_unsigned = val;
|
||||
pnv.pnv_is_unsigned = true;
|
||||
|
||||
return (_prop_number_alloc(&pnv));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_copy --
|
||||
* Copy a prop_number_t.
|
||||
*/
|
||||
prop_number_t
|
||||
prop_number_copy(prop_number_t opn)
|
||||
{
|
||||
|
||||
if (! prop_object_is_number(opn))
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Because we only ever allocate one object for any given
|
||||
* value, this can be reduced to a simple retain operation.
|
||||
*/
|
||||
prop_object_retain(opn);
|
||||
return (opn);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_unsigned --
|
||||
* Returns true if the prop_number_t has an unsigned value.
|
||||
*/
|
||||
bool
|
||||
prop_number_unsigned(prop_number_t pn)
|
||||
{
|
||||
|
||||
return (pn->pn_value.pnv_is_unsigned);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_size --
|
||||
* Return the size, in bits, required to hold the value of
|
||||
* the specified number.
|
||||
*/
|
||||
int
|
||||
prop_number_size(prop_number_t pn)
|
||||
{
|
||||
struct _prop_number_value *pnv;
|
||||
|
||||
if (! prop_object_is_number(pn))
|
||||
return (0);
|
||||
|
||||
pnv = &pn->pn_value;
|
||||
|
||||
if (pnv->pnv_is_unsigned) {
|
||||
if (pnv->pnv_unsigned > UINT32_MAX)
|
||||
return (64);
|
||||
if (pnv->pnv_unsigned > UINT16_MAX)
|
||||
return (32);
|
||||
if (pnv->pnv_unsigned > UINT8_MAX)
|
||||
return (16);
|
||||
return (8);
|
||||
}
|
||||
|
||||
if (pnv->pnv_signed > INT32_MAX || pnv->pnv_signed < INT32_MIN)
|
||||
return (64);
|
||||
if (pnv->pnv_signed > INT16_MAX || pnv->pnv_signed < INT16_MIN)
|
||||
return (32);
|
||||
if (pnv->pnv_signed > INT8_MAX || pnv->pnv_signed < INT8_MIN)
|
||||
return (16);
|
||||
return (8);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_integer_value --
|
||||
* Get the integer value of a prop_number_t.
|
||||
*/
|
||||
int64_t
|
||||
prop_number_integer_value(prop_number_t pn)
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX Impossible to distinguish between "not a prop_number_t"
|
||||
* XXX and "prop_number_t has a value of 0".
|
||||
*/
|
||||
if (! prop_object_is_number(pn))
|
||||
return (0);
|
||||
|
||||
return (pn->pn_value.pnv_signed);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_unsigned_integer_value --
|
||||
* Get the unsigned integer value of a prop_number_t.
|
||||
*/
|
||||
uint64_t
|
||||
prop_number_unsigned_integer_value(prop_number_t pn)
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX Impossible to distinguish between "not a prop_number_t"
|
||||
* XXX and "prop_number_t has a value of 0".
|
||||
*/
|
||||
if (! prop_object_is_number(pn))
|
||||
return (0);
|
||||
|
||||
return (pn->pn_value.pnv_unsigned);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_equals --
|
||||
* Return true if two numbers are equivalent.
|
||||
*/
|
||||
bool
|
||||
prop_number_equals(prop_number_t num1, prop_number_t num2)
|
||||
{
|
||||
if (!prop_object_is_number(num1) || !prop_object_is_number(num2))
|
||||
return (false);
|
||||
|
||||
return (prop_object_equals(num1, num2));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_equals_integer --
|
||||
* Return true if the number is equivalent to the specified integer.
|
||||
*/
|
||||
bool
|
||||
prop_number_equals_integer(prop_number_t pn, int64_t val)
|
||||
{
|
||||
|
||||
if (! prop_object_is_number(pn))
|
||||
return (false);
|
||||
|
||||
if (pn->pn_value.pnv_is_unsigned &&
|
||||
(pn->pn_value.pnv_unsigned > INT64_MAX || val < 0))
|
||||
return (false);
|
||||
|
||||
return (pn->pn_value.pnv_signed == val);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_equals_unsigned_integer --
|
||||
* Return true if the number is equivalent to the specified
|
||||
* unsigned integer.
|
||||
*/
|
||||
bool
|
||||
prop_number_equals_unsigned_integer(prop_number_t pn, uint64_t val)
|
||||
{
|
||||
|
||||
if (! prop_object_is_number(pn))
|
||||
return (false);
|
||||
|
||||
if (! pn->pn_value.pnv_is_unsigned &&
|
||||
(pn->pn_value.pnv_signed < 0 || val > INT64_MAX))
|
||||
return (false);
|
||||
|
||||
return (pn->pn_value.pnv_unsigned == val);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_number_internalize_unsigned(struct _prop_object_internalize_context *ctx,
|
||||
struct _prop_number_value *pnv)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
_PROP_ASSERT(/*CONSTCOND*/sizeof(unsigned long long) ==
|
||||
sizeof(uint64_t));
|
||||
|
||||
errno = 0;
|
||||
pnv->pnv_unsigned = (uint64_t) strtoull(ctx->poic_cp, &cp, 0);
|
||||
if (pnv->pnv_unsigned == UINT64_MAX && errno == ERANGE)
|
||||
return (false);
|
||||
|
||||
pnv->pnv_is_unsigned = true;
|
||||
ctx->poic_cp = cp;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_number_internalize_signed(struct _prop_object_internalize_context *ctx,
|
||||
struct _prop_number_value *pnv)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
_PROP_ASSERT(/*CONSTCOND*/sizeof(long long) == sizeof(int64_t));
|
||||
|
||||
errno = 0;
|
||||
pnv->pnv_signed = (int64_t) strtoll(ctx->poic_cp, &cp, 0);
|
||||
if ((pnv->pnv_signed == INT64_MAX || pnv->pnv_signed == INT64_MIN) &&
|
||||
errno == ERANGE)
|
||||
return (false);
|
||||
|
||||
pnv->pnv_is_unsigned = false;
|
||||
ctx->poic_cp = cp;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_number_internalize --
|
||||
* Parse a <number>...</number> and return the object created from
|
||||
* the external representation.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
bool
|
||||
_prop_number_internalize(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
struct _prop_number_value pnv;
|
||||
|
||||
memset(&pnv, 0, sizeof(pnv));
|
||||
|
||||
/* No attributes, no empty elements. */
|
||||
if (ctx->poic_tagattr != NULL || ctx->poic_is_empty_element)
|
||||
return (true);
|
||||
|
||||
/*
|
||||
* If the first character is '-', then we treat as signed.
|
||||
* If the first two characters are "0x" (i.e. the number is
|
||||
* in hex), then we treat as unsigned. Otherwise, we try
|
||||
* signed first, and if that fails (presumably due to ERANGE),
|
||||
* then we switch to unsigned.
|
||||
*/
|
||||
if (ctx->poic_cp[0] == '-') {
|
||||
if (_prop_number_internalize_signed(ctx, &pnv) == false)
|
||||
return (true);
|
||||
} else if (ctx->poic_cp[0] == '0' && ctx->poic_cp[1] == 'x') {
|
||||
if (_prop_number_internalize_unsigned(ctx, &pnv) == false)
|
||||
return (true);
|
||||
} else {
|
||||
if (_prop_number_internalize_signed(ctx, &pnv) == false &&
|
||||
_prop_number_internalize_unsigned(ctx, &pnv) == false)
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (_prop_object_internalize_find_tag(ctx, "integer",
|
||||
_PROP_TAG_TYPE_END) == false)
|
||||
return (true);
|
||||
|
||||
*obj = _prop_number_alloc(&pnv);
|
||||
return (true);
|
||||
}
|
1242
lib/portableproplib/prop_object.c
Normal file
1242
lib/portableproplib/prop_object.c
Normal file
File diff suppressed because it is too large
Load Diff
336
lib/portableproplib/prop_object_impl.h
Normal file
336
lib/portableproplib/prop_object_impl.h
Normal file
@@ -0,0 +1,336 @@
|
||||
/* $NetBSD: prop_object_impl.h,v 1.31 2012/07/27 09:10:59 pooka 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_OBJECT_IMPL_H_
|
||||
#define _PROPLIB_PROP_OBJECT_IMPL_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "prop_stack.h"
|
||||
|
||||
struct _prop_object_externalize_context {
|
||||
char * poec_buf; /* string buffer */
|
||||
size_t poec_capacity; /* capacity of buffer */
|
||||
size_t poec_len; /* current length of string */
|
||||
unsigned int poec_depth; /* nesting depth */
|
||||
};
|
||||
|
||||
bool _prop_object_externalize_start_tag(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
bool _prop_object_externalize_end_tag(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
bool _prop_object_externalize_empty_tag(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
bool _prop_object_externalize_append_cstring(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
bool _prop_object_externalize_append_encoded_cstring(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
bool _prop_object_externalize_append_char(
|
||||
struct _prop_object_externalize_context *,
|
||||
unsigned char);
|
||||
bool _prop_object_externalize_header(
|
||||
struct _prop_object_externalize_context *);
|
||||
bool _prop_object_externalize_footer(
|
||||
struct _prop_object_externalize_context *);
|
||||
|
||||
struct _prop_object_externalize_context *
|
||||
_prop_object_externalize_context_alloc(void);
|
||||
void _prop_object_externalize_context_free(
|
||||
struct _prop_object_externalize_context *);
|
||||
|
||||
typedef enum {
|
||||
_PROP_TAG_TYPE_START, /* e.g. <dict> */
|
||||
_PROP_TAG_TYPE_END, /* e.g. </dict> */
|
||||
_PROP_TAG_TYPE_EITHER
|
||||
} _prop_tag_type_t;
|
||||
|
||||
struct _prop_object_internalize_context {
|
||||
const char *poic_xml;
|
||||
const char *poic_cp;
|
||||
|
||||
const char *poic_tag_start;
|
||||
|
||||
const char *poic_tagname;
|
||||
size_t poic_tagname_len;
|
||||
const char *poic_tagattr;
|
||||
size_t poic_tagattr_len;
|
||||
const char *poic_tagattrval;
|
||||
size_t poic_tagattrval_len;
|
||||
|
||||
bool poic_is_empty_element;
|
||||
_prop_tag_type_t poic_tag_type;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
_PROP_OBJECT_FREE_DONE,
|
||||
_PROP_OBJECT_FREE_RECURSE,
|
||||
_PROP_OBJECT_FREE_FAILED
|
||||
} _prop_object_free_rv_t;
|
||||
|
||||
typedef enum {
|
||||
_PROP_OBJECT_EQUALS_FALSE,
|
||||
_PROP_OBJECT_EQUALS_TRUE,
|
||||
_PROP_OBJECT_EQUALS_RECURSE
|
||||
} _prop_object_equals_rv_t;
|
||||
|
||||
#define _PROP_EOF(c) ((c) == '\0')
|
||||
#define _PROP_ISSPACE(c) \
|
||||
((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
|
||||
|
||||
#define _PROP_TAG_MATCH(ctx, t) \
|
||||
_prop_object_internalize_match((ctx)->poic_tagname, \
|
||||
(ctx)->poic_tagname_len, \
|
||||
(t), strlen(t))
|
||||
|
||||
#define _PROP_TAGATTR_MATCH(ctx, a) \
|
||||
_prop_object_internalize_match((ctx)->poic_tagattr, \
|
||||
(ctx)->poic_tagattr_len, \
|
||||
(a), strlen(a))
|
||||
|
||||
#define _PROP_TAGATTRVAL_MATCH(ctx, a) \
|
||||
_prop_object_internalize_match((ctx)->poic_tagattrval, \
|
||||
(ctx)->poic_tagattrval_len,\
|
||||
(a), strlen(a))
|
||||
|
||||
bool _prop_object_internalize_find_tag(
|
||||
struct _prop_object_internalize_context *,
|
||||
const char *, _prop_tag_type_t);
|
||||
bool _prop_object_internalize_match(const char *, size_t,
|
||||
const char *, size_t);
|
||||
prop_object_t _prop_object_internalize_by_tag(
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_object_internalize_decode_string(
|
||||
struct _prop_object_internalize_context *,
|
||||
char *, size_t, size_t *, const char **);
|
||||
prop_object_t _prop_generic_internalize(const char *, const char *);
|
||||
|
||||
struct _prop_object_internalize_context *
|
||||
_prop_object_internalize_context_alloc(const char *);
|
||||
void _prop_object_internalize_context_free(
|
||||
struct _prop_object_internalize_context *);
|
||||
|
||||
bool _prop_object_externalize_write_file(const char *,
|
||||
const char *, size_t, bool);
|
||||
|
||||
struct _prop_object_internalize_mapped_file {
|
||||
char * poimf_xml;
|
||||
size_t poimf_mapsize;
|
||||
};
|
||||
|
||||
struct _prop_object_internalize_mapped_file *
|
||||
_prop_object_internalize_map_file(const char *);
|
||||
void _prop_object_internalize_unmap_file(
|
||||
struct _prop_object_internalize_mapped_file *);
|
||||
|
||||
typedef bool (*prop_object_internalizer_t)(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
typedef bool (*prop_object_internalizer_continue_t)(prop_stack_t,
|
||||
prop_object_t *,
|
||||
struct _prop_object_internalize_context *,
|
||||
void *, prop_object_t);
|
||||
|
||||
/* These are here because they're required by shared code. */
|
||||
bool _prop_array_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_bool_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_data_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_dictionary_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_number_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
bool _prop_string_internalize(prop_stack_t, prop_object_t *,
|
||||
struct _prop_object_internalize_context *);
|
||||
|
||||
struct _prop_object_type {
|
||||
/* type indicator */
|
||||
uint32_t pot_type;
|
||||
/* func to free object */
|
||||
_prop_object_free_rv_t
|
||||
(*pot_free)(prop_stack_t, prop_object_t *);
|
||||
/*
|
||||
* func to free the child returned by pot_free with stack == NULL.
|
||||
*
|
||||
* Must be implemented if pot_free can return anything other than
|
||||
* _PROP_OBJECT_FREE_DONE.
|
||||
*/
|
||||
void (*pot_emergency_free)(prop_object_t);
|
||||
/* func to externalize object */
|
||||
bool (*pot_extern)(struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
/* func to test quality */
|
||||
_prop_object_equals_rv_t
|
||||
(*pot_equals)(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
/*
|
||||
* func to finish equality iteration.
|
||||
*
|
||||
* Must be implemented if pot_equals can return
|
||||
* _PROP_OBJECT_EQUALS_RECURSE
|
||||
*/
|
||||
void (*pot_equals_finish)(prop_object_t, prop_object_t);
|
||||
void (*pot_lock)(void);
|
||||
void (*pot_unlock)(void);
|
||||
};
|
||||
|
||||
struct _prop_object {
|
||||
const struct _prop_object_type *po_type;/* type descriptor */
|
||||
uint32_t po_refcnt; /* reference count */
|
||||
};
|
||||
|
||||
void _prop_object_init(struct _prop_object *,
|
||||
const struct _prop_object_type *);
|
||||
void _prop_object_fini(struct _prop_object *);
|
||||
|
||||
struct _prop_object_iterator {
|
||||
prop_object_t (*pi_next_object)(void *);
|
||||
void (*pi_reset)(void *);
|
||||
prop_object_t pi_obj;
|
||||
uint32_t pi_version;
|
||||
};
|
||||
|
||||
#define _PROP_NOTHREAD_ONCE_DECL(x) static bool x = false;
|
||||
#define _PROP_NOTHREAD_ONCE_RUN(x,f) \
|
||||
do { \
|
||||
if ((x) == false) { \
|
||||
f(); \
|
||||
x = true; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/*
|
||||
* proplib in user space...
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define _PROP_ASSERT(x) /*LINTED*/assert(x)
|
||||
|
||||
#define _PROP_MALLOC(s, t) malloc((s))
|
||||
#define _PROP_CALLOC(s, t) calloc(1, (s))
|
||||
#define _PROP_REALLOC(v, s, t) realloc((v), (s))
|
||||
#define _PROP_FREE(v, t) free((v))
|
||||
|
||||
#define _PROP_POOL_GET(p) malloc((p))
|
||||
#define _PROP_POOL_PUT(p, v) free((v))
|
||||
|
||||
#define _PROP_POOL_INIT(p, s, d) static const size_t p = s;
|
||||
|
||||
#define _PROP_MALLOC_DEFINE(t, s, l) /* nothing */
|
||||
|
||||
/*
|
||||
* Use pthread mutexes everywhere else.
|
||||
*/
|
||||
#include <pthread.h>
|
||||
#define _PROP_MUTEX_DECL_STATIC(x) static pthread_mutex_t x;
|
||||
#define _PROP_MUTEX_INIT(x) pthread_mutex_init(&(x), NULL)
|
||||
#define _PROP_MUTEX_LOCK(x) pthread_mutex_lock(&(x))
|
||||
#define _PROP_MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
|
||||
|
||||
#define _PROP_RWLOCK_DECL(x) pthread_rwlock_t x ;
|
||||
#define _PROP_RWLOCK_INIT(x) pthread_rwlock_init(&(x), NULL)
|
||||
#define _PROP_RWLOCK_RDLOCK(x) pthread_rwlock_rdlock(&(x))
|
||||
#define _PROP_RWLOCK_WRLOCK(x) pthread_rwlock_wrlock(&(x))
|
||||
#define _PROP_RWLOCK_UNLOCK(x) pthread_rwlock_unlock(&(x))
|
||||
#define _PROP_RWLOCK_DESTROY(x) pthread_rwlock_destroy(&(x))
|
||||
|
||||
#define _PROP_ONCE_DECL(x) \
|
||||
static pthread_once_t x = PTHREAD_ONCE_INIT;
|
||||
#define _PROP_ONCE_RUN(x,f) pthread_once(&(x),(void(*)(void))f)
|
||||
|
||||
#ifndef HAVE_ATOMICS /* NO ATOMIC SUPPORT, USE A MUTEX */
|
||||
|
||||
#define _PROP_NEED_REFCNT_MTX
|
||||
#define _PROP_ATOMIC_INC32(x) \
|
||||
do { \
|
||||
pthread_mutex_lock(&_prop_refcnt_mtx); \
|
||||
(*(x))++; \
|
||||
pthread_mutex_unlock(&_prop_refcnt_mtx); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define _PROP_ATOMIC_DEC32(x) \
|
||||
do { \
|
||||
pthread_mutex_lock(&_prop_refcnt_mtx); \
|
||||
(*(x))--; \
|
||||
pthread_mutex_unlock(&_prop_refcnt_mtx); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define _PROP_ATOMIC_INC32_NV(x, v) \
|
||||
do { \
|
||||
pthread_mutex_lock(&_prop_refcnt_mtx); \
|
||||
v = ++(*(x)); \
|
||||
pthread_mutex_unlock(&_prop_refcnt_mtx); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define _PROP_ATOMIC_DEC32_NV(x, v) \
|
||||
do { \
|
||||
pthread_mutex_lock(&_prop_refcnt_mtx); \
|
||||
v = --(*(x)); \
|
||||
pthread_mutex_unlock(&_prop_refcnt_mtx); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#else /* GCC ATOMIC BUILTINS */
|
||||
|
||||
#define _PROP_ATOMIC_INC32(x) \
|
||||
do { \
|
||||
(void)__sync_fetch_and_add(x, 1); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define _PROP_ATOMIC_DEC32(x) \
|
||||
do { \
|
||||
(void)__sync_fetch_and_sub(x, 1); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define _PROP_ATOMIC_INC32_NV(x, v) \
|
||||
do { \
|
||||
v = __sync_add_and_fetch(x, 1); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define _PROP_ATOMIC_DEC32_NV(x, v) \
|
||||
do { \
|
||||
v = __sync_sub_and_fetch(x, 1); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#endif /* !HAVE_ATOMICS */
|
||||
|
||||
/*
|
||||
* Language features.
|
||||
*/
|
||||
#define _PROP_ARG_UNUSED __attribute__((unused))
|
||||
|
||||
#endif /* _PROPLIB_PROP_OBJECT_IMPL_H_ */
|
46
lib/portableproplib/prop_rb_impl.h
Normal file
46
lib/portableproplib/prop_rb_impl.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* $NetBSD: prop_rb_impl.h,v 1.8 2010/09/25 01:42:38 matt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Matt Thomas <matt@3am-software.com>.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROP_RB_IMPL_H_
|
||||
#define _PROP_RB_IMPL_H_
|
||||
|
||||
#include <rbtree.h>
|
||||
|
||||
/*
|
||||
* Define local names for common rb_tree functions.
|
||||
*/
|
||||
#define _prop_rb_tree_init rb_tree_init
|
||||
#define _prop_rb_tree_insert_node rb_tree_insert_node
|
||||
#define _prop_rb_tree_find rb_tree_find_node
|
||||
#define _prop_rb_tree_remove_node rb_tree_remove_node
|
||||
#define _prop_rb_tree_iterate rb_tree_iterate
|
||||
|
||||
#endif /* _PROP_RB_IMPL_H_*/
|
118
lib/portableproplib/prop_stack.c
Normal file
118
lib/portableproplib/prop_stack.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/* $NetBSD: prop_stack.c,v 1.2 2007/08/30 12:23:54 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
|
||||
* 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 COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDERS 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 "prop_stack.h"
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
void
|
||||
_prop_stack_init(prop_stack_t stack)
|
||||
{
|
||||
stack->used_intern_elems = 0;
|
||||
SLIST_INIT(&stack->extern_elems);
|
||||
}
|
||||
|
||||
bool
|
||||
_prop_stack_push(prop_stack_t stack, prop_object_t obj, void *data1,
|
||||
void *data2, void *data3)
|
||||
{
|
||||
struct _prop_stack_extern_elem *eelem;
|
||||
struct _prop_stack_intern_elem *ielem;
|
||||
|
||||
if (stack->used_intern_elems == PROP_STACK_INTERN_ELEMS) {
|
||||
eelem = _PROP_MALLOC(sizeof(*eelem), M_TEMP);
|
||||
|
||||
if (eelem == NULL)
|
||||
return false;
|
||||
|
||||
eelem->object = obj;
|
||||
eelem->object_data[0] = data1;
|
||||
eelem->object_data[1] = data2;
|
||||
eelem->object_data[2] = data3;
|
||||
|
||||
SLIST_INSERT_HEAD(&stack->extern_elems, eelem, stack_link);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_PROP_ASSERT(stack->used_intern_elems < PROP_STACK_INTERN_ELEMS);
|
||||
_PROP_ASSERT(SLIST_EMPTY(&stack->extern_elems));
|
||||
|
||||
ielem = &stack->intern_elems[stack->used_intern_elems];
|
||||
ielem->object = obj;
|
||||
ielem->object_data[0] = data1;
|
||||
ielem->object_data[1] = data2;
|
||||
ielem->object_data[2] = data3;
|
||||
|
||||
++stack->used_intern_elems;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
_prop_stack_pop(prop_stack_t stack, prop_object_t *obj, void **data1,
|
||||
void **data2, void **data3)
|
||||
{
|
||||
struct _prop_stack_extern_elem *eelem;
|
||||
struct _prop_stack_intern_elem *ielem;
|
||||
|
||||
if (stack->used_intern_elems == 0)
|
||||
return false;
|
||||
|
||||
if ((eelem = SLIST_FIRST(&stack->extern_elems)) != NULL) {
|
||||
_PROP_ASSERT(stack->used_intern_elems == PROP_STACK_INTERN_ELEMS);
|
||||
|
||||
SLIST_REMOVE_HEAD(&stack->extern_elems, stack_link);
|
||||
if (obj)
|
||||
*obj = eelem->object;
|
||||
if (data1)
|
||||
*data1 = eelem->object_data[0];
|
||||
if (data2)
|
||||
*data2 = eelem->object_data[1];
|
||||
if (data3)
|
||||
*data3 = eelem->object_data[2];
|
||||
_PROP_FREE(eelem, M_TEMP);
|
||||
return true;
|
||||
}
|
||||
|
||||
--stack->used_intern_elems;
|
||||
ielem = &stack->intern_elems[stack->used_intern_elems];
|
||||
|
||||
if (obj)
|
||||
*obj = ielem->object;
|
||||
if (data1)
|
||||
*data1 = ielem->object_data[0];
|
||||
if (data2)
|
||||
*data2 = ielem->object_data[1];
|
||||
if (data3)
|
||||
*data3 = ielem->object_data[2];
|
||||
|
||||
return true;
|
||||
}
|
64
lib/portableproplib/prop_stack.h
Normal file
64
lib/portableproplib/prop_stack.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* $NetBSD: prop_stack.h,v 1.2 2007/08/30 12:23:54 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
|
||||
* 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 COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
#ifndef _PROP_STACK_H
|
||||
#define _PROP_STACK_H
|
||||
|
||||
#include <queue.h>
|
||||
#include <prop/prop_object.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct _prop_stack_intern_elem {
|
||||
prop_object_t object;
|
||||
void *object_data[3];
|
||||
};
|
||||
|
||||
struct _prop_stack_extern_elem {
|
||||
SLIST_ENTRY(_prop_stack_extern_elem) stack_link;
|
||||
prop_object_t object;
|
||||
void *object_data[3];
|
||||
};
|
||||
|
||||
#define PROP_STACK_INTERN_ELEMS 16
|
||||
|
||||
struct _prop_stack {
|
||||
struct _prop_stack_intern_elem intern_elems[PROP_STACK_INTERN_ELEMS];
|
||||
size_t used_intern_elems;
|
||||
SLIST_HEAD(, _prop_stack_extern_elem) extern_elems;
|
||||
};
|
||||
|
||||
typedef struct _prop_stack *prop_stack_t;
|
||||
|
||||
void _prop_stack_init(prop_stack_t);
|
||||
bool _prop_stack_push(prop_stack_t, prop_object_t, void *, void *, void *);
|
||||
bool _prop_stack_pop(prop_stack_t, prop_object_t *, void **, void **, void **);
|
||||
|
||||
#endif
|
469
lib/portableproplib/prop_string.c
Normal file
469
lib/portableproplib/prop_string.c
Normal file
@@ -0,0 +1,469 @@
|
||||
/* $NetBSD: prop_string.c,v 1.12 2014/03/26 18:12:46 christos 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.
|
||||
*
|
||||
* 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 <prop/prop_string.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
struct _prop_string {
|
||||
struct _prop_object ps_obj;
|
||||
union {
|
||||
char * psu_mutable;
|
||||
const char * psu_immutable;
|
||||
} ps_un;
|
||||
#define ps_mutable ps_un.psu_mutable
|
||||
#define ps_immutable ps_un.psu_immutable
|
||||
size_t ps_size; /* not including \0 */
|
||||
int ps_flags;
|
||||
};
|
||||
|
||||
#define PS_F_NOCOPY 0x01
|
||||
|
||||
_PROP_POOL_INIT(_prop_string_pool, sizeof(struct _prop_string), "propstng")
|
||||
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
_prop_string_free(prop_stack_t, prop_object_t *);
|
||||
static bool _prop_string_externalize(
|
||||
struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_string_equals(prop_object_t, prop_object_t,
|
||||
void **, void **,
|
||||
prop_object_t *, prop_object_t *);
|
||||
|
||||
static const struct _prop_object_type _prop_object_type_string = {
|
||||
.pot_type = PROP_TYPE_STRING,
|
||||
.pot_free = _prop_string_free,
|
||||
.pot_extern = _prop_string_externalize,
|
||||
.pot_equals = _prop_string_equals,
|
||||
};
|
||||
|
||||
#define prop_object_is_string(x) \
|
||||
((x) != NULL && (x)->ps_obj.po_type == &_prop_object_type_string)
|
||||
#define prop_string_contents(x) ((x)->ps_immutable ? (x)->ps_immutable : "")
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_free_rv_t
|
||||
_prop_string_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_string_t ps = *obj;
|
||||
|
||||
if ((ps->ps_flags & PS_F_NOCOPY) == 0 && ps->ps_mutable != NULL)
|
||||
_PROP_FREE(ps->ps_mutable, M_PROP_STRING);
|
||||
_PROP_POOL_PUT(_prop_string_pool, ps);
|
||||
|
||||
return (_PROP_OBJECT_FREE_DONE);
|
||||
}
|
||||
|
||||
static bool
|
||||
_prop_string_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_string_t ps = v;
|
||||
|
||||
if (ps->ps_size == 0)
|
||||
return (_prop_object_externalize_empty_tag(ctx, "string"));
|
||||
|
||||
if (_prop_object_externalize_start_tag(ctx, "string") == false ||
|
||||
_prop_object_externalize_append_encoded_cstring(ctx,
|
||||
ps->ps_immutable) == false ||
|
||||
_prop_object_externalize_end_tag(ctx, "string") == false)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static _prop_object_equals_rv_t
|
||||
_prop_string_equals(prop_object_t v1, prop_object_t v2,
|
||||
void **stored_pointer1, void **stored_pointer2,
|
||||
prop_object_t *next_obj1, prop_object_t *next_obj2)
|
||||
{
|
||||
prop_string_t str1 = v1;
|
||||
prop_string_t str2 = v2;
|
||||
|
||||
if (str1 == str2)
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
if (str1->ps_size != str2->ps_size)
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
if (strcmp(prop_string_contents(str1), prop_string_contents(str2)))
|
||||
return (_PROP_OBJECT_EQUALS_FALSE);
|
||||
else
|
||||
return (_PROP_OBJECT_EQUALS_TRUE);
|
||||
}
|
||||
|
||||
static prop_string_t
|
||||
_prop_string_alloc(void)
|
||||
{
|
||||
prop_string_t ps;
|
||||
|
||||
ps = _PROP_POOL_GET(_prop_string_pool);
|
||||
if (ps != NULL) {
|
||||
_prop_object_init(&ps->ps_obj, &_prop_object_type_string);
|
||||
|
||||
ps->ps_mutable = NULL;
|
||||
ps->ps_size = 0;
|
||||
ps->ps_flags = 0;
|
||||
}
|
||||
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_create --
|
||||
* Create an empty mutable string.
|
||||
*/
|
||||
prop_string_t
|
||||
prop_string_create(void)
|
||||
{
|
||||
|
||||
return (_prop_string_alloc());
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_create_cstring --
|
||||
* Create a string that contains a copy of the provided C string.
|
||||
*/
|
||||
prop_string_t
|
||||
prop_string_create_cstring(const char *str)
|
||||
{
|
||||
prop_string_t ps;
|
||||
char *cp;
|
||||
size_t len;
|
||||
|
||||
ps = _prop_string_alloc();
|
||||
if (ps != NULL) {
|
||||
len = strlen(str);
|
||||
cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
|
||||
if (cp == NULL) {
|
||||
prop_object_release(ps);
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(cp, str);
|
||||
ps->ps_mutable = cp;
|
||||
ps->ps_size = len;
|
||||
}
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_create_cstring_nocopy --
|
||||
* Create an immutable string that contains a refrence to the
|
||||
* provided C string.
|
||||
*/
|
||||
prop_string_t
|
||||
prop_string_create_cstring_nocopy(const char *str)
|
||||
{
|
||||
prop_string_t ps;
|
||||
|
||||
ps = _prop_string_alloc();
|
||||
if (ps != NULL) {
|
||||
ps->ps_immutable = str;
|
||||
ps->ps_size = strlen(str);
|
||||
ps->ps_flags |= PS_F_NOCOPY;
|
||||
}
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_copy --
|
||||
* Copy a string. If the original string is immutable, then the
|
||||
* copy is also immutable and references the same external data.
|
||||
*/
|
||||
prop_string_t
|
||||
prop_string_copy(prop_string_t ops)
|
||||
{
|
||||
prop_string_t ps;
|
||||
|
||||
if (! prop_object_is_string(ops))
|
||||
return (NULL);
|
||||
|
||||
ps = _prop_string_alloc();
|
||||
if (ps != NULL) {
|
||||
ps->ps_size = ops->ps_size;
|
||||
ps->ps_flags = ops->ps_flags;
|
||||
if (ops->ps_flags & PS_F_NOCOPY)
|
||||
ps->ps_immutable = ops->ps_immutable;
|
||||
else {
|
||||
char *cp = _PROP_MALLOC(ps->ps_size + 1, M_PROP_STRING);
|
||||
if (cp == NULL) {
|
||||
prop_object_release(ps);
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(cp, prop_string_contents(ops));
|
||||
ps->ps_mutable = cp;
|
||||
}
|
||||
}
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_copy_mutable --
|
||||
* Copy a string, always returning a mutable copy.
|
||||
*/
|
||||
prop_string_t
|
||||
prop_string_copy_mutable(prop_string_t ops)
|
||||
{
|
||||
prop_string_t ps;
|
||||
char *cp;
|
||||
|
||||
if (! prop_object_is_string(ops))
|
||||
return (NULL);
|
||||
|
||||
ps = _prop_string_alloc();
|
||||
if (ps != NULL) {
|
||||
ps->ps_size = ops->ps_size;
|
||||
cp = _PROP_MALLOC(ps->ps_size + 1, M_PROP_STRING);
|
||||
if (cp == NULL) {
|
||||
prop_object_release(ps);
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(cp, prop_string_contents(ops));
|
||||
ps->ps_mutable = cp;
|
||||
}
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_size --
|
||||
* Return the size of the string, not including the terminating NUL.
|
||||
*/
|
||||
size_t
|
||||
prop_string_size(prop_string_t ps)
|
||||
{
|
||||
|
||||
if (! prop_object_is_string(ps))
|
||||
return (0);
|
||||
|
||||
return (ps->ps_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_mutable --
|
||||
* Return true if the string is a mutable string.
|
||||
*/
|
||||
bool
|
||||
prop_string_mutable(prop_string_t ps)
|
||||
{
|
||||
|
||||
if (! prop_object_is_string(ps))
|
||||
return (false);
|
||||
|
||||
return ((ps->ps_flags & PS_F_NOCOPY) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_cstring --
|
||||
* Return a copy of the contents of the string as a C string.
|
||||
* The string is allocated with the M_TEMP malloc type.
|
||||
*/
|
||||
char *
|
||||
prop_string_cstring(prop_string_t ps)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
if (! prop_object_is_string(ps))
|
||||
return (NULL);
|
||||
|
||||
cp = _PROP_MALLOC(ps->ps_size + 1, M_TEMP);
|
||||
if (cp != NULL)
|
||||
strcpy(cp, prop_string_contents(ps));
|
||||
|
||||
return (cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_cstring_nocopy --
|
||||
* Return an immutable reference to the contents of the string
|
||||
* as a C string.
|
||||
*/
|
||||
const char *
|
||||
prop_string_cstring_nocopy(prop_string_t ps)
|
||||
{
|
||||
|
||||
if (! prop_object_is_string(ps))
|
||||
return (NULL);
|
||||
|
||||
return (prop_string_contents(ps));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_append --
|
||||
* Append the contents of one string to another. Returns true
|
||||
* upon success. The destination string must be mutable.
|
||||
*/
|
||||
bool
|
||||
prop_string_append(prop_string_t dst, prop_string_t src)
|
||||
{
|
||||
char *ocp, *cp;
|
||||
size_t len;
|
||||
|
||||
if (! (prop_object_is_string(dst) &&
|
||||
prop_object_is_string(src)))
|
||||
return (false);
|
||||
|
||||
if (dst->ps_flags & PS_F_NOCOPY)
|
||||
return (false);
|
||||
|
||||
len = dst->ps_size + src->ps_size;
|
||||
cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
|
||||
if (cp == NULL)
|
||||
return (false);
|
||||
snprintf(cp, len + 1, "%s%s", prop_string_contents(dst),
|
||||
prop_string_contents(src));
|
||||
ocp = dst->ps_mutable;
|
||||
dst->ps_mutable = cp;
|
||||
dst->ps_size = len;
|
||||
if (ocp != NULL)
|
||||
_PROP_FREE(ocp, M_PROP_STRING);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_append_cstring --
|
||||
* Append a C string to a string. Returns true upon success.
|
||||
* The destination string must be mutable.
|
||||
*/
|
||||
bool
|
||||
prop_string_append_cstring(prop_string_t dst, const char *src)
|
||||
{
|
||||
char *ocp, *cp;
|
||||
size_t len;
|
||||
|
||||
if (! prop_object_is_string(dst))
|
||||
return (false);
|
||||
|
||||
_PROP_ASSERT(src != NULL);
|
||||
|
||||
if (dst->ps_flags & PS_F_NOCOPY)
|
||||
return (false);
|
||||
|
||||
len = dst->ps_size + strlen(src);
|
||||
cp = _PROP_MALLOC(len + 1, M_PROP_STRING);
|
||||
if (cp == NULL)
|
||||
return (false);
|
||||
snprintf(cp, len + 1, "%s%s", prop_string_contents(dst), src);
|
||||
ocp = dst->ps_mutable;
|
||||
dst->ps_mutable = cp;
|
||||
dst->ps_size = len;
|
||||
if (ocp != NULL)
|
||||
_PROP_FREE(ocp, M_PROP_STRING);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_equals --
|
||||
* Return true if two strings are equivalent.
|
||||
*/
|
||||
bool
|
||||
prop_string_equals(prop_string_t str1, prop_string_t str2)
|
||||
{
|
||||
if (!prop_object_is_string(str1) || !prop_object_is_string(str2))
|
||||
return (false);
|
||||
|
||||
return prop_object_equals(str1, str2);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_equals_cstring --
|
||||
* Return true if the string is equivalent to the specified
|
||||
* C string.
|
||||
*/
|
||||
bool
|
||||
prop_string_equals_cstring(prop_string_t ps, const char *cp)
|
||||
{
|
||||
|
||||
if (! prop_object_is_string(ps))
|
||||
return (false);
|
||||
|
||||
return (strcmp(prop_string_contents(ps), cp) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_string_internalize --
|
||||
* Parse a <string>...</string> and return the object created from the
|
||||
* external representation.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
bool
|
||||
_prop_string_internalize(prop_stack_t stack, prop_object_t *obj,
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
prop_string_t string;
|
||||
char *str;
|
||||
size_t len, alen;
|
||||
|
||||
if (ctx->poic_is_empty_element) {
|
||||
*obj = prop_string_create();
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* No attributes recognized here. */
|
||||
if (ctx->poic_tagattr != NULL)
|
||||
return (true);
|
||||
|
||||
/* Compute the length of the result. */
|
||||
if (_prop_object_internalize_decode_string(ctx, NULL, 0, &len,
|
||||
NULL) == false)
|
||||
return (true);
|
||||
|
||||
str = _PROP_MALLOC(len + 1, M_PROP_STRING);
|
||||
if (str == NULL)
|
||||
return (true);
|
||||
|
||||
if (_prop_object_internalize_decode_string(ctx, str, len, &alen,
|
||||
&ctx->poic_cp) == false ||
|
||||
alen != len) {
|
||||
_PROP_FREE(str, M_PROP_STRING);
|
||||
return (true);
|
||||
}
|
||||
str[len] = '\0';
|
||||
|
||||
if (_prop_object_internalize_find_tag(ctx, "string",
|
||||
_PROP_TAG_TYPE_END) == false) {
|
||||
_PROP_FREE(str, M_PROP_STRING);
|
||||
return (true);
|
||||
}
|
||||
|
||||
string = _prop_string_alloc();
|
||||
if (string == NULL) {
|
||||
_PROP_FREE(str, M_PROP_STRING);
|
||||
return (true);
|
||||
}
|
||||
|
||||
string->ps_mutable = str;
|
||||
string->ps_size = len;
|
||||
*obj = string;
|
||||
|
||||
return (true);
|
||||
}
|
129
lib/portableproplib/prop_zlib.c
Normal file
129
lib/portableproplib/prop_zlib.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*-
|
||||
* Copyright (c) 2010-2014 Juan Romero Pardines.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <prop/proplib.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#define _READ_CHUNK 8192
|
||||
|
||||
#define TEMPLATE(type, objtype) \
|
||||
bool \
|
||||
prop ## type ## _externalize_to_zfile(prop ## type ## _t obj, const char *fname) \
|
||||
{ \
|
||||
char *xml; \
|
||||
bool rv; \
|
||||
int save_errno = 0; \
|
||||
\
|
||||
xml = prop ## type ## _externalize(obj); \
|
||||
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 ## type ## _t \
|
||||
prop ## type ## _internalize_from_zfile(const char *fname) \
|
||||
{ \
|
||||
struct _prop_object_internalize_mapped_file *mf; \
|
||||
prop ## type ## _t obj = NULL; \
|
||||
z_stream strm; \
|
||||
unsigned char out[_READ_CHUNK+1]; \
|
||||
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; \
|
||||
\
|
||||
/* If it's an ordinary uncompressed plist we are done */ \
|
||||
obj = prop ## type ## _internalize(mf->poimf_xml); \
|
||||
if (prop_object_type(obj) == PROP_TYPE_## objtype) \
|
||||
goto out; \
|
||||
\
|
||||
/* Output buffer (uncompressed) */ \
|
||||
uncomp_xml = _PROP_MALLOC(_READ_CHUNK, M_TEMP); \
|
||||
if (uncomp_xml == NULL) \
|
||||
goto out; \
|
||||
\
|
||||
/* 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) \
|
||||
goto out2; \
|
||||
\
|
||||
strm.avail_in = mf->poimf_mapsize; \
|
||||
strm.next_in = (unsigned char *)mf->poimf_xml; \
|
||||
\
|
||||
/* 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: \
|
||||
case Z_STREAM_ERROR: \
|
||||
case Z_NEED_DICT: \
|
||||
case Z_MEM_ERROR: \
|
||||
errno = EINVAL; \
|
||||
goto out1; \
|
||||
} \
|
||||
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 */ \
|
||||
out2: \
|
||||
(void)inflateEnd(&strm); \
|
||||
out1: \
|
||||
obj = prop ## type ## _internalize(uncomp_xml); \
|
||||
_PROP_FREE(uncomp_xml, M_TEMP); \
|
||||
out: \
|
||||
_prop_object_internalize_unmap_file(mf); \
|
||||
\
|
||||
return obj; \
|
||||
}
|
||||
|
||||
TEMPLATE(_array, ARRAY)
|
||||
TEMPLATE(_dictionary, DICTIONARY)
|
||||
|
||||
#undef TEMPLATE
|
1315
lib/portableproplib/rb.c
Normal file
1315
lib/portableproplib/rb.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user