diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/plist.c | 106 | ||||
| -rw-r--r-- | src/plist.h | 3 | 
2 files changed, 101 insertions, 8 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]);  	} diff --git a/src/plist.h b/src/plist.h index 61965fc..ab79386 100644 --- a/src/plist.h +++ b/src/plist.h @@ -29,9 +29,10 @@ xmlNode *add_key_dict_node(xmlDocPtr plist, xmlNode *dict, const char *key, cons  xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth);  xmlNode *add_key_data_dict_element(xmlDocPtr plist, xmlNode *dict, const char *key, const char *value, int depth);  xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode *to_node, int depth); +  void free_plist(xmlDocPtr plist);  xmlDocPtr new_plist(); +  char **read_dict_element_strings(xmlNode *dict);  void free_dictionary(char **dictionary); -char **read_dict_element_strings(xmlNode *dict);  #endif | 
