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:
thorpej 2006-04-27 20:11:27 +00:00
parent ed14057f29
commit 774eb1a395
26 changed files with 5578 additions and 0 deletions

View File

@ -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>

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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

View File

@ -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 .

View File

@ -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);
}

View File

@ -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 .

View File

@ -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));
}

View File

@ -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 .

View File

@ -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);
}

View File

@ -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 .

View File

@ -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);
}

View File

@ -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 .

View File

@ -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));
}

View File

@ -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 .

View File

@ -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,
"&lt;") == FALSE)
return (FALSE);
break;
case '>':
if (_prop_object_externalize_append_cstring(ctx,
"&gt;") == FALSE)
return (FALSE);
break;
case '&':
if (_prop_object_externalize_append_cstring(ctx,
"&amp;") == 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);
}

View File

@ -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_ */

View File

@ -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 .

View File

@ -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);
}

View File

@ -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.