diff options
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | libplist.pc.in | 2 | ||||
-rw-r--r-- | src/CMakeLists.txt | 20 | ||||
-rw-r--r-- | src/base64.c | 127 | ||||
-rw-r--r-- | src/base64.h | 29 | ||||
-rw-r--r-- | src/bplist.c | 339 | ||||
-rw-r--r-- | src/bytearray.c | 52 | ||||
-rw-r--r-- | src/bytearray.h | 36 | ||||
-rw-r--r-- | src/common.h | 15 | ||||
-rw-r--r-- | src/hashtable.c | 107 | ||||
-rw-r--r-- | src/hashtable.h | 48 | ||||
-rw-r--r-- | src/plist.c | 101 | ||||
-rw-r--r-- | src/plist.h | 13 | ||||
-rw-r--r-- | src/ptrarray.c | 61 | ||||
-rw-r--r-- | src/ptrarray.h | 37 | ||||
-rw-r--r-- | src/xplist.c | 85 | ||||
-rw-r--r-- | test/CMakeLists.txt | 2 | ||||
-rw-r--r-- | test/plist_cmp.c | 6 |
18 files changed, 876 insertions, 210 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 02461dd..0790f74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,6 @@ IF(NOT DEFINED CMAKE_INSTALL_LIBDIR) ENDIF(NOT DEFINED CMAKE_INSTALL_LIBDIR) FIND_PACKAGE( LibXml2 REQUIRED ) -FIND_PACKAGE( GLIB2 REQUIRED ) OPTION(ENABLE_PYTHON "Enable Python bindings (needs Swig)" ON) @@ -31,6 +30,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/include ENABLE_TESTING() +ADD_SUBDIRECTORY( libcnary ) ADD_SUBDIRECTORY( src ) ADD_SUBDIRECTORY( plutil ) ADD_SUBDIRECTORY( include ) @@ -40,6 +40,10 @@ IF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) ADD_SUBDIRECTORY( swig ) ENDIF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) +INCLUDE (TestBigEndian) +TEST_BIG_ENDIAN(endianess) +SET ( PLIST_BYTE_ORDER ${endianess} ) + # add uninstall target CONFIGURE_FILE( "${CMAKE_SOURCE_DIR}/cmake/modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") diff --git a/libplist.pc.in b/libplist.pc.in index ad83877..971b8b5 100644 --- a/libplist.pc.in +++ b/libplist.pc.in @@ -6,7 +6,7 @@ includedir=${CMAKE_INSTALL_PREFIX}/include Name: libplist Description: A library to handle Apple Property Lists whereas they are binary or XML Version: ${LIBPLIST_VERSION} -Requires.private: libxml-2.0 >= 2.6.30 glib-2.0 >= 2.14.1 +Requires.private: libxml-2.0 >= 2.6.30 Libs: -L${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} -lplist Cflags: -I${CMAKE_INSTALL_PREFIX}/include diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 85ce6eb..76f323a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,10 +1,14 @@ -INCLUDE_DIRECTORIES( ${LIBXML2_INCLUDE_DIR} ${GLIB2_INCLUDE_DIR} ) +INCLUDE_DIRECTORIES( ${LIBXML2_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/libcnary/include ) SET(libplist_SRC plist.c + hashtable.c + bytearray.c + ptrarray.c bplist.c + base64.c xplist.c ) SET(libplist++_SRC @@ -20,8 +24,18 @@ SET(libplist++_SRC Dictionary.cpp ) -ADD_LIBRARY( plist SHARED ${libplist_SRC} ) -TARGET_LINK_LIBRARIES( plist ${LIBXML2_LIBRARIES} ${GLIB2_LIBRARIES} ) +SET(libcnary_object_files + ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/iterator.c.o + ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/list.c.o + ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/node.c.o + ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/node_iterator.c.o + ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/node_list.c.o +) + +SET_SOURCE_FILES_PROPERTIES(${libcnary_object_files} PROPERTIES EXTERNAL_OBJECT true GENERATED true) + +ADD_LIBRARY( plist SHARED ${libplist_SRC} ${libcnary_object_files} ) +TARGET_LINK_LIBRARIES( plist ${LIBXML2_LIBRARIES} ) SET_TARGET_PROPERTIES( plist PROPERTIES VERSION ${LIBPLIST_LIBVERSION} ) SET_TARGET_PROPERTIES( plist PROPERTIES SOVERSION ${LIBPLIST_SOVERSION} ) if(APPLE) diff --git a/src/base64.c b/src/base64.c new file mode 100644 index 0000000..066494e --- /dev/null +++ b/src/base64.c @@ -0,0 +1,127 @@ +/* + * base64.c + * base64 encode/decode implementation + * + * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <string.h> +#include "base64.h" + +static const char base64_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char base64_pad = '='; + +static const int8_t base64_table[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +char *base64encode(const unsigned char *buf, size_t *size) +{ + if (!buf || !size || !(*size > 0)) return NULL; + int outlen = (*size / 3) * 4; + char *outbuf = (char*)malloc(outlen+5); // 4 spare bytes + 1 for '\0' + size_t n = 0; + size_t m = 0; + unsigned char input[3]; + unsigned int output[4]; + while (n < *size) { + input[0] = buf[n++]; + input[1] = (n < *size) ? buf[n++] : 0; + input[2] = (n < *size) ? buf[n++] : 0; + output[0] = input[0] >> 2; + output[1] = ((input[0] & 3) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 15) << 2) + (input[2] >> 6); + output[3] = input[2] & 63; + outbuf[m++] = base64_str[(int)output[0]]; + outbuf[m++] = base64_str[(int)output[1]]; + outbuf[m++] = base64_str[(int)output[2]]; + outbuf[m++] = base64_str[(int)output[3]]; + } + while ((m % 4) != 0) { + outbuf[m++] = base64_pad; + } + outbuf[m] = 0; // 0-termination! + *size = m; + return outbuf; +} + +static int base64decode_block(unsigned char *target, const char *data, size_t data_size) +{ + int w1,w2,w3,w4; + int n,i; + + if (!data || (data_size <= 0)) { + return 0; + } + + n = 0; + i = 0; + while (n < data_size-3) { + w1 = base64_table[(int)data[n]]; + w2 = base64_table[(int)data[n+1]]; + w3 = base64_table[(int)data[n+2]]; + w4 = base64_table[(int)data[n+3]]; + + if (w2 >= 0) { + target[i++] = (char)((w1*4 + (w2 >> 4)) & 255); + } + if (w3 >= 0) { + target[i++] = (char)((w2*16 + (w3 >> 2)) & 255); + } + if (w4 >= 0) { + target[i++] = (char)((w3*64 + w4) & 255); + } + n+=4; + } + return i; +} + +unsigned char *base64decode(const char *buf, size_t *size) +{ + if (!buf) return; + size_t len = strlen(buf); + if (len <= 0) return; + unsigned char *outbuf = (unsigned char*)malloc((len/4)*3+3); + + unsigned char *line; + int p = 0; + + line = (unsigned char*)strtok((char*)buf, "\r\n\t "); + while (line) { + p+=base64decode_block(outbuf+p, line, strlen((char*)line)); + + // get next line of base64 encoded block + line = (unsigned char*)strtok(NULL, "\r\n\t "); + } + outbuf[p] = 0; + *size = p; + return outbuf; +} diff --git a/src/base64.h b/src/base64.h new file mode 100644 index 0000000..dbaf104 --- /dev/null +++ b/src/base64.h @@ -0,0 +1,29 @@ +/* + * base64.h + * base64 encode/decode implementation + * + * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef BASE64_H +#define BASE64_H +#include <stdlib.h> +#include "common.h" + +_PLIST_INTERNAL char *base64encode(const unsigned char *buf, size_t *size); +_PLIST_INTERNAL unsigned char *base64decode(const char *buf, size_t *size); + +#endif diff --git a/src/bplist.c b/src/bplist.c index 82d1813..77e6245 100644 --- a/src/bplist.c +++ b/src/bplist.c @@ -29,6 +29,12 @@ #include <plist/plist.h> #include "plist.h" +#include "hashtable.h" +#include "bytearray.h" +#include "ptrarray.h" + +#include <node.h> +#include <node_iterator.h> /* Magic marker and size. */ #define BPLIST_MAGIC ((uint8_t*)"bplist") @@ -66,7 +72,7 @@ enum static void float_byte_convert(uint8_t * address, size_t size) { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN && !defined (__VFP_FP__) +#if PLIST_BYTE_ORDER == PLIST_LITTLE_ENDIAN && !defined (__VFP_FP__) uint8_t i = 0, j = 0; uint8_t tmp = 0; @@ -100,7 +106,7 @@ union plist_uint_ptr static void byte_convert(uint8_t * address, size_t size) { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#if PLIST_BYTE_ORDER == PLIST_LITTLE_ENDIAN uint8_t i = 0, j = 0; uint8_t tmp = 0; @@ -131,10 +137,10 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf) ({ \ union plist_uint_ptr __up; \ __up.src = x; \ - (n == 8 ? GUINT64_FROM_BE( get_unaligned(__up.u64ptr) ) : \ - (n == 4 ? GUINT32_FROM_BE( get_unaligned(__up.u32ptr) ) : \ + (n == 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \ + (n == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \ (n == 3 ? uint24_from_be( __up ) : \ - (n == 2 ? GUINT16_FROM_BE( get_unaligned(__up.u16ptr) ) : \ + (n == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \ *__up.u8ptr )))); \ }) @@ -142,7 +148,7 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf) ({ \ union plist_uint_ptr __up; \ __up.src = x; \ - GUINT64_FROM_BE( get_unaligned(__up.u64ptr) ); \ + be64toh( get_unaligned(__up.u64ptr) ); \ }) #define get_needed_bytes(x) \ @@ -153,6 +159,7 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf) #define get_real_bytes(x) (x == (float) x ? 4 : 8) +#define NODE_IS_ROOT(x) (((node_t*)x)->isRoot) static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) { @@ -177,7 +184,7 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) data->type = PLIST_UINT; data->length = sizeof(uint64_t); - return g_node_new(data); + return node_create(NULL, data); } static plist_t parse_real_node(char *bnode, uint8_t size) @@ -208,7 +215,7 @@ static plist_t parse_real_node(char *bnode, uint8_t size) data->type = PLIST_REAL; data->length = sizeof(double); - return g_node_new(data); + return node_create(NULL, data); } static plist_t parse_date_node(char *bnode, uint8_t size) @@ -217,10 +224,10 @@ static plist_t parse_date_node(char *bnode, uint8_t size) plist_data_t data = plist_get_data(node); double time_real = data->realval; - data->timeval.tv_sec = (glong) time_real; - data->timeval.tv_usec = (time_real - (glong) time_real) * G_USEC_PER_SEC; + data->timeval.tv_sec = (long) time_real; + data->timeval.tv_usec = (time_real - (long) time_real) * 1000000; data->type = PLIST_DATE; - data->length = sizeof(GTimeVal); + data->length = sizeof(struct timeval); return node; } @@ -235,26 +242,58 @@ static plist_t parse_string_node(char *bnode, uint64_t size) data->strval[size] = '\0'; data->length = strlen(data->strval); - return g_node_new(data); + return node_create(NULL, data); +} + +static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, long *items_written) +{ + if (!unistr || (len <= 0)) return NULL; + char *outbuf = (char*)malloc(3*(len+1)); + int p = 0; + int i = 0; + + uint16_t wc; + + while (i < len) { + wc = unistr[i++]; + if (wc >= 0x800) { + outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF)); + outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F)); + outbuf[p++] = (char)(0x80 + (wc & 0x3F)); + } else if (wc >= 0x80) { + outbuf[p++] = (char)(0xC0 + ((wc >> 6) & 0x1F)); + outbuf[p++] = (char)(0x80 + (wc & 0x3F)); + } else { + outbuf[p++] = (char)(wc & 0x7F); + } + } + if (items_read) { + *items_read = i; + } + if (items_written) { + *items_written = p; + } + outbuf[p] = 0; + + return outbuf; } static plist_t parse_unicode_node(char *bnode, uint64_t size) { plist_data_t data = plist_new_plist_data(); uint64_t i = 0; - gunichar2 *unicodestr = NULL; - gchar *tmpstr = NULL; - glong items_read = 0; - glong items_written = 0; - GError *error = NULL; + uint16_t *unicodestr = NULL; + char *tmpstr = NULL; + long items_read = 0; + long items_written = 0; data->type = PLIST_STRING; - unicodestr = (gunichar2 *) malloc(sizeof(gunichar2) * size); - memcpy(unicodestr, bnode, sizeof(gunichar2) * size); + unicodestr = (uint16_t*) malloc(sizeof(uint16_t) * size); + memcpy(unicodestr, bnode, sizeof(uint16_t) * size); for (i = 0; i < size; i++) - byte_convert((uint8_t *) (unicodestr + i), sizeof(gunichar2)); + byte_convert((uint8_t *) (unicodestr + i), sizeof(uint16_t)); - tmpstr = g_utf16_to_utf8(unicodestr, size, &items_read, &items_written, &error); + tmpstr = plist_utf16_to_utf8(unicodestr, size, &items_read, &items_written); free(unicodestr); data->type = PLIST_STRING; @@ -262,8 +301,8 @@ static plist_t parse_unicode_node(char *bnode, uint64_t size) memcpy(data->strval, tmpstr, items_written); data->strval[items_written] = '\0'; data->length = strlen(data->strval); - g_free(tmpstr); - return g_node_new(data); + free(tmpstr); + return node_create(NULL, data); } static plist_t parse_data_node(char *bnode, uint64_t size) @@ -275,7 +314,7 @@ static plist_t parse_data_node(char *bnode, uint64_t size) data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size); memcpy(data->buff, bnode, sizeof(uint8_t) * size); - return g_node_new(data); + return node_create(NULL, data); } static plist_t parse_dict_node(char *bnode, uint64_t size, uint32_t ref_size) @@ -287,7 +326,7 @@ static plist_t parse_dict_node(char *bnode, uint64_t size, uint32_t ref_size) data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size * 2); memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size * 2); - return g_node_new(data); + return node_create(NULL, data); } static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) @@ -299,7 +338,7 @@ static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size); memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size); - return g_node_new(data); + return node_create(NULL, data); } @@ -329,7 +368,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec data->type = PLIST_BOOLEAN; data->boolval = TRUE; data->length = 1; - return g_node_new(data); + return node_create(NULL, data); } case BPLIST_FALSE: @@ -338,7 +377,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec data->type = PLIST_BOOLEAN; data->boolval = FALSE; data->length = 1; - return g_node_new(data); + return node_create(NULL, data); } case BPLIST_NULL: @@ -420,7 +459,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec return NULL; } -static gpointer copy_plist_data(gconstpointer src, gpointer data) +static void* copy_plist_data(const void* src) { plist_data_t srcdata = (plist_data_t) src; plist_data_t dstdata = plist_new_plist_data(); @@ -541,18 +580,18 @@ void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) if (index1 < num_objects) { - if (G_NODE_IS_ROOT(nodeslist[index1])) - g_node_append(nodeslist[i], nodeslist[index1]); + if (NODE_IS_ROOT(nodeslist[index1])) + node_attach(nodeslist[i], nodeslist[index1]); else - g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index1], copy_plist_data, NULL)); + node_attach(nodeslist[i], node_copy_deep(nodeslist[index1], copy_plist_data)); } if (index2 < num_objects) { - if (G_NODE_IS_ROOT(nodeslist[index2])) - g_node_append(nodeslist[i], nodeslist[index2]); + if (NODE_IS_ROOT(nodeslist[index2])) + node_attach(nodeslist[i], nodeslist[index2]); else - g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index2], copy_plist_data, NULL)); + node_attach(nodeslist[i], node_copy_deep(nodeslist[index2], copy_plist_data)); } } @@ -567,10 +606,10 @@ void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) if (index1 < num_objects) { - if (G_NODE_IS_ROOT(nodeslist[index1])) - g_node_append(nodeslist[i], nodeslist[index1]); + if (NODE_IS_ROOT(nodeslist[index1])) + node_attach(nodeslist[i], nodeslist[index1]); else - g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index1], copy_plist_data, NULL)); + node_attach(nodeslist[i], node_copy_deep(nodeslist[index1], copy_plist_data)); } } free(data->buff); @@ -584,15 +623,15 @@ void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) free(nodeslist); } -static guint plist_data_hash(gconstpointer key) +static unsigned int plist_data_hash(const void* key) { plist_data_t data = plist_get_data((plist_t) key); - guint hash = data->type; - guint i = 0; + unsigned int hash = data->type; + unsigned int i = 0; char *buff = NULL; - guint size = 0; + unsigned int size = 0; switch (data->type) { @@ -612,7 +651,7 @@ static guint plist_data_hash(gconstpointer key) case PLIST_DICT: //for these types only hash pointer buff = (char *) &key; - size = sizeof(gconstpointer); + size = sizeof(const void*); break; case PLIST_DATE: buff = (char *) &(data->timeval); @@ -629,22 +668,20 @@ static guint plist_data_hash(gconstpointer key) return hash; } - - struct serialize_s { - GPtrArray *objects; - GHashTable *ref_table; + ptrarray_t* objects; + hashtable_t* ref_table; }; -static void serialize_plist(GNode * node, gpointer data) +static void serialize_plist(node_t* node, void* data) { uint64_t *index_val = NULL; struct serialize_s *ser = (struct serialize_s *) data; uint64_t current_index = ser->objects->len; //first check that node is not yet in objects - gpointer val = g_hash_table_lookup(ser->ref_table, node); + void* val = hash_table_lookup(ser->ref_table, node); if (val) { //data is already in table @@ -653,17 +690,23 @@ static void serialize_plist(GNode * node, gpointer data) //insert new ref index_val = (uint64_t *) malloc(sizeof(uint64_t)); *index_val = current_index; - g_hash_table_insert(ser->ref_table, node, index_val); + hash_table_insert(ser->ref_table, node, index_val); //now append current node to object array - g_ptr_array_add(ser->objects, node); + ptr_array_add(ser->objects, node); //now recurse on children - g_node_children_foreach(node, G_TRAVERSE_ALL, serialize_plist, data); + node_iterator_t *ni = node_iterator_create(node->children); + node_t *ch; + while ((ch = node_iterator_next(ni))) { + serialize_plist(ch, data); + } + node_iterator_destroy(ni); + return; } -static gboolean free_index(gpointer key, gpointer value, gpointer user_data) +static int free_index(void* key, void* value, void* user_data) { free((uint64_t *) value); return TRUE; @@ -671,7 +714,7 @@ static gboolean free_index(gpointer key, gpointer value, gpointer user_data) #define Log2(x) (x == 8 ? 3 : (x == 4 ? 2 : (x == 2 ? 1 : 0))) -static void write_int(GByteArray * bplist, uint64_t val) +static void write_int(bytearray_t * bplist, uint64_t val) { uint64_t size = get_needed_bytes(val); uint8_t *buff = NULL; @@ -679,7 +722,7 @@ static void write_int(GByteArray * bplist, uint64_t val) if (size == 3) size++; -#if G_BYTE_ORDER == G_BIG_ENDIAN +#if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN val = val << ((sizeof(uint64_t) - size) * 8); #endif @@ -687,11 +730,11 @@ static void write_int(GByteArray * bplist, uint64_t val) buff[0] = BPLIST_UINT | Log2(size); memcpy(buff + 1, &val, size); byte_convert(buff + 1, size); - g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); + byte_array_append(bplist, buff, sizeof(uint8_t) + size); free(buff); } -static void write_real(GByteArray * bplist, double val) +static void write_real(bytearray_t * bplist, double val) { uint64_t size = get_real_bytes(val); //cheat to know used space uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); @@ -706,89 +749,89 @@ static void write_real(GByteArray * bplist, double val) memcpy(buff + 1, &tmpval, size); } float_byte_convert(buff + 1, size); - g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); + byte_array_append(bplist, buff, sizeof(uint8_t) + size); free(buff); } -static void write_date(GByteArray * bplist, double val) +static void write_date(bytearray_t * bplist, double val) { uint64_t size = 8; //dates always use 8 bytes uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); buff[0] = BPLIST_DATE | Log2(size); memcpy(buff + 1, &val, size); float_byte_convert(buff + 1, size); - g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); + byte_array_append(bplist, buff, sizeof(uint8_t) + size); free(buff); } -static void write_raw_data(GByteArray * bplist, uint8_t mark, uint8_t * val, uint64_t size) +static void write_raw_data(bytearray_t * bplist, uint8_t mark, uint8_t * val, uint64_t size) { uint8_t *buff = NULL; uint8_t marker = mark | (size < 15 ? size : 0xf); - g_byte_array_append(bplist, &marker, sizeof(uint8_t)); + byte_array_append(bplist, &marker, sizeof(uint8_t)); if (size >= 15) { - GByteArray *int_buff = g_byte_array_new(); + bytearray_t *int_buff = byte_array_new(); write_int(int_buff, size); - g_byte_array_append(bplist, int_buff->data, int_buff->len); - g_byte_array_free(int_buff, TRUE); + byte_array_append(bplist, int_buff->data, int_buff->len); + byte_array_free(int_buff); } //stupid unicode buffer length if (BPLIST_UNICODE==mark) size *= 2; buff = (uint8_t *) malloc(size); memcpy(buff, val, size); - g_byte_array_append(bplist, buff, size); + byte_array_append(bplist, buff, size); free(buff); } -static void write_data(GByteArray * bplist, uint8_t * val, uint64_t size) +static void write_data(bytearray_t * bplist, uint8_t * val, uint64_t size) { write_raw_data(bplist, BPLIST_DATA, val, size); } -static void write_string(GByteArray * bplist, char *val) +static void write_string(bytearray_t * bplist, char *val) { uint64_t size = strlen(val); write_raw_data(bplist, BPLIST_STRING, (uint8_t *) val, size); } -static void write_unicode(GByteArray * bplist, gunichar2 * val, uint64_t size) +static void write_unicode(bytearray_t * bplist, uint16_t * val, uint64_t size) { uint64_t i = 0; - uint64_t size2 = size * sizeof(gunichar2); + uint64_t size2 = size * sizeof(uint16_t); uint8_t *buff = (uint8_t *) malloc(size2); memcpy(buff, val, size2); for (i = 0; i < size; i++) - byte_convert(buff + i * sizeof(gunichar2), sizeof(gunichar2)); + byte_convert(buff + i * sizeof(uint16_t), sizeof(uint16_t)); write_raw_data(bplist, BPLIST_UNICODE, buff, size); free(buff); } -static void write_array(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) +static void write_array(bytearray_t * bplist, node_t* node, hashtable_t* ref_table, uint8_t dict_param_size) { uint64_t idx = 0; uint8_t *buff = NULL; - GNode *cur = NULL; + node_t* cur = NULL; uint64_t i = 0; - uint64_t size = g_node_n_children(node); + uint64_t size = node_n_children(node); uint8_t marker = BPLIST_ARRAY | (size < 15 ? size : 0xf); - g_byte_array_append(bplist, &marker, sizeof(uint8_t)); + byte_array_append(bplist, &marker, sizeof(uint8_t)); if (size >= 15) { - GByteArray *int_buff = g_byte_array_new(); + bytearray_t *int_buff = byte_array_new(); write_int(int_buff, size); - g_byte_array_append(bplist, int_buff->data, int_buff->len); - g_byte_array_free(int_buff, TRUE); + byte_array_append(bplist, int_buff->data, int_buff->len); + byte_array_free(int_buff); } buff = (uint8_t *) malloc(size * dict_param_size); - for (i = 0, cur = node->children; cur && i < size; cur = cur->next, i++) + for (i = 0, cur = node_first_child(node); cur && i < size; cur = node_next_sibling(cur), i++) { - idx = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); -#if G_BYTE_ORDER == G_BIG_ENDIAN + idx = *(uint64_t *) (hash_table_lookup(ref_table, cur)); +#if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN idx = idx << ((sizeof(uint64_t) - dict_param_size) * 8); #endif memcpy(buff + i * dict_param_size, &idx, dict_param_size); @@ -796,44 +839,43 @@ static void write_array(GByteArray * bplist, GNode * node, GHashTable * ref_tabl } //now append to bplist - g_byte_array_append(bplist, buff, size * dict_param_size); + byte_array_append(bplist, buff, size * dict_param_size); free(buff); } -static void write_dict(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) +static void write_dict(bytearray_t * bplist, node_t* node, hashtable_t* ref_table, uint8_t dict_param_size) { uint64_t idx1 = 0; uint64_t idx2 = 0; uint8_t *buff = NULL; - GNode *cur = NULL; + node_t* cur = NULL; uint64_t i = 0; - uint64_t size = g_node_n_children(node) / 2; + uint64_t size = node_n_children(node) / 2; uint8_t marker = BPLIST_DICT | (size < 15 ? size : 0xf); - g_byte_array_append(bplist, &marker, sizeof(uint8_t)); + byte_array_append(bplist, &marker, sizeof(uint8_t)); if (size >= 15) { - GByteArray *int_buff = g_byte_array_new(); + bytearray_t *int_buff = byte_array_new(); write_int(int_buff, size); - g_byte_array_append(bplist, int_buff->data, int_buff->len); - g_byte_array_free(int_buff, TRUE); + byte_array_append(bplist, int_buff->data, int_buff->len); + byte_array_free(int_buff); } buff = (uint8_t *) malloc(size * 2 * dict_param_size); - - for (i = 0, cur = node->children; cur && i < size; cur = cur->next->next, i++) + for (i = 0, cur = node_first_child(node); cur && i < size; cur = node_next_sibling(node_next_sibling(cur)), i++) { - idx1 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); -#if G_BYTE_ORDER == G_BIG_ENDIAN + idx1 = *(uint64_t *) (hash_table_lookup(ref_table, cur)); +#if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN idx1 = idx1 << ((sizeof(uint64_t) - dict_param_size) * 8); #endif memcpy(buff + i * dict_param_size, &idx1, dict_param_size); byte_convert(buff + i * dict_param_size, dict_param_size); - idx2 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur->next)); -#if G_BYTE_ORDER == G_BIG_ENDIAN + idx2 = *(uint64_t *) (hash_table_lookup(ref_table, cur->next)); +#if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN idx2 = idx2 << ((sizeof(uint64_t) - dict_param_size) * 8); #endif memcpy(buff + (i + size) * dict_param_size, &idx2, dict_param_size); @@ -841,7 +883,7 @@ static void write_dict(GByteArray * bplist, GNode * node, GHashTable * ref_table } //now append to bplist - g_byte_array_append(bplist, buff, size * 2 * dict_param_size); + byte_array_append(bplist, buff, size * 2 * dict_param_size); free(buff); } @@ -860,38 +902,81 @@ static int is_ascii_string(char* s, int len) return ret; } +uint16_t *plist_utf8_to_utf16(char *unistr, long size, long *items_read, long *items_written) +{ + uint16_t *outbuf = (uint16_t*)malloc((size+1)*sizeof(uint16_t)); + int p = 0; + int i = 0; + + unsigned char c0; + unsigned char c1; + unsigned char c2; + + while (i < size) { + c0 = unistr[i]; + c1 = (i < size-1) ? unistr[i+1] : 0; + c2 = (i < size-2) ? unistr[i+2] : 0; + if ((c0 >= 0xE0) && (i < size-2) && (c1 >= 0x80) && (c2 >= 0x80)) { + // 3 byte sequence + outbuf[p++] = ((c2 & 0x3F) + ((c1 & 3) << 6)) + (((c1 >> 2) & 15) << 8) + ((c0 & 15) << 12); + i+=3; + } else if ((c0 >= 0xC0) && (i < size-1) && (c1 >= 0x80)) { + // 2 byte sequence + outbuf[p++] = ((c1 & 0x3F) + ((c0 & 3) << 6)) + (((c0 >> 2) & 7) << 8); + i+=2; + } else if (c0 < 0x80) { + // 1 byte sequence + outbuf[p++] = c0; + i+=1; + } else { + // invalid character + fprintf(stderr, "invalid utf8 sequence in string at index %d\n", i); + break; + } + } + if (items_read) { + *items_read = i; + } + if (items_written) { + *items_written = p; + } + outbuf[p] = 0; + + return outbuf; + +} + void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) { - GPtrArray *objects = NULL; - GHashTable *ref_table = NULL; + ptrarray_t* objects = NULL; + hashtable_t* ref_table = NULL; struct serialize_s ser_s; uint8_t offset_size = 0; uint8_t dict_param_size = 0; uint64_t num_objects = 0; uint64_t root_object = 0; uint64_t offset_table_index = 0; - GByteArray *bplist_buff = NULL; + bytearray_t *bplist_buff = NULL; uint64_t i = 0; uint8_t *buff = NULL; uint64_t *offsets = NULL; uint8_t pad[6] = { 0, 0, 0, 0, 0, 0 }; uint8_t trailer[BPLIST_TRL_SIZE]; //for string - glong len = 0; + long len = 0; int type = 0; - glong items_read = 0; - glong items_written = 0; - GError *error = NULL; - gunichar2 *unicodestr = NULL; + long items_read = 0; + long items_written = 0; + uint16_t *unicodestr = NULL; //check for valid input if (!plist || !plist_bin || *plist_bin || !length) return; //list of objects - objects = g_ptr_array_new(); + objects = ptr_array_new(256); //hashtable to write only once same nodes - ref_table = g_hash_table_new(plist_data_hash, plist_data_compare); + ref_table = hash_table_new(plist_data_hash, plist_data_compare); //serialize plist ser_s.objects = objects; @@ -906,18 +991,18 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) offset_table_index = 0; //unknown yet //setup a dynamic bytes array to store bplist in - bplist_buff = g_byte_array_new(); + bplist_buff = byte_array_new(); //set magic number and version - g_byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); - g_byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE); + byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); + byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE); //write objects and table offsets = (uint64_t *) malloc(num_objects * sizeof(uint64_t)); for (i = 0; i < num_objects; i++) { - plist_data_t data = plist_get_data(g_ptr_array_index(objects, i)); + plist_data_t data = plist_get_data(ptr_array_index(objects, i)); offsets[i] = bplist_buff->len; switch (data->type) @@ -925,7 +1010,7 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) case PLIST_BOOLEAN: buff = (uint8_t *) malloc(sizeof(uint8_t)); buff[0] = data->boolval ? BPLIST_TRUE : BPLIST_FALSE; - g_byte_array_append(bplist_buff, buff, sizeof(uint8_t)); + byte_array_append(bplist_buff, buff, sizeof(uint8_t)); free(buff); break; @@ -946,21 +1031,21 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) } else { - unicodestr = g_utf8_to_utf16(data->strval, len, &items_read, &items_written, &error); + unicodestr = plist_utf8_to_utf16(data->strval, len, &items_read, &items_written); write_unicode(bplist_buff, unicodestr, items_written); - g_free(unicodestr); + free(unicodestr); } break; case PLIST_DATA: write_data(bplist_buff, data->buff, data->length); case PLIST_ARRAY: - write_array(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); + write_array(bplist_buff, ptr_array_index(objects, i), ref_table, dict_param_size); break; case PLIST_DICT: - write_dict(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); + write_dict(bplist_buff, ptr_array_index(objects, i), ref_table, dict_param_size); break; case PLIST_DATE: - write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / G_USEC_PER_SEC); + write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / 1000000); break; default: break; @@ -968,9 +1053,9 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) } //free intermediate objects - g_hash_table_foreach_remove(ref_table, free_index, NULL); - g_ptr_array_free(objects, TRUE); - g_hash_table_destroy(ref_table); + //hash_table_foreach_remove(ref_table, free_index, NULL); + ptr_array_free(objects); + hash_table_destroy(ref_table); //write offsets offset_size = get_needed_bytes(bplist_buff->len); @@ -979,23 +1064,23 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) { uint8_t *offsetbuff = (uint8_t *) malloc(offset_size); -#if G_BYTE_ORDER == G_BIG_ENDIAN +#if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN offsets[i] = offsets[i] << ((sizeof(uint64_t) - offset_size) * 8); #endif memcpy(offsetbuff, &offsets[i], offset_size); byte_convert(offsetbuff, offset_size); - g_byte_array_append(bplist_buff, offsetbuff, offset_size); + byte_array_append(bplist_buff, offsetbuff, offset_size); free(offsetbuff); } //experimental pad to reflect apple's files - g_byte_array_append(bplist_buff, pad, 6); + byte_array_append(bplist_buff, pad, 6); //setup trailer - num_objects = GUINT64_FROM_BE(num_objects); - root_object = GUINT64_FROM_BE(root_object); - offset_table_index = GUINT64_FROM_BE(offset_table_index); + num_objects = be64toh(num_objects); + root_object = be64toh(root_object); + offset_table_index = be64toh(offset_table_index); memcpy(trailer + BPLIST_TRL_OFFSIZE_IDX, &offset_size, sizeof(uint8_t)); memcpy(trailer + BPLIST_TRL_PARMSIZE_IDX, &dict_param_size, sizeof(uint8_t)); @@ -1003,13 +1088,13 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) memcpy(trailer + BPLIST_TRL_ROOTOBJ_IDX, &root_object, sizeof(uint64_t)); memcpy(trailer + BPLIST_TRL_OFFTAB_IDX, &offset_table_index, sizeof(uint64_t)); - g_byte_array_append(bplist_buff, trailer, BPLIST_TRL_SIZE); + byte_array_append(bplist_buff, trailer, BPLIST_TRL_SIZE); //duplicate buffer *plist_bin = (char *) malloc(bplist_buff->len); memcpy(*plist_bin, bplist_buff->data, bplist_buff->len); *length = bplist_buff->len; - g_byte_array_free(bplist_buff, TRUE); + byte_array_free(bplist_buff); free(offsets); } diff --git a/src/bytearray.c b/src/bytearray.c new file mode 100644 index 0000000..0abfe49 --- /dev/null +++ b/src/bytearray.c @@ -0,0 +1,52 @@ +/* + * bytearray.c + * simple byte array implementation + * + * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <string.h> +#include "bytearray.h" + +bytearray_t *byte_array_new() +{ + bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t)); + a->data = malloc(256); + a->len = 0; + a->capacity = 256; + return a; +} + +void byte_array_free(bytearray_t *ba) +{ + if (!ba) return; + if (ba->data) { + free(ba->data); + } + free(ba); +} + +void byte_array_append(bytearray_t *ba, void *buf, size_t len) +{ + if (!ba || !ba->data || (len <= 0)) return; + size_t remaining = ba->capacity-ba->len; + if (len > remaining) { + ba->data = realloc(ba->data, ba->capacity + (len - remaining)); + ba->capacity += (len - remaining); + } + memcpy(ba->data+ba->len, buf, len); + ba->len += len; +} diff --git a/src/bytearray.h b/src/bytearray.h new file mode 100644 index 0000000..3e67d7e --- /dev/null +++ b/src/bytearray.h @@ -0,0 +1,36 @@ +/* + * bytearray.h + * header file for simple byte array implementation + * + * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef BYTEARRAY_H +#define BYTEARRAY_H +#include <stdlib.h> +#include "common.h" + +typedef struct bytearray_t { + void *data; + size_t len; + size_t capacity; +} bytearray_t; + +_PLIST_INTERNAL bytearray_t *byte_array_new(); +_PLIST_INTERNAL void byte_array_free(bytearray_t *ba); +_PLIST_INTERNAL void byte_array_append(bytearray_t *ba, void *buf, size_t len); + +#endif diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..4f16df7 --- /dev/null +++ b/src/common.h @@ -0,0 +1,15 @@ +#ifndef COMMON_H +#define COMMON_H + +#define PLIST_LITTLE_ENDIAN 0 +#define PLIST_BIG_ENDIAN 1 + +#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__CYGWIN__) +# define _PLIST_INTERNAL __attribute__((visibility("hidden"))) +#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) +# define _PLIST_INTERNAL __hidden +#else /* not gcc >= 4 and not Sun Studio >= 8 */ +# define _PLIST_INTERNAL +#endif /* GNUC >= 4 */ + +#endif diff --git a/src/hashtable.c b/src/hashtable.c new file mode 100644 index 0000000..9716c25 --- /dev/null +++ b/src/hashtable.c @@ -0,0 +1,107 @@ +/* + * hashtable.c + * really simple hash table implementation + * + * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "hashtable.h" + +hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func) +{ + hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t)); + int i; + for (i = 0; i < 256; i++) { + ht->entries[i] = NULL; + } + ht->count = 0; + ht->hash_func = hash_func; + ht->compare_func = compare_func; + return ht; +} + +void hash_table_destroy(hashtable_t *ht) +{ + if (!ht) return; + + int i = 0; + for (i = 0; i < 256; i++) { + if (ht->entries[i]) { + hashentry_t* e = ht->entries[i]; + while (e) { + free(e->value); + hashentry_t* old = e; + e = e->next; + free(old); + } + } + } + free(ht); +} + +void hash_table_insert(hashtable_t* ht, void *key, void *value) +{ + if (!ht || !key) return; + int i; + + unsigned int hash = ht->hash_func(key); + + int idx0 = hash & 0xFF; + + // get the idx0 list + hashentry_t* e = ht->entries[idx0]; + while (e) { + if (ht->compare_func(e->key, key)) { + // element already present. replace value. + e->value = value; + return; + } + e = e->next; + } + + // if we get here, the element is not yet in the list. + + // make a new entry. + hashentry_t* entry = (hashentry_t*)malloc(sizeof(hashentry_t)); + entry->key = key; + entry->value = value; + if (!ht->entries[idx0]) { + // first entry + entry->next = NULL; + } else { + // add to list + entry->next = ht->entries[idx0]; + } + ht->entries[idx0] = entry; + ht->count++; +} + +void* hash_table_lookup(hashtable_t* ht, void *key) +{ + if (!ht || !key) return NULL; + unsigned int hash = ht->hash_func(key); + + int idx0 = hash & 0xFF; + + hashentry_t* e = ht->entries[idx0]; + while (e) { + if (ht->compare_func(e->key, key)) { + return e->value; + } + e = e->next; + } + return NULL; +} diff --git a/src/hashtable.h b/src/hashtable.h new file mode 100644 index 0000000..8c72c82 --- /dev/null +++ b/src/hashtable.h @@ -0,0 +1,48 @@ +/* + * hashtable.h + * header file for really simple hash table implementation + * + * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef HASHTABLE_H +#define HASHTABLE_H +#include <stdlib.h> +#include "common.h" + +typedef struct hashentry_t { + void *key; + void *value; + void *next; +} hashentry_t; + +typedef unsigned int(*hash_func_t)(const void* key); +typedef int (*compare_func_t)(const void *a, const void *b); + +typedef struct hashtable_t { + hashentry_t *entries[256]; + size_t count; + hash_func_t hash_func; + compare_func_t compare_func; +} hashtable_t; + +_PLIST_INTERNAL hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func); +_PLIST_INTERNAL void hash_table_destroy(hashtable_t *ht); + +_PLIST_INTERNAL void hash_table_insert(hashtable_t* ht, void *key, void *value); +_PLIST_INTERNAL void* hash_table_lookup(hashtable_t* ht, void *key); + +#endif diff --git a/src/plist.c b/src/plist.c index 7028d81..6ee54cd 100644 --- a/src/plist.c +++ b/src/plist.c @@ -26,16 +26,19 @@ #include <stdlib.h> #include <stdio.h> +#include <node.h> +#include <node_iterator.h> + plist_t plist_new_node(plist_data_t data) { - return (plist_t) g_node_new(data); + return (plist_t) node_create(NULL, data); } plist_data_t plist_get_data(const plist_t node) { if (!node) return NULL; - return ((GNode *) node)->data; + return ((node_t*)node)->data; } plist_data_t plist_new_plist_data(void) @@ -64,15 +67,22 @@ static void plist_free_data(plist_data_t data) } } -static void plist_free_node(GNode * node, gpointer none) +static void plist_free_node(node_t* node) { plist_data_t data = NULL; - g_node_unlink(node); + node_detach(node->parent, node); data = plist_get_data(node); plist_free_data(data); node->data = NULL; - g_node_children_foreach(node, G_TRAVERSE_ALL, plist_free_node, NULL); - g_node_destroy(node); + + node_iterator_t *ni = node_iterator_create(node->children); + node_t *ch; + while ((ch = node_iterator_next(ni))) { + plist_free_node(ch); + } + node_iterator_destroy(ni); + + node_destroy(node); } plist_t plist_new_dict(void) @@ -151,7 +161,7 @@ plist_t plist_new_date(int32_t sec, int32_t usec) data->type = PLIST_DATE; data->timeval.tv_sec = sec; data->timeval.tv_usec = usec; - data->length = sizeof(GTimeVal); + data->length = sizeof(struct timeval); return plist_new_node(data); } @@ -159,11 +169,11 @@ void plist_free(plist_t plist) { if (plist) { - plist_free_node(plist, NULL); + plist_free_node(plist); } } -static void plist_copy_node(GNode * node, gpointer parent_node_ptr) +static void plist_copy_node(node_t *node, void *parent_node_ptr) { plist_type node_type = PLIST_NONE; plist_t newnode = NULL; @@ -195,14 +205,19 @@ static void plist_copy_node(GNode * node, gpointer parent_node_ptr) if (*(plist_t*)parent_node_ptr) { - g_node_append(*(plist_t*)parent_node_ptr, newnode); + node_attach(*(plist_t*)parent_node_ptr, newnode); } else { *(plist_t*)parent_node_ptr = newnode; } - g_node_children_foreach(node, G_TRAVERSE_ALL, plist_copy_node, &newnode); + node_iterator_t *ni = node_iterator_create(node->children); + node_t *ch; + while ((ch = node_iterator_next(ni))) { + plist_copy_node(ch, &newnode); + } + node_iterator_destroy(ni); } plist_t plist_copy(plist_t node) @@ -217,7 +232,7 @@ uint32_t plist_array_get_size(plist_t node) uint32_t ret = 0; if (node && PLIST_ARRAY == plist_get_node_type(node)) { - ret = g_node_n_children(node); + ret = node_n_children(node); } return ret; } @@ -227,7 +242,7 @@ plist_t plist_array_get_item(plist_t node, uint32_t n) plist_t ret = NULL; if (node && PLIST_ARRAY == plist_get_node_type(node)) { - ret = (plist_t)g_node_nth_child(node, n); + ret = (plist_t)node_nth_child(node, n); } return ret; } @@ -237,7 +252,7 @@ uint32_t plist_array_get_item_index(plist_t node) plist_t father = plist_get_parent(node); if (PLIST_ARRAY == plist_get_node_type(father)) { - return g_node_child_position(father, node); + return node_child_position(father, node); } return 0; } @@ -249,7 +264,7 @@ void plist_array_set_item(plist_t node, plist_t item, uint32_t n) plist_t old_item = plist_array_get_item(node, n); if (old_item) { - plist_free_node(old_item, NULL); + plist_free_node(old_item); old_item = NULL; plist_copy_node(item, &old_item); } @@ -261,7 +276,7 @@ void plist_array_append_item(plist_t node, plist_t item) { if (node && PLIST_ARRAY == plist_get_node_type(node)) { - g_node_append(node, item); + node_attach(node, item); } return; } @@ -270,7 +285,7 @@ void plist_array_insert_item(plist_t node, plist_t item, uint32_t n) { if (node && PLIST_ARRAY == plist_get_node_type(node)) { - g_node_insert(node, n, item); + node_insert(node, n, item); } return; } @@ -293,7 +308,7 @@ uint32_t plist_dict_get_size(plist_t node) uint32_t ret = 0; if (node && PLIST_DICT == plist_get_node_type(node)) { - ret = g_node_n_children(node) / 2; + ret = node_n_children(node) / 2; } return ret; } @@ -321,17 +336,17 @@ void plist_dict_next_item(plist_t node, plist_dict_iter iter, char **key, plist_ *val = NULL; } - if (node && PLIST_DICT == plist_get_node_type(node) && *iter_int < g_node_n_children(node)) + if (node && PLIST_DICT == plist_get_node_type(node) && *iter_int < node_n_children(node)) { if (key) { - plist_get_key_val((plist_t)g_node_nth_child(node, *iter_int), key); + plist_get_key_val((plist_t)node_nth_child(node, *iter_int), key); } if (val) { - *val = (plist_t) g_node_nth_child(node, *iter_int + 1); + *val = (plist_t) node_nth_child(node, *iter_int + 1); } *iter_int += 2; @@ -344,7 +359,7 @@ void plist_dict_get_item_key(plist_t node, char **key) plist_t father = plist_get_parent(node); if (PLIST_DICT == plist_get_node_type(father)) { - plist_get_key_val( (plist_t) g_node_prev_sibling(node), key); + plist_get_key_val( (plist_t) node_prev_sibling(node), key); } } @@ -356,9 +371,9 @@ plist_t plist_dict_get_item(plist_t node, const char* key) { plist_t current = NULL; - for (current = (plist_t)g_node_first_child(node); + for (current = (plist_t)node_first_child(node); current; - current = (plist_t)g_node_next_sibling(g_node_next_sibling(current))) + current = (plist_t)node_next_sibling(node_next_sibling(current))) { plist_data_t data = plist_get_data(current); @@ -366,7 +381,7 @@ plist_t plist_dict_get_item(plist_t node, const char* key) if (data && !strcmp(key, data->strval)) { - ret = (plist_t)g_node_next_sibling(current); + ret = (plist_t)node_next_sibling(current); break; } } @@ -381,7 +396,7 @@ void plist_dict_set_item(plist_t node, const char* key, plist_t item) plist_t old_item = plist_dict_get_item(node, key); if (old_item) { - plist_free_node(old_item, NULL); + plist_free_node(old_item); old_item = NULL; plist_copy_node(item, &old_item); } @@ -393,8 +408,8 @@ void plist_dict_insert_item(plist_t node, const char* key, plist_t item) { if (node && PLIST_DICT == plist_get_node_type(node)) { - g_node_append(node, plist_new_key(key)); - g_node_append(node, item); + node_attach(node, plist_new_key(key)); + node_attach(node, item); } return; } @@ -406,7 +421,7 @@ void plist_dict_remove_item(plist_t node, const char* key) plist_t old_item = plist_dict_get_item(node, key); if (old_item) { - plist_t key_node = g_node_prev_sibling(old_item); + plist_t key_node = node_prev_sibling(old_item); plist_free(key_node); plist_free(old_item); } @@ -482,8 +497,8 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu break; case PLIST_DATE: //exception : here we use memory on the stack since it is just a temporary buffer - ((GTimeVal *) value)->tv_sec = data->timeval.tv_sec; - ((GTimeVal *) value)->tv_usec = data->timeval.tv_usec; + ((struct timeval*) value)->tv_sec = data->timeval.tv_sec; + ((struct timeval*) value)->tv_usec = data->timeval.tv_usec; break; case PLIST_ARRAY: case PLIST_DICT: @@ -494,7 +509,7 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu plist_t plist_get_parent(plist_t node) { - return node ? (plist_t) ((GNode *) node)->parent : NULL; + return node ? (plist_t) ((node_t*) node)->parent : NULL; } plist_type plist_get_node_type(plist_t node) @@ -564,15 +579,15 @@ void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec) { plist_type type = plist_get_node_type(node); uint64_t length = 0; - GTimeVal val = { 0, 0 }; + struct timeval val = { 0, 0 }; if (PLIST_DATE == type) plist_get_type_and_value(node, &type, (void *) &val, &length); - assert(length == sizeof(GTimeVal)); + assert(length == sizeof(struct timeval)); *sec = val.tv_sec; *usec = val.tv_usec; } -gboolean plist_data_compare(gconstpointer a, gconstpointer b) +int plist_data_compare(const void *a, const void *b) { plist_data_t val_a = NULL; plist_data_t val_b = NULL; @@ -580,7 +595,7 @@ gboolean plist_data_compare(gconstpointer a, gconstpointer b) if (!a || !b) return FALSE; - if (!((GNode *) a)->data || !((GNode *) b)->data) + if (!((node_t*) a)->data || !((node_t*) b)->data) return FALSE; val_a = plist_get_data((plist_t) a); @@ -620,7 +635,7 @@ gboolean plist_data_compare(gconstpointer a, gconstpointer b) return FALSE; break; case PLIST_DATE: - if (!memcmp(&(val_a->timeval), &(val_b->timeval), sizeof(GTimeVal))) + if (!memcmp(&(val_a->timeval), &(val_b->timeval), sizeof(struct timeval))) return TRUE; else return FALSE; @@ -681,8 +696,8 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val memcpy(data->buff, value, length); break; case PLIST_DATE: - data->timeval.tv_sec = ((GTimeVal *) value)->tv_sec; - data->timeval.tv_usec = ((GTimeVal *) value)->tv_usec; + data->timeval.tv_sec = ((struct timeval*) value)->tv_sec; + data->timeval.tv_usec = ((struct timeval*) value)->tv_usec; break; case PLIST_ARRAY: case PLIST_DICT: @@ -693,7 +708,7 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val void plist_set_type(plist_t node, plist_type type) { - if ( g_node_n_children(node) == 0 ) + if ( node_n_children(node) == 0 ) { plist_data_t data = plist_get_data(node); plist_free_data( data ); @@ -711,7 +726,7 @@ void plist_set_type(plist_t node, plist_type type) data->length = sizeof(double); break; case PLIST_DATE: - data->length = sizeof(GTimeVal); + data->length = sizeof(struct timeval); break; default: data->length = 0; @@ -752,7 +767,7 @@ void plist_set_data_val(plist_t node, const char *val, uint64_t length) void plist_set_date_val(plist_t node, int32_t sec, int32_t usec) { - GTimeVal val = { sec, usec }; - plist_set_element_val(node, PLIST_DATE, &val, sizeof(GTimeVal)); + struct timeval val = { sec, usec }; + plist_set_element_val(node, PLIST_DATE, &val, sizeof(struct timeval)); } diff --git a/src/plist.h b/src/plist.h index 12578af..036fd42 100644 --- a/src/plist.h +++ b/src/plist.h @@ -23,11 +23,10 @@ #define PLIST_H #include "plist/plist.h" - +#include "common.h" #include <sys/types.h> #include <sys/stat.h> -#include <glib.h> #ifdef _MSC_VER #pragma warning(disable:4996) @@ -44,7 +43,7 @@ struct plist_data_s double realval; char *strval; uint8_t *buff; - GTimeVal timeval; + struct timeval timeval; }; uint64_t length; plist_type type; @@ -52,10 +51,10 @@ struct plist_data_s typedef struct plist_data_s *plist_data_t; -G_GNUC_INTERNAL plist_t plist_new_node(plist_data_t data); -G_GNUC_INTERNAL plist_data_t plist_get_data(const plist_t node); -G_GNUC_INTERNAL plist_data_t plist_new_plist_data(void); -G_GNUC_INTERNAL gboolean plist_data_compare(gconstpointer a, gconstpointer b); +_PLIST_INTERNAL plist_t plist_new_node(plist_data_t data); +_PLIST_INTERNAL plist_data_t plist_get_data(const plist_t node); +_PLIST_INTERNAL plist_data_t plist_new_plist_data(void); +_PLIST_INTERNAL int plist_data_compare(const void *a, const void *b); #endif diff --git a/src/ptrarray.c b/src/ptrarray.c new file mode 100644 index 0000000..8567752 --- /dev/null +++ b/src/ptrarray.c @@ -0,0 +1,61 @@ +/* + * ptrarray.c + * simple pointer array implementation + * + * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "ptrarray.h" + +ptrarray_t *ptr_array_new(int capacity) +{ + ptrarray_t *pa = (ptrarray_t*)malloc(sizeof(ptrarray_t)); + pa->pdata = (void**)malloc(sizeof(void*) * capacity); + pa->capacity = capacity; + pa->capacity_step = (capacity > 64) ? 64 : capacity; + pa->len = 0; + return pa; +} + +void ptr_array_free(ptrarray_t *pa) +{ + if (!pa) return; + if (pa->pdata) { + free(pa->pdata); + } + free(pa); +} + +void ptr_array_add(ptrarray_t *pa, void *data) +{ + if (!pa || !pa->pdata || !data) return; + size_t remaining = pa->capacity-pa->len; + if (remaining == 0) { + pa->pdata = realloc(pa->pdata, sizeof(void*) * (pa->capacity + pa->capacity_step)); + pa->capacity += pa->capacity_step; + } + pa->pdata[pa->len] = data; + pa->len++; +} + +void* ptr_array_index(ptrarray_t *pa, size_t index) +{ + if (!pa) return NULL; + if (index >= pa->len) { + return NULL; + } + return pa->pdata[index]; +} diff --git a/src/ptrarray.h b/src/ptrarray.h new file mode 100644 index 0000000..84f9ef0 --- /dev/null +++ b/src/ptrarray.h @@ -0,0 +1,37 @@ +/* + * ptrarray.h + * header file for simple pointer array implementation + * + * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef PTRARRAY_H +#define PTRARRAY_H +#include <stdlib.h> +#include "common.h" + +typedef struct ptrarray_t { + void **pdata; + size_t len; + size_t capacity; + size_t capacity_step; +} ptrarray_t; + +_PLIST_INTERNAL ptrarray_t *ptr_array_new(int capacity); +_PLIST_INTERNAL void ptr_array_free(ptrarray_t *pa); +_PLIST_INTERNAL void ptr_array_add(ptrarray_t *pa, void *data); +_PLIST_INTERNAL void* ptr_array_index(ptrarray_t *pa, size_t index); +#endif diff --git a/src/xplist.c b/src/xplist.c index 1319f56..899cc81 100644 --- a/src/xplist.c +++ b/src/xplist.c @@ -24,6 +24,7 @@ #include <assert.h> #include <stdlib.h> #include <stdio.h> +#include <time.h> #include <inttypes.h> #include <locale.h> @@ -31,7 +32,12 @@ #include <libxml/parser.h> #include <libxml/tree.h> +#include <node.h> +#include <node_list.h> +#include <node_iterator.h> + #include "plist.h" +#include "base64.h" #define XPLIST_TEXT BAD_CAST("text") #define XPLIST_KEY BAD_CAST("key") @@ -61,18 +67,22 @@ static const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ * * @return The formatted string. */ -static gchar *format_string(const char *buf, int cols, int depth) +static char *format_string(const char *buf, size_t len, int cols, int depth) { + if (!buf || !(len > 0)) return NULL; int colw = depth + cols + 1; - int len = strlen(buf); int nlines = len / cols + 1; - gchar *new_buf = (gchar *) g_malloc0(nlines * colw + depth + 1); + char *new_buf = NULL; int i = 0; int j = 0; assert(cols >= 0); assert(depth >= 0); + new_buf = (char*) malloc(nlines * colw + depth + 1); + assert(new_buf != 0); + memset(new_buf, 0, nlines * colw + depth + 1); + // Inserts new lines and tabs at appropriate locations for (i = 0; i < nlines; i++) { @@ -116,7 +126,7 @@ static xmlDocPtr new_xml_plist(void) return plist_xml; } -static void node_to_xml(GNode * node, gpointer xml_struct) +static void node_to_xml(node_t* node, void *xml_struct) { struct xml_node *xstruct = NULL; plist_data_t node_data = NULL; @@ -125,10 +135,10 @@ static void node_to_xml(GNode * node, gpointer xml_struct) char isStruct = FALSE; const xmlChar *tag = NULL; - gchar *val = NULL; + char *val = NULL; //for base64 - gchar *valtmp = NULL; + char *valtmp = NULL; uint32_t i = 0; @@ -151,31 +161,32 @@ static void node_to_xml(GNode * node, gpointer xml_struct) case PLIST_UINT: tag = XPLIST_INT; - val = g_strdup_printf("%"PRIu64, node_data->intval); + (void)asprintf(&val, "%"PRIu64, node_data->intval); break; case PLIST_REAL: tag = XPLIST_REAL; - val = g_strdup_printf("%f", node_data->realval); + (void)asprintf(&val, "%f", node_data->realval); break; case PLIST_STRING: tag = XPLIST_STRING; - val = g_strdup(node_data->strval); + val = strdup(node_data->strval); break; case PLIST_KEY: tag = XPLIST_KEY; - val = g_strdup((gchar *) node_data->strval); + val = strdup((char*) node_data->strval); break; case PLIST_DATA: tag = XPLIST_DATA; if (node_data->length) { - valtmp = g_base64_encode(node_data->buff, node_data->length); - val = format_string(valtmp, 68, xstruct->depth); - g_free(valtmp); + size_t len = node_data->length; + valtmp = base64encode(node_data->buff, &len); + val = format_string(valtmp, len, 68, xstruct->depth); + free(valtmp); } break; case PLIST_ARRAY: @@ -188,7 +199,18 @@ static void node_to_xml(GNode * node, gpointer xml_struct) break; case PLIST_DATE: tag = XPLIST_DATE; - val = g_time_val_to_iso8601(&node_data->timeval); + { + time_t time = (time_t)node_data->timeval.tv_sec; + struct tm *btime = localtime(&time); + if (btime) { + val = (char*)malloc(24); + memset(val, 0, 24); + if (strftime(val, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) { + free (val); + val = NULL; + } + } + } break; default: break; @@ -205,7 +227,9 @@ static void node_to_xml(GNode * node, gpointer xml_struct) } else child_node = xmlNewChild(xstruct->xml, NULL, tag, BAD_CAST(val)); xmlNodeAddContent(xstruct->xml, BAD_CAST("\n")); - g_free(val); + if (val) { + free(val); + } //add return for structured types if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT) @@ -214,7 +238,12 @@ static void node_to_xml(GNode * node, gpointer xml_struct) if (isStruct) { struct xml_node child = { child_node, xstruct->depth + 1 }; - g_node_children_foreach(node, G_TRAVERSE_ALL, node_to_xml, &child); + node_iterator_t *ni = node_iterator_create(node->children); + node_t *ch; + while ((ch = node_iterator_next(ni))) { + node_to_xml(ch, &child); + } + node_iterator_destroy(ni); } //fix indent for structured types if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT) @@ -236,7 +265,7 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) plist_t subnode = NULL; //for string - glong len = 0; + long len = 0; int type = 0; if (!xml_node) @@ -253,7 +282,7 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) data = plist_new_plist_data(); subnode = plist_new_node(data); if (*plist_node) - g_node_append(*plist_node, subnode); + node_attach(*plist_node, subnode); else *plist_node = subnode; @@ -276,7 +305,7 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) if (!xmlStrcmp(node->name, XPLIST_INT)) { xmlChar *strval = xmlNodeGetContent(node); - data->intval = g_ascii_strtoull((char *) strval, NULL, 0); + data->intval = strtoull((char*)strval, NULL, 0); data->type = PLIST_UINT; data->length = 8; xmlFree(strval); @@ -296,9 +325,17 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) if (!xmlStrcmp(node->name, XPLIST_DATE)) { xmlChar *strval = xmlNodeGetContent(node); - g_time_val_from_iso8601((char *) strval, &data->timeval); + time_t time = 0; + if (strlen(strval) >= 11) { + struct tm btime; + memset(&btime, 0, sizeof(struct tm)); + strptime((char*)strval, "%Y-%m-%dT%H:%M:%SZ", &btime); + time = mktime(&btime); + } + data->timeval.tv_sec = (long)time; + data->timeval.tv_usec = 0; data->type = PLIST_DATE; - data->length = sizeof(GTimeVal); + data->length = sizeof(struct timeval); xmlFree(strval); continue; } @@ -332,11 +369,11 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) if (!xmlStrcmp(node->name, XPLIST_DATA)) { xmlChar *strval = xmlNodeGetContent(node); - gsize size = 0; - guchar *dec = g_base64_decode((char *) strval, &size); + size_t size = 0; + unsigned char *dec = base64decode((char*)strval, &size); data->buff = (uint8_t *) malloc(size * sizeof(uint8_t)); memcpy(data->buff, dec, size * sizeof(uint8_t)); - g_free(dec); + free(dec); data->length = size; data->type = PLIST_DATA; xmlFree(strval); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f933cc1..1b3d2f7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,6 @@ #build the test executable -INCLUDE_DIRECTORIES( ${GLIB2_INCLUDE_DIR} ) +INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/libcnary/include ) SET(plist_test_SRC plist_test.c) diff --git a/test/plist_cmp.c b/test/plist_cmp.c index af54c4c..a07452b 100644 --- a/test/plist_cmp.c +++ b/test/plist_cmp.c @@ -27,7 +27,7 @@ #include <string.h> #include <sys/stat.h> -#include <glib.h> +#include <node.h> #ifdef _MSC_VER #pragma warning(disable:4996) @@ -35,12 +35,12 @@ static plist_t plist_get_first_child(plist_t node) { - return (plist_t) g_node_first_child((GNode *) node); + return (plist_t) node_first_child((node_t*) node); } static plist_t plist_get_next_sibling(plist_t node) { - return (plist_t) g_node_next_sibling((GNode *) node); + return (plist_t) node_next_sibling((node_t*) node); } static char compare_plist(plist_t node_l, plist_t node_r) |