diff --git a/pkg.h b/pkg.h index ad2551b..b42dc70 100644 --- a/pkg.h +++ b/pkg.h @@ -158,5 +158,6 @@ char *pkg_fgetline(char *line, size_t size, FILE *stream); pkg_tuple_t *pkg_tuple_add(pkg_tuple_t *parent, const char *key, const char *value); char *pkg_tuple_find(pkg_tuple_t *head, const char *key); char *pkg_tuple_parse(pkg_tuple_t *vars, const char *value); +void pkg_tuple_free(pkg_tuple_t *head); #endif diff --git a/tuple.c b/tuple.c new file mode 100644 index 0000000..2ebd20e --- /dev/null +++ b/tuple.c @@ -0,0 +1,118 @@ +/* + * tuple.c + * management of key->value tuples + * + * Copyright (c) 2011, 2012 William Pitcock . + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pkg.h" +#include "bsdstubs.h" + +pkg_tuple_t * +pkg_tuple_add(pkg_tuple_t *parent, const char *key, const char *value) +{ + pkg_tuple_t *tuple = calloc(sizeof(pkg_tuple_t), 1); + + tuple->key = strdup(key); + tuple->value = pkg_tuple_parse(parent, value); + + tuple->next = parent; + if (tuple->next != NULL) + tuple->next->prev = tuple; + + return tuple; +} + +char * +pkg_tuple_find(pkg_tuple_t *head, const char *key) +{ + pkg_tuple_t *node; + + foreach_list_entry(head, node) + { + if (!strcasecmp(node->key, key)) + return node->value; + } + + return NULL; +} + +char * +pkg_tuple_parse(pkg_tuple_t *vars, const char *value) +{ + char buf[BUFSIZ]; + const char *ptr; + char *bptr = buf; + + for (ptr = value; *ptr != '\0' && bptr - buf < BUFSIZ; ptr++) + { + if (*ptr != '$') + *bptr++ = *ptr; + else if (*(ptr + 1) == '{') + { + static char varname[BUFSIZ]; + char *vptr = varname; + const char *pptr; + char *kv, *parsekv; + + *vptr = '\0'; + + for (pptr = ptr + 2; *pptr != '\0'; pptr++) + { + if (*pptr != '}') + *vptr++ = *pptr; + else + { + *vptr = '\0'; + break; + } + } + + ptr += (pptr - ptr); + kv = pkg_tuple_find(vars, varname); + + if (kv != NULL) + { + parsekv = pkg_tuple_parse(vars, kv); + + strncpy(bptr, parsekv, BUFSIZ - (bptr - buf)); + bptr += strlen(parsekv); + + free(parsekv); + } + } + } + + *bptr = '\0'; + + return strdup(buf); +} + +void +pkg_tuple_free(pkg_tuple_t *head) +{ + pkg_tuple_t *node, *next; + + foreach_list_entry_safe(head, next, node) + { + free(node->key); + free(node->value); + free(node); + } +}