summaryrefslogtreecommitdiffstats
path: root/librdfa/rdfa_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'librdfa/rdfa_utils.c')
-rw-r--r--librdfa/rdfa_utils.c543
1 files changed, 543 insertions, 0 deletions
diff --git a/librdfa/rdfa_utils.c b/librdfa/rdfa_utils.c
new file mode 100644
index 0000000..a2e65f2
--- /dev/null
+++ b/librdfa/rdfa_utils.c
@@ -0,0 +1,543 @@
+/*
+ * Copyright 2008-2011 Digital Bazaar, Inc.
+ *
+ * This file is part of librdfa.
+ *
+ * librdfa is Free Software, and can be licensed under any of the
+ * following three licenses:
+ *
+ * 1. GNU Lesser General Public License (LGPL) V2.1 or any
+ * newer version
+ * 2. GNU General Public License (GPL) V2 or any newer version
+ * 3. Apache License, V2.0 or any newer version
+ *
+ * You may not use this file except in compliance with at least one of
+ * the above three licenses.
+ *
+ * See LICENSE-* at the top of this software distribution for more
+ * information regarding the details of each license.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with librdfa. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "rdfa_utils.h"
+#include "rdfa.h"
+#include "strtok_r.h"
+
+#define RDFA_WHITESPACE_CHARACTERS " \a\b\t\n\v\f\r"
+
+char* rdfa_join_string(const char* prefix, const char* suffix)
+{
+ char* rval = NULL;
+ size_t prefix_size = strlen(prefix);
+ size_t suffix_size = strlen(suffix);
+ rval = (char*)malloc(prefix_size + suffix_size + 1);
+
+ memcpy(rval, prefix, prefix_size);
+ memcpy(rval+prefix_size, suffix, suffix_size + 1);
+
+ return rval;
+}
+
+char* rdfa_n_append_string(
+ char* old_string, size_t* string_size,
+ const char* suffix, size_t suffix_size)
+{
+ char* rval = NULL;
+ rval = (char*)realloc(old_string, *string_size + suffix_size + 1);
+ memcpy(rval + *string_size, suffix, suffix_size + 1);
+ *string_size = *string_size + suffix_size;
+ return rval;
+}
+
+char* rdfa_replace_string(char* old_string, const char* new_string)
+{
+ char* rval = NULL;
+
+ if(new_string != NULL)
+ {
+ /* free the memory associated with the old string */
+ free(old_string);
+
+ /* copy the new string */
+ rval = rdfa_strdup(new_string);
+ }
+
+ return rval;
+}
+
+char* rdfa_canonicalize_string(const char* str)
+{
+ char* rval = (char*)malloc(sizeof(char) * (strlen(str) + 2));
+ char* working_string = NULL;
+ char* token = NULL;
+ char* wptr = NULL;
+ char* offset = rval;
+
+ working_string = rdfa_replace_string(working_string, str);
+
+ /* split on any whitespace character that we may find */
+ token = strtok_r(working_string, RDFA_WHITESPACE_CHARACTERS, &wptr);
+ while(token != NULL)
+ {
+ size_t token_length = strlen(token);
+ memcpy(offset, token, token_length);
+ offset += token_length;
+ *offset++ = ' ';
+ *offset = '\0';
+
+ token = strtok_r(NULL, RDFA_WHITESPACE_CHARACTERS, &wptr);
+ }
+
+ if(offset != rval)
+ {
+ offset--;
+ *offset = '\0';
+ }
+
+ free(working_string);
+
+ return rval;
+}
+
+rdfalist* rdfa_create_list(size_t size)
+{
+ rdfalist* rval = (rdfalist*)malloc(sizeof(rdfalist));
+
+ rval->max_items = size;
+ rval->num_items = 0;
+ rval->items = (rdfalistitem**)malloc(
+ sizeof(rdfalistitem*) * rval->max_items);
+
+ return rval;
+}
+
+rdfalist* rdfa_replace_list(rdfalist* old_list, rdfalist* new_list)
+{
+ rdfalist* rval = NULL;
+
+ if(new_list != NULL)
+ {
+ /* free the memory associated with the old list */
+ rdfa_free_list(old_list);
+
+ /* copy the new list */
+ rval = rdfa_copy_list(new_list);
+ }
+
+ return rval;
+}
+
+rdfalist* rdfa_copy_list(rdfalist* list)
+{
+ rdfalist* rval = NULL;
+
+ if(list != NULL)
+ {
+ unsigned int i;
+ rval = rdfa_create_list(list->max_items);
+
+ /* copy the base list variables over */
+ rval->num_items = list->num_items;
+ rval->user_data = list->user_data;
+
+ /* copy the data of every list member along with all of the flags
+ * for each list member. */
+ for(i = 0; i < list->max_items; i++)
+ {
+ if(i < list->num_items)
+ {
+ rval->items[i] = (rdfalistitem*)malloc(sizeof(rdfalistitem));
+ rval->items[i]->data = NULL;
+ rval->items[i]->flags = list->items[i]->flags;
+
+ /* copy specific data type */
+ if(list->items[i]->flags & RDFALIST_FLAG_TEXT)
+ {
+ rval->items[i]->data = rdfa_strdup((char*)list->items[i]->data);
+ }
+ else if(list->items[i]->flags & RDFALIST_FLAG_TRIPLE)
+ {
+ rdftriple* t = (rdftriple*)list->items[i]->data;
+ rval->items[i]->data =
+ rdfa_create_triple(t->subject, t->predicate, t->object,
+ t->object_type, t->datatype, t->language);
+ }
+ else if(list->items[i]->flags & RDFALIST_FLAG_CONTEXT)
+ {
+ /* TODO: Implement the copy for context, if it is needed. */
+ }
+ }
+ else
+ {
+ rval->items[i] = NULL;
+ }
+ }
+ }
+
+ return rval;
+}
+
+void rdfa_print_list(rdfalist* list)
+{
+ unsigned int i;
+
+ printf("[ ");
+
+ for(i = 0; i < list->num_items; i++)
+ {
+ if(i != 0)
+ {
+ printf(", ");
+ }
+
+ puts((const char*)list->items[i]->data);
+ }
+
+ printf(" ]\n");
+}
+
+void rdfa_print_triple_list(rdfalist* list)
+{
+ unsigned int i;
+
+ if(list != NULL)
+ {
+ printf("[ ");
+
+ for(i = 0; i < list->num_items; i++)
+ {
+ if(i != 0)
+ {
+ printf(", ");
+ }
+
+ rdfa_print_triple((rdftriple*)list->items[i]->data);
+ }
+
+ printf(" ]\n");
+ }
+ else
+ {
+ printf("NULL\n");
+ }
+}
+
+void rdfa_free_list(rdfalist* list)
+{
+ if(list != NULL)
+ {
+ unsigned int i;
+ for(i = 0; i < list->num_items; i++)
+ {
+ if(list->items[i]->flags & RDFALIST_FLAG_TEXT)
+ {
+ free(list->items[i]->data);
+ }
+ else if(list->items[i]->flags & RDFALIST_FLAG_TRIPLE)
+ {
+ rdftriple* t = (rdftriple*)list->items[i]->data;
+ rdfa_free_triple(t);
+ }
+
+ free(list->items[i]);
+ }
+
+ free(list->items);
+ free(list);
+ }
+}
+
+void rdfa_push_item(rdfalist* stack, void* data, liflag_t flags)
+{
+ rdfa_add_item(stack, data, flags);
+}
+
+void* rdfa_pop_item(rdfalist* stack)
+{
+ void* rval = NULL;
+
+ if(stack->num_items > 0)
+ {
+ --stack->num_items;
+ rval = stack->items[stack->num_items]->data;
+ free(stack->items[stack->num_items]);
+ stack->items[stack->num_items] = NULL;
+ }
+
+ return rval;
+}
+
+void rdfa_add_item(rdfalist* list, void* data, liflag_t flags)
+{
+ rdfalistitem* item;
+
+ if(!list)
+ return;
+
+ item = (rdfalistitem*)malloc(sizeof(rdfalistitem));
+
+ item->data = NULL;
+
+ if((flags & RDFALIST_FLAG_CONTEXT) || (flags & RDFALIST_FLAG_TRIPLE))
+ {
+ item->data = data;
+ }
+ else
+ {
+ item->data = (char*)rdfa_replace_string(
+ (char*)item->data, (const char*)data);
+ }
+
+ item->flags = flags;
+
+ if(list->num_items == list->max_items)
+ {
+ list->max_items = 1 + (list->max_items * 2);
+ list->items = (rdfalistitem**)realloc(
+ list->items, sizeof(rdfalistitem*) * list->max_items);
+ }
+
+ list->items[list->num_items] = item;
+ ++list->num_items;
+}
+
+void** rdfa_create_mapping(size_t elements)
+{
+ size_t mapping_size = sizeof(void*) * MAX_URI_MAPPINGS * 2;
+ void** mapping = (void**)malloc(mapping_size);
+
+ /* only initialize the mapping if it is not null. */
+ if(mapping != NULL)
+ {
+ memset(mapping, 0, mapping_size);
+ }
+
+ return mapping;
+}
+
+void rdfa_create_list_mapping(
+ rdfacontext* context, void** mapping,
+ const char* subject, const char* key)
+{
+ char* realkey = NULL;
+ size_t str_size;
+ rdfalist* value = NULL;
+ char* list_bnode;
+ rdftriple* triple;
+
+ /* Attempt to find the list mapping */
+ value = (rdfalist*)rdfa_get_list_mapping(mapping, subject, key);
+
+ if(value == NULL)
+ {
+ /* create the mapping */
+ value = rdfa_create_list(MAX_LIST_ITEMS);
+ value->user_data = context->depth;
+
+ /* build the real key to use when updating the mapping */
+ str_size = strlen(subject);
+ realkey = rdfa_strdup(subject);
+ realkey = rdfa_n_append_string(realkey, &str_size, " ", 1);
+ realkey = rdfa_n_append_string(realkey, &str_size, key, strlen(key));
+ rdfa_update_mapping(mapping, realkey, value,
+ (update_mapping_value_fp)rdfa_replace_list);
+ free(realkey);
+ rdfa_free_list(value);
+
+ /* add the first item in the list as the bnode for the list */
+ list_bnode = rdfa_create_bnode(context);
+ triple = rdfa_create_triple(
+ list_bnode, list_bnode, list_bnode, RDF_TYPE_IRI, NULL, NULL);
+ rdfa_append_to_list_mapping(mapping, subject, key, (void*)triple);
+ free(list_bnode);
+ }
+}
+
+void rdfa_append_to_list_mapping(
+ void** mapping, const char* subject, const char* key, void* value)
+{
+ rdfalist* list = (rdfalist*)rdfa_get_list_mapping(mapping, subject, key);
+ rdfa_add_item(list, value, RDFALIST_FLAG_TRIPLE);
+}
+
+void** rdfa_copy_mapping(
+ void** mapping, copy_mapping_value_fp copy_mapping_value)
+{
+ void** rval = (void**)calloc(MAX_URI_MAPPINGS * 2, sizeof(void*));
+ void** mptr = mapping;
+ void** rptr = rval;
+
+ /* copy each element of the old mapping to the new mapping. */
+ while(*mptr != NULL)
+ {
+ /* copy the key */
+ *rptr = rdfa_replace_string((char*)*rptr, (const char*)*mptr);
+ rptr++;
+ mptr++;
+
+ /* copy the value */
+ *rptr = copy_mapping_value(*rptr, *mptr);
+ rptr++;
+ mptr++;
+ }
+
+ return rval;
+}
+
+void rdfa_update_mapping(void** mapping, const char* key, const void* value,
+ update_mapping_value_fp update_mapping_value)
+{
+ int found = 0;
+ void** mptr = mapping;
+
+ /* search the current mapping to see if the key exists in the mapping */
+ while(!found && (*mptr != NULL))
+ {
+ if(strcmp((char*)*mptr, key) == 0)
+ {
+ mptr++;
+ *mptr = update_mapping_value(*mptr, value);
+ found = 1;
+ }
+ else
+ {
+ mptr++;
+ }
+ mptr++;
+ }
+
+ /* if we made it through the entire URI mapping and the key was not
+ * found, create a new key-value pair. */
+ if(!found)
+ {
+ *mptr = rdfa_replace_string((char*)*mptr, key);
+ mptr++;
+ *mptr = update_mapping_value(*mptr, value);
+ }
+}
+
+const void* rdfa_get_mapping(void** mapping, const char* key)
+{
+ const void* rval = NULL;
+ char** mptr = (char**)mapping;
+
+ /* search the current mapping to see if the key exists in the mapping. */
+ while(*mptr != NULL)
+ {
+ if(strcmp(*mptr, key) == 0)
+ {
+ mptr++;
+ rval = *mptr;
+ }
+ else
+ {
+ mptr++;
+ }
+ mptr++;
+ }
+
+ return rval;
+}
+
+const void* rdfa_get_list_mapping(
+ void** mapping, const char* subject, const char* key)
+{
+ void* rval;
+ char* realkey = NULL;
+ size_t str_size = strlen(subject);
+
+ /* generate the real list mapping key and retrieve it from the mapping */
+ realkey = rdfa_strdup(subject);
+ realkey = rdfa_n_append_string(realkey, &str_size, " ", 1);
+ realkey = rdfa_n_append_string(realkey, &str_size, key, strlen(key));
+ rval = (void*)rdfa_get_mapping(mapping, realkey);
+ free(realkey);
+
+ return (const void*)rval;
+}
+
+void rdfa_next_mapping(void** mapping, char** key, void** value)
+{
+ *key = NULL;
+ *value = NULL;
+
+ if(*mapping != NULL)
+ {
+ *key = *(char**)mapping++;
+ *value = *mapping++;
+ }
+}
+
+void rdfa_print_mapping(void** mapping, print_mapping_value_fp print_value)
+{
+ void** mptr = mapping;
+ printf("{\n");
+ while(*mptr != NULL)
+ {
+ char* key;
+ void* value;
+ key = (char*)*mptr++;
+ value = *mptr++;
+
+ printf(" %s : ", key);
+ print_value(value);
+
+ if(*mptr != NULL)
+ {
+ printf(",\n");
+ }
+ else
+ {
+ printf("\n");
+ }
+ }
+ printf("}\n");
+}
+
+void rdfa_print_string(const char* str)
+{
+ printf("%s", str);
+}
+
+void rdfa_free_mapping(void** mapping, free_mapping_value_fp free_value)
+{
+ void** mptr = mapping;
+
+ if(mapping != NULL)
+ {
+ /* free all of the memory in the mapping */
+ while(*mptr != NULL)
+ {
+ free(*mptr);
+ mptr++;
+ free_value(*mptr);
+ mptr++;
+ }
+
+ free(mapping);
+ }
+}
+
+char*
+rdfa_strdup(const char* s)
+{
+ size_t len;
+ char *buf;
+
+ if(!s)
+ return NULL;
+
+ len = strlen(s) + 1;
+ buf = (char*)malloc(len);
+ if(buf)
+ memcpy(buf, s, len);
+ return buf;
+}