Initial commit of proplib, a library for manipulating property lists and
converting to/from an XML external representation (based on Apple XML property lists). Works in the kernel and user space.
This commit is contained in:
parent
ed14057f29
commit
774eb1a395
|
@ -0,0 +1,8 @@
|
|||
# $NetBSD: Makefile,v 1.1 2006/04/27 20:11:27 thorpej Exp $
|
||||
|
||||
INCS= prop_array.h prop_bool.h prop_data.h prop_dictionary.h \
|
||||
prop_number.h prop_object.h prop_string.h proplib.h
|
||||
|
||||
INCSDIR= /usr/include/prop
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,68 @@
|
|||
/* $NetBSD: prop_array.h,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_ARRAY_H_
|
||||
#define _PROPLIB_PROP_ARRAY_H_
|
||||
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_array *prop_array_t;
|
||||
|
||||
__BEGIN_DECLS
|
||||
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);
|
||||
boolean_t prop_array_ensure_capacity(prop_array_t, unsigned int);
|
||||
|
||||
void prop_array_make_immutable(prop_array_t);
|
||||
boolean_t 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);
|
||||
boolean_t prop_array_set(prop_array_t, unsigned int, prop_object_t);
|
||||
boolean_t prop_array_add(prop_array_t, prop_object_t);
|
||||
void prop_array_remove(prop_array_t, unsigned int);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _PROPLIB_PROP_ARRAY_H_ */
|
|
@ -0,0 +1,53 @@
|
|||
/* $NetBSD: prop_bool.h,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_BOOL_H_
|
||||
#define _PROPLIB_PROP_BOOL_H_
|
||||
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_bool *prop_bool_t;
|
||||
|
||||
__BEGIN_DECLS
|
||||
prop_bool_t prop_bool_create(boolean_t);
|
||||
prop_bool_t prop_bool_copy(prop_bool_t);
|
||||
|
||||
boolean_t prop_bool_true(prop_bool_t);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _PROPLIB_PROP_BOOL_H_ */
|
|
@ -0,0 +1,61 @@
|
|||
/* $NetBSD: prop_data.h,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_DATA_H_
|
||||
#define _PROPLIB_PROP_DATA_H_
|
||||
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_data *prop_data_t;
|
||||
|
||||
__BEGIN_DECLS
|
||||
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);
|
||||
|
||||
boolean_t prop_data_equals(prop_data_t, prop_data_t);
|
||||
boolean_t prop_data_equals_data(prop_data_t, const void *, size_t);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _PROPLIB_PROP_DATA_H_ */
|
|
@ -0,0 +1,83 @@
|
|||
/* $NetBSD: prop_dictionary.h,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_DICTIONARY_H_
|
||||
#define _PROPLIB_PROP_DICTIONARY_H_
|
||||
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_dictionary *prop_dictionary_t;
|
||||
typedef struct _prop_dictionary_keysym *prop_dictionary_keysym_t;
|
||||
|
||||
__BEGIN_DECLS
|
||||
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_capacity(prop_dictionary_t);
|
||||
unsigned int prop_dictionary_count(prop_dictionary_t);
|
||||
boolean_t prop_dictionary_ensure_capacity(prop_dictionary_t,
|
||||
unsigned int);
|
||||
|
||||
void prop_dictionary_make_immutable(prop_dictionary_t);
|
||||
boolean_t prop_dictionary_mutable(prop_dictionary_t);
|
||||
|
||||
prop_object_iterator_t prop_dictionary_iterator(prop_dictionary_t);
|
||||
|
||||
prop_object_t prop_dictionary_get(prop_dictionary_t, const char *);
|
||||
boolean_t 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);
|
||||
boolean_t 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);
|
||||
|
||||
char * prop_dictionary_externalize(prop_dictionary_t);
|
||||
prop_dictionary_t prop_dictionary_internalize(const char *);
|
||||
|
||||
const char * prop_dictionary_keysym_cstring_nocopy(prop_dictionary_keysym_t);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _PROPLIB_PROP_DICTIONARY_H_ */
|
|
@ -0,0 +1,62 @@
|
|||
/* $NetBSD: prop_number.h,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_NUMBER_H_
|
||||
#define _PROPLIB_PROP_NUMBER_H_
|
||||
|
||||
#ifndef _KERNEL
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_number *prop_number_t;
|
||||
|
||||
__BEGIN_DECLS
|
||||
prop_number_t prop_number_create_integer(uintmax_t);
|
||||
|
||||
prop_number_t prop_number_copy(prop_number_t);
|
||||
|
||||
int prop_number_size(prop_number_t);
|
||||
|
||||
uintmax_t prop_number_integer_value(prop_number_t);
|
||||
|
||||
boolean_t prop_number_equals(prop_number_t, prop_number_t);
|
||||
boolean_t prop_number_equals_integer(prop_number_t, uintmax_t);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _PROPLIB_PROP_NUMBER_H_ */
|
|
@ -0,0 +1,79 @@
|
|||
/* $NetBSD: prop_object.h,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_OBJECT_H_
|
||||
#define _PROPLIB_PROP_OBJECT_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef _KERNEL
|
||||
|
||||
typedef int boolean_t;
|
||||
#undef TRUE
|
||||
#define TRUE 1
|
||||
#undef FALSE
|
||||
#define FALSE 0
|
||||
|
||||
#endif /* ! _KERNEL */
|
||||
|
||||
typedef void *prop_object_t;
|
||||
|
||||
typedef enum {
|
||||
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;
|
||||
|
||||
__BEGIN_DECLS
|
||||
void prop_object_retain(prop_object_t);
|
||||
void prop_object_release(prop_object_t);
|
||||
|
||||
prop_type_t prop_object_type(prop_object_t);
|
||||
|
||||
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);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _PROPLIB_PROP_OBJECT_H_ */
|
|
@ -0,0 +1,67 @@
|
|||
/* $NetBSD: prop_string.h,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_STRING_H_
|
||||
#define _PROPLIB_PROP_STRING_H_
|
||||
|
||||
#include <prop/prop_object.h>
|
||||
|
||||
typedef struct _prop_string *prop_string_t;
|
||||
|
||||
__BEGIN_DECLS
|
||||
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);
|
||||
boolean_t prop_string_mutable(prop_string_t);
|
||||
|
||||
char * prop_string_cstring(prop_string_t);
|
||||
const char * prop_string_cstring_nocopy(prop_string_t);
|
||||
|
||||
boolean_t prop_string_append(prop_string_t, prop_string_t);
|
||||
boolean_t prop_string_append_cstring(prop_string_t, const char *);
|
||||
|
||||
boolean_t prop_string_equals(prop_string_t, prop_string_t);
|
||||
boolean_t prop_string_equals_cstring(prop_string_t, const char *);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _PROPLIB_PROP_STRING_H_ */
|
|
@ -0,0 +1,49 @@
|
|||
/* $NetBSD: proplib.h,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROPLIB_H_
|
||||
#define _PROPLIB_PROPLIB_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>
|
||||
|
||||
#endif /* _PROPLIB_PROPLIB_H_ */
|
|
@ -0,0 +1,6 @@
|
|||
# $NetBSD: Makefile.inc,v 1.1 2006/04/27 20:11:27 thorpej Exp $
|
||||
|
||||
.PATH: ${.PARSEDIR}
|
||||
|
||||
SRCS+= prop_array.c prop_bool.c prop_data.c prop_dictionary.c \
|
||||
prop_number.c prop_object.c prop_string.c
|
|
@ -0,0 +1,201 @@
|
|||
.\" $NetBSD: prop_array.3,v 1.1 2006/04/27 20:11:27 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 22, 2006
|
||||
.Dt PROP_ARRAY 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm prop_array ,
|
||||
.Nm prop_array_create ,
|
||||
.Nm prop_array_create_with_capacity ,
|
||||
.Nm prop_array_copy ,
|
||||
.Nm prop_array_copy_mutable ,
|
||||
.Nm prop_array_capacity ,
|
||||
.Nm prop_array_count ,
|
||||
.Nm prop_array_ensure_capacity ,
|
||||
.Nm prop_array_iterator ,
|
||||
.Nm prop_array_make_immutable ,
|
||||
.Nm prop_array_mutable ,
|
||||
.Nm prop_array_get ,
|
||||
.Nm prop_array_set ,
|
||||
.Nm prop_array_add ,
|
||||
.Nm prop_array_remove
|
||||
.Nd array property collection object
|
||||
.Sh LIBRARY
|
||||
.Lb libprop
|
||||
.Sh SYNOPSIS
|
||||
.In prop/proplib.h
|
||||
.\"
|
||||
.Ft prop_array_t
|
||||
.Fn prop_array_create "void"
|
||||
.Ft prop_array_t
|
||||
.Fn prop_array_create_with_capacity "unsigned int capacity"
|
||||
.\"
|
||||
.Ft prop_array_t
|
||||
.Fn prop_array_copy "prop_array_t array"
|
||||
.Ft prop_array_t
|
||||
.Fn prop_array_copy_mutable "prop_array_t array"
|
||||
.\"
|
||||
.Ft unsigned int
|
||||
.Fn prop_array_capacity "prop_array_t array"
|
||||
.Ft unsigned int
|
||||
.Fn prop_array_count "prop_array_t array"
|
||||
.Ft boolean_t
|
||||
.Fn prop_array_ensure_capacity "prop_array_t array" "unsigned int capacity"
|
||||
.\"
|
||||
.Ft prop_object_iterator_t
|
||||
.Fn prop_array_iterator "prop_array_t array"
|
||||
.\"
|
||||
.Ft void
|
||||
.Fn prop_array_make_immutable "prop_array_t array"
|
||||
.Ft boolean_t
|
||||
.Fn prop_array_mutable "prop_array_t array"
|
||||
.\"
|
||||
.Ft prop_object_t
|
||||
.Fn prop_array_get "prop_array_t array" "unsigned int index"
|
||||
.Ft boolean_t
|
||||
.Fn prop_array_set "prop_array_t array" "unsigned int index" "prop_object_t obj"
|
||||
.Ft boolean_t
|
||||
.Fn prop_array_add "prop_array_t array" "prop_object_t obj"
|
||||
.Ft void
|
||||
.Fn prop_array_remove "prop_array_t array" "unsigned int index"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm prop_array
|
||||
family of functions operate on the array property collection object type.
|
||||
An array is an ordered set; an iterated array will return objects in the
|
||||
same order with which they were stored.
|
||||
.Bl -tag -width "xxxxx"
|
||||
.It Fn prop_array_create "void"
|
||||
Create an empty array.
|
||||
The array initially has no capacity.
|
||||
.It Fn prop_array_create_with_capacity "unsigned int capacity"
|
||||
Create an array with the capacity to store
|
||||
.Fa capacity
|
||||
objects.
|
||||
.It Fn prop_array_copy "prop_array_t array"
|
||||
Copy an array.
|
||||
The new array has an initial capacity equal to the number of objects stored
|
||||
in the array being copied.
|
||||
The new array contains references to the original array's objects, not
|
||||
copies of those objects
|
||||
.Pq i.e. a shallow copy is made .
|
||||
If the original array is immutable, the resulting array is also immutable.
|
||||
.It Fn prop_array_copy_mutable "prop_array_t array"
|
||||
Like
|
||||
.Fn prop_array_copy ,
|
||||
except the resulting array is always mutable.
|
||||
.It Fn prop_array_capacity "prop_array_t array"
|
||||
Returns the total capacity of the array, including objects already stored
|
||||
in the array.
|
||||
.It Fn prop_array_count "prop_array_t array"
|
||||
Returns the number of objects stored in the array.
|
||||
.It Fn prop_array_ensure_capacity "prop_array_t array" "unsigned int capacity"
|
||||
Ensure that the array has a total capacity of
|
||||
.Fa capacity ,
|
||||
including objects already stored in the array.
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the capacity of the array is greater or equal to
|
||||
.Fa capacity
|
||||
or if expansion of the array's capacity was successful
|
||||
and
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
.It Fn prop_array_iterator "prop_array_t array"
|
||||
Create an iterator for the array.
|
||||
The array is retained by the iterator.
|
||||
An array iterator returns the object references stored in the array.
|
||||
Storing to or removing from the array invalidates any active iterators for
|
||||
the array.
|
||||
.It Fn prop_array_make_immutable "prop_array_t array"
|
||||
Make
|
||||
.Fa array
|
||||
immutable.
|
||||
.It Fn prop_array_mutable "prop_array_t array"
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the array is mutable.
|
||||
.It Fn prop_array_get "prop_array_t array" "unsigned int index"
|
||||
Return the object stored at the array index
|
||||
.Fa index .
|
||||
.It Fn prop_array_set "prop_array_t array" "unsigned int index" \
|
||||
"prop_object_t obj"
|
||||
Store a reference to the object
|
||||
.Fa obj
|
||||
at the array index
|
||||
.Fa index .
|
||||
This function 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.
|
||||
The object will be retained by the array.
|
||||
If an existing object reference is being replaced, that object will be
|
||||
released.
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if storing the object was successful and
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
.It Fn prop_array_add "prop_array_t array" "prop_object_t obj"
|
||||
Add a reference to the object
|
||||
.Fa obj
|
||||
to the array, appending to the end and growing the array's capacity of
|
||||
necessary.
|
||||
The object will be retained by the array.
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if storing the object was successful and
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
.It Fn prop_array_remove "prop_array_t array" "unsigned int index"
|
||||
Remove the reference to the object stored at array index
|
||||
.Fa index .
|
||||
The object will be released and the array compacted following
|
||||
the removal.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr prop_bool 3 ,
|
||||
.Xr prop_data 3 ,
|
||||
.Xr prop_dictionary 3 ,
|
||||
.Xr prop_number 3 ,
|
||||
.Xr prop_object 3 ,
|
||||
.Xr prop_string 3 ,
|
||||
.Xr proplib 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm proplib
|
||||
property container object library first appeared in
|
||||
.Nx 4.0 .
|
|
@ -0,0 +1,535 @@
|
|||
/* $NetBSD: prop_array.c,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/prop_array.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
struct _prop_array {
|
||||
struct _prop_object pa_obj;
|
||||
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")
|
||||
_PROP_MALLOC_DEFINE(M_PROP_ARRAY, "prop array",
|
||||
"property array container object")
|
||||
|
||||
#define prop_object_is_array(x) ((x)->pa_obj.po_type == PROP_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 void
|
||||
_prop_array_free(void *v)
|
||||
{
|
||||
prop_array_t pa = v;
|
||||
prop_object_t po;
|
||||
unsigned int idx;
|
||||
|
||||
_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));
|
||||
|
||||
for (idx = 0; idx < pa->pa_count; idx++) {
|
||||
po = pa->pa_array[idx];
|
||||
_PROP_ASSERT(po != NULL);
|
||||
prop_object_release(po);
|
||||
}
|
||||
|
||||
if (pa->pa_array != NULL)
|
||||
_PROP_FREE(pa->pa_array, M_PROP_ARRAY);
|
||||
|
||||
_PROP_POOL_PUT(_prop_array_pool, pa);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
_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;
|
||||
|
||||
if (pa->pa_count == 0)
|
||||
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)
|
||||
return (FALSE);
|
||||
|
||||
pi = prop_array_iterator(pa);
|
||||
if (pi == NULL)
|
||||
return (FALSE);
|
||||
|
||||
ctx->poec_depth++;
|
||||
_PROP_ASSERT(ctx->poec_depth != 0);
|
||||
|
||||
while ((po = prop_object_iterator_next(pi)) != NULL) {
|
||||
if ((*po->po_extern)(ctx, po) == FALSE) {
|
||||
prop_object_iterator_release(pi);
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
return (FALSE);
|
||||
}
|
||||
if (_prop_object_externalize_end_tag(ctx, "array") == FALSE)
|
||||
return (FALSE);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
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);
|
||||
pa->pa_obj.po_type = PROP_TYPE_ARRAY;
|
||||
pa->pa_obj.po_free = _prop_array_free;
|
||||
pa->pa_obj.po_extern = _prop_array_externalize;
|
||||
|
||||
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 boolean_t
|
||||
_prop_array_expand(prop_array_t pa, unsigned int capacity)
|
||||
{
|
||||
prop_object_t *array, *oarray;
|
||||
|
||||
oarray = pa->pa_array;
|
||||
|
||||
array = _PROP_CALLOC(capacity * sizeof(prop_object_t), M_PROP_ARRAY);
|
||||
if (array == NULL)
|
||||
return (FALSE);
|
||||
if (oarray != NULL)
|
||||
memcpy(array, oarray, pa->pa_capacity * sizeof(prop_object_t));
|
||||
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(void *v)
|
||||
{
|
||||
struct _prop_array_iterator *pai = v;
|
||||
prop_array_t pa = pai->pai_base.pi_obj;
|
||||
prop_object_t po;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
if (pa->pa_version != pai->pai_base.pi_version)
|
||||
return (NULL); /* array changed during iteration */
|
||||
|
||||
_PROP_ASSERT(pai->pai_index <= pa->pa_count);
|
||||
|
||||
if (pai->pai_index == pa->pa_count)
|
||||
return (NULL); /* we've iterated all objects */
|
||||
|
||||
po = pa->pa_array[pai->pai_index];
|
||||
pai->pai_index++;
|
||||
|
||||
return (po);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_array_iterator_reset(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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(opa));
|
||||
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
return (pa->pa_capacity);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_count --
|
||||
* Return the number of objects stored in the array.
|
||||
*/
|
||||
unsigned int
|
||||
prop_array_count(prop_array_t pa)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
return (pa->pa_count);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
boolean_t
|
||||
prop_array_ensure_capacity(prop_array_t pa, unsigned int capacity)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
if (capacity > pa->pa_capacity)
|
||||
return (_prop_array_expand(pa, capacity - pa->pa_capacity));
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
struct _prop_array_iterator *pai;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
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;
|
||||
pai->pai_base.pi_version = pa->pa_version;
|
||||
|
||||
_prop_array_iterator_reset(pai);
|
||||
|
||||
return (&pai->pai_base);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_make_immutable --
|
||||
* Make the array immutable.
|
||||
*/
|
||||
void
|
||||
prop_array_make_immutable(prop_array_t pa)
|
||||
{
|
||||
|
||||
if (prop_array_is_immutable(pa) == FALSE)
|
||||
pa->pa_flags |= PA_F_IMMUTABLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_mutable --
|
||||
* Returns TRUE if the array is mutable.
|
||||
*/
|
||||
boolean_t
|
||||
prop_array_mutable(prop_array_t pa)
|
||||
{
|
||||
|
||||
return (prop_array_is_immutable(pa) == FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
if (idx >= pa->pa_count)
|
||||
return (NULL);
|
||||
po = pa->pa_array[idx];
|
||||
_PROP_ASSERT(po != NULL);
|
||||
return (po);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
boolean_t
|
||||
prop_array_set(prop_array_t pa, unsigned int idx, prop_object_t po)
|
||||
{
|
||||
prop_object_t opo;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
|
||||
if (prop_array_is_immutable(pa))
|
||||
return (FALSE);
|
||||
|
||||
if (idx == pa->pa_count)
|
||||
return (prop_array_add(pa, po));
|
||||
|
||||
_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);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_array_add --
|
||||
* Add a refrerence to an object to the specified array, appending
|
||||
* to the end and growing the array's capacity, if necessary.
|
||||
*/
|
||||
boolean_t
|
||||
prop_array_add(prop_array_t pa, prop_object_t po)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
_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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_array(pa));
|
||||
_PROP_ASSERT(idx < pa->pa_count);
|
||||
|
||||
/* XXX Should this be a _PROP_ASSERT()? */
|
||||
if (prop_array_is_immutable(pa))
|
||||
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_object_release(po);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_array_internalize --
|
||||
* Parse an <array>...</array> and return the object created from the
|
||||
* external representation.
|
||||
*/
|
||||
prop_object_t
|
||||
_prop_array_internalize(struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
prop_array_t array;
|
||||
prop_object_t obj;
|
||||
|
||||
/* We don't currently understand any attributes. */
|
||||
if (ctx->poic_tagattr != NULL)
|
||||
return (NULL);
|
||||
|
||||
array = prop_array_create();
|
||||
if (array == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (ctx->poic_is_empty_element)
|
||||
return (array);
|
||||
|
||||
for (;;) {
|
||||
/* 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)
|
||||
break;
|
||||
|
||||
/* Fetch the object. */
|
||||
obj = _prop_object_internalize_by_tag(ctx);
|
||||
if (obj == NULL)
|
||||
goto bad;
|
||||
|
||||
if (prop_array_add(array, obj) == FALSE) {
|
||||
prop_object_release(obj);
|
||||
goto bad;
|
||||
}
|
||||
prop_object_release(obj);
|
||||
}
|
||||
|
||||
return (array);
|
||||
|
||||
bad:
|
||||
prop_object_release(array);
|
||||
return (NULL);
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
.\" $NetBSD: prop_bool.3,v 1.1 2006/04/27 20:11:27 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 22, 2006
|
||||
.Dt PROP_BOOL 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm prop_bool ,
|
||||
.Nm prop_bool_create ,
|
||||
.Nm prop_bool_copy ,
|
||||
.Nm prop_bool_true
|
||||
.Nd boolean value property object
|
||||
.Sh LIBRARY
|
||||
.Lb libprop
|
||||
.Sh SYNOPSIS
|
||||
.In prop/proplib.h
|
||||
.\"
|
||||
.Ft prop_bool_t
|
||||
.Fn prop_bool_create "boolean_t val"
|
||||
.Ft prop_bool_t
|
||||
.Fn prop_booly_copy "prop_bool_t bool"
|
||||
.\"
|
||||
.Ft boolean_t
|
||||
.Fn prop_bool_true "prop_bool_t bool"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm prop_bool
|
||||
family of functions operate on a boolean value property object type.
|
||||
.Bl -tag -width "xxxxx"
|
||||
.It Fn prop_bool_create "boolean_t val"
|
||||
Create a boolean value object with the value
|
||||
.Fa val .
|
||||
.It Fn prop_bool_copy "prop_bool_t bool"
|
||||
Copy a boolean value object.
|
||||
.It Fn prop_bool_true "prop_bool_t bool"
|
||||
Returns the value of the boolean value object.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr prop_array 3 ,
|
||||
.Xr prop_data 3 ,
|
||||
.Xr prop_dictionary 3 ,
|
||||
.Xr prop_number 3 ,
|
||||
.Xr prop_object 3 ,
|
||||
.Xr prop_string 3 ,
|
||||
.Xr proplib 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm proplib
|
||||
property container object library first appeared in
|
||||
.Nx 4.0 .
|
|
@ -0,0 +1,152 @@
|
|||
/* $NetBSD: prop_bool.c,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/prop_bool.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
struct _prop_bool {
|
||||
struct _prop_object pb_obj;
|
||||
boolean_t pb_value;
|
||||
};
|
||||
|
||||
_PROP_POOL_INIT(_prop_bool_pool, sizeof(struct _prop_bool), "propbool")
|
||||
|
||||
#define prop_object_is_bool(x) ((x)->pb_obj.po_type == PROP_TYPE_BOOL)
|
||||
|
||||
static void
|
||||
_prop_bool_free(void *v)
|
||||
{
|
||||
|
||||
_PROP_POOL_PUT(_prop_bool_pool, v);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
_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"));
|
||||
}
|
||||
|
||||
static prop_bool_t
|
||||
_prop_bool_alloc(void)
|
||||
{
|
||||
prop_bool_t pb;
|
||||
|
||||
pb = _PROP_POOL_GET(_prop_bool_pool);
|
||||
if (pb != NULL) {
|
||||
_prop_object_init(&pb->pb_obj);
|
||||
pb->pb_obj.po_type = PROP_TYPE_BOOL;
|
||||
pb->pb_obj.po_free = _prop_bool_free;
|
||||
pb->pb_obj.po_extern = _prop_bool_externalize;
|
||||
}
|
||||
|
||||
return (pb);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_create --
|
||||
* Create a prop_bool_t and initialize it with the
|
||||
* provided boolean value.
|
||||
*/
|
||||
prop_bool_t
|
||||
prop_bool_create(boolean_t val)
|
||||
{
|
||||
prop_bool_t pb;
|
||||
|
||||
pb = _prop_bool_alloc();
|
||||
if (pb != NULL)
|
||||
pb->pb_value = val;
|
||||
return (pb);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_copy --
|
||||
* Copy a prop_bool_t.
|
||||
*/
|
||||
prop_bool_t
|
||||
prop_bool_copy(prop_bool_t opb)
|
||||
{
|
||||
prop_bool_t pb;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_bool(opb));
|
||||
|
||||
pb = _prop_bool_alloc();
|
||||
if (pb != NULL)
|
||||
pb->pb_value = opb->pb_value;
|
||||
return (pb);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_bool_true --
|
||||
* Get the value of a prop_bool_t.
|
||||
*/
|
||||
boolean_t
|
||||
prop_bool_true(prop_bool_t pb)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_bool(pb));
|
||||
return (pb->pb_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_bool_internalize --
|
||||
* Parse a <true/> or <false/> and return the object created from
|
||||
* the external representation.
|
||||
*/
|
||||
prop_object_t
|
||||
_prop_bool_internalize(struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
boolean_t val;
|
||||
|
||||
/* No attributes, and it must be an empty element. */
|
||||
if (ctx->poic_tagattr != NULL ||
|
||||
ctx->poic_is_empty_element == FALSE)
|
||||
return (NULL);
|
||||
|
||||
if (_PROP_TAG_MATCH(ctx, "true"))
|
||||
val = TRUE;
|
||||
else {
|
||||
_PROP_ASSERT(_PROP_TAG_MATCH(ctx, "false"));
|
||||
val = FALSE;
|
||||
}
|
||||
|
||||
return (prop_bool_create(val));
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
.\" $NetBSD: prop_data.3,v 1.1 2006/04/27 20:11:27 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 22, 2006
|
||||
.Dt PROP_DATA 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm prop_data ,
|
||||
.Nm prop_data_create_data ,
|
||||
.Nm prop_data_create_data_nocopy ,
|
||||
.Nm prop_data_copy ,
|
||||
.Nm prop_data_size ,
|
||||
.Nm prop_data_data ,
|
||||
.Nm prop_data_data_nocopy ,
|
||||
.Nm prop_data_equals ,
|
||||
.Nm prop_data_equals_data
|
||||
.Nd opaque data value property object
|
||||
.Sh LIBRARY
|
||||
.Lb libprop
|
||||
.Sh SYNOPSIS
|
||||
.In prop/proplib.h
|
||||
.\"
|
||||
.Ft prop_data_t
|
||||
.Fn prop_data_create_data "const void *blob" "size_t len"
|
||||
.Ft prop_data_t
|
||||
.Fn prop_data_create_data_nocopy "const void *blob" "size_t len"
|
||||
.\"
|
||||
.Ft prop_data_t
|
||||
.Fn prop_data_copy "prop_data_t data"
|
||||
.\"
|
||||
.Ft void *
|
||||
.Fn prop_data_data "prop_data_t data"
|
||||
.Ft const void *
|
||||
.Fn prop_data_data_nocopy "prop_data_t data"
|
||||
.\"
|
||||
.Ft boolean_t
|
||||
.Fn prop_data_equals "prop_data_t dat1" "prop_data_t dat2"
|
||||
.Ft boolean_t
|
||||
.Fn prop_data_equals_data "prop_data_t data" "const void *blob" "size_t len"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm prop_data
|
||||
family of functions operate on an opaque data value property object type.
|
||||
.Bl -tag -width "xxxxx"
|
||||
.It Fn prop_data_create_data "const void *blob" "size_t len"
|
||||
Create a data object that contains a copy of
|
||||
.Fa blob
|
||||
with size
|
||||
.Fa len .
|
||||
.It Fn prop_data_create_data_nocopy "const void *blob" "size_t len"
|
||||
Create a data object that contains a reference to
|
||||
.Fa blob
|
||||
with size
|
||||
.Fa len .
|
||||
.It Fn prop_data_copy "prop_data_t data"
|
||||
Copy a data object.
|
||||
If the the data object being copied is an external data reference,
|
||||
then the copy also references the same external data.
|
||||
.It Fn prop_data_size "prop_data_t data"
|
||||
Returns the size of the data object.
|
||||
.It Fn prop_data_data "prop_data_t data"
|
||||
Returns a copy of the data object's contents.
|
||||
The caller is responsible for freeing the returned buffer.
|
||||
.Pp
|
||||
In user space, the buffer is allocated using
|
||||
.Xr malloc 3 .
|
||||
In the kernel, the buffer is allocated using
|
||||
.Xr malloc 9
|
||||
using the malloc type
|
||||
.Dv M_TEMP .
|
||||
.It Fn prop_data_data_nocopy "prop_data_t data"
|
||||
Returns an immutable reference to the contents of the data object.
|
||||
.It Fn prop_data_equals "prop_data_t dat1" "prop_data_t dat2"
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the two data objects are equivalent.
|
||||
.It Fn prop_data_equals_data "prop_data_t data" "const void *blob" "size_t len"
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the data object's value is equivalent to
|
||||
.Fa blob
|
||||
with size
|
||||
.Fa len .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr prop_array 3 ,
|
||||
.Xr prop_bool 3 ,
|
||||
.Xr prop_dictionary 3 ,
|
||||
.Xr prop_number 3 ,
|
||||
.Xr prop_object 3 ,
|
||||
.Xr prop_string 3 ,
|
||||
.Xr proplib 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm proplib
|
||||
property container object library first appeared in
|
||||
.Nx 4.0 .
|
|
@ -0,0 +1,569 @@
|
|||
/* $NetBSD: prop_data.c,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/prop_data.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
#if defined(_KERNEL)
|
||||
#include <sys/systm.h>
|
||||
#elif defined(_STANDALONE)
|
||||
#include <sys/param.h>
|
||||
#include <lib/libkern/libkern.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
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")
|
||||
|
||||
_PROP_MALLOC_DEFINE(M_PROP_DATA, "prop data",
|
||||
"property data container object")
|
||||
|
||||
#define prop_object_is_data(x) ((x)->pd_obj.po_type == PROP_TYPE_DATA)
|
||||
|
||||
static void
|
||||
_prop_data_free(void *v)
|
||||
{
|
||||
prop_data_t pd = v;
|
||||
|
||||
if ((pd->pd_flags & PD_F_NOCOPY) == 0 && pd->pd_mutable != NULL)
|
||||
_PROP_FREE(pd->pd_mutable, M_PROP_DATA);
|
||||
_PROP_POOL_PUT(_prop_data_pool, v);
|
||||
}
|
||||
|
||||
static const char _prop_data_base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char _prop_data_pad64 = '=';
|
||||
|
||||
static boolean_t
|
||||
_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] = ((u_int32_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] = ((u_int32_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);
|
||||
}
|
||||
|
||||
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);
|
||||
pd->pd_obj.po_type = PROP_TYPE_DATA;
|
||||
pd->pd_obj.po_free = _prop_data_free;
|
||||
pd->pd_obj.po_extern = _prop_data_externalize;
|
||||
|
||||
pd->pd_mutable = NULL;
|
||||
pd->pd_size = 0;
|
||||
pd->pd_flags = 0;
|
||||
}
|
||||
|
||||
return (pd);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_create_data --
|
||||
* Create a data container that contains a copy of the data.
|
||||
*/
|
||||
prop_data_t
|
||||
prop_data_create_data(const void *v, size_t size)
|
||||
{
|
||||
prop_data_t pd;
|
||||
void *nv;
|
||||
|
||||
pd = _prop_data_alloc();
|
||||
if (pd != NULL) {
|
||||
nv = _PROP_MALLOC(size, M_PROP_DATA);
|
||||
if (nv == NULL) {
|
||||
_prop_data_free(pd);
|
||||
return (NULL);
|
||||
}
|
||||
memcpy(nv, v, size);
|
||||
pd->pd_mutable = nv;
|
||||
pd->pd_size = size;
|
||||
}
|
||||
return (pd);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_create_data_nocopy --
|
||||
* Create an immutable data container that contains a refrence to the
|
||||
* provided external data.
|
||||
*/
|
||||
prop_data_t
|
||||
prop_data_create_data_nocopy(const void *v, size_t size)
|
||||
{
|
||||
prop_data_t pd;
|
||||
|
||||
pd = _prop_data_alloc();
|
||||
if (pd != NULL) {
|
||||
pd->pd_immutable = v;
|
||||
pd->pd_size = size;
|
||||
pd->pd_flags |= PD_F_NOCOPY;
|
||||
}
|
||||
return (pd);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_copy --
|
||||
* Copy a data container. If the original data is external, then
|
||||
* the copy is also references the same external data.
|
||||
*/
|
||||
prop_data_t
|
||||
prop_data_copy(prop_data_t opd)
|
||||
{
|
||||
prop_data_t pd;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_data(opd));
|
||||
|
||||
pd = _prop_data_alloc();
|
||||
if (pd != NULL) {
|
||||
pd->pd_size = opd->pd_size;
|
||||
pd->pd_flags = opd->pd_flags;
|
||||
if (opd->pd_flags & PD_F_NOCOPY)
|
||||
pd->pd_immutable = opd->pd_immutable;
|
||||
else if (opd->pd_size != 0) {
|
||||
void *nv = _PROP_MALLOC(pd->pd_size, M_PROP_DATA);
|
||||
if (nv == NULL) {
|
||||
_prop_data_free(pd);
|
||||
return (NULL);
|
||||
}
|
||||
memcpy(nv, opd->pd_immutable, opd->pd_size);
|
||||
pd->pd_mutable = nv;
|
||||
}
|
||||
}
|
||||
return (pd);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_size --
|
||||
* Return the size of the data.
|
||||
*/
|
||||
size_t
|
||||
prop_data_size(prop_data_t pd)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_data(pd));
|
||||
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;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_data(pd));
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_data(pd));
|
||||
_PROP_ASSERT((pd->pd_size == 0 && pd->pd_immutable == NULL) ||
|
||||
(pd->pd_size != 0 && pd->pd_immutable != NULL));
|
||||
|
||||
return (pd->pd_immutable);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_equals --
|
||||
* Return TRUE if two strings are equivalent.
|
||||
*/
|
||||
boolean_t
|
||||
prop_data_equals(prop_data_t pd1, prop_data_t pd2)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_data(pd1));
|
||||
_PROP_ASSERT(prop_object_is_data(pd2));
|
||||
if (pd1 == pd2)
|
||||
return (TRUE);
|
||||
if (pd1->pd_size != pd2->pd_size)
|
||||
return (FALSE);
|
||||
if (pd1->pd_size == 0) {
|
||||
_PROP_ASSERT(pd1->pd_immutable == NULL);
|
||||
_PROP_ASSERT(pd2->pd_immutable == NULL);
|
||||
return (TRUE);
|
||||
}
|
||||
return (memcmp(pd1->pd_immutable, pd2->pd_immutable,
|
||||
pd1->pd_size) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_data_equals_data --
|
||||
* Return TRUE if the contained data is equivalent to the specified
|
||||
* external data.
|
||||
*/
|
||||
boolean_t
|
||||
prop_data_equals_data(prop_data_t pd, const void *v, size_t size)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_data(pd));
|
||||
if (pd->pd_size != size)
|
||||
return (FALSE);
|
||||
return (memcmp(pd->pd_immutable, v, size) == 0);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
_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] =
|
||||
(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] =
|
||||
((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] =
|
||||
((pos - _prop_data_base64) & 0x3) << 6;
|
||||
}
|
||||
tarindex++;
|
||||
state = 3;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (target) {
|
||||
if (tarindex >= targsize)
|
||||
return (FALSE);
|
||||
target[tarindex] |= (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);
|
||||
ch = (unsigned char) *src;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 3: /* Valid, two bytes of info */
|
||||
/*
|
||||
* We know this char is a =. Is there anything but
|
||||
* whitespace after it?
|
||||
*/
|
||||
for (; ch != '<'; ch = (unsigned char) *src++) {
|
||||
if (_PROP_EOF(ch))
|
||||
return (FALSE);
|
||||
if (!_PROP_ISSPACE(ch))
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
} 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.
|
||||
*/
|
||||
prop_object_t
|
||||
_prop_data_internalize(struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
prop_data_t data;
|
||||
uint8_t *buf;
|
||||
size_t len, alen;
|
||||
|
||||
/* We don't accept empty elements. */
|
||||
if (ctx->poic_is_empty_element)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* 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 (NULL);
|
||||
|
||||
#ifndef _KERNEL
|
||||
errno = 0;
|
||||
#endif
|
||||
/* XXX Assumes size_t and unsigned long are the same size. */
|
||||
len = strtoul(ctx->poic_tagattrval, &cp, 0);
|
||||
#ifndef _KERNEL /* XXX can't check for ERANGE in the kernel */
|
||||
if (len == ULONG_MAX && errno == ERANGE)
|
||||
return (NULL);
|
||||
#endif
|
||||
if (cp != ctx->poic_tagattrval + ctx->poic_tagattrval_len)
|
||||
return (NULL);
|
||||
_PROP_ASSERT(*cp == '\"');
|
||||
} else if (_prop_data_internalize_decode(ctx, NULL, 0, &len,
|
||||
NULL) == FALSE)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* 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 (NULL);
|
||||
|
||||
if (_prop_data_internalize_decode(ctx, buf, len + 1, &alen,
|
||||
&ctx->poic_cp) == FALSE) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (NULL);
|
||||
}
|
||||
if (alen != len) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (_prop_object_internalize_find_tag(ctx, "data",
|
||||
_PROP_TAG_TYPE_END) == FALSE) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
data = _prop_data_alloc();
|
||||
if (data == NULL) {
|
||||
_PROP_FREE(buf, M_PROP_DATA);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
data->pd_mutable = buf;
|
||||
data->pd_size = len;
|
||||
|
||||
return (data);
|
||||
}
|
|
@ -0,0 +1,266 @@
|
|||
.\" $NetBSD: prop_dictionary.3,v 1.1 2006/04/27 20:11:27 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 22, 2006
|
||||
.Dt PROP_DICTIONARY 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm prop_dictionary ,
|
||||
.Nm prop_dictionary_create ,
|
||||
.Nm prop_dictionary_create_with_capacity ,
|
||||
.Nm prop_dictionary_copy ,
|
||||
.Nm prop_dictionary_copy_mutable ,
|
||||
.Nm prop_dictionary_capacity ,
|
||||
.Nm prop_dictionary_count ,
|
||||
.Nm prop_dictionary_ensure_capacity ,
|
||||
.Nm prop_dictionary_iterator ,
|
||||
.Nm prop_dictionary_make_immutable ,
|
||||
.Nm prop_dictionary_mutable ,
|
||||
.Nm prop_dictionary_get ,
|
||||
.Nm prop_dictionary_set ,
|
||||
.Nm prop_dictionary_remove ,
|
||||
.Nm prop_dictionary_get_keysym ,
|
||||
.Nm prop_dictionary_set_keysym ,
|
||||
.Nm prop_dictionary_remove_keysym ,
|
||||
.Nm prop_dictionary_externalize ,
|
||||
.Nm prop_dictionary_internalize ,
|
||||
.Nm prop_dictionary_keysym_cstring_nocopy
|
||||
.Nd dictionary property collection object
|
||||
.Sh LIBRARY
|
||||
.Lb libprop
|
||||
.Sh SYNOPSIS
|
||||
.In prop/proplib.h
|
||||
.\"
|
||||
.Ft prop_dictionary_t
|
||||
.Fn prop_dictionary_create "void"
|
||||
.Ft prop_dictionary_t
|
||||
.Fn prop_dictionary_create_with_capacity "unsigned int capacity"
|
||||
.\"
|
||||
.Ft prop_dictionary_t
|
||||
.Fn prop_dictionary_copy "prop_dictionary_t dict"
|
||||
.Ft prop_dictionary_t
|
||||
.Fn prop_dictionary_copy_mutable "prop_dictionary_t dict"
|
||||
.\"
|
||||
.Ft unsigned int
|
||||
.Fn prop_dictionary_capacity "prop_dictionary_t dict"
|
||||
.Ft unsigned int
|
||||
.Fn prop_dictionary_count "prop_dictionary_t dict"
|
||||
.Ft boolean_t
|
||||
.Fn prop_dictionary_ensure_capacity "prop_dictionary_t dict" \
|
||||
"unsigned int capacity"
|
||||
.\"
|
||||
.Ft prop_object_iterator_t
|
||||
.Fn prop_dictionary_iterator "prop_dictionary_t dict"
|
||||
.\"
|
||||
.Ft void
|
||||
.Fn prop_dictionary_make_immutable "prop_dictionary_t dict"
|
||||
.Ft boolean_t
|
||||
.Fn prop_dictionary_mutable "prop_dictionary_t dict"
|
||||
.\"
|
||||
.Ft prop_object_t
|
||||
.Fn prop_dictionary_get "prop_dictionary_t dict" "const char *key"
|
||||
.Ft boolean_t
|
||||
.Fn prop_dictionary_set "prop_dictionary_t dict" "const char *key" \
|
||||
"prop_object_t obj"
|
||||
.Ft void
|
||||
.Fn prop_dictionary_remove "prop_dictionary_t dict" "const char *key"
|
||||
.\"
|
||||
.Ft prop_object_t
|
||||
.Fn prop_dictionary_get_keysym "prop_dictionary_t dict" \
|
||||
"prop_dictionary_keysym_t keysym"
|
||||
.Ft boolean_t
|
||||
.Fn prop_dictionary_set_keysym "prop_dictionary_t dict" \
|
||||
"prop_dictionary_keysym_t keysym" "prop_object_t obj"
|
||||
.Ft void
|
||||
.Fn prop_dictionary_remove_keysym "prop_dictionary_t dict" \
|
||||
"prop_dictionary_keysym_t keysym"
|
||||
.\"
|
||||
.Ft const char *
|
||||
.Fn prop_dictionary_keysym_cstring_nocopy "prop_dictionary_keysym_t sym"
|
||||
.\"
|
||||
.Ft char *
|
||||
.Fn prop_dictionary_externalize "prop_dictionary_t dict"
|
||||
.Ft prop_dictionary_t
|
||||
.Fn prop_dictionary_internalize "const char *xml"
|
||||
.\"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm prop_dictionary
|
||||
family of functions operate on the dictionary property collection object type.
|
||||
A dictionary is an unordered set of objects stored as key-value pairs.
|
||||
.Bl -tag -width "xxxxx"
|
||||
.It Fn prop_dictionary_create "void"
|
||||
Create an empty dictionary.
|
||||
The dictionary initially has no capacity.
|
||||
.It Fn prop_dictionary_create_with_capacity "unsigned int capacity"
|
||||
Create a dictionary with the capacity to store
|
||||
.Fa capacity
|
||||
objects.
|
||||
.It Fn prop_dictionary_copy "prop_dictionary_t dict"
|
||||
Copy an dictionary.
|
||||
The new dictionary has an initial capacity equal to the number of objects
|
||||
stored in the dictionary being copied.
|
||||
The new dictionary contains references to the original dictionary's objects,
|
||||
not copies of those objects
|
||||
.Pq i.e. a shallow copy is made .
|
||||
If the original dictionary is immutable, the resulting dictionary is also
|
||||
immutable.
|
||||
.It Fn prop_dictionary_copy_mutable "prop_dictionary_t dict"
|
||||
Like
|
||||
.Fn prop_dictionary_copy ,
|
||||
except the resulting dictionary is always mutable.
|
||||
.It Fn prop_dictionary_capacity "prop_dictionary_t dict"
|
||||
Returns the total capacity of the dictionary, including objects already stored
|
||||
in the dictionary.
|
||||
.It Fn prop_dictionary_count "prop_dictionary_t dict"
|
||||
Returns the number of objects stored in the dictionary.
|
||||
.It Fn prop_dictionary_ensure_capacity "prop_dictionary_t dict"
|
||||
Ensure that the dictionary has a total capacity of
|
||||
.Fa capacity ,
|
||||
including objects already stored in the dictionary.
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the capacity of the dictionary is greater or equal to
|
||||
.Fa capacity
|
||||
or if the expansion of the dictionary's capacity was successful
|
||||
and
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
.It Fn prop_dictionary_iterator "prop_dictionary_t dict"
|
||||
Create an iterator for the dictionary.
|
||||
The dictionary is retained by the iterator.
|
||||
A dictionary iterator returns the key symbols used to look up objects stored
|
||||
in the dictionary; to get the object itself, a dictionary lookup using this
|
||||
key symbol must be performed.
|
||||
Storing to or removing from the dictionary invalidates any active iterators for
|
||||
the dictionary.
|
||||
.It Fn prop_dictionary_make_immutable "prop_dictionary_t dict"
|
||||
Make
|
||||
.Fa dict
|
||||
immutable.
|
||||
.It Fn prop_dictionary_mutable "prop_dictionary_t dict"
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the dictionary is mutable.
|
||||
.It Fn prop_dictionary_get "prop_dictionary_t dict" "const char *key"
|
||||
Return the object stored in the dictionary with the key
|
||||
.Fa key .
|
||||
If no object is stored with the specified key,
|
||||
.Dv NULL
|
||||
is returned.
|
||||
.It Fn prop_dictionary_set "prop_dictionary_t dict" "const char *key" \
|
||||
"prop_object_t obj"
|
||||
Store a reference to the object
|
||||
.Fa obj
|
||||
with the key
|
||||
.Fa key .
|
||||
The object will be retained by the array.
|
||||
If the key already exists in the dictionary, the object associated with
|
||||
that key will be released and replaced with the new object.
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if storing the object was successful and
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
.It Fn prop_dictionary_remove "prop_dictionary_t dict" "const char *key"
|
||||
Remove the reference to the object stored in the dictionary with the key
|
||||
.Fa key .
|
||||
The object will be released.
|
||||
.It Fn prop_dictionary_get_keysym "prop_dictionary_t dict" \
|
||||
"prop_dictionary_keysym_t sym"
|
||||
Like
|
||||
.Fn prop_dictionary_get ,
|
||||
but the lookup is performed using a key symbol returned by a dictionary
|
||||
iterator.
|
||||
The results are undefined if the iterator used to obtain the key symbol
|
||||
is not associated with
|
||||
.Fa dict .
|
||||
.It Fn prop_dictionary_set_keysym "prop_dictionary_t dict" \
|
||||
"prop_dictionary_keysym_t sym"
|
||||
Like
|
||||
.Fn prop_dictionary_set ,
|
||||
but the lookup of the object to replace is performed using a key symbol
|
||||
returned by a dictionary iterator.
|
||||
The results are undefined if the iterator used to obtain the key symbol
|
||||
is not associated with
|
||||
.Fa dict .
|
||||
.It Fn prop_dictionary_remove_keysym "prop_dictionary_t dict" \
|
||||
"prop_dictionary_keysym_t sym"
|
||||
Like
|
||||
.Fn prop_dictionary_remove ,
|
||||
but the lookup of the object to remove is performed using a key symbol
|
||||
returned by a dictionary iterator.
|
||||
The results are undefined if the iterator used to obtain the key symbol
|
||||
is not associated with
|
||||
.Fa dict .
|
||||
.It Fn prop_dictionary_keysym_cstring_nocopy "prop_dictionary_keysym_t sym"
|
||||
Returns an immutable reference to the dictionary key symbol's string value.
|
||||
.It Fn prop_dictionary_externalize "prop_dictionary_t dict"
|
||||
Externalizes a dictionary, returning a NUL-terminated buffer containing
|
||||
the XML representation of the dictionary.
|
||||
The caller is responsible for freeing the returned buffer.
|
||||
If converting to the external representation fails for any reason,
|
||||
.Dv NULL
|
||||
is returned.
|
||||
.Pp
|
||||
In user space, the buffer is allocated using
|
||||
.Xr malloc 3 .
|
||||
In the kernel, the buffer is allocated using
|
||||
.Xr malloc 9
|
||||
using the malloc type
|
||||
.Dv M_TEMP .
|
||||
.It Fn prop_dictionary_internalize "const char *xml"
|
||||
Parse the XML representation of a property list in the NUL-terminated
|
||||
buffer
|
||||
.Fa xml
|
||||
and return the corresponding dictionary.
|
||||
Returns
|
||||
.Dv NULL
|
||||
if parsing fails for any reason.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr prop_array 3 ,
|
||||
.Xr prop_bool 3 ,
|
||||
.Xr prop_data 3 ,
|
||||
.Xr prop_number 3 ,
|
||||
.Xr prop_object 3 ,
|
||||
.Xr prop_string 3 ,
|
||||
.Xr proplib 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm proplib
|
||||
property container object library first appeared in
|
||||
.Nx 4.0 .
|
|
@ -0,0 +1,890 @@
|
|||
/* $NetBSD: prop_dictionary.c,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/prop_dictionary.h>
|
||||
#include <prop/prop_string.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
/*
|
||||
* We implement these like arrays, but we keep them sorted by key.
|
||||
* This allows us to binary-search as well as keep externalized output
|
||||
* sane-looking for human eyes.
|
||||
*/
|
||||
|
||||
#define EXPAND_STEP 16
|
||||
|
||||
/*
|
||||
* prop_dictionary_keysym_t is allocated with space at the end to hold the
|
||||
* key. This must be a regular object so that we can maintain sane iterator
|
||||
* semantics -- we don't want to require that the caller release the result
|
||||
* of prop_object_iterator_next().
|
||||
*
|
||||
* We'd like to have some small'ish keysym objects for up-to-16 characters
|
||||
* in a key, some for up-to-32 characters in a key, and then a final bucket
|
||||
* for up-to-128 characters in a key (not including NUL). Keys longer than
|
||||
* 128 characters are not allowed.
|
||||
*/
|
||||
struct _prop_dictionary_keysym {
|
||||
struct _prop_object pde_obj;
|
||||
prop_object_t pde_objref;
|
||||
size_t pde_size;
|
||||
char pde_key[1];
|
||||
/* actually variable length */
|
||||
};
|
||||
|
||||
/* pde_key[1] takes care of the NUL */
|
||||
#define PDE_SIZE_16 (sizeof(struct _prop_dictionary_keysym) + 16)
|
||||
#define PDE_SIZE_32 (sizeof(struct _prop_dictionary_keysym) + 32)
|
||||
#define PDE_SIZE_128 (sizeof(struct _prop_dictionary_keysym) + 128)
|
||||
|
||||
#define PDE_MAXKEY 128
|
||||
|
||||
_PROP_POOL_INIT(_prop_dictionary_keysym16_pool, PDE_SIZE_16, "pdict16")
|
||||
_PROP_POOL_INIT(_prop_dictionary_keysym32_pool, PDE_SIZE_32, "pdict32")
|
||||
_PROP_POOL_INIT(_prop_dictionary_keysym128_pool, PDE_SIZE_128, "pdict128")
|
||||
|
||||
struct _prop_dictionary {
|
||||
struct _prop_object pd_obj;
|
||||
prop_dictionary_keysym_t *pd_array;
|
||||
unsigned int pd_capacity;
|
||||
unsigned int pd_count;
|
||||
int pd_flags;
|
||||
|
||||
uint32_t pd_version;
|
||||
};
|
||||
|
||||
#define PD_F_IMMUTABLE 0x01 /* dictionary is immutable */
|
||||
|
||||
_PROP_POOL_INIT(_prop_dictionary_pool, sizeof(struct _prop_dictionary),
|
||||
"propdict")
|
||||
_PROP_MALLOC_DEFINE(M_PROP_DICT, "prop dictionary",
|
||||
"property dictionary container object")
|
||||
|
||||
#define prop_object_is_dictionary(x) \
|
||||
((x)->pd_obj.po_type == PROP_TYPE_DICTIONARY)
|
||||
#define prop_object_is_dictionary_keysym(x) \
|
||||
((x)->pde_obj.po_type == PROP_TYPE_DICT_KEYSYM)
|
||||
|
||||
#define prop_dictionary_is_immutable(x) \
|
||||
(((x)->pd_flags & PD_F_IMMUTABLE) != 0)
|
||||
|
||||
struct _prop_dictionary_iterator {
|
||||
struct _prop_object_iterator pdi_base;
|
||||
unsigned int pdi_index;
|
||||
};
|
||||
|
||||
static void
|
||||
_prop_dict_entry_free(void *v)
|
||||
{
|
||||
prop_dictionary_keysym_t pde = v;
|
||||
prop_object_t po;
|
||||
|
||||
_PROP_ASSERT(pde->pde_objref != NULL);
|
||||
po = pde->pde_objref;
|
||||
|
||||
if (pde->pde_size <= PDE_SIZE_16)
|
||||
_PROP_POOL_PUT(_prop_dictionary_keysym16_pool, pde);
|
||||
else if (pde->pde_size <= PDE_SIZE_32)
|
||||
_PROP_POOL_PUT(_prop_dictionary_keysym32_pool, pde);
|
||||
else {
|
||||
_PROP_ASSERT(pde->pde_size <= PDE_SIZE_128);
|
||||
_PROP_POOL_PUT(_prop_dictionary_keysym128_pool, pde);
|
||||
}
|
||||
|
||||
prop_object_release(po);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
_prop_dict_entry_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_dictionary_keysym_t pde = v;
|
||||
|
||||
/* We externalize these as strings, and they're never empty. */
|
||||
|
||||
_PROP_ASSERT(pde->pde_key[0] != '\0');
|
||||
|
||||
if (_prop_object_externalize_start_tag(ctx, "string") == FALSE ||
|
||||
_prop_object_externalize_append_encoded_cstring(ctx,
|
||||
pde->pde_key) == FALSE ||
|
||||
_prop_object_externalize_end_tag(ctx, "string") == FALSE)
|
||||
return (FALSE);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static prop_dictionary_keysym_t
|
||||
_prop_dict_entry_alloc(const char *key, prop_object_t obj)
|
||||
{
|
||||
prop_dictionary_keysym_t pde;
|
||||
size_t size;
|
||||
|
||||
size = sizeof(*pde) + strlen(key) /* pde_key[1] covers the NUL */;
|
||||
|
||||
if (size <= PDE_SIZE_16)
|
||||
pde = _PROP_POOL_GET(_prop_dictionary_keysym16_pool);
|
||||
else if (size <= PDE_SIZE_32)
|
||||
pde = _PROP_POOL_GET(_prop_dictionary_keysym32_pool);
|
||||
else if (size <= PDE_SIZE_128)
|
||||
pde = _PROP_POOL_GET(_prop_dictionary_keysym128_pool);
|
||||
else
|
||||
return (NULL); /* key too long */
|
||||
|
||||
if (pde != NULL) {
|
||||
_prop_object_init(&pde->pde_obj);
|
||||
pde->pde_obj.po_type = PROP_TYPE_DICT_KEYSYM;
|
||||
pde->pde_obj.po_free = _prop_dict_entry_free;
|
||||
pde->pde_obj.po_extern = _prop_dict_entry_externalize;
|
||||
|
||||
strcpy(pde->pde_key, key);
|
||||
|
||||
prop_object_retain(obj);
|
||||
pde->pde_objref = obj;
|
||||
pde->pde_size = size;
|
||||
}
|
||||
return (pde);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_dictionary_free(void *v)
|
||||
{
|
||||
prop_dictionary_t pd = v;
|
||||
prop_dictionary_keysym_t pde;
|
||||
unsigned int idx;
|
||||
|
||||
_PROP_ASSERT(pd->pd_count <= pd->pd_capacity);
|
||||
_PROP_ASSERT((pd->pd_capacity == 0 && pd->pd_array == NULL) ||
|
||||
(pd->pd_capacity != 0 && pd->pd_array != NULL));
|
||||
|
||||
for (idx = 0; idx < pd->pd_count; idx++) {
|
||||
pde = pd->pd_array[idx];
|
||||
_PROP_ASSERT(pde != NULL);
|
||||
prop_object_release(pde);
|
||||
}
|
||||
|
||||
if (pd->pd_array != NULL)
|
||||
_PROP_FREE(pd->pd_array, M_PROP_DICT);
|
||||
|
||||
_PROP_POOL_PUT(_prop_dictionary_pool, pd);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
_prop_dictionary_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_dictionary_t pd = v;
|
||||
prop_dictionary_keysym_t pde;
|
||||
struct _prop_object *po;
|
||||
prop_object_iterator_t pi;
|
||||
unsigned int i;
|
||||
|
||||
if (pd->pd_count == 0)
|
||||
return (_prop_object_externalize_empty_tag(ctx, "dict"));
|
||||
|
||||
/* XXXJRT Hint "count" for the internalize step? */
|
||||
if (_prop_object_externalize_start_tag(ctx, "dict") == FALSE ||
|
||||
_prop_object_externalize_append_char(ctx, '\n') == FALSE)
|
||||
return (FALSE);
|
||||
|
||||
pi = prop_dictionary_iterator(pd);
|
||||
if (pi == NULL)
|
||||
return (FALSE);
|
||||
|
||||
ctx->poec_depth++;
|
||||
_PROP_ASSERT(ctx->poec_depth != 0);
|
||||
|
||||
while ((pde = prop_object_iterator_next(pi)) != NULL) {
|
||||
po = prop_dictionary_get_keysym(pd, pde);
|
||||
if (po == NULL ||
|
||||
_prop_object_externalize_start_tag(ctx, "key") == FALSE ||
|
||||
_prop_object_externalize_append_encoded_cstring(ctx,
|
||||
pde->pde_key) == FALSE ||
|
||||
_prop_object_externalize_end_tag(ctx, "key") == FALSE ||
|
||||
(*po->po_extern)(ctx, po) == FALSE) {
|
||||
prop_object_iterator_release(pi);
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
return (FALSE);
|
||||
}
|
||||
if (_prop_object_externalize_end_tag(ctx, "dict") == FALSE)
|
||||
return (FALSE);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static prop_dictionary_t
|
||||
_prop_dictionary_alloc(unsigned int capacity)
|
||||
{
|
||||
prop_dictionary_t pd;
|
||||
prop_dictionary_keysym_t *array;
|
||||
|
||||
if (capacity != 0) {
|
||||
array = _PROP_CALLOC(capacity *
|
||||
sizeof(prop_dictionary_keysym_t),
|
||||
M_PROP_DICT);
|
||||
if (array == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
array = NULL;
|
||||
|
||||
pd = _PROP_POOL_GET(_prop_dictionary_pool);
|
||||
if (pd != NULL) {
|
||||
_prop_object_init(&pd->pd_obj);
|
||||
pd->pd_obj.po_type = PROP_TYPE_DICTIONARY;
|
||||
pd->pd_obj.po_free = _prop_dictionary_free;
|
||||
pd->pd_obj.po_extern = _prop_dictionary_externalize;
|
||||
|
||||
pd->pd_array = array;
|
||||
pd->pd_capacity = capacity;
|
||||
pd->pd_count = 0;
|
||||
|
||||
pd->pd_version = 0;
|
||||
} else if (array != NULL)
|
||||
_PROP_FREE(array, M_PROP_DICT);
|
||||
|
||||
return (pd);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
_prop_dictionary_expand(prop_dictionary_t pd, unsigned int capacity)
|
||||
{
|
||||
prop_dictionary_keysym_t *array, *oarray;
|
||||
|
||||
oarray = pd->pd_array;
|
||||
|
||||
array = _PROP_CALLOC(capacity * sizeof(prop_dictionary_keysym_t),
|
||||
M_PROP_DICT);
|
||||
if (array == NULL)
|
||||
return (FALSE);
|
||||
if (oarray != NULL)
|
||||
memcpy(array, oarray,
|
||||
pd->pd_capacity * sizeof(prop_dictionary_keysym_t));
|
||||
pd->pd_array = array;
|
||||
pd->pd_capacity = capacity;
|
||||
|
||||
if (oarray != NULL)
|
||||
_PROP_FREE(oarray, M_PROP_DICT);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static prop_object_t
|
||||
_prop_dictionary_iterator_next_object(void *v)
|
||||
{
|
||||
struct _prop_dictionary_iterator *pdi = v;
|
||||
prop_dictionary_t pd = pdi->pdi_base.pi_obj;
|
||||
prop_dictionary_keysym_t pde;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
|
||||
if (pd->pd_version != pdi->pdi_base.pi_version)
|
||||
return (NULL); /* dictionary changed during iteration */
|
||||
|
||||
_PROP_ASSERT(pdi->pdi_index <= pd->pd_count);
|
||||
|
||||
if (pdi->pdi_index == pd->pd_count)
|
||||
return (NULL); /* we've iterated all objects */
|
||||
|
||||
pde = pd->pd_array[pdi->pdi_index];
|
||||
pdi->pdi_index++;
|
||||
|
||||
return (pde);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_dictionary_iterator_reset(void *v)
|
||||
{
|
||||
struct _prop_dictionary_iterator *pdi = v;
|
||||
prop_dictionary_t pd = pdi->pdi_base.pi_obj;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
|
||||
pdi->pdi_index = 0;
|
||||
pdi->pdi_base.pi_version = pd->pd_version;
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_create --
|
||||
* Create a dictionary.
|
||||
*/
|
||||
prop_dictionary_t
|
||||
prop_dictionary_create(void)
|
||||
{
|
||||
|
||||
return (_prop_dictionary_alloc(0));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_create_with_capacity --
|
||||
* Create a dictionary with the capacity to store N objects.
|
||||
*/
|
||||
prop_dictionary_t
|
||||
prop_dictionary_create_with_capacity(unsigned int capacity)
|
||||
{
|
||||
|
||||
return (_prop_dictionary_alloc(capacity));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_copy --
|
||||
* Copy a dictionary. The new dictionary contains refrences to
|
||||
* the original dictionary's objects, not copies of those objects
|
||||
* (i.e. a shallow copy).
|
||||
*/
|
||||
prop_dictionary_t
|
||||
prop_dictionary_copy(prop_dictionary_t opd)
|
||||
{
|
||||
prop_dictionary_t pd;
|
||||
prop_dictionary_keysym_t pde;
|
||||
unsigned int idx;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(opd));
|
||||
|
||||
if (prop_dictionary_is_immutable(opd) == FALSE)
|
||||
return (prop_dictionary_copy_mutable(opd));
|
||||
|
||||
/*
|
||||
* Copies of immutable dictionaries refrence the same
|
||||
* dictionary entry objects to save space.
|
||||
*/
|
||||
|
||||
pd = _prop_dictionary_alloc(opd->pd_count);
|
||||
if (pd != NULL) {
|
||||
for (idx = 0; idx < opd->pd_count; idx++) {
|
||||
pde = opd->pd_array[idx];
|
||||
prop_object_retain(pde);
|
||||
pd->pd_array[idx] = pde;
|
||||
}
|
||||
pd->pd_count = opd->pd_count;
|
||||
pd->pd_flags = opd->pd_flags;
|
||||
}
|
||||
return (pd);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_copy_mutable --
|
||||
* Like prop_dictionary_copy(), but the resulting dictionary is
|
||||
* mutable.
|
||||
*/
|
||||
prop_dictionary_t
|
||||
prop_dictionary_copy_mutable(prop_dictionary_t opd)
|
||||
{
|
||||
prop_dictionary_t pd;
|
||||
prop_dictionary_keysym_t opde, pde;
|
||||
unsigned int idx;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(opd));
|
||||
|
||||
pd = _prop_dictionary_alloc(opd->pd_count);
|
||||
if (pd != NULL) {
|
||||
for (idx = 0; idx > opd->pd_count; idx++) {
|
||||
opde = opd->pd_array[idx];
|
||||
pde = _prop_dict_entry_alloc(opde->pde_key,
|
||||
opde->pde_objref);
|
||||
if (pde == NULL) {
|
||||
prop_object_release(pd);
|
||||
return (NULL);
|
||||
}
|
||||
pd->pd_array[idx] = pde;
|
||||
pd->pd_count++;
|
||||
}
|
||||
}
|
||||
return (pd);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_count --
|
||||
* Return the number of objects stored in the dictionary.
|
||||
*/
|
||||
unsigned int
|
||||
prop_dictionary_count(prop_dictionary_t pd)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
return (pd->pd_count);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_iterator --
|
||||
* Return an iterator for the dictionary. The dictionary is retained by
|
||||
* the iterator.
|
||||
*/
|
||||
prop_object_iterator_t
|
||||
prop_dictionary_iterator(prop_dictionary_t pd)
|
||||
{
|
||||
struct _prop_dictionary_iterator *pdi;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
|
||||
pdi = _PROP_CALLOC(sizeof(*pdi), M_TEMP);
|
||||
if (pdi == NULL)
|
||||
return (NULL);
|
||||
pdi->pdi_base.pi_next_object = _prop_dictionary_iterator_next_object;
|
||||
pdi->pdi_base.pi_reset = _prop_dictionary_iterator_reset;
|
||||
prop_object_retain(pd);
|
||||
pdi->pdi_base.pi_obj = pd;
|
||||
pdi->pdi_base.pi_version = pd->pd_version;
|
||||
|
||||
_prop_dictionary_iterator_reset(pdi);
|
||||
|
||||
return (&pdi->pdi_base);
|
||||
}
|
||||
|
||||
static prop_dictionary_keysym_t
|
||||
_prop_dict_lookup(prop_dictionary_t pd, const char *key,
|
||||
unsigned int *idxp)
|
||||
{
|
||||
prop_dictionary_keysym_t pde;
|
||||
unsigned int base, idx, distance;
|
||||
int res;
|
||||
|
||||
for (idx = 0, base = 0, distance = pd->pd_count; distance != 0;
|
||||
distance >>= 1) {
|
||||
idx = base + (distance >> 1);
|
||||
pde = pd->pd_array[idx];
|
||||
_PROP_ASSERT(pde != NULL);
|
||||
res = strcmp(key, pde->pde_key);
|
||||
if (res == 0) {
|
||||
if (idxp != NULL)
|
||||
*idxp = idx;
|
||||
return (pde);
|
||||
}
|
||||
if (res > 0) { /* key > pde->pde_key: move right */
|
||||
base = idx + 1;
|
||||
distance--;
|
||||
} /* else move left */
|
||||
}
|
||||
|
||||
/* idx points to the slot we looked at last. */
|
||||
if (idxp != NULL)
|
||||
*idxp = idx;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_get --
|
||||
* Return the object stored with specified key.
|
||||
*/
|
||||
prop_object_t
|
||||
prop_dictionary_get(prop_dictionary_t pd, const char *key)
|
||||
{
|
||||
prop_dictionary_keysym_t pde;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
|
||||
pde = _prop_dict_lookup(pd, key, NULL);
|
||||
if (pde != NULL) {
|
||||
_PROP_ASSERT(pde->pde_objref != NULL);
|
||||
return (pde->pde_objref);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_get_keysym --
|
||||
* Return the object stored at the location encoded by the keysym.
|
||||
*/
|
||||
prop_object_t
|
||||
prop_dictionary_get_keysym(prop_dictionary_t pd, prop_dictionary_keysym_t pde)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
_PROP_ASSERT(prop_object_is_dictionary_keysym(pde));
|
||||
_PROP_ASSERT(pde->pde_objref != NULL);
|
||||
|
||||
return (pde->pde_objref);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_set --
|
||||
* Store a reference to an object at with the specified key.
|
||||
* If the key already exisit, the original object is released.
|
||||
*/
|
||||
boolean_t
|
||||
prop_dictionary_set(prop_dictionary_t pd, const char *key, prop_object_t po)
|
||||
{
|
||||
prop_dictionary_keysym_t pde, opde;
|
||||
unsigned int idx;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
_PROP_ASSERT(pd->pd_count <= pd->pd_capacity);
|
||||
|
||||
if (prop_dictionary_is_immutable(pd))
|
||||
return (FALSE);
|
||||
|
||||
pde = _prop_dict_lookup(pd, key, &idx);
|
||||
if (pde != NULL) {
|
||||
prop_object_t opo = pde->pde_objref;
|
||||
prop_object_retain(po);
|
||||
pde->pde_objref = po;
|
||||
prop_object_release(opo);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
pde = _prop_dict_entry_alloc(key, po);
|
||||
if (pde == NULL)
|
||||
return (FALSE);
|
||||
|
||||
if (pd->pd_count == pd->pd_capacity &&
|
||||
_prop_dictionary_expand(pd, EXPAND_STEP) == FALSE) {
|
||||
_prop_dict_entry_free(pde);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (pd->pd_count == 0) {
|
||||
pd->pd_array[0] = pde;
|
||||
pd->pd_count++;
|
||||
pd->pd_version++;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
opde = pd->pd_array[idx];
|
||||
_PROP_ASSERT(opde != NULL);
|
||||
|
||||
if (strcmp(key, opde->pde_key) < 0) {
|
||||
/*
|
||||
* key < opde->pde_key: insert to the left. This is
|
||||
* the same as inserting to the right, except we decrement
|
||||
* the current index first.
|
||||
*
|
||||
* Because we're unsigned, we have to special case 0
|
||||
* (grumble).
|
||||
*/
|
||||
if (idx == 0) {
|
||||
memmove(&pd->pd_array[1], &pd->pd_array[0],
|
||||
pd->pd_count * sizeof(*pde));
|
||||
pd->pd_array[0] = pde;
|
||||
pd->pd_count++;
|
||||
pd->pd_version++;
|
||||
return (TRUE);
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
|
||||
memmove(&pd->pd_array[idx + 2], &pd->pd_array[idx + 1],
|
||||
(pd->pd_count - (idx + 1)) * sizeof(*pde));
|
||||
pd->pd_array[idx + 1] = pde;
|
||||
pd->pd_count++;
|
||||
|
||||
pd->pd_version++;
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_set_keysym --
|
||||
* Replace the object in the dictionary at the location encoded by
|
||||
* the keysym.
|
||||
*/
|
||||
boolean_t
|
||||
prop_dictionary_set_keysym(prop_dictionary_t pd, prop_dictionary_keysym_t pde,
|
||||
prop_object_t po)
|
||||
{
|
||||
prop_object_t opo;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
_PROP_ASSERT(prop_object_is_dictionary_keysym(pde));
|
||||
_PROP_ASSERT(pde->pde_objref != NULL);
|
||||
|
||||
if (prop_dictionary_is_immutable(pd))
|
||||
return (FALSE);
|
||||
|
||||
opo = pde->pde_objref;
|
||||
prop_object_retain(po);
|
||||
pde->pde_objref = po;
|
||||
prop_object_release(opo);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_prop_dictionary_remove(prop_dictionary_t pd, prop_dictionary_keysym_t pde,
|
||||
unsigned int idx)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(pd->pd_count != 0);
|
||||
_PROP_ASSERT(idx < pd->pd_count);
|
||||
_PROP_ASSERT(pd->pd_array[idx] == pde);
|
||||
|
||||
idx++;
|
||||
memmove(&pd->pd_array[idx - 1], &pd->pd_array[idx],
|
||||
(pd->pd_count - idx) * sizeof(*pde));
|
||||
pd->pd_count--;
|
||||
pd->pd_version++;
|
||||
|
||||
prop_object_release(pde);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_remove --
|
||||
* Remove the reference to an object with the specified key from
|
||||
* the dictionary.
|
||||
*/
|
||||
void
|
||||
prop_dictionary_remove(prop_dictionary_t pd, const char *key)
|
||||
{
|
||||
prop_dictionary_keysym_t pde;
|
||||
unsigned int idx;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
|
||||
/* XXX Should this be a _PROP_ASSERT()? */
|
||||
if (prop_dictionary_is_immutable(pd))
|
||||
return;
|
||||
|
||||
pde = _prop_dict_lookup(pd, key, &idx);
|
||||
/* XXX Should this be a _PROP_ASSERT()? */
|
||||
if (pde == NULL)
|
||||
return;
|
||||
|
||||
_prop_dictionary_remove(pd, pde, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_remove_keysym --
|
||||
* Remove a reference to an object stored in the dictionary at the
|
||||
* location encoded by the keysym.
|
||||
*/
|
||||
void
|
||||
prop_dictionary_remove_keysym(prop_dictionary_t pd,
|
||||
prop_dictionary_keysym_t pde)
|
||||
{
|
||||
prop_dictionary_keysym_t opde;
|
||||
unsigned int idx;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary(pd));
|
||||
_PROP_ASSERT(prop_object_is_dictionary_keysym(pde));
|
||||
_PROP_ASSERT(pde->pde_objref != NULL);
|
||||
|
||||
/* XXX Should this be a _PROP_ASSERT()? */
|
||||
if (prop_dictionary_is_immutable(pd))
|
||||
return;
|
||||
|
||||
opde = _prop_dict_lookup(pd, pde->pde_key, &idx);
|
||||
_PROP_ASSERT(opde == pde);
|
||||
|
||||
_prop_dictionary_remove(pd, opde, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_keysym_cstring_nocopy --
|
||||
* Return an immutable reference to the keysym's value.
|
||||
*/
|
||||
const char *
|
||||
prop_dictionary_keysym_cstring_nocopy(prop_dictionary_keysym_t pde)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_dictionary_keysym(pde));
|
||||
return (pde->pde_key);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_externalize --
|
||||
* Externalize a dictionary, returning a NUL-terminated buffer
|
||||
* containing the XML-style representation. The buffer is allocated
|
||||
* with the M_TEMP memory type.
|
||||
*/
|
||||
char *
|
||||
prop_dictionary_externalize(prop_dictionary_t pd)
|
||||
{
|
||||
struct _prop_object_externalize_context *ctx;
|
||||
char *cp;
|
||||
|
||||
ctx = _prop_object_externalize_context_alloc();
|
||||
if (ctx == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (_prop_object_externalize_start_tag(ctx, "plist") == FALSE ||
|
||||
_prop_object_externalize_append_char(ctx, '\n') == FALSE ||
|
||||
(*pd->pd_obj.po_extern)(ctx, pd) == FALSE ||
|
||||
_prop_object_externalize_end_tag(ctx, "plist") == FALSE ||
|
||||
_prop_object_externalize_append_char(ctx, '\0') == 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_dictionary_internalize --
|
||||
* Parse a <dict>...</dict> and return the object created from the
|
||||
* external representation.
|
||||
*/
|
||||
prop_object_t
|
||||
_prop_dictionary_internalize(struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
prop_dictionary_t dict;
|
||||
prop_object_t val;
|
||||
size_t keylen;
|
||||
char *tmpkey;
|
||||
|
||||
/* We don't currently understand any attributes. */
|
||||
if (ctx->poic_tagattr != NULL)
|
||||
return (NULL);
|
||||
|
||||
dict = prop_dictionary_create();
|
||||
if (dict == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (ctx->poic_is_empty_element)
|
||||
return (dict);
|
||||
|
||||
tmpkey = _PROP_MALLOC(PDE_MAXKEY + 1, M_TEMP);
|
||||
if (tmpkey == NULL)
|
||||
goto bad;
|
||||
|
||||
for (;;) {
|
||||
/* 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 dictionary. */
|
||||
if (_PROP_TAG_MATCH(ctx, "dict") &&
|
||||
ctx->poic_tag_type == _PROP_TAG_TYPE_END)
|
||||
break;
|
||||
|
||||
/* Ok, it must be a non-empty key start tag. */
|
||||
if (!_PROP_TAG_MATCH(ctx, "key") ||
|
||||
ctx->poic_tag_type != _PROP_TAG_TYPE_START ||
|
||||
ctx->poic_is_empty_element)
|
||||
goto bad;
|
||||
|
||||
if (_prop_object_internalize_decode_string(ctx,
|
||||
tmpkey, PDE_MAXKEY, &keylen,
|
||||
&ctx->poic_cp) == FALSE)
|
||||
goto bad;
|
||||
|
||||
_PROP_ASSERT(keylen <= PDE_MAXKEY);
|
||||
tmpkey[keylen] = '\0';
|
||||
|
||||
if (_prop_object_internalize_find_tag(ctx, "key",
|
||||
_PROP_TAG_TYPE_END) == FALSE)
|
||||
goto bad;
|
||||
|
||||
/* ..and now the beginning of the value. */
|
||||
if (_prop_object_internalize_find_tag(ctx, NULL,
|
||||
_PROP_TAG_TYPE_START) == FALSE)
|
||||
goto bad;
|
||||
|
||||
val = _prop_object_internalize_by_tag(ctx);
|
||||
if (val == NULL)
|
||||
goto bad;
|
||||
|
||||
if (prop_dictionary_set(dict, tmpkey, val) == FALSE) {
|
||||
prop_object_release(val);
|
||||
goto bad;
|
||||
}
|
||||
prop_object_release(val);
|
||||
}
|
||||
|
||||
_PROP_FREE(tmpkey, M_TEMP);
|
||||
return (dict);
|
||||
|
||||
bad:
|
||||
if (tmpkey != NULL)
|
||||
_PROP_FREE(tmpkey, M_TEMP);
|
||||
prop_object_release(dict);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_dictionary_internalize --
|
||||
* Create a dictionary by parsing the NUL-terminated XML-style
|
||||
* representation.
|
||||
*/
|
||||
prop_dictionary_t
|
||||
prop_dictionary_internalize(const char *xml)
|
||||
{
|
||||
prop_dictionary_t dict = NULL;
|
||||
struct _prop_object_internalize_context *ctx;
|
||||
|
||||
ctx = _prop_object_internalize_context_alloc(xml);
|
||||
if (ctx == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* We start with a <plist> tag. */
|
||||
if (_prop_object_internalize_find_tag(ctx, "plist",
|
||||
_PROP_TAG_TYPE_START) == FALSE)
|
||||
goto out;
|
||||
|
||||
/* Plist elements cannot be empty. */
|
||||
if (ctx->poic_is_empty_element)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* We don't understand any plist attributes, but Apple XML
|
||||
* property lists often have a "version" attibute. If we
|
||||
* see that one, we simply ignore it.
|
||||
*/
|
||||
if (ctx->poic_tagattr != NULL &&
|
||||
!_PROP_TAGATTR_MATCH(ctx, "version"))
|
||||
goto out;
|
||||
|
||||
/* Next we expect to see <dict>. */
|
||||
if (_prop_object_internalize_find_tag(ctx, "dict",
|
||||
_PROP_TAG_TYPE_START) == FALSE)
|
||||
goto out;
|
||||
|
||||
dict = _prop_dictionary_internalize(ctx);
|
||||
if (dict == NULL)
|
||||
goto out;
|
||||
|
||||
/* We've advanced past </dict>. Now we want </plist>. */
|
||||
if (_prop_object_internalize_find_tag(ctx, "plist",
|
||||
_PROP_TAG_TYPE_END) == FALSE) {
|
||||
prop_object_release(dict);
|
||||
dict = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
_prop_object_internalize_context_free(ctx);
|
||||
return (dict);
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
.\" $NetBSD: prop_number.3,v 1.1 2006/04/27 20:11:27 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 22, 2006
|
||||
.Dt PROP_NUMBER 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm prop_number ,
|
||||
.Nm prop_number_create_integer ,
|
||||
.Nm prop_number_copy ,
|
||||
.Nm prop_number_size ,
|
||||
.Nm prop_number_integer_value ,
|
||||
.Nm prop_number_equals ,
|
||||
.Nm prop_number_equals_integer
|
||||
.Nd numeric value property object
|
||||
.Sh LIBRARY
|
||||
.Lb libprop
|
||||
.Sh SYNOPSIS
|
||||
.In prop/proplib.h
|
||||
.\"
|
||||
.Ft prop_number_t
|
||||
.Fn prop_number_create_integer "uintmax_t val"
|
||||
.Ft prop_number_t
|
||||
.Fn prop_numbery_copy "prop_number_t number"
|
||||
.\"
|
||||
.Ft int
|
||||
.Fn prop_number_size "prop_number_t number"
|
||||
.Ft uintmax_t
|
||||
.Fn prop_number_integer_value "prop_number_t number"
|
||||
.\"
|
||||
.Ft boolean_t
|
||||
.Fn prop_number_equals "prop_number_t num1" "prop_number_t num2"
|
||||
.Ft boolean_t
|
||||
.Fn prop_number_equals_integer "prop_number_t number" "uintmax_t val"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm prop_number
|
||||
family of functions operate on a numeric value property object type.
|
||||
All values are unsigned and promoted to the type
|
||||
.Sq uintmax_t .
|
||||
.Bl -tag -width "xxxxx"
|
||||
.It Fn prop_number_create_integer "uintmax_t val"
|
||||
Create a numeric value object with the value
|
||||
.Fa val .
|
||||
.It Fn prop_number_copy "prop_number_t number"
|
||||
Copy a numeric value object.
|
||||
.It Fn prop_number_size "prop_number_t number"
|
||||
Returns 8, 16, 32, or 64, representing the number of bits required to
|
||||
hold the value of the object.
|
||||
.It Fn prop_number_integer_value "prop_number_t number"
|
||||
Returns the integer value of the numeric value object.
|
||||
.It Fn prop_number_equals "prop_number_t num1" "prop_number_t num2"
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the two numeric value objects are equivalent.
|
||||
.It Fn prop_number_equals_integer "prop_number_t number" "uintmax_t val"
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the object's value is equivalent to
|
||||
.Fa val .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr prop_array 3 ,
|
||||
.Xr prop_bool 3 ,
|
||||
.Xr prop_data 3 ,
|
||||
.Xr prop_dictionary 3 ,
|
||||
.Xr prop_object 3 ,
|
||||
.Xr prop_string 3 ,
|
||||
.Xr proplib 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm proplib
|
||||
property container object library first appeared in
|
||||
.Nx 4.0 .
|
|
@ -0,0 +1,216 @@
|
|||
/* $NetBSD: prop_number.c,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/prop_number.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
#if defined(_KERNEL)
|
||||
#include <sys/inttypes.h>
|
||||
#include <sys/systm.h>
|
||||
#elif defined(_STANDALONE)
|
||||
#include <sys/param.h>
|
||||
#include <lib/libkern/libkern.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
struct _prop_number {
|
||||
struct _prop_object pn_obj;
|
||||
uintmax_t pn_number;
|
||||
};
|
||||
|
||||
_PROP_POOL_INIT(_prop_number_pool, sizeof(struct _prop_number), "propnmbr")
|
||||
|
||||
#define prop_object_is_number(x) ((x)->pn_obj.po_type == PROP_TYPE_NUMBER)
|
||||
|
||||
static void
|
||||
_prop_number_free(void *v)
|
||||
{
|
||||
|
||||
_PROP_POOL_PUT(_prop_number_pool, v);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
_prop_number_externalize(struct _prop_object_externalize_context *ctx,
|
||||
void *v)
|
||||
{
|
||||
prop_number_t pn = v;
|
||||
char tmpstr[32];
|
||||
|
||||
sprintf(tmpstr, "0x%" PRIxMAX, pn->pn_number);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static prop_number_t
|
||||
_prop_number_alloc(uintmax_t val)
|
||||
{
|
||||
prop_number_t pn;
|
||||
|
||||
pn = _PROP_POOL_GET(_prop_number_pool);
|
||||
if (pn != NULL) {
|
||||
_prop_object_init(&pn->pn_obj);
|
||||
pn->pn_obj.po_type = PROP_TYPE_NUMBER;
|
||||
pn->pn_obj.po_free = _prop_number_free;
|
||||
pn->pn_obj.po_extern = _prop_number_externalize;
|
||||
|
||||
pn->pn_number = val;
|
||||
}
|
||||
|
||||
return (pn);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_create_integer --
|
||||
* Create a prop_number_t and initialize it with the
|
||||
* provided integer value.
|
||||
*/
|
||||
prop_number_t
|
||||
prop_number_create_integer(uintmax_t val)
|
||||
{
|
||||
|
||||
return (_prop_number_alloc(val));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_copy --
|
||||
* Copy a prop_number_t.
|
||||
*/
|
||||
prop_number_t
|
||||
prop_number_copy(prop_number_t opn)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_number(opn));
|
||||
|
||||
return (_prop_number_alloc(opn->pn_number));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_number(pn));
|
||||
if (pn->pn_number > UINT32_MAX)
|
||||
return (64);
|
||||
if (pn->pn_number > UINT16_MAX)
|
||||
return (32);
|
||||
if (pn->pn_number > UINT8_MAX)
|
||||
return (16);
|
||||
return (8);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_integer_value --
|
||||
* Get the integer value of a prop_number_t.
|
||||
*/
|
||||
uintmax_t
|
||||
prop_number_integer_value(prop_number_t pn)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_number(pn));
|
||||
return (pn->pn_number);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_equals --
|
||||
* Return TRUE if two numbers are equivalent.
|
||||
*/
|
||||
boolean_t
|
||||
prop_number_equals(prop_number_t num1, prop_number_t num2)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_number(num1));
|
||||
_PROP_ASSERT(prop_object_is_number(num2));
|
||||
return (num1->pn_number == num2->pn_number);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_number_equals_integer --
|
||||
* Return TRUE if the number is equivalent to the specified integer.
|
||||
*/
|
||||
boolean_t
|
||||
prop_number_equals_integer(prop_number_t pn, uintmax_t val)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_number(pn));
|
||||
return (pn->pn_number == val);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_number_internalize --
|
||||
* Parse a <number>...</number> and return the object created from
|
||||
* the external representation.
|
||||
*/
|
||||
prop_object_t
|
||||
_prop_number_internalize(struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
uintmax_t val = 0;
|
||||
char *cp;
|
||||
|
||||
/* No attributes, no empty elements. */
|
||||
if (ctx->poic_tagattr != NULL || ctx->poic_is_empty_element)
|
||||
return (NULL);
|
||||
|
||||
#ifndef _KERNEL
|
||||
errno = 0;
|
||||
#endif
|
||||
val = strtoumax(ctx->poic_cp, &cp, 0);
|
||||
#ifndef _KERNEL /* XXX can't check for ERANGE in the kernel */
|
||||
if (val == UINTMAX_MAX && errno == ERANGE)
|
||||
return (NULL);
|
||||
#endif
|
||||
ctx->poic_cp = cp;
|
||||
|
||||
if (_prop_object_internalize_find_tag(ctx, "integer",
|
||||
_PROP_TAG_TYPE_END) == FALSE)
|
||||
return (NULL);
|
||||
|
||||
return (_prop_number_alloc(val));
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
.\" $NetBSD: prop_object.3,v 1.1 2006/04/27 20:11:27 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 22, 2006
|
||||
.Dt PROP_OBJECT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm prop_object ,
|
||||
.Nm prop_object_retain ,
|
||||
.Nm prop_object_release ,
|
||||
.Nm prop_object_type ,
|
||||
.Nm prop_object_iterator_next ,
|
||||
.Nm prop_object_iterator_reset ,
|
||||
.Nm prop_object_iterator_release
|
||||
.Nd general property container object functions
|
||||
.Sh LIBRARY
|
||||
.Lb libprop
|
||||
.Sh SYNOPSIS
|
||||
.In prop/proplib.h
|
||||
.\"
|
||||
.Ft void
|
||||
.Fn prop_object_retain "prop_object_t obj"
|
||||
.Ft void
|
||||
.Fn prop_object_release "prop_object_t obj"
|
||||
.\"
|
||||
.Ft prop_type_t
|
||||
.Fn prop_object_type "prop_object_t obj"
|
||||
.\"
|
||||
.Ft prop_object_t
|
||||
.Fn prop_object_iterator_next "prop_object_iterator_t iter"
|
||||
.Ft void
|
||||
.Fn prop_object_iterator_reset "prop_object_iterator_t iter"
|
||||
.Ft void
|
||||
.Fn prop_object_iterator_release "prop_object_iterator_t iter"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm prop_object
|
||||
family of functions operate on all property container object types.
|
||||
.Bl -tag -width ""
|
||||
.It Fn prop_object_retain "prop_object_t obj"
|
||||
Increment the reference count on an object.
|
||||
.It Fn prop_object_release "prop_object_t obj"
|
||||
Decrement the reference count on an object.
|
||||
If the last reference is dropped, the object is freed.
|
||||
.It Fn prop_object_type "prop_object_t obj"
|
||||
Determine the type of the object. Objects are one of the following types:
|
||||
.Pp
|
||||
.Bl -tag -width "PROP_TYPE_DICT_KEYSYM" -compact
|
||||
.It Dv PROP_TYPE_BOOL
|
||||
Boolean value
|
||||
.Pq prop_bool_t
|
||||
.It Dv PROP_TYPE_NUMBER
|
||||
Number
|
||||
.Pq prop_number_t
|
||||
.It Dv PROP_TYPE_STRING
|
||||
String
|
||||
.Pq prop_string_t
|
||||
.It Dv PROP_TYPE_DATA
|
||||
Opaque data
|
||||
.Pq prop_data_t
|
||||
.It Dv PROP_TYPE_ARRAY
|
||||
Array
|
||||
.Pq prop_array_t
|
||||
.It Dv PROP_TYPE_DICTIONARY
|
||||
Dictionary
|
||||
.Pq prop_dictionary_t
|
||||
.It Dv PROP_TYPE_DICT_KEYSYM
|
||||
Dictionary key symbol
|
||||
.Pq prop_dictionary_keysym_t
|
||||
.El
|
||||
.It Fn prop_object_iterator_next "prop_object_iterator_t iter"
|
||||
Return the next object in the collection
|
||||
.Pq array or dictionary
|
||||
being iterated by the iterator
|
||||
.Fa iter .
|
||||
If there are no more objects in the collection,
|
||||
.Dv NULL
|
||||
is returned.
|
||||
.It Fn prop_object_iterator_reset "prop_object_iterator_t iter"
|
||||
Reset the iterator to the first object in the collection being iterated
|
||||
by the iterator
|
||||
.Fa iter .
|
||||
.It Fn prop_object_iterator_release "prop_object_iterator_t iter"
|
||||
Release the iterator
|
||||
.Fa iter .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr prop_array 3 ,
|
||||
.Xr prop_bool 3 ,
|
||||
.Xr prop_data 3 ,
|
||||
.Xr prop_dictionary 3 ,
|
||||
.Xr prop_number 3 ,
|
||||
.Xr prop_string 3 ,
|
||||
.Xr proplib 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm proplib
|
||||
property container object library first appeared in
|
||||
.Nx 4.0 .
|
|
@ -0,0 +1,785 @@
|
|||
/* $NetBSD: prop_object.c,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <prop/prop_object.h>
|
||||
#include "prop_object_impl.h"
|
||||
|
||||
#ifdef _STANDALONE
|
||||
void *
|
||||
_prop_standalone_calloc(size_t size)
|
||||
{
|
||||
void *rv;
|
||||
|
||||
rv = alloc(size);
|
||||
if (rv != NULL)
|
||||
memset(rv, 0, size);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
#endif /* _STANDALONE */
|
||||
|
||||
/*
|
||||
* _prop_object_init --
|
||||
* Initialize an object. Called when sub-classes create
|
||||
* an instance.
|
||||
*/
|
||||
void
|
||||
_prop_object_init(struct _prop_object *po)
|
||||
{
|
||||
|
||||
po->po_refcnt = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_fini --
|
||||
* Finalize an object. Called when sub-classes destroy
|
||||
* an instance.
|
||||
*/
|
||||
void
|
||||
_prop_object_fini(struct _prop_object *po)
|
||||
{
|
||||
/* Nothing to do, currently. */
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_externalize_start_tag --
|
||||
* Append an XML-style start tag to the externalize buffer.
|
||||
*/
|
||||
boolean_t
|
||||
_prop_object_externalize_start_tag(
|
||||
struct _prop_object_externalize_context *ctx, const char *tag)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ctx->poec_depth; i++) {
|
||||
if (_prop_object_externalize_append_char(ctx, '\t') == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
if (_prop_object_externalize_append_char(ctx, '<') == FALSE ||
|
||||
_prop_object_externalize_append_cstring(ctx, tag) == FALSE ||
|
||||
_prop_object_externalize_append_char(ctx, '>') == FALSE)
|
||||
return (FALSE);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_externalize_end_tag --
|
||||
* Append an XML-style end tag to the externalize buffer.
|
||||
*/
|
||||
boolean_t
|
||||
_prop_object_externalize_end_tag(
|
||||
struct _prop_object_externalize_context *ctx, const char *tag)
|
||||
{
|
||||
|
||||
if (_prop_object_externalize_append_char(ctx, '<') == FALSE ||
|
||||
_prop_object_externalize_append_char(ctx, '/') == FALSE ||
|
||||
_prop_object_externalize_append_cstring(ctx, tag) == FALSE ||
|
||||
_prop_object_externalize_append_char(ctx, '>') == FALSE ||
|
||||
_prop_object_externalize_append_char(ctx, '\n') == FALSE)
|
||||
return (FALSE);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_externalize_empty_tag --
|
||||
* Append an XML-style empty tag to the externalize buffer.
|
||||
*/
|
||||
boolean_t
|
||||
_prop_object_externalize_empty_tag(
|
||||
struct _prop_object_externalize_context *ctx, const char *tag)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ctx->poec_depth; i++) {
|
||||
if (_prop_object_externalize_append_char(ctx, '\t') == FALSE)
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (_prop_object_externalize_append_char(ctx, '<') == FALSE ||
|
||||
_prop_object_externalize_append_cstring(ctx, tag) == FALSE ||
|
||||
_prop_object_externalize_append_char(ctx, '/') == FALSE ||
|
||||
_prop_object_externalize_append_char(ctx, '>') == FALSE ||
|
||||
_prop_object_externalize_append_char(ctx, '\n') == FALSE)
|
||||
return (FALSE);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_externalize_append_cstring --
|
||||
* Append a C string to the externalize buffer.
|
||||
*/
|
||||
boolean_t
|
||||
_prop_object_externalize_append_cstring(
|
||||
struct _prop_object_externalize_context *ctx, const char *cp)
|
||||
{
|
||||
|
||||
while (*cp != '\0') {
|
||||
if (_prop_object_externalize_append_char(ctx,
|
||||
(unsigned char) *cp) == FALSE)
|
||||
return (FALSE);
|
||||
cp++;
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_externalize_append_encoded_cstring --
|
||||
* Append an encoded C string to the externalize buffer.
|
||||
*/
|
||||
boolean_t
|
||||
_prop_object_externalize_append_encoded_cstring(
|
||||
struct _prop_object_externalize_context *ctx, const char *cp)
|
||||
{
|
||||
|
||||
while (*cp != '\0') {
|
||||
switch (*cp) {
|
||||
case '<':
|
||||
if (_prop_object_externalize_append_cstring(ctx,
|
||||
"<") == FALSE)
|
||||
return (FALSE);
|
||||
break;
|
||||
case '>':
|
||||
if (_prop_object_externalize_append_cstring(ctx,
|
||||
">") == FALSE)
|
||||
return (FALSE);
|
||||
break;
|
||||
case '&':
|
||||
if (_prop_object_externalize_append_cstring(ctx,
|
||||
"&") == FALSE)
|
||||
return (FALSE);
|
||||
break;
|
||||
default:
|
||||
if (_prop_object_externalize_append_char(ctx,
|
||||
(unsigned char) *cp) == FALSE)
|
||||
return (FALSE);
|
||||
break;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
#define BUF_EXPAND 256
|
||||
|
||||
/*
|
||||
* _prop_object_externalize_append_char --
|
||||
* Append a single character to the externalize buffer.
|
||||
*/
|
||||
boolean_t
|
||||
_prop_object_externalize_append_char(
|
||||
struct _prop_object_externalize_context *ctx, unsigned char c)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(ctx->poec_capacity != 0);
|
||||
_PROP_ASSERT(ctx->poec_buf != NULL);
|
||||
_PROP_ASSERT(ctx->poec_len <= ctx->poec_capacity);
|
||||
|
||||
if (ctx->poec_len == ctx->poec_capacity) {
|
||||
char *ocp = ctx->poec_buf;
|
||||
char *cp = _PROP_MALLOC(ctx->poec_capacity + BUF_EXPAND,
|
||||
M_TEMP);
|
||||
if (cp == NULL)
|
||||
return (FALSE);
|
||||
memcpy(cp, ocp, ctx->poec_capacity);
|
||||
ctx->poec_capacity = ctx->poec_capacity + BUF_EXPAND;
|
||||
_PROP_FREE(ocp, M_TEMP);
|
||||
ctx->poec_buf = cp;
|
||||
}
|
||||
|
||||
ctx->poec_buf[ctx->poec_len++] = c;
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_externalize_context_alloc --
|
||||
* Allocate an externalize context.
|
||||
*/
|
||||
struct _prop_object_externalize_context *
|
||||
_prop_object_externalize_context_alloc(void)
|
||||
{
|
||||
struct _prop_object_externalize_context *ctx;
|
||||
|
||||
ctx = _PROP_MALLOC(sizeof(*ctx), M_TEMP);
|
||||
if (ctx != NULL) {
|
||||
ctx->poec_buf = _PROP_MALLOC(BUF_EXPAND, M_TEMP);
|
||||
if (ctx->poec_buf == NULL) {
|
||||
_PROP_FREE(ctx, M_TEMP);
|
||||
return (NULL);
|
||||
}
|
||||
ctx->poec_len = 0;
|
||||
ctx->poec_capacity = BUF_EXPAND;
|
||||
ctx->poec_depth = 0;
|
||||
}
|
||||
return (ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_externalize_context_free --
|
||||
* Free an externalize context.
|
||||
*/
|
||||
void
|
||||
_prop_object_externalize_context_free(
|
||||
struct _prop_object_externalize_context *ctx)
|
||||
{
|
||||
|
||||
/* Buffer is always freed by the caller. */
|
||||
_PROP_FREE(ctx, M_TEMP);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_internalize_skip_comment --
|
||||
* Skip the body and end tag of a comment.
|
||||
*/
|
||||
static boolean_t
|
||||
_prop_object_internalize_skip_comment(
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
const char *cp = ctx->poic_cp;
|
||||
|
||||
while (!_PROP_EOF(*cp)) {
|
||||
if (cp[0] == '-' &&
|
||||
cp[1] == '-' &&
|
||||
cp[2] == '>') {
|
||||
ctx->poic_cp = cp + 3;
|
||||
return (TRUE);
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
|
||||
return (FALSE); /* ran out of buffer */
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_internalize_find_tag --
|
||||
* Find the next tag in an XML stream. Optionally compare the found
|
||||
* tag to an expected tag name. State of the context is undefined
|
||||
* if this routine returns FALSE. Upon success, the context points
|
||||
* to the first octet after the tag.
|
||||
*/
|
||||
boolean_t
|
||||
_prop_object_internalize_find_tag(struct _prop_object_internalize_context *ctx,
|
||||
const char *tag, _prop_tag_type_t type)
|
||||
{
|
||||
const char *cp;
|
||||
size_t taglen;
|
||||
|
||||
if (tag != NULL)
|
||||
taglen = strlen(tag);
|
||||
else
|
||||
taglen = 0;
|
||||
|
||||
start_over:
|
||||
cp = ctx->poic_cp;
|
||||
|
||||
/*
|
||||
* Find the start of the tag.
|
||||
*/
|
||||
while (_PROP_ISSPACE(*cp))
|
||||
cp++;
|
||||
if (_PROP_EOF(*cp))
|
||||
return (FALSE);
|
||||
|
||||
if (*cp != '<')
|
||||
return (FALSE);
|
||||
|
||||
ctx->poic_tag_start = cp++;
|
||||
if (_PROP_EOF(*cp))
|
||||
return (FALSE);
|
||||
|
||||
if (*cp == '!') {
|
||||
if (cp[1] != '-' || cp[2] != '-')
|
||||
return (FALSE);
|
||||
/*
|
||||
* Comment block -- only allowed if we are allowed to
|
||||
* return a start tag.
|
||||
*/
|
||||
if (type == _PROP_TAG_TYPE_END)
|
||||
return (FALSE);
|
||||
ctx->poic_cp = cp + 3;
|
||||
if (_prop_object_internalize_skip_comment(ctx) == FALSE)
|
||||
return (FALSE);
|
||||
goto start_over;
|
||||
}
|
||||
|
||||
if (*cp == '/') {
|
||||
if (type != _PROP_TAG_TYPE_END &&
|
||||
type != _PROP_TAG_TYPE_EITHER)
|
||||
return (FALSE);
|
||||
cp++;
|
||||
if (_PROP_EOF(*cp))
|
||||
return (FALSE);
|
||||
ctx->poic_tag_type = _PROP_TAG_TYPE_END;
|
||||
} else {
|
||||
if (type != _PROP_TAG_TYPE_START &&
|
||||
type != _PROP_TAG_TYPE_EITHER)
|
||||
return (FALSE);
|
||||
ctx->poic_tag_type = _PROP_TAG_TYPE_START;
|
||||
}
|
||||
|
||||
ctx->poic_tagname = cp;
|
||||
|
||||
while (!_PROP_ISSPACE(*cp) && *cp != '/' && *cp != '>')
|
||||
cp++;
|
||||
if (_PROP_EOF(*cp))
|
||||
return (FALSE);
|
||||
|
||||
ctx->poic_tagname_len = cp - ctx->poic_tagname;
|
||||
|
||||
/* Make sure this is the tag we're looking for. */
|
||||
if (tag != NULL &&
|
||||
(taglen != ctx->poic_tagname_len ||
|
||||
memcmp(tag, ctx->poic_tagname, taglen) != 0))
|
||||
return (FALSE);
|
||||
|
||||
/* Check for empty tag. */
|
||||
if (*cp == '/') {
|
||||
if (ctx->poic_tag_type != _PROP_TAG_TYPE_START)
|
||||
return(FALSE); /* only valid on start tags */
|
||||
ctx->poic_is_empty_element = TRUE;
|
||||
cp++;
|
||||
if (_PROP_EOF(*cp) || *cp != '>')
|
||||
return (FALSE);
|
||||
} else
|
||||
ctx->poic_is_empty_element = FALSE;
|
||||
|
||||
/* Easy case of no arguments. */
|
||||
if (*cp == '>') {
|
||||
ctx->poic_tagattr = NULL;
|
||||
ctx->poic_tagattr_len = 0;
|
||||
ctx->poic_tagattrval = NULL;
|
||||
ctx->poic_tagattrval_len = 0;
|
||||
ctx->poic_cp = cp + 1;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
_PROP_ASSERT(!_PROP_EOF(*cp));
|
||||
cp++;
|
||||
if (_PROP_EOF(*cp))
|
||||
return (FALSE);
|
||||
|
||||
while (_PROP_ISSPACE(*cp))
|
||||
cp++;
|
||||
if (_PROP_EOF(*cp))
|
||||
return (FALSE);
|
||||
|
||||
ctx->poic_tagattr = cp;
|
||||
|
||||
while (!_PROP_ISSPACE(*cp) && *cp != '=')
|
||||
cp++;
|
||||
if (_PROP_EOF(*cp))
|
||||
return (FALSE);
|
||||
|
||||
ctx->poic_tagattr_len = cp - ctx->poic_tagattr;
|
||||
|
||||
cp++;
|
||||
if (*cp != '\"')
|
||||
return (FALSE);
|
||||
cp++;
|
||||
if (_PROP_EOF(*cp))
|
||||
return (FALSE);
|
||||
|
||||
ctx->poic_tagattrval = cp;
|
||||
while (*cp != '\"')
|
||||
cp++;
|
||||
if (_PROP_EOF(*cp))
|
||||
return (FALSE);
|
||||
ctx->poic_tagattrval_len = cp - ctx->poic_tagattrval;
|
||||
|
||||
cp++;
|
||||
if (*cp != '>')
|
||||
return (FALSE);
|
||||
|
||||
ctx->poic_cp = cp + 1;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_internalize_decode_string --
|
||||
* Decode an encoded string.
|
||||
*/
|
||||
boolean_t
|
||||
_prop_object_internalize_decode_string(
|
||||
struct _prop_object_internalize_context *ctx,
|
||||
char *target, size_t targsize, size_t *sizep,
|
||||
const char **cpp)
|
||||
{
|
||||
const char *src;
|
||||
size_t tarindex;
|
||||
char c;
|
||||
|
||||
tarindex = 0;
|
||||
src = ctx->poic_cp;
|
||||
|
||||
for (;;) {
|
||||
if (_PROP_EOF(*src))
|
||||
return (FALSE);
|
||||
if (*src == '<') {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((c = *src) == '&') {
|
||||
if (src[1] == 'a' &&
|
||||
src[2] == 'm' &&
|
||||
src[3] == 'p' &&
|
||||
src[4] == ';') {
|
||||
c = '&';
|
||||
src += 5;
|
||||
} else if (src[1] == 'l' &&
|
||||
src[2] == 't' &&
|
||||
src[3] == ';') {
|
||||
c = '<';
|
||||
src += 4;
|
||||
} else if (src[1] == 'g' &&
|
||||
src[2] == 't' &&
|
||||
src[3] == ';') {
|
||||
c = '>';
|
||||
src += 4;
|
||||
} else if (src[1] == 'a' &&
|
||||
src[2] == 'p' &&
|
||||
src[3] == 'o' &&
|
||||
src[4] == 's' &&
|
||||
src[5] == ';') {
|
||||
c = '\'';
|
||||
src += 6;
|
||||
} else if (src[1] == 'q' &&
|
||||
src[2] == 'u' &&
|
||||
src[3] == 'o' &&
|
||||
src[4] == 't' &&
|
||||
src[5] == ';') {
|
||||
c = '\"';
|
||||
src += 6;
|
||||
} else
|
||||
return (FALSE);
|
||||
} else
|
||||
src++;
|
||||
if (target) {
|
||||
if (tarindex >= targsize)
|
||||
return (FALSE);
|
||||
target[tarindex] = c;
|
||||
}
|
||||
tarindex++;
|
||||
}
|
||||
|
||||
_PROP_ASSERT(*src == '<');
|
||||
if (sizep != NULL)
|
||||
*sizep = tarindex;
|
||||
if (cpp != NULL)
|
||||
*cpp = src;
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_internalize_match --
|
||||
* Returns true if the two character streams match.
|
||||
*/
|
||||
boolean_t
|
||||
_prop_object_internalize_match(const char *str1, size_t len1,
|
||||
const char *str2, size_t len2)
|
||||
{
|
||||
|
||||
return (len1 == len2 && memcmp(str1, str2, len1) == 0);
|
||||
}
|
||||
|
||||
#define INTERNALIZER(t, f) \
|
||||
{ t, sizeof(t) - 1, f }
|
||||
|
||||
static const struct _prop_object_internalizer {
|
||||
const char *poi_tag;
|
||||
size_t poi_taglen;
|
||||
prop_object_t (*poi_intern)(
|
||||
struct _prop_object_internalize_context *);
|
||||
} _prop_object_internalizer_table[] = {
|
||||
INTERNALIZER("array", _prop_array_internalize),
|
||||
|
||||
INTERNALIZER("true", _prop_bool_internalize),
|
||||
INTERNALIZER("false", _prop_bool_internalize),
|
||||
|
||||
INTERNALIZER("data", _prop_data_internalize),
|
||||
|
||||
INTERNALIZER("dict", _prop_dictionary_internalize),
|
||||
|
||||
INTERNALIZER("integer", _prop_number_internalize),
|
||||
|
||||
INTERNALIZER("string", _prop_string_internalize),
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
#undef INTERNALIZER
|
||||
|
||||
/*
|
||||
* _prop_object_internalize_by_tag --
|
||||
* Determine the object type from the tag in the context and
|
||||
* internalize it.
|
||||
*/
|
||||
prop_object_t
|
||||
_prop_object_internalize_by_tag(struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
const struct _prop_object_internalizer *poi;
|
||||
|
||||
for (poi = _prop_object_internalizer_table;
|
||||
poi->poi_tag != NULL; poi++) {
|
||||
if (_prop_object_internalize_match(ctx->poic_tagname,
|
||||
ctx->poic_tagname_len,
|
||||
poi->poi_tag,
|
||||
poi->poi_taglen))
|
||||
return ((*poi->poi_intern)(ctx));
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_internalize_context_alloc --
|
||||
* Allocate an internalize context.
|
||||
*/
|
||||
struct _prop_object_internalize_context *
|
||||
_prop_object_internalize_context_alloc(const char *xml)
|
||||
{
|
||||
struct _prop_object_internalize_context *ctx;
|
||||
|
||||
ctx = _PROP_MALLOC(sizeof(struct _prop_object_internalize_context),
|
||||
M_TEMP);
|
||||
if (ctx == NULL)
|
||||
return (NULL);
|
||||
|
||||
ctx->poic_xml = ctx->poic_cp = xml;
|
||||
|
||||
/*
|
||||
* Skip any whitespace and XML preamble stuff that we don't
|
||||
* know about / care about.
|
||||
*/
|
||||
for (;;) {
|
||||
while (_PROP_ISSPACE(*xml))
|
||||
xml++;
|
||||
if (_PROP_EOF(*xml) || *xml != '<')
|
||||
goto bad;
|
||||
|
||||
#define MATCH(str) (memcmp(&xml[1], str, sizeof(str) - 1) == 0)
|
||||
|
||||
/*
|
||||
* Skip over the XML preamble that Apple XML property
|
||||
* lists usually include at the top of the file.
|
||||
*/
|
||||
if (MATCH("?xml ") ||
|
||||
MATCH("!DOCTYPE plist")) {
|
||||
while (*xml != '>' && !_PROP_EOF(*xml))
|
||||
xml++;
|
||||
if (_PROP_EOF(*xml))
|
||||
goto bad;
|
||||
xml++; /* advance past the '>' */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MATCH("<!--")) {
|
||||
ctx->poic_cp = xml + 4;
|
||||
if (_prop_object_internalize_skip_comment(ctx) == FALSE)
|
||||
goto bad;
|
||||
xml = ctx->poic_cp;
|
||||
continue;
|
||||
}
|
||||
|
||||
#undef MATCH
|
||||
|
||||
/*
|
||||
* We don't think we should skip it, so let's hope we can
|
||||
* parse it.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->poic_cp = xml;
|
||||
return (ctx);
|
||||
bad:
|
||||
_PROP_FREE(ctx, M_TEMP);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_object_internalize_context_free --
|
||||
* Free an internalize context.
|
||||
*/
|
||||
void
|
||||
_prop_object_internalize_context_free(
|
||||
struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
|
||||
_PROP_FREE(ctx, M_TEMP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retain / release serialization --
|
||||
*
|
||||
* Eventually we would like to use atomic operations. But until we have
|
||||
* an MI API for them that is common to userland and the kernel, we will
|
||||
* use a lock instead.
|
||||
*
|
||||
* We use a single global mutex for all serialization. In the kernel, because
|
||||
* we are still under a biglock, this will basically never contend (properties
|
||||
* cannot be manipulated at interrupt level). In userland, this will cost
|
||||
* nothing for single-threaded programs. For multi-threaded programs, there
|
||||
* could be contention, but it probably won't cost that much unless the program
|
||||
* makes heavy use of property lists.
|
||||
*/
|
||||
#if defined(_KERNEL)
|
||||
#include <sys/lock.h>
|
||||
static struct simplelock _prop_refcnt_mutex = SIMPLELOCK_INITIALIZER;
|
||||
|
||||
#define _PROP_REFCNT_LOCK() simple_lock(&_prop_refcnt_mutex)
|
||||
#define _PROP_REFCNT_UNLOCK() simple_unlock(&_prop_refcnt_mutex)
|
||||
#elif defined(_STANDALONE)
|
||||
/*
|
||||
* No locking necessary for standalone environments.
|
||||
*/
|
||||
#define _PROP_REFCNT_LOCK() /* nothing */
|
||||
#define _PROP_REFCNT_UNLOCK() /* nothing */
|
||||
#elif defined(__NetBSD__) && defined(_LIBPROP)
|
||||
/*
|
||||
* Use the same mechanism as libc; we get pthread mutexes for threaded
|
||||
* programs and do-nothing stubs for non-threaded programs.
|
||||
*/
|
||||
#include "reentrant.h"
|
||||
static mutex_t _prop_refcnt_mutex = MUTEX_INITIALIZER;
|
||||
|
||||
#define _PROP_REFCNT_LOCK() mutex_lock(&_prop_refcnt_mutex)
|
||||
#define _PROP_REFCNT_UNLOCK() mutex_unlock(&_prop_refcnt_mutex)
|
||||
#elif defined(HAVE_NBTOOL_CONFIG_H)
|
||||
/* None of NetBSD's build tools are multi-threaded. */
|
||||
#define _PROP_REFCNT_LOCK() /* nothing */
|
||||
#define _PROP_REFCNT_UNLOCK() /* nothing */
|
||||
#else
|
||||
/* Use pthread mutexes everywhere else. */
|
||||
#include <pthread.h>
|
||||
static pthread_mutex_t _prop_refcnt_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#define _PROP_REFCNT_LOCK() pthread_mutex_lock(&_prop_refcnt_mutex)
|
||||
#define _PROP_REFCNT_UNLOCK() pthread_mutex_unlock(&_prop_refcnt_mutex)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* prop_object_retain --
|
||||
* Increment the reference count on an object.
|
||||
*/
|
||||
void
|
||||
prop_object_retain(prop_object_t obj)
|
||||
{
|
||||
struct _prop_object *po = obj;
|
||||
uint32_t ocnt;
|
||||
|
||||
_PROP_REFCNT_LOCK();
|
||||
ocnt = po->po_refcnt++;
|
||||
_PROP_REFCNT_UNLOCK();
|
||||
|
||||
_PROP_ASSERT(ocnt != 0xffffffffU);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_object_release --
|
||||
* Decrement the reference count on an object.
|
||||
*
|
||||
* Free the object if we are releasing the final
|
||||
* reference.
|
||||
*/
|
||||
void
|
||||
prop_object_release(prop_object_t obj)
|
||||
{
|
||||
struct _prop_object *po = obj;
|
||||
uint32_t ocnt;
|
||||
|
||||
_PROP_REFCNT_LOCK();
|
||||
ocnt = po->po_refcnt--;
|
||||
_PROP_REFCNT_UNLOCK();
|
||||
|
||||
_PROP_ASSERT(ocnt != 0);
|
||||
if (ocnt == 1)
|
||||
(*po->po_free)(po);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_object_type --
|
||||
* Return the type of an object.
|
||||
*/
|
||||
prop_type_t
|
||||
prop_object_type(prop_object_t obj)
|
||||
{
|
||||
struct _prop_object *po = obj;
|
||||
|
||||
return (po->po_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_object_iterator_next --
|
||||
* Return the next item during an iteration.
|
||||
*/
|
||||
prop_object_t
|
||||
prop_object_iterator_next(prop_object_iterator_t pi)
|
||||
{
|
||||
|
||||
return ((*pi->pi_next_object)(pi));
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_object_iterator_reset --
|
||||
* Reset the iterator to the first object so as to restart
|
||||
* iteration.
|
||||
*/
|
||||
void
|
||||
prop_object_iterator_reset(prop_object_iterator_t pi)
|
||||
{
|
||||
|
||||
(*pi->pi_reset)(pi);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_object_iterator_release --
|
||||
* Release the object iterator.
|
||||
*/
|
||||
void
|
||||
prop_object_iterator_release(prop_object_iterator_t pi)
|
||||
{
|
||||
|
||||
prop_object_release(pi->pi_obj);
|
||||
_PROP_FREE(pi, M_TEMP);
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
/* $NetBSD: prop_object_impl.h,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PROPLIB_PROP_OBJECT_IMPL_H_
|
||||
#define _PROPLIB_PROP_OBJECT_IMPL_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 */
|
||||
};
|
||||
|
||||
boolean_t _prop_object_externalize_start_tag(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
boolean_t _prop_object_externalize_end_tag(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
boolean_t _prop_object_externalize_empty_tag(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
boolean_t _prop_object_externalize_append_cstring(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
boolean_t _prop_object_externalize_append_encoded_cstring(
|
||||
struct _prop_object_externalize_context *,
|
||||
const char *);
|
||||
boolean_t _prop_object_externalize_append_char(
|
||||
struct _prop_object_externalize_context *,
|
||||
unsigned char);
|
||||
|
||||
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;
|
||||
|
||||
boolean_t poic_is_empty_element;
|
||||
_prop_tag_type_t poic_tag_type;
|
||||
};
|
||||
|
||||
#define _PROP_EOF(c) ((c) == '\0')
|
||||
#define _PROP_ISSPACE(c) \
|
||||
((c) == ' ' || (c) == '\t' || (c) == '\n' || _PROP_EOF(c))
|
||||
|
||||
#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))
|
||||
|
||||
boolean_t _prop_object_internalize_find_tag(
|
||||
struct _prop_object_internalize_context *,
|
||||
const char *, _prop_tag_type_t);
|
||||
boolean_t _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 *);
|
||||
boolean_t _prop_object_internalize_decode_string(
|
||||
struct _prop_object_internalize_context *,
|
||||
char *, size_t, size_t *, 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 *);
|
||||
|
||||
/* These are here because they're required by shared code. */
|
||||
prop_object_t _prop_array_internalize(
|
||||
struct _prop_object_internalize_context *);
|
||||
prop_object_t _prop_bool_internalize(
|
||||
struct _prop_object_internalize_context *);
|
||||
prop_object_t _prop_data_internalize(
|
||||
struct _prop_object_internalize_context *);
|
||||
prop_object_t _prop_dictionary_internalize(
|
||||
struct _prop_object_internalize_context *);
|
||||
prop_object_t _prop_number_internalize(
|
||||
struct _prop_object_internalize_context *);
|
||||
prop_object_t _prop_string_internalize(
|
||||
struct _prop_object_internalize_context *);
|
||||
|
||||
struct _prop_object {
|
||||
uint32_t po_refcnt; /* reference count */
|
||||
uint32_t po_type; /* type indicator */
|
||||
void (*po_free)(void *); /* func to free object */
|
||||
boolean_t (*po_extern) /* func to externalize object */
|
||||
(struct _prop_object_externalize_context *,
|
||||
void *);
|
||||
};
|
||||
|
||||
void _prop_object_init(struct _prop_object *);
|
||||
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;
|
||||
};
|
||||
|
||||
#if defined(_KERNEL)
|
||||
|
||||
/*
|
||||
* proplib in the kernel...
|
||||
*/
|
||||
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/pool.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#define _PROP_ASSERT(x) KASSERT(x)
|
||||
|
||||
#define _PROP_MALLOC(s, t) malloc((s), (t), M_WAITOK)
|
||||
#define _PROP_CALLOC(s, t) malloc((s), (t), M_WAITOK | M_ZERO)
|
||||
#define _PROP_FREE(v, t) free((v), (t))
|
||||
|
||||
#define _PROP_POOL_GET(p) pool_get(&(p), PR_WAITOK)
|
||||
#define _PROP_POOL_PUT(p, v) pool_put(&(p), (v))
|
||||
|
||||
#define _PROP_POOL_INIT(p, s, d) \
|
||||
POOL_INIT(p, s, 0, 0, 0, d, &pool_allocator_nointr);
|
||||
|
||||
#define _PROP_MALLOC_DEFINE(t, s, l) \
|
||||
MALLOC_DEFINE(t, s, l);
|
||||
|
||||
#elif defined(_STANDALONE)
|
||||
|
||||
/*
|
||||
* proplib in a standalone environment...
|
||||
*/
|
||||
|
||||
#include <lib/libsa/stand.h>
|
||||
#include <lib/libkern/libkern.h>
|
||||
|
||||
void * _prop_standalone_calloc(size_t);
|
||||
|
||||
#define _PROP_ASSERT(x) /* nothing */
|
||||
|
||||
#define _PROP_MALLOC(s, t) alloc((s))
|
||||
#define _PROP_CALLOC(s, t) _prop_standalone_calloc((s))
|
||||
#define _PROP_FREE(v, t) dealloc((v), 0) /* XXX */
|
||||
|
||||
#define _PROP_POOL_GET(p) alloc((p))
|
||||
#define _PROP_POOL_PUT(p, v) dealloc((v), (p))
|
||||
|
||||
#define _PROP_POOL_INIT(p, s, d) static const size_t p = s;
|
||||
|
||||
#define _PROP_MALLOC_DEFINE(t, s, l) /* nothing */
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* proplib in user space...
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define _PROP_ASSERT(x) assert(x)
|
||||
|
||||
#define _PROP_MALLOC(s, t) malloc((s))
|
||||
#define _PROP_CALLOC(s, t) calloc(1, (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 */
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _PROPLIB_PROP_OBJECT_IMPL_H_ */
|
|
@ -0,0 +1,169 @@
|
|||
.\" $NetBSD: prop_string.3,v 1.1 2006/04/27 20:11:27 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 22, 2006
|
||||
.Dt PROP_STRING 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm prop_string ,
|
||||
.Nm prop_string_create ,
|
||||
.Nm prop_string_create_cstring ,
|
||||
.Nm prop_string_create_cstring_nocopy ,
|
||||
.Nm prop_string_copy ,
|
||||
.Nm prop_string_copy_mutable ,
|
||||
.Nm prop_string_size ,
|
||||
.Nm prop_string_mutable ,
|
||||
.Nm prop_string_cstring ,
|
||||
.Nm prop_string_cstring_nocopy ,
|
||||
.Nm prop_string_append ,
|
||||
.Nm prop_string_append_cstring ,
|
||||
.Nm prop_string_equals ,
|
||||
.Nm prop_string_equals_cstring
|
||||
.Nd string value property object
|
||||
.Sh LIBRARY
|
||||
.Lb libprop
|
||||
.Sh SYNOPSIS
|
||||
.In prop/proplib.h
|
||||
.\"
|
||||
.Ft prop_string_t
|
||||
.Fn prop_string_create "void"
|
||||
.Ft prop_string_t
|
||||
.Fn prop_string_create_cstring "const char *cstring"
|
||||
.Ft prop_string_t
|
||||
.Fn prop_string_create_cstring_nocopy "const char *cstring"
|
||||
.\"
|
||||
.Ft prop_string_t
|
||||
.Fn prop_stringy_copy "prop_string_t string"
|
||||
.Ft prop_string_t
|
||||
.Fn prop_stringy_copy_mutable "prop_string_t string"
|
||||
.\"
|
||||
.Ft char *
|
||||
.Fn prop_string_cstring "prop_string_t string"
|
||||
.Ft const char *
|
||||
.Fn prop_string_cstring_nocopy "prop_string_t string"
|
||||
.\"
|
||||
.Ft boolean_t
|
||||
.Fn prop_string_append "prop_string_t str1" "prop_string_t str2"
|
||||
.Ft boolean_t
|
||||
.Fn prop_string_append_cstring "prop_string_t string" "const char *cstring"
|
||||
.\"
|
||||
.Ft boolean_t
|
||||
.Fn prop_string_equals "prop_string_t str1" "prop_string_t str2"
|
||||
.Ft boolean_t
|
||||
.Fn prop_string_equals_cstring "prop_string_t string" "const char *cstring"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm prop_string
|
||||
family of functions operate on a string value property object type.
|
||||
.Bl -tag -width "xxxxx"
|
||||
.It Fn prop_string_create "void"
|
||||
Create an empty mutable string.
|
||||
.It Fn prop_string_create_cstring "const char *cstring"
|
||||
Create a mutable string that contains a copy of
|
||||
.Fa cstring .
|
||||
.It Fn prop_string_create_cstring_nocopy "const char *cstring"
|
||||
Create an immutable string that contains a reference to
|
||||
.Fa cstring .
|
||||
.It Fn prop_string_copy "prop_string_t string"
|
||||
Copy a string.
|
||||
If the the string being copied is an immutable external C string reference,
|
||||
then the copy is also immutable and references the same external C string.
|
||||
.It Fn prop_string_copy_mutable "prop_string_t string"
|
||||
Copy a string, always creating a mutable copy.
|
||||
.It Fn prop_string_size "prop_string_t string"
|
||||
Returns the size of the string, not including the terminating NUL.
|
||||
.It Fn prop_string_mutable "prop_string_t string"
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the string is mutable.
|
||||
.It Fn prop_string_cstring "prop_string_t string"
|
||||
Returns a copy of the string's contents as a C string.
|
||||
The caller is responsible for freeing the returned buffer.
|
||||
.Pp
|
||||
In user space, the buffer is allocated using
|
||||
.Xr malloc 3 .
|
||||
In the kernel, the buffer is allocated using
|
||||
.Xr malloc 9
|
||||
using the malloc type
|
||||
.Dv M_TEMP .
|
||||
.It Fn prop_string_cstring_nocopy "prop_string_t string"
|
||||
Returns an immutable reference to the contents of the string as a
|
||||
C string.
|
||||
.It Fn prop_string_append "prop_string_t str1" "prop_string_t str2"
|
||||
Append the contents of
|
||||
.Fa str2
|
||||
to
|
||||
.Fa str1 ,
|
||||
which must be mutable.
|
||||
Returns
|
||||
.Dv TRUE
|
||||
upon success and
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
.It Fn prop_string_append_cstring "prop_string_t string" "const char *cstring"
|
||||
Append the C string
|
||||
.Fa cstring
|
||||
to
|
||||
.Fa string ,
|
||||
which must be mutable.
|
||||
Returns
|
||||
.Dv TRUE
|
||||
upon success and
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
.It Fn prop_string_equals "prop_string_t str1" "prop_string_t str2"
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the two string objects are equivalent.
|
||||
.It Fn prop_string_equals_cstring "prop_string_t string" "const char *cstring"
|
||||
Returns
|
||||
.Dv TRUE
|
||||
if the string's value is equivalent to
|
||||
.Fa cstring .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr prop_array 3 ,
|
||||
.Xr prop_bool 3 ,
|
||||
.Xr prop_data 3 ,
|
||||
.Xr prop_dictionary 3 ,
|
||||
.Xr prop_number 3 ,
|
||||
.Xr prop_object 3 ,
|
||||
.Xr proplib 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm proplib
|
||||
property container object library first appeared in
|
||||
.Nx 4.0 .
|
|
@ -0,0 +1,426 @@
|
|||
/* $NetBSD: prop_string.c,v 1.1 2006/04/27 20:11:27 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <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")
|
||||
|
||||
_PROP_MALLOC_DEFINE(M_PROP_STRING, "prop string",
|
||||
"property string container object")
|
||||
|
||||
#define prop_object_is_string(x) ((x)->ps_obj.po_type == PROP_TYPE_STRING)
|
||||
#define prop_string_contents(x) ((x)->ps_immutable ? (x)->ps_immutable : "")
|
||||
|
||||
static void
|
||||
_prop_string_free(void *v)
|
||||
{
|
||||
prop_string_t ps = v;
|
||||
|
||||
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, v);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
_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);
|
||||
}
|
||||
|
||||
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);
|
||||
ps->ps_obj.po_type = PROP_TYPE_STRING;
|
||||
ps->ps_obj.po_free = _prop_string_free;
|
||||
ps->ps_obj.po_extern = _prop_string_externalize;
|
||||
|
||||
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_string_free(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;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_string(ops));
|
||||
|
||||
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_string_free(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;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_string(ops));
|
||||
|
||||
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_string_free(ps);
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(cp, prop_string_contents(ops));
|
||||
ps->ps_mutable = cp;
|
||||
}
|
||||
return (ps);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_size --
|
||||
* Return the size of the string, no including the terminating NUL.
|
||||
*/
|
||||
size_t
|
||||
prop_string_size(prop_string_t ps)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_string(ps));
|
||||
return (ps->ps_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_mutable --
|
||||
* Return TRUE if the string is a mutable string.
|
||||
*/
|
||||
boolean_t
|
||||
prop_string_mutable(prop_string_t ps)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_string(ps));
|
||||
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;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_string(ps));
|
||||
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)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_string(ps));
|
||||
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.
|
||||
*/
|
||||
boolean_t
|
||||
prop_string_append(prop_string_t dst, prop_string_t src)
|
||||
{
|
||||
char *ocp, *cp;
|
||||
size_t len;
|
||||
|
||||
_PROP_ASSERT(prop_object_is_string(dst));
|
||||
_PROP_ASSERT(prop_object_is_string(src));
|
||||
|
||||
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);
|
||||
sprintf(cp, "%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.
|
||||
*/
|
||||
boolean_t
|
||||
prop_string_append_cstring(prop_string_t dst, const char *src)
|
||||
{
|
||||
char *ocp, *cp;
|
||||
size_t len;
|
||||
|
||||
_PROP_ASSERT(src != NULL);
|
||||
_PROP_ASSERT(prop_object_is_string(dst));
|
||||
|
||||
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);
|
||||
sprintf(cp, "%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.
|
||||
*/
|
||||
boolean_t
|
||||
prop_string_equals(prop_string_t str1, prop_string_t str2)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_string(str1));
|
||||
_PROP_ASSERT(prop_object_is_string(str2));
|
||||
if (str1 == str2)
|
||||
return (TRUE);
|
||||
if (str1->ps_size != str2->ps_size)
|
||||
return (FALSE);
|
||||
return (strcmp(prop_string_contents(str1),
|
||||
prop_string_contents(str2)) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* prop_string_equals_cstring --
|
||||
* Return TRUE if the string is equivalent to the specified
|
||||
* C string.
|
||||
*/
|
||||
boolean_t
|
||||
prop_string_equals_cstring(prop_string_t ps, const char *cp)
|
||||
{
|
||||
|
||||
_PROP_ASSERT(prop_object_is_string(ps));
|
||||
return (strcmp(prop_string_contents(ps), cp) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* _prop_string_internalize --
|
||||
* Parse a <string>...</string> and return the object created from the
|
||||
* external representation.
|
||||
*/
|
||||
prop_object_t
|
||||
_prop_string_internalize(struct _prop_object_internalize_context *ctx)
|
||||
{
|
||||
prop_string_t string;
|
||||
char *str;
|
||||
size_t len, alen;
|
||||
|
||||
if (ctx->poic_is_empty_element)
|
||||
return (prop_string_create());
|
||||
|
||||
/* No attributes recognized here. */
|
||||
if (ctx->poic_tagattr != NULL)
|
||||
return (NULL);
|
||||
|
||||
/* Compute the length of the result. */
|
||||
if (_prop_object_internalize_decode_string(ctx, NULL, 0, &len,
|
||||
NULL) == FALSE)
|
||||
return (NULL);
|
||||
|
||||
str = _PROP_MALLOC(len + 1, M_PROP_STRING);
|
||||
if (str == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (_prop_object_internalize_decode_string(ctx, str, len, &alen,
|
||||
&ctx->poic_cp) == FALSE ||
|
||||
alen != len) {
|
||||
_PROP_FREE(str, M_PROP_STRING);
|
||||
return (NULL);
|
||||
}
|
||||
str[len] = '\0';
|
||||
|
||||
if (_prop_object_internalize_find_tag(ctx, "string",
|
||||
_PROP_TAG_TYPE_END) == FALSE) {
|
||||
_PROP_FREE(str, M_PROP_STRING);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
string = _prop_string_alloc();
|
||||
if (string == NULL) {
|
||||
_PROP_FREE(str, M_PROP_STRING);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
string->ps_mutable = str;
|
||||
string->ps_size = len;
|
||||
|
||||
return (string);
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
.\" $NetBSD: proplib.3,v 1.1 2006/04/27 20:11:27 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 22, 2006
|
||||
.Dt PROPLIB 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm proplib
|
||||
.Nd property container object library
|
||||
.Sh LIBRARY
|
||||
.Lb libprop
|
||||
.Sh SYNOPSIS
|
||||
.In prop/proplib.h
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
library provides an abstract interface for creating and manipulating
|
||||
property lists.
|
||||
Property lists have object types for boolean values, opaque data, numbers,
|
||||
and strings.
|
||||
Structure is provided by the array and dictionary collection types.
|
||||
.Pp
|
||||
Property lists can be passed across protection boundaries by translating
|
||||
them to an external representation.
|
||||
This external representation is an XML document whose format is described
|
||||
by the following DTD:
|
||||
.Bd -literal -offset indent
|
||||
http://www.apple.com/DTDs/PropertyList-1.0.dtd
|
||||
.Ed
|
||||
.Pp
|
||||
Property container objects are reference counted.
|
||||
When an object is created, its reference count is set to 1.
|
||||
Any code that keeps a reference to an object, including the collection
|
||||
types
|
||||
.Pq arrays and dictionaries ,
|
||||
must
|
||||
.Dq retain
|
||||
the object
|
||||
.Pq increment its reference count .
|
||||
When that reference is dropped, the object must be
|
||||
.Dq released
|
||||
.Pq reference count decremented .
|
||||
When an object's reference count drops to 0, it is automatically freed.
|
||||
.Pp
|
||||
The rules for managing reference counts are very simple:
|
||||
.Bl -bullet
|
||||
.It
|
||||
If you create an object and do not explicitly maintain a reference to it,
|
||||
you must release it.
|
||||
.It
|
||||
If you get a reference to an object from other code and wish to maintain
|
||||
a reference to it, you must retain the object. You are responsible for
|
||||
releasing the object once you drop that reference.
|
||||
.It
|
||||
You must never release an object unless you create it or retain it.
|
||||
.El
|
||||
.Pp
|
||||
Object collections may be iterated by creating a special iterator object.
|
||||
Iterator objects are special; they may not be retained, and they are
|
||||
released using an iterator-specific release function.
|
||||
.Sh SEE ALSO
|
||||
.Xr prop_array 3 ,
|
||||
.Xr prop_bool 3 ,
|
||||
.Xr prop_data 3 ,
|
||||
.Xr prop_dictionary 3 ,
|
||||
.Xr prop_number 3 ,
|
||||
.Xr prop_object 3 ,
|
||||
.Xr prop_string 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
property container object library first appeared in
|
||||
.Nx 4.0 .
|
||||
.Sh CAVEATS
|
||||
.Nm
|
||||
does not have a
|
||||
.Sq date
|
||||
object type, and thus will not parse
|
||||
.Sq date
|
||||
elements from an Apple XML property list.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
.Sq number
|
||||
object type differs from the Apple XML property list format in the following
|
||||
ways:
|
||||
.Bl -bullet
|
||||
.It
|
||||
The external representation is in base 16, not base 10.
|
||||
.Nm
|
||||
is able to parse base 8, base 10, and base 16
|
||||
.Sq integer
|
||||
elements.
|
||||
.It
|
||||
Internally, integers are always stored as unsigned numbers
|
||||
.Pq uintmax_t .
|
||||
Therefore, the external representation will never be negative.
|
||||
.It
|
||||
Because floating point numbers are not supported,
|
||||
.Sq real
|
||||
elements from an Apple XML property list will not be parsed.
|
||||
.El
|
||||
.Pp
|
||||
In order to facilitate use of
|
||||
.Nm
|
||||
in kernel, standalone, and user space environments, the
|
||||
.Nm
|
||||
parser is not a real XML parser.
|
||||
It is hard-coded to parse only the property list external representation.
|
Loading…
Reference in New Issue