/* $NetBSD$ */ /*- * Copyright (c) 2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jachym Holecek . * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "prop_object_impl.h" #include "prop_codec_impl.h" extern const struct _prop_codec prop_codec_xml; extern const struct _prop_codec prop_codec_scn; static prop_codec_t prop_codec_table[] = { #if defined(_PROPLIB_CODEC_XML) &prop_codec_xml, #endif #if defined(_PROPLIB_CODEC_SCN) &prop_codec_scn, #endif NULL }; /* Default to the codec with smallest external representation available. */ #if !defined(_PROP_DEFAULT_CODEC) #if defined(_PROPLIB_CODEC_SCN) #define _PROP_DEFAULT_CODEC "scn" #elif defined(_PROPLIB_CODEC_XML) #define _PROP_DEFAULT_CODEC "xml" #else #define _PROP_DEFAULT_CODEC "" /* Runtime failure */ #endif #endif static const char * prop_skip_space(const char *str) { if (str == NULL) return (NULL); while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r') str++; return (str); } static prop_codec_t prop_codec_guess(char c) { int i; /* * Must be able to tell codec by the first non-white character. * For binary codecs this implies their header must not begin * with whitespace characters. */ for (i = 0; prop_codec_table[i]; i++) if (strchr((const char *)prop_codec_table[i]->codec_sense, c) != NULL) return (prop_codec_table[i]); return (NULL); } static prop_object_t prop_parse_single(prop_codec_t co, const char *str, prop_type_t type) { prop_parser_t pa; prop_object_t po, pq; if (prop_parser_create(co, &pa)) goto fail_0; if (prop_parser_exec(co, pa, (const u_char *)str, strlen(str))) goto fail_1; if ((po = prop_parser_yield(co, pa)) == NULL) goto fail_1; /* Expect ${str} contains exactly one object. */ if ((pq = prop_parser_yield(co, pa)) != NULL) { prop_object_release(pq); goto fail_2; } if (prop_object_type(po) != type) goto fail_2; prop_parser_destroy(co, pa); return (po); fail_2: prop_object_release(po); fail_1: prop_parser_destroy(co, pa); fail_0: return (NULL); } const char * prop_codec_list(void) { static boolean_t doinit = TRUE; static char names[8]; /* XXX Large enough */ size_t idx = 0; int i; /* XXX locking? */ if (doinit) { for (i = 0; prop_codec_table[i]; i++) { strcpy(names + idx, prop_codec_table[i]->codec_name); idx += strlen(prop_codec_table[i]->codec_name); if (prop_codec_table[i + 1]) names[idx++] = ' '; } names[idx] = '\0'; doinit = FALSE; } return (names); } prop_codec_t prop_codec_lookup(const char *name) { int i; if (name == NULL) name = _PROP_DEFAULT_CODEC; for (i = 0; prop_codec_table[i]; i++) if (strcmp(prop_codec_table[i]->codec_name, name) == 0) return (prop_codec_table[i]); return (NULL); } prop_dictionary_t prop_dictionary_internalize(const char *str) { prop_codec_t co; if ((str = prop_skip_space(str)) == NULL) return (NULL); if ((co = prop_codec_guess(*str)) == NULL) return (NULL); if (co->codec_dictionary_internalize) return ((co->codec_dictionary_internalize)(str)); return (prop_parse_single(co, str, PROP_TYPE_DICTIONARY)); } prop_array_t prop_array_internalize(const char *str) { prop_codec_t co; if ((str = prop_skip_space(str)) == NULL) return (NULL); if ((co = prop_codec_guess(*str)) == NULL) return (NULL); if (co->codec_array_internalize) return ((co->codec_array_internalize)(str)); return (prop_parse_single(co, str, PROP_TYPE_ARRAY)); } char * prop_dictionary_externalize(prop_dictionary_t pd) { prop_codec_t co = prop_codec_lookup(_PROP_DEFAULT_CODEC); _PROP_ASSERT(co); if (co->codec_dictionary_externalize) return ((co->codec_dictionary_externalize)(pd)); if (co->codec_externalize_compound) return ((co->codec_externalize_compound)(pd)); return (NULL); } char * prop_array_externalize(prop_array_t pa) { prop_codec_t co = prop_codec_lookup(_PROP_DEFAULT_CODEC); _PROP_ASSERT(co); if (co->codec_array_externalize) return ((co->codec_array_externalize)(pa)); if (co->codec_externalize_compound) return ((co->codec_externalize_compound)(pa)); return (NULL); } char * prop_codec_externalize(prop_codec_t co, prop_object_t po) { _PROP_ASSERT(co); if (co->codec_externalize_compound) return ((co->codec_externalize_compound)(po)); switch (prop_object_type(po)) { case PROP_TYPE_DICTIONARY: return ((co->codec_dictionary_externalize)(po)); case PROP_TYPE_ARRAY: return ((co->codec_array_externalize)(po)); default: return (NULL); } } int prop_parser_create(prop_codec_t co, prop_parser_t *pp) { _PROP_ASSERT(co); if (pp == NULL) return (EINVAL); if (co->codec_parser_create) return ((co->codec_parser_create)(pp)); return (EOPNOTSUPP); } int prop_parser_exec(prop_codec_t co, prop_parser_t pa, const u_char *str, size_t len) { _PROP_ASSERT(co); if (co->codec_parser_exec) return ((co->codec_parser_exec)(pa, str, len)); return (EOPNOTSUPP); } prop_object_t prop_parser_yield(prop_codec_t co, prop_parser_t pa) { _PROP_ASSERT(co); if (co->codec_parser_yield) return ((co->codec_parser_yield)(pa)); return (NULL); } void prop_parser_destroy(prop_codec_t co, prop_parser_t pa) { _PROP_ASSERT(co); if (co->codec_parser_destroy) (co->codec_parser_destroy)(pa); }