diff options
Diffstat (limited to 'src/plist.c')
-rw-r--r-- | src/plist.c | 106 |
1 files changed, 99 insertions, 7 deletions
diff --git a/src/plist.c b/src/plist.c index 4d4fce4..c86e166 100644 --- a/src/plist.c +++ b/src/plist.c @@ -22,6 +22,7 @@ #include <libxml/parser.h> #include <libxml/tree.h> #include <string.h> +#include <assert.h> #include "plist.h" const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ @@ -29,15 +30,29 @@ const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ <plist version=\"1.0\">\n\ </plist>\0"; +/** Formats a block of text to be a given indentation and width. + * + * The total width of the return string will be depth + cols. + * + * @param buf The string to format. + * @param cols The number of text columns for returned block of text. + * @param depth The number of tabs to indent the returned block of text. + * + * @return The formatted string. + */ char* format_string(const char* buf, int cols, int depth) { - int colw = depth + cols + 1; //new buf cols width + int colw = depth + cols + 1; int len = strlen(buf); - //int nlines = ceil((float)len / (float)cols); int nlines = len / cols + 1; char* new_buf = (char*)malloc(nlines * colw + depth + 1); int i = 0; int j = 0; + + assert(cols > 0); + assert(depth > 0); + + // Inserts new lines and tabs at appropriate locations for (i = 0; i < nlines; i++){ new_buf[i * colw] = '\n'; for (j = 0; j < depth; j++) @@ -45,62 +60,137 @@ char* format_string(const char* buf, int cols, int depth) memcpy(new_buf + i * colw + 1 + depth, buf + i * cols, cols); } new_buf[len+(1+depth)*nlines] = '\n'; + + // Inserts final row of indentation and termination character for (j = 0; j < depth; j++) new_buf[len+(1+depth)*nlines + 1 + j] = '\t'; new_buf[len+(1+depth)*nlines+depth+1] = '\0'; + return new_buf; } +/** Creates a new plist XML document. + * + * @return The plist XML document. + */ xmlDocPtr new_plist() { char *plist = strdup(plist_base); xmlDocPtr plist_xml = xmlReadMemory(plist, strlen(plist), NULL, NULL, 0); + if (!plist_xml) return NULL; + free(plist); + return plist_xml; } +/** Destroys a previously created XML document. + * + * @param plist The XML document to destroy. + */ void free_plist(xmlDocPtr plist) { if (!plist) return; + xmlFreeDoc(plist); } +/** Adds a new node as a child to a given node. + * + * This is a lower level function so you probably want to use + * add_key_str_dict_element, add_key_dict_node or add_key_data_dict_element + * instead. + * + * @param plist The plist XML document to which the to_node belongs. + * @param name The name of the new node. + * @param content The string containing the text node of the new node. + * @param to_node The node to attach the child node to. If none is given, the + * root node of the given document is used. + * @param depth The number of tabs to indent the new node. + * + * @return The newly created node. + */ xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode *to_node, int depth) { - if (!plist) return NULL; int i = 0; xmlNode *child; + + if (!plist) return NULL; + assert(depth > 0); if (!to_node) to_node = xmlDocGetRootElement(plist); + for (i = 0; i < depth; i++) { xmlNodeAddContent(to_node, "\t"); } child = xmlNewChild(to_node, NULL, name, content); xmlNodeAddContent(to_node, "\n"); + return child; } +/** Adds a string key-pair to a plist XML document. + * + * @param plist The plist XML document to add the new node to. + * @param dict The dictionary node within the plist XML document to add the new node to. + * @param key The string containing the key value. + * @param value The string containing the value. + * @param depth The number of tabs to indent the new node. + * + * @return The newly created key node. + */ xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth) { xmlNode *keyPtr; + keyPtr = add_child_to_plist(plist, "key", key, dict, depth); add_child_to_plist(plist, "string", value, dict, depth); + return keyPtr; } +/** Adds a new dictionary key-pair to a plist XML document. + * + * @param plist The plist XML document to add the new node to. + * @param dict The dictionary node within the plist XML document to add the new node to. + * @param key The string containing the key value. + * @param value The string containing the value. + * @param depth The number of tabs to indent the new node. + * + * @return The newly created dict node. + */ xmlNode *add_key_dict_node(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth) { xmlNode *child; + add_child_to_plist(plist, "key", key, dict, depth); child = add_child_to_plist(plist, "dict", value, dict, depth); + return child; } +/** Adds a new data dictionary key-pair to a plist XML document. + * + * @param plist The plist XML document to add the new node to. + * @param dict The dictionary node within the plist XML document to add the new node to. + * @param key The string containing the key value. + * @param value The string containing the value. + * @param depth The number of tabs to indent the new node. + * + * @return The newly created key node. + */ xmlNode *add_key_data_dict_element(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth) { xmlNode *keyPtr; + keyPtr = add_child_to_plist(plist, "key", key, dict, depth); add_child_to_plist(plist, "data", format_string(value, 60, depth), dict, depth); + return keyPtr; } +/** Reads a set of keys and strings into an array from a plist XML document. + * + * @param dict The root XMLNode of a plist XML document to be read. + * + * @return An array where each even number is a key and the odd numbers are + * values. If the odd number is \0, that's the end of the list. + */ char **read_dict_element_strings(xmlNode *dict) { - // reads a set of keys and strings into an array where each even number is a key and odd numbers are values. - // if the odd number is \0, that's the end of the list. char **return_me = NULL, **old = NULL; int current_length = 0; int current_pos = 0; @@ -120,7 +210,6 @@ char **read_dict_element_strings(xmlNode *dict) { } } - // one last thing... old = return_me; return_me = realloc(return_me, sizeof(char*) * (current_length+1)); return_me[current_pos] = strdup(""); @@ -128,10 +217,13 @@ char **read_dict_element_strings(xmlNode *dict) { return return_me; } +/** Destroys a dictionary as returned by read_dict_element_strings + */ void free_dictionary(char **dictionary) { - if (!dictionary) return; int i = 0; + if (!dictionary) return; + for (i = 0; strcmp(dictionary[i], ""); i++) { free(dictionary[i]); } |