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) | |||
| 16 | ENDIF(NOT DEFINED CMAKE_INSTALL_LIBDIR) | 16 | ENDIF(NOT DEFINED CMAKE_INSTALL_LIBDIR) |
| 17 | 17 | ||
| 18 | FIND_PACKAGE( LibXml2 REQUIRED ) | 18 | FIND_PACKAGE( LibXml2 REQUIRED ) |
| 19 | FIND_PACKAGE( GLIB2 REQUIRED ) | ||
| 20 | 19 | ||
| 21 | OPTION(ENABLE_PYTHON "Enable Python bindings (needs Swig)" ON) | 20 | OPTION(ENABLE_PYTHON "Enable Python bindings (needs Swig)" ON) |
| 22 | 21 | ||
| @@ -31,6 +30,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/include | |||
| 31 | 30 | ||
| 32 | ENABLE_TESTING() | 31 | ENABLE_TESTING() |
| 33 | 32 | ||
| 33 | ADD_SUBDIRECTORY( libcnary ) | ||
| 34 | ADD_SUBDIRECTORY( src ) | 34 | ADD_SUBDIRECTORY( src ) |
| 35 | ADD_SUBDIRECTORY( plutil ) | 35 | ADD_SUBDIRECTORY( plutil ) |
| 36 | ADD_SUBDIRECTORY( include ) | 36 | ADD_SUBDIRECTORY( include ) |
| @@ -40,6 +40,10 @@ IF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) | |||
| 40 | ADD_SUBDIRECTORY( swig ) | 40 | ADD_SUBDIRECTORY( swig ) |
| 41 | ENDIF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) | 41 | ENDIF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) |
| 42 | 42 | ||
| 43 | INCLUDE (TestBigEndian) | ||
| 44 | TEST_BIG_ENDIAN(endianess) | ||
| 45 | SET ( PLIST_BYTE_ORDER ${endianess} ) | ||
| 46 | |||
| 43 | # add uninstall target | 47 | # add uninstall target |
| 44 | CONFIGURE_FILE( "${CMAKE_SOURCE_DIR}/cmake/modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) | 48 | CONFIGURE_FILE( "${CMAKE_SOURCE_DIR}/cmake/modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) |
| 45 | ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") | 49 | 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 | |||
| 6 | Name: libplist | 6 | Name: libplist |
| 7 | Description: A library to handle Apple Property Lists whereas they are binary or XML | 7 | Description: A library to handle Apple Property Lists whereas they are binary or XML |
| 8 | Version: ${LIBPLIST_VERSION} | 8 | Version: ${LIBPLIST_VERSION} |
| 9 | Requires.private: libxml-2.0 >= 2.6.30 glib-2.0 >= 2.14.1 | 9 | Requires.private: libxml-2.0 >= 2.6.30 |
| 10 | Libs: -L${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} -lplist | 10 | Libs: -L${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} -lplist |
| 11 | Cflags: -I${CMAKE_INSTALL_PREFIX}/include | 11 | Cflags: -I${CMAKE_INSTALL_PREFIX}/include |
| 12 | 12 | ||
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 @@ | |||
| 1 | 1 | ||
| 2 | INCLUDE_DIRECTORIES( ${LIBXML2_INCLUDE_DIR} ${GLIB2_INCLUDE_DIR} ) | 2 | INCLUDE_DIRECTORIES( ${LIBXML2_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/libcnary/include ) |
| 3 | 3 | ||
| 4 | 4 | ||
| 5 | SET(libplist_SRC | 5 | SET(libplist_SRC |
| 6 | plist.c | 6 | plist.c |
| 7 | hashtable.c | ||
| 8 | bytearray.c | ||
| 9 | ptrarray.c | ||
| 7 | bplist.c | 10 | bplist.c |
| 11 | base64.c | ||
| 8 | xplist.c ) | 12 | xplist.c ) |
| 9 | 13 | ||
| 10 | SET(libplist++_SRC | 14 | SET(libplist++_SRC |
| @@ -20,8 +24,18 @@ SET(libplist++_SRC | |||
| 20 | Dictionary.cpp | 24 | Dictionary.cpp |
| 21 | ) | 25 | ) |
| 22 | 26 | ||
| 23 | ADD_LIBRARY( plist SHARED ${libplist_SRC} ) | 27 | SET(libcnary_object_files |
| 24 | TARGET_LINK_LIBRARIES( plist ${LIBXML2_LIBRARIES} ${GLIB2_LIBRARIES} ) | 28 | ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/iterator.c.o |
| 29 | ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/list.c.o | ||
| 30 | ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/node.c.o | ||
| 31 | ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/node_iterator.c.o | ||
| 32 | ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/node_list.c.o | ||
| 33 | ) | ||
| 34 | |||
| 35 | SET_SOURCE_FILES_PROPERTIES(${libcnary_object_files} PROPERTIES EXTERNAL_OBJECT true GENERATED true) | ||
| 36 | |||
| 37 | ADD_LIBRARY( plist SHARED ${libplist_SRC} ${libcnary_object_files} ) | ||
| 38 | TARGET_LINK_LIBRARIES( plist ${LIBXML2_LIBRARIES} ) | ||
| 25 | SET_TARGET_PROPERTIES( plist PROPERTIES VERSION ${LIBPLIST_LIBVERSION} ) | 39 | SET_TARGET_PROPERTIES( plist PROPERTIES VERSION ${LIBPLIST_LIBVERSION} ) |
| 26 | SET_TARGET_PROPERTIES( plist PROPERTIES SOVERSION ${LIBPLIST_SOVERSION} ) | 40 | SET_TARGET_PROPERTIES( plist PROPERTIES SOVERSION ${LIBPLIST_SOVERSION} ) |
| 27 | if(APPLE) | 41 | 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 @@ | |||
| 1 | /* | ||
| 2 | * base64.c | ||
| 3 | * base64 encode/decode implementation | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | #include <string.h> | ||
| 22 | #include "base64.h" | ||
| 23 | |||
| 24 | static const char base64_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
| 25 | static const char base64_pad = '='; | ||
| 26 | |||
| 27 | static const int8_t base64_table[256] = { | ||
| 28 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 29 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 30 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, | ||
| 31 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, | ||
| 32 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | ||
| 33 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, | ||
| 34 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, | ||
| 35 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, | ||
| 36 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 37 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 38 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 39 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 40 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 41 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 42 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 43 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 | ||
| 44 | }; | ||
| 45 | |||
| 46 | char *base64encode(const unsigned char *buf, size_t *size) | ||
| 47 | { | ||
| 48 | if (!buf || !size || !(*size > 0)) return NULL; | ||
| 49 | int outlen = (*size / 3) * 4; | ||
| 50 | char *outbuf = (char*)malloc(outlen+5); // 4 spare bytes + 1 for '\0' | ||
| 51 | size_t n = 0; | ||
| 52 | size_t m = 0; | ||
| 53 | unsigned char input[3]; | ||
| 54 | unsigned int output[4]; | ||
| 55 | while (n < *size) { | ||
| 56 | input[0] = buf[n++]; | ||
| 57 | input[1] = (n < *size) ? buf[n++] : 0; | ||
| 58 | input[2] = (n < *size) ? buf[n++] : 0; | ||
| 59 | output[0] = input[0] >> 2; | ||
| 60 | output[1] = ((input[0] & 3) << 4) + (input[1] >> 4); | ||
| 61 | output[2] = ((input[1] & 15) << 2) + (input[2] >> 6); | ||
| 62 | output[3] = input[2] & 63; | ||
| 63 | outbuf[m++] = base64_str[(int)output[0]]; | ||
| 64 | outbuf[m++] = base64_str[(int)output[1]]; | ||
| 65 | outbuf[m++] = base64_str[(int)output[2]]; | ||
| 66 | outbuf[m++] = base64_str[(int)output[3]]; | ||
| 67 | } | ||
| 68 | while ((m % 4) != 0) { | ||
| 69 | outbuf[m++] = base64_pad; | ||
| 70 | } | ||
| 71 | outbuf[m] = 0; // 0-termination! | ||
| 72 | *size = m; | ||
| 73 | return outbuf; | ||
| 74 | } | ||
| 75 | |||
| 76 | static int base64decode_block(unsigned char *target, const char *data, size_t data_size) | ||
| 77 | { | ||
| 78 | int w1,w2,w3,w4; | ||
| 79 | int n,i; | ||
| 80 | |||
| 81 | if (!data || (data_size <= 0)) { | ||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | n = 0; | ||
| 86 | i = 0; | ||
| 87 | while (n < data_size-3) { | ||
| 88 | w1 = base64_table[(int)data[n]]; | ||
| 89 | w2 = base64_table[(int)data[n+1]]; | ||
| 90 | w3 = base64_table[(int)data[n+2]]; | ||
| 91 | w4 = base64_table[(int)data[n+3]]; | ||
| 92 | |||
| 93 | if (w2 >= 0) { | ||
| 94 | target[i++] = (char)((w1*4 + (w2 >> 4)) & 255); | ||
| 95 | } | ||
| 96 | if (w3 >= 0) { | ||
| 97 | target[i++] = (char)((w2*16 + (w3 >> 2)) & 255); | ||
| 98 | } | ||
| 99 | if (w4 >= 0) { | ||
| 100 | target[i++] = (char)((w3*64 + w4) & 255); | ||
| 101 | } | ||
| 102 | n+=4; | ||
| 103 | } | ||
| 104 | return i; | ||
| 105 | } | ||
| 106 | |||
| 107 | unsigned char *base64decode(const char *buf, size_t *size) | ||
| 108 | { | ||
| 109 | if (!buf) return; | ||
| 110 | size_t len = strlen(buf); | ||
| 111 | if (len <= 0) return; | ||
| 112 | unsigned char *outbuf = (unsigned char*)malloc((len/4)*3+3); | ||
| 113 | |||
| 114 | unsigned char *line; | ||
| 115 | int p = 0; | ||
| 116 | |||
| 117 | line = (unsigned char*)strtok((char*)buf, "\r\n\t "); | ||
| 118 | while (line) { | ||
| 119 | p+=base64decode_block(outbuf+p, line, strlen((char*)line)); | ||
| 120 | |||
| 121 | // get next line of base64 encoded block | ||
| 122 | line = (unsigned char*)strtok(NULL, "\r\n\t "); | ||
| 123 | } | ||
| 124 | outbuf[p] = 0; | ||
| 125 | *size = p; | ||
| 126 | return outbuf; | ||
| 127 | } | ||
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 @@ | |||
| 1 | /* | ||
| 2 | * base64.h | ||
| 3 | * base64 encode/decode implementation | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | #ifndef BASE64_H | ||
| 22 | #define BASE64_H | ||
| 23 | #include <stdlib.h> | ||
| 24 | #include "common.h" | ||
| 25 | |||
| 26 | _PLIST_INTERNAL char *base64encode(const unsigned char *buf, size_t *size); | ||
| 27 | _PLIST_INTERNAL unsigned char *base64decode(const char *buf, size_t *size); | ||
| 28 | |||
| 29 | #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 @@ | |||
| 29 | 29 | ||
| 30 | #include <plist/plist.h> | 30 | #include <plist/plist.h> |
| 31 | #include "plist.h" | 31 | #include "plist.h" |
| 32 | #include "hashtable.h" | ||
| 33 | #include "bytearray.h" | ||
| 34 | #include "ptrarray.h" | ||
| 35 | |||
| 36 | #include <node.h> | ||
| 37 | #include <node_iterator.h> | ||
| 32 | 38 | ||
| 33 | /* Magic marker and size. */ | 39 | /* Magic marker and size. */ |
| 34 | #define BPLIST_MAGIC ((uint8_t*)"bplist") | 40 | #define BPLIST_MAGIC ((uint8_t*)"bplist") |
| @@ -66,7 +72,7 @@ enum | |||
| 66 | 72 | ||
| 67 | static void float_byte_convert(uint8_t * address, size_t size) | 73 | static void float_byte_convert(uint8_t * address, size_t size) |
| 68 | { | 74 | { |
| 69 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN && !defined (__VFP_FP__) | 75 | #if PLIST_BYTE_ORDER == PLIST_LITTLE_ENDIAN && !defined (__VFP_FP__) |
| 70 | uint8_t i = 0, j = 0; | 76 | uint8_t i = 0, j = 0; |
| 71 | uint8_t tmp = 0; | 77 | uint8_t tmp = 0; |
| 72 | 78 | ||
| @@ -100,7 +106,7 @@ union plist_uint_ptr | |||
| 100 | 106 | ||
| 101 | static void byte_convert(uint8_t * address, size_t size) | 107 | static void byte_convert(uint8_t * address, size_t size) |
| 102 | { | 108 | { |
| 103 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | 109 | #if PLIST_BYTE_ORDER == PLIST_LITTLE_ENDIAN |
| 104 | uint8_t i = 0, j = 0; | 110 | uint8_t i = 0, j = 0; |
| 105 | uint8_t tmp = 0; | 111 | uint8_t tmp = 0; |
| 106 | 112 | ||
| @@ -131,10 +137,10 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf) | |||
| 131 | ({ \ | 137 | ({ \ |
| 132 | union plist_uint_ptr __up; \ | 138 | union plist_uint_ptr __up; \ |
| 133 | __up.src = x; \ | 139 | __up.src = x; \ |
| 134 | (n == 8 ? GUINT64_FROM_BE( get_unaligned(__up.u64ptr) ) : \ | 140 | (n == 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \ |
| 135 | (n == 4 ? GUINT32_FROM_BE( get_unaligned(__up.u32ptr) ) : \ | 141 | (n == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \ |
| 136 | (n == 3 ? uint24_from_be( __up ) : \ | 142 | (n == 3 ? uint24_from_be( __up ) : \ |
| 137 | (n == 2 ? GUINT16_FROM_BE( get_unaligned(__up.u16ptr) ) : \ | 143 | (n == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \ |
| 138 | *__up.u8ptr )))); \ | 144 | *__up.u8ptr )))); \ |
| 139 | }) | 145 | }) |
| 140 | 146 | ||
| @@ -142,7 +148,7 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf) | |||
| 142 | ({ \ | 148 | ({ \ |
| 143 | union plist_uint_ptr __up; \ | 149 | union plist_uint_ptr __up; \ |
| 144 | __up.src = x; \ | 150 | __up.src = x; \ |
| 145 | GUINT64_FROM_BE( get_unaligned(__up.u64ptr) ); \ | 151 | be64toh( get_unaligned(__up.u64ptr) ); \ |
| 146 | }) | 152 | }) |
| 147 | 153 | ||
| 148 | #define get_needed_bytes(x) \ | 154 | #define get_needed_bytes(x) \ |
| @@ -153,6 +159,7 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf) | |||
| 153 | 159 | ||
| 154 | #define get_real_bytes(x) (x == (float) x ? 4 : 8) | 160 | #define get_real_bytes(x) (x == (float) x ? 4 : 8) |
| 155 | 161 | ||
| 162 | #define NODE_IS_ROOT(x) (((node_t*)x)->isRoot) | ||
| 156 | 163 | ||
| 157 | static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) | 164 | static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) |
| 158 | { | 165 | { |
| @@ -177,7 +184,7 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) | |||
| 177 | data->type = PLIST_UINT; | 184 | data->type = PLIST_UINT; |
| 178 | data->length = sizeof(uint64_t); | 185 | data->length = sizeof(uint64_t); |
| 179 | 186 | ||
| 180 | return g_node_new(data); | 187 | return node_create(NULL, data); |
| 181 | } | 188 | } |
| 182 | 189 | ||
| 183 | static plist_t parse_real_node(char *bnode, uint8_t size) | 190 | 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) | |||
| 208 | data->type = PLIST_REAL; | 215 | data->type = PLIST_REAL; |
| 209 | data->length = sizeof(double); | 216 | data->length = sizeof(double); |
| 210 | 217 | ||
| 211 | return g_node_new(data); | 218 | return node_create(NULL, data); |
| 212 | } | 219 | } |
| 213 | 220 | ||
| 214 | static plist_t parse_date_node(char *bnode, uint8_t size) | 221 | 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) | |||
| 217 | plist_data_t data = plist_get_data(node); | 224 | plist_data_t data = plist_get_data(node); |
| 218 | 225 | ||
| 219 | double time_real = data->realval; | 226 | double time_real = data->realval; |
| 220 | data->timeval.tv_sec = (glong) time_real; | 227 | data->timeval.tv_sec = (long) time_real; |
| 221 | data->timeval.tv_usec = (time_real - (glong) time_real) * G_USEC_PER_SEC; | 228 | data->timeval.tv_usec = (time_real - (long) time_real) * 1000000; |
| 222 | data->type = PLIST_DATE; | 229 | data->type = PLIST_DATE; |
| 223 | data->length = sizeof(GTimeVal); | 230 | data->length = sizeof(struct timeval); |
| 224 | 231 | ||
| 225 | return node; | 232 | return node; |
| 226 | } | 233 | } |
| @@ -235,26 +242,58 @@ static plist_t parse_string_node(char *bnode, uint64_t size) | |||
| 235 | data->strval[size] = '\0'; | 242 | data->strval[size] = '\0'; |
| 236 | data->length = strlen(data->strval); | 243 | data->length = strlen(data->strval); |
| 237 | 244 | ||
| 238 | return g_node_new(data); | 245 | return node_create(NULL, data); |
| 246 | } | ||
| 247 | |||
| 248 | static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, long *items_written) | ||
| 249 | { | ||
| 250 | if (!unistr || (len <= 0)) return NULL; | ||
| 251 | char *outbuf = (char*)malloc(3*(len+1)); | ||
| 252 | int p = 0; | ||
| 253 | int i = 0; | ||
| 254 | |||
| 255 | uint16_t wc; | ||
| 256 | |||
| 257 | while (i < len) { | ||
| 258 | wc = unistr[i++]; | ||
| 259 | if (wc >= 0x800) { | ||
| 260 | outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF)); | ||
| 261 | outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F)); | ||
| 262 | outbuf[p++] = (char)(0x80 + (wc & 0x3F)); | ||
| 263 | } else if (wc >= 0x80) { | ||
| 264 | outbuf[p++] = (char)(0xC0 + ((wc >> 6) & 0x1F)); | ||
| 265 | outbuf[p++] = (char)(0x80 + (wc & 0x3F)); | ||
| 266 | } else { | ||
| 267 | outbuf[p++] = (char)(wc & 0x7F); | ||
| 268 | } | ||
| 269 | } | ||
| 270 | if (items_read) { | ||
| 271 | *items_read = i; | ||
| 272 | } | ||
| 273 | if (items_written) { | ||
| 274 | *items_written = p; | ||
| 275 | } | ||
| 276 | outbuf[p] = 0; | ||
| 277 | |||
| 278 | return outbuf; | ||
| 239 | } | 279 | } |
| 240 | 280 | ||
| 241 | static plist_t parse_unicode_node(char *bnode, uint64_t size) | 281 | static plist_t parse_unicode_node(char *bnode, uint64_t size) |
| 242 | { | 282 | { |
| 243 | plist_data_t data = plist_new_plist_data(); | 283 | plist_data_t data = plist_new_plist_data(); |
| 244 | uint64_t i = 0; | 284 | uint64_t i = 0; |
| 245 | gunichar2 *unicodestr = NULL; | 285 | uint16_t *unicodestr = NULL; |
| 246 | gchar *tmpstr = NULL; | 286 | char *tmpstr = NULL; |
| 247 | glong items_read = 0; | 287 | long items_read = 0; |
| 248 | glong items_written = 0; | 288 | long items_written = 0; |
| 249 | GError *error = NULL; | ||
| 250 | 289 | ||
| 251 | data->type = PLIST_STRING; | 290 | data->type = PLIST_STRING; |
| 252 | unicodestr = (gunichar2 *) malloc(sizeof(gunichar2) * size); | 291 | unicodestr = (uint16_t*) malloc(sizeof(uint16_t) * size); |
| 253 | memcpy(unicodestr, bnode, sizeof(gunichar2) * size); | 292 | memcpy(unicodestr, bnode, sizeof(uint16_t) * size); |
| 254 | for (i = 0; i < size; i++) | 293 | for (i = 0; i < size; i++) |
| 255 | byte_convert((uint8_t *) (unicodestr + i), sizeof(gunichar2)); | 294 | byte_convert((uint8_t *) (unicodestr + i), sizeof(uint16_t)); |
| 256 | 295 | ||
| 257 | tmpstr = g_utf16_to_utf8(unicodestr, size, &items_read, &items_written, &error); | 296 | tmpstr = plist_utf16_to_utf8(unicodestr, size, &items_read, &items_written); |
| 258 | free(unicodestr); | 297 | free(unicodestr); |
| 259 | 298 | ||
| 260 | data->type = PLIST_STRING; | 299 | data->type = PLIST_STRING; |
| @@ -262,8 +301,8 @@ static plist_t parse_unicode_node(char *bnode, uint64_t size) | |||
| 262 | memcpy(data->strval, tmpstr, items_written); | 301 | memcpy(data->strval, tmpstr, items_written); |
| 263 | data->strval[items_written] = '\0'; | 302 | data->strval[items_written] = '\0'; |
| 264 | data->length = strlen(data->strval); | 303 | data->length = strlen(data->strval); |
| 265 | g_free(tmpstr); | 304 | free(tmpstr); |
| 266 | return g_node_new(data); | 305 | return node_create(NULL, data); |
| 267 | } | 306 | } |
| 268 | 307 | ||
| 269 | static plist_t parse_data_node(char *bnode, uint64_t size) | 308 | 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) | |||
| 275 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size); | 314 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size); |
| 276 | memcpy(data->buff, bnode, sizeof(uint8_t) * size); | 315 | memcpy(data->buff, bnode, sizeof(uint8_t) * size); |
| 277 | 316 | ||
| 278 | return g_node_new(data); | 317 | return node_create(NULL, data); |
| 279 | } | 318 | } |
| 280 | 319 | ||
| 281 | static plist_t parse_dict_node(char *bnode, uint64_t size, uint32_t ref_size) | 320 | 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) | |||
| 287 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size * 2); | 326 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size * 2); |
| 288 | memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size * 2); | 327 | memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size * 2); |
| 289 | 328 | ||
| 290 | return g_node_new(data); | 329 | return node_create(NULL, data); |
| 291 | } | 330 | } |
| 292 | 331 | ||
| 293 | static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) | 332 | 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) | |||
| 299 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size); | 338 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size); |
| 300 | memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size); | 339 | memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size); |
| 301 | 340 | ||
| 302 | return g_node_new(data); | 341 | return node_create(NULL, data); |
| 303 | } | 342 | } |
| 304 | 343 | ||
| 305 | 344 | ||
| @@ -329,7 +368,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec | |||
| 329 | data->type = PLIST_BOOLEAN; | 368 | data->type = PLIST_BOOLEAN; |
| 330 | data->boolval = TRUE; | 369 | data->boolval = TRUE; |
| 331 | data->length = 1; | 370 | data->length = 1; |
| 332 | return g_node_new(data); | 371 | return node_create(NULL, data); |
| 333 | } | 372 | } |
| 334 | 373 | ||
| 335 | case BPLIST_FALSE: | 374 | case BPLIST_FALSE: |
| @@ -338,7 +377,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec | |||
| 338 | data->type = PLIST_BOOLEAN; | 377 | data->type = PLIST_BOOLEAN; |
| 339 | data->boolval = FALSE; | 378 | data->boolval = FALSE; |
| 340 | data->length = 1; | 379 | data->length = 1; |
| 341 | return g_node_new(data); | 380 | return node_create(NULL, data); |
| 342 | } | 381 | } |
| 343 | 382 | ||
| 344 | case BPLIST_NULL: | 383 | case BPLIST_NULL: |
| @@ -420,7 +459,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec | |||
| 420 | return NULL; | 459 | return NULL; |
| 421 | } | 460 | } |
| 422 | 461 | ||
| 423 | static gpointer copy_plist_data(gconstpointer src, gpointer data) | 462 | static void* copy_plist_data(const void* src) |
| 424 | { | 463 | { |
| 425 | plist_data_t srcdata = (plist_data_t) src; | 464 | plist_data_t srcdata = (plist_data_t) src; |
| 426 | plist_data_t dstdata = plist_new_plist_data(); | 465 | 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) | |||
| 541 | 580 | ||
| 542 | if (index1 < num_objects) | 581 | if (index1 < num_objects) |
| 543 | { | 582 | { |
| 544 | if (G_NODE_IS_ROOT(nodeslist[index1])) | 583 | if (NODE_IS_ROOT(nodeslist[index1])) |
| 545 | g_node_append(nodeslist[i], nodeslist[index1]); | 584 | node_attach(nodeslist[i], nodeslist[index1]); |
| 546 | else | 585 | else |
| 547 | g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index1], copy_plist_data, NULL)); | 586 | node_attach(nodeslist[i], node_copy_deep(nodeslist[index1], copy_plist_data)); |
| 548 | } | 587 | } |
| 549 | 588 | ||
| 550 | if (index2 < num_objects) | 589 | if (index2 < num_objects) |
| 551 | { | 590 | { |
| 552 | if (G_NODE_IS_ROOT(nodeslist[index2])) | 591 | if (NODE_IS_ROOT(nodeslist[index2])) |
| 553 | g_node_append(nodeslist[i], nodeslist[index2]); | 592 | node_attach(nodeslist[i], nodeslist[index2]); |
| 554 | else | 593 | else |
| 555 | g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index2], copy_plist_data, NULL)); | 594 | node_attach(nodeslist[i], node_copy_deep(nodeslist[index2], copy_plist_data)); |
| 556 | } | 595 | } |
| 557 | } | 596 | } |
| 558 | 597 | ||
| @@ -567,10 +606,10 @@ void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) | |||
| 567 | 606 | ||
| 568 | if (index1 < num_objects) | 607 | if (index1 < num_objects) |
| 569 | { | 608 | { |
| 570 | if (G_NODE_IS_ROOT(nodeslist[index1])) | 609 | if (NODE_IS_ROOT(nodeslist[index1])) |
| 571 | g_node_append(nodeslist[i], nodeslist[index1]); | 610 | node_attach(nodeslist[i], nodeslist[index1]); |
| 572 | else | 611 | else |
| 573 | g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index1], copy_plist_data, NULL)); | 612 | node_attach(nodeslist[i], node_copy_deep(nodeslist[index1], copy_plist_data)); |
| 574 | } | 613 | } |
| 575 | } | 614 | } |
| 576 | free(data->buff); | 615 | free(data->buff); |
| @@ -584,15 +623,15 @@ void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) | |||
| 584 | free(nodeslist); | 623 | free(nodeslist); |
| 585 | } | 624 | } |
| 586 | 625 | ||
| 587 | static guint plist_data_hash(gconstpointer key) | 626 | static unsigned int plist_data_hash(const void* key) |
| 588 | { | 627 | { |
| 589 | plist_data_t data = plist_get_data((plist_t) key); | 628 | plist_data_t data = plist_get_data((plist_t) key); |
| 590 | 629 | ||
| 591 | guint hash = data->type; | 630 | unsigned int hash = data->type; |
| 592 | guint i = 0; | 631 | unsigned int i = 0; |
| 593 | 632 | ||
| 594 | char *buff = NULL; | 633 | char *buff = NULL; |
| 595 | guint size = 0; | 634 | unsigned int size = 0; |
| 596 | 635 | ||
| 597 | switch (data->type) | 636 | switch (data->type) |
| 598 | { | 637 | { |
| @@ -612,7 +651,7 @@ static guint plist_data_hash(gconstpointer key) | |||
| 612 | case PLIST_DICT: | 651 | case PLIST_DICT: |
| 613 | //for these types only hash pointer | 652 | //for these types only hash pointer |
| 614 | buff = (char *) &key; | 653 | buff = (char *) &key; |
| 615 | size = sizeof(gconstpointer); | 654 | size = sizeof(const void*); |
| 616 | break; | 655 | break; |
| 617 | case PLIST_DATE: | 656 | case PLIST_DATE: |
| 618 | buff = (char *) &(data->timeval); | 657 | buff = (char *) &(data->timeval); |
| @@ -629,22 +668,20 @@ static guint plist_data_hash(gconstpointer key) | |||
| 629 | return hash; | 668 | return hash; |
| 630 | } | 669 | } |
| 631 | 670 | ||
| 632 | |||
| 633 | |||
| 634 | struct serialize_s | 671 | struct serialize_s |
| 635 | { | 672 | { |
| 636 | GPtrArray *objects; | 673 | ptrarray_t* objects; |
| 637 | GHashTable *ref_table; | 674 | hashtable_t* ref_table; |
| 638 | }; | 675 | }; |
| 639 | 676 | ||
| 640 | static void serialize_plist(GNode * node, gpointer data) | 677 | static void serialize_plist(node_t* node, void* data) |
| 641 | { | 678 | { |
| 642 | uint64_t *index_val = NULL; | 679 | uint64_t *index_val = NULL; |
| 643 | struct serialize_s *ser = (struct serialize_s *) data; | 680 | struct serialize_s *ser = (struct serialize_s *) data; |
| 644 | uint64_t current_index = ser->objects->len; | 681 | uint64_t current_index = ser->objects->len; |
| 645 | 682 | ||
| 646 | //first check that node is not yet in objects | 683 | //first check that node is not yet in objects |
| 647 | gpointer val = g_hash_table_lookup(ser->ref_table, node); | 684 | void* val = hash_table_lookup(ser->ref_table, node); |
| 648 | if (val) | 685 | if (val) |
| 649 | { | 686 | { |
| 650 | //data is already in table | 687 | //data is already in table |
| @@ -653,17 +690,23 @@ static void serialize_plist(GNode * node, gpointer data) | |||
| 653 | //insert new ref | 690 | //insert new ref |
| 654 | index_val = (uint64_t *) malloc(sizeof(uint64_t)); | 691 | index_val = (uint64_t *) malloc(sizeof(uint64_t)); |
| 655 | *index_val = current_index; | 692 | *index_val = current_index; |
| 656 | g_hash_table_insert(ser->ref_table, node, index_val); | 693 | hash_table_insert(ser->ref_table, node, index_val); |
| 657 | 694 | ||
| 658 | //now append current node to object array | 695 | //now append current node to object array |
| 659 | g_ptr_array_add(ser->objects, node); | 696 | ptr_array_add(ser->objects, node); |
| 660 | 697 | ||
| 661 | //now recurse on children | 698 | //now recurse on children |
| 662 | g_node_children_foreach(node, G_TRAVERSE_ALL, serialize_plist, data); | 699 | node_iterator_t *ni = node_iterator_create(node->children); |
| 700 | node_t *ch; | ||
| 701 | while ((ch = node_iterator_next(ni))) { | ||
| 702 | serialize_plist(ch, data); | ||
| 703 | } | ||
| 704 | node_iterator_destroy(ni); | ||
| 705 | |||
| 663 | return; | 706 | return; |
| 664 | } | 707 | } |
| 665 | 708 | ||
| 666 | static gboolean free_index(gpointer key, gpointer value, gpointer user_data) | 709 | static int free_index(void* key, void* value, void* user_data) |
| 667 | { | 710 | { |
| 668 | free((uint64_t *) value); | 711 | free((uint64_t *) value); |
| 669 | return TRUE; | 712 | return TRUE; |
| @@ -671,7 +714,7 @@ static gboolean free_index(gpointer key, gpointer value, gpointer user_data) | |||
| 671 | 714 | ||
| 672 | #define Log2(x) (x == 8 ? 3 : (x == 4 ? 2 : (x == 2 ? 1 : 0))) | 715 | #define Log2(x) (x == 8 ? 3 : (x == 4 ? 2 : (x == 2 ? 1 : 0))) |
| 673 | 716 | ||
| 674 | static void write_int(GByteArray * bplist, uint64_t val) | 717 | static void write_int(bytearray_t * bplist, uint64_t val) |
| 675 | { | 718 | { |
| 676 | uint64_t size = get_needed_bytes(val); | 719 | uint64_t size = get_needed_bytes(val); |
| 677 | uint8_t *buff = NULL; | 720 | uint8_t *buff = NULL; |
| @@ -679,7 +722,7 @@ static void write_int(GByteArray * bplist, uint64_t val) | |||
| 679 | if (size == 3) | 722 | if (size == 3) |
| 680 | size++; | 723 | size++; |
| 681 | 724 | ||
| 682 | #if G_BYTE_ORDER == G_BIG_ENDIAN | 725 | #if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN |
| 683 | val = val << ((sizeof(uint64_t) - size) * 8); | 726 | val = val << ((sizeof(uint64_t) - size) * 8); |
| 684 | #endif | 727 | #endif |
| 685 | 728 | ||
| @@ -687,11 +730,11 @@ static void write_int(GByteArray * bplist, uint64_t val) | |||
| 687 | buff[0] = BPLIST_UINT | Log2(size); | 730 | buff[0] = BPLIST_UINT | Log2(size); |
| 688 | memcpy(buff + 1, &val, size); | 731 | memcpy(buff + 1, &val, size); |
| 689 | byte_convert(buff + 1, size); | 732 | byte_convert(buff + 1, size); |
| 690 | g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); | 733 | byte_array_append(bplist, buff, sizeof(uint8_t) + size); |
| 691 | free(buff); | 734 | free(buff); |
| 692 | } | 735 | } |
| 693 | 736 | ||
| 694 | static void write_real(GByteArray * bplist, double val) | 737 | static void write_real(bytearray_t * bplist, double val) |
| 695 | { | 738 | { |
| 696 | uint64_t size = get_real_bytes(val); //cheat to know used space | 739 | uint64_t size = get_real_bytes(val); //cheat to know used space |
| 697 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); | 740 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); |
| @@ -706,89 +749,89 @@ static void write_real(GByteArray * bplist, double val) | |||
| 706 | memcpy(buff + 1, &tmpval, size); | 749 | memcpy(buff + 1, &tmpval, size); |
| 707 | } | 750 | } |
| 708 | float_byte_convert(buff + 1, size); | 751 | float_byte_convert(buff + 1, size); |
| 709 | g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); | 752 | byte_array_append(bplist, buff, sizeof(uint8_t) + size); |
| 710 | free(buff); | 753 | free(buff); |
| 711 | } | 754 | } |
| 712 | 755 | ||
| 713 | static void write_date(GByteArray * bplist, double val) | 756 | static void write_date(bytearray_t * bplist, double val) |
| 714 | { | 757 | { |
| 715 | uint64_t size = 8; //dates always use 8 bytes | 758 | uint64_t size = 8; //dates always use 8 bytes |
| 716 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); | 759 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); |
| 717 | buff[0] = BPLIST_DATE | Log2(size); | 760 | buff[0] = BPLIST_DATE | Log2(size); |
| 718 | memcpy(buff + 1, &val, size); | 761 | memcpy(buff + 1, &val, size); |
| 719 | float_byte_convert(buff + 1, size); | 762 | float_byte_convert(buff + 1, size); |
| 720 | g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); | 763 | byte_array_append(bplist, buff, sizeof(uint8_t) + size); |
| 721 | free(buff); | 764 | free(buff); |
| 722 | } | 765 | } |
| 723 | 766 | ||
| 724 | static void write_raw_data(GByteArray * bplist, uint8_t mark, uint8_t * val, uint64_t size) | 767 | static void write_raw_data(bytearray_t * bplist, uint8_t mark, uint8_t * val, uint64_t size) |
| 725 | { | 768 | { |
| 726 | uint8_t *buff = NULL; | 769 | uint8_t *buff = NULL; |
| 727 | uint8_t marker = mark | (size < 15 ? size : 0xf); | 770 | uint8_t marker = mark | (size < 15 ? size : 0xf); |
| 728 | g_byte_array_append(bplist, &marker, sizeof(uint8_t)); | 771 | byte_array_append(bplist, &marker, sizeof(uint8_t)); |
| 729 | if (size >= 15) | 772 | if (size >= 15) |
| 730 | { | 773 | { |
| 731 | GByteArray *int_buff = g_byte_array_new(); | 774 | bytearray_t *int_buff = byte_array_new(); |
| 732 | write_int(int_buff, size); | 775 | write_int(int_buff, size); |
| 733 | g_byte_array_append(bplist, int_buff->data, int_buff->len); | 776 | byte_array_append(bplist, int_buff->data, int_buff->len); |
| 734 | g_byte_array_free(int_buff, TRUE); | 777 | byte_array_free(int_buff); |
| 735 | } | 778 | } |
| 736 | //stupid unicode buffer length | 779 | //stupid unicode buffer length |
| 737 | if (BPLIST_UNICODE==mark) size *= 2; | 780 | if (BPLIST_UNICODE==mark) size *= 2; |
| 738 | buff = (uint8_t *) malloc(size); | 781 | buff = (uint8_t *) malloc(size); |
| 739 | memcpy(buff, val, size); | 782 | memcpy(buff, val, size); |
| 740 | g_byte_array_append(bplist, buff, size); | 783 | byte_array_append(bplist, buff, size); |
| 741 | free(buff); | 784 | free(buff); |
| 742 | } | 785 | } |
| 743 | 786 | ||
| 744 | static void write_data(GByteArray * bplist, uint8_t * val, uint64_t size) | 787 | static void write_data(bytearray_t * bplist, uint8_t * val, uint64_t size) |
| 745 | { | 788 | { |
| 746 | write_raw_data(bplist, BPLIST_DATA, val, size); | 789 | write_raw_data(bplist, BPLIST_DATA, val, size); |
| 747 | } | 790 | } |
| 748 | 791 | ||
| 749 | static void write_string(GByteArray * bplist, char *val) | 792 | static void write_string(bytearray_t * bplist, char *val) |
| 750 | { | 793 | { |
| 751 | uint64_t size = strlen(val); | 794 | uint64_t size = strlen(val); |
| 752 | write_raw_data(bplist, BPLIST_STRING, (uint8_t *) val, size); | 795 | write_raw_data(bplist, BPLIST_STRING, (uint8_t *) val, size); |
| 753 | } | 796 | } |
| 754 | 797 | ||
| 755 | static void write_unicode(GByteArray * bplist, gunichar2 * val, uint64_t size) | 798 | static void write_unicode(bytearray_t * bplist, uint16_t * val, uint64_t size) |
| 756 | { | 799 | { |
| 757 | uint64_t i = 0; | 800 | uint64_t i = 0; |
| 758 | uint64_t size2 = size * sizeof(gunichar2); | 801 | uint64_t size2 = size * sizeof(uint16_t); |
| 759 | uint8_t *buff = (uint8_t *) malloc(size2); | 802 | uint8_t *buff = (uint8_t *) malloc(size2); |
| 760 | memcpy(buff, val, size2); | 803 | memcpy(buff, val, size2); |
| 761 | for (i = 0; i < size; i++) | 804 | for (i = 0; i < size; i++) |
| 762 | byte_convert(buff + i * sizeof(gunichar2), sizeof(gunichar2)); | 805 | byte_convert(buff + i * sizeof(uint16_t), sizeof(uint16_t)); |
| 763 | write_raw_data(bplist, BPLIST_UNICODE, buff, size); | 806 | write_raw_data(bplist, BPLIST_UNICODE, buff, size); |
| 764 | free(buff); | 807 | free(buff); |
| 765 | } | 808 | } |
| 766 | 809 | ||
| 767 | static void write_array(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) | 810 | static void write_array(bytearray_t * bplist, node_t* node, hashtable_t* ref_table, uint8_t dict_param_size) |
| 768 | { | 811 | { |
| 769 | uint64_t idx = 0; | 812 | uint64_t idx = 0; |
| 770 | uint8_t *buff = NULL; | 813 | uint8_t *buff = NULL; |
| 771 | 814 | ||
| 772 | GNode *cur = NULL; | 815 | node_t* cur = NULL; |
| 773 | uint64_t i = 0; | 816 | uint64_t i = 0; |
| 774 | 817 | ||
| 775 | uint64_t size = g_node_n_children(node); | 818 | uint64_t size = node_n_children(node); |
| 776 | uint8_t marker = BPLIST_ARRAY | (size < 15 ? size : 0xf); | 819 | uint8_t marker = BPLIST_ARRAY | (size < 15 ? size : 0xf); |
| 777 | g_byte_array_append(bplist, &marker, sizeof(uint8_t)); | 820 | byte_array_append(bplist, &marker, sizeof(uint8_t)); |
| 778 | if (size >= 15) | 821 | if (size >= 15) |
| 779 | { | 822 | { |
| 780 | GByteArray *int_buff = g_byte_array_new(); | 823 | bytearray_t *int_buff = byte_array_new(); |
| 781 | write_int(int_buff, size); | 824 | write_int(int_buff, size); |
| 782 | g_byte_array_append(bplist, int_buff->data, int_buff->len); | 825 | byte_array_append(bplist, int_buff->data, int_buff->len); |
| 783 | g_byte_array_free(int_buff, TRUE); | 826 | byte_array_free(int_buff); |
| 784 | } | 827 | } |
| 785 | 828 | ||
| 786 | buff = (uint8_t *) malloc(size * dict_param_size); | 829 | buff = (uint8_t *) malloc(size * dict_param_size); |
| 787 | 830 | ||
| 788 | for (i = 0, cur = node->children; cur && i < size; cur = cur->next, i++) | 831 | for (i = 0, cur = node_first_child(node); cur && i < size; cur = node_next_sibling(cur), i++) |
| 789 | { | 832 | { |
| 790 | idx = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); | 833 | idx = *(uint64_t *) (hash_table_lookup(ref_table, cur)); |
| 791 | #if G_BYTE_ORDER == G_BIG_ENDIAN | 834 | #if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN |
| 792 | idx = idx << ((sizeof(uint64_t) - dict_param_size) * 8); | 835 | idx = idx << ((sizeof(uint64_t) - dict_param_size) * 8); |
| 793 | #endif | 836 | #endif |
| 794 | memcpy(buff + i * dict_param_size, &idx, dict_param_size); | 837 | 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 | |||
| 796 | } | 839 | } |
| 797 | 840 | ||
| 798 | //now append to bplist | 841 | //now append to bplist |
| 799 | g_byte_array_append(bplist, buff, size * dict_param_size); | 842 | byte_array_append(bplist, buff, size * dict_param_size); |
| 800 | free(buff); | 843 | free(buff); |
| 801 | 844 | ||
| 802 | } | 845 | } |
| 803 | 846 | ||
| 804 | static void write_dict(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) | 847 | static void write_dict(bytearray_t * bplist, node_t* node, hashtable_t* ref_table, uint8_t dict_param_size) |
| 805 | { | 848 | { |
| 806 | uint64_t idx1 = 0; | 849 | uint64_t idx1 = 0; |
| 807 | uint64_t idx2 = 0; | 850 | uint64_t idx2 = 0; |
| 808 | uint8_t *buff = NULL; | 851 | uint8_t *buff = NULL; |
| 809 | 852 | ||
| 810 | GNode *cur = NULL; | 853 | node_t* cur = NULL; |
| 811 | uint64_t i = 0; | 854 | uint64_t i = 0; |
| 812 | 855 | ||
| 813 | uint64_t size = g_node_n_children(node) / 2; | 856 | uint64_t size = node_n_children(node) / 2; |
| 814 | uint8_t marker = BPLIST_DICT | (size < 15 ? size : 0xf); | 857 | uint8_t marker = BPLIST_DICT | (size < 15 ? size : 0xf); |
| 815 | g_byte_array_append(bplist, &marker, sizeof(uint8_t)); | 858 | byte_array_append(bplist, &marker, sizeof(uint8_t)); |
| 816 | if (size >= 15) | 859 | if (size >= 15) |
| 817 | { | 860 | { |
| 818 | GByteArray *int_buff = g_byte_array_new(); | 861 | bytearray_t *int_buff = byte_array_new(); |
| 819 | write_int(int_buff, size); | 862 | write_int(int_buff, size); |
| 820 | g_byte_array_append(bplist, int_buff->data, int_buff->len); | 863 | byte_array_append(bplist, int_buff->data, int_buff->len); |
| 821 | g_byte_array_free(int_buff, TRUE); | 864 | byte_array_free(int_buff); |
| 822 | } | 865 | } |
| 823 | 866 | ||
| 824 | buff = (uint8_t *) malloc(size * 2 * dict_param_size); | 867 | buff = (uint8_t *) malloc(size * 2 * dict_param_size); |
| 825 | 868 | for (i = 0, cur = node_first_child(node); cur && i < size; cur = node_next_sibling(node_next_sibling(cur)), i++) | |
| 826 | for (i = 0, cur = node->children; cur && i < size; cur = cur->next->next, i++) | ||
| 827 | { | 869 | { |
| 828 | idx1 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); | 870 | idx1 = *(uint64_t *) (hash_table_lookup(ref_table, cur)); |
| 829 | #if G_BYTE_ORDER == G_BIG_ENDIAN | 871 | #if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN |
| 830 | idx1 = idx1 << ((sizeof(uint64_t) - dict_param_size) * 8); | 872 | idx1 = idx1 << ((sizeof(uint64_t) - dict_param_size) * 8); |
| 831 | #endif | 873 | #endif |
| 832 | memcpy(buff + i * dict_param_size, &idx1, dict_param_size); | 874 | memcpy(buff + i * dict_param_size, &idx1, dict_param_size); |
| 833 | byte_convert(buff + i * dict_param_size, dict_param_size); | 875 | byte_convert(buff + i * dict_param_size, dict_param_size); |
| 834 | 876 | ||
| 835 | idx2 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur->next)); | 877 | idx2 = *(uint64_t *) (hash_table_lookup(ref_table, cur->next)); |
| 836 | #if G_BYTE_ORDER == G_BIG_ENDIAN | 878 | #if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN |
| 837 | idx2 = idx2 << ((sizeof(uint64_t) - dict_param_size) * 8); | 879 | idx2 = idx2 << ((sizeof(uint64_t) - dict_param_size) * 8); |
| 838 | #endif | 880 | #endif |
| 839 | memcpy(buff + (i + size) * dict_param_size, &idx2, dict_param_size); | 881 | 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 | |||
| 841 | } | 883 | } |
| 842 | 884 | ||
| 843 | //now append to bplist | 885 | //now append to bplist |
| 844 | g_byte_array_append(bplist, buff, size * 2 * dict_param_size); | 886 | byte_array_append(bplist, buff, size * 2 * dict_param_size); |
| 845 | free(buff); | 887 | free(buff); |
| 846 | 888 | ||
| 847 | } | 889 | } |
| @@ -860,38 +902,81 @@ static int is_ascii_string(char* s, int len) | |||
| 860 | return ret; | 902 | return ret; |
| 861 | } | 903 | } |
| 862 | 904 | ||
| 905 | uint16_t *plist_utf8_to_utf16(char *unistr, long size, long *items_read, long *items_written) | ||
| 906 | { | ||
| 907 | uint16_t *outbuf = (uint16_t*)malloc((size+1)*sizeof(uint16_t)); | ||
| 908 | int p = 0; | ||
| 909 | int i = 0; | ||
| 910 | |||
| 911 | unsigned char c0; | ||
| 912 | unsigned char c1; | ||
| 913 | unsigned char c2; | ||
| 914 | |||
| 915 | while (i < size) { | ||
| 916 | c0 = unistr[i]; | ||
| 917 | c1 = (i < size-1) ? unistr[i+1] : 0; | ||
| 918 | c2 = (i < size-2) ? unistr[i+2] : 0; | ||
| 919 | if ((c0 >= 0xE0) && (i < size-2) && (c1 >= 0x80) && (c2 >= 0x80)) { | ||
| 920 | // 3 byte sequence | ||
| 921 | outbuf[p++] = ((c2 & 0x3F) + ((c1 & 3) << 6)) + (((c1 >> 2) & 15) << 8) + ((c0 & 15) << 12); | ||
| 922 | i+=3; | ||
| 923 | } else if ((c0 >= 0xC0) && (i < size-1) && (c1 >= 0x80)) { | ||
| 924 | // 2 byte sequence | ||
| 925 | outbuf[p++] = ((c1 & 0x3F) + ((c0 & 3) << 6)) + (((c0 >> 2) & 7) << 8); | ||
| 926 | i+=2; | ||
| 927 | } else if (c0 < 0x80) { | ||
| 928 | // 1 byte sequence | ||
| 929 | outbuf[p++] = c0; | ||
| 930 | i+=1; | ||
| 931 | } else { | ||
| 932 | // invalid character | ||
| 933 | fprintf(stderr, "invalid utf8 sequence in string at index %d\n", i); | ||
| 934 | break; | ||
| 935 | } | ||
| 936 | } | ||
| 937 | if (items_read) { | ||
| 938 | *items_read = i; | ||
| 939 | } | ||
| 940 | if (items_written) { | ||
| 941 | *items_written = p; | ||
| 942 | } | ||
| 943 | outbuf[p] = 0; | ||
| 944 | |||
| 945 | return outbuf; | ||
| 946 | |||
| 947 | } | ||
| 948 | |||
| 863 | void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | 949 | void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) |
| 864 | { | 950 | { |
| 865 | GPtrArray *objects = NULL; | 951 | ptrarray_t* objects = NULL; |
| 866 | GHashTable *ref_table = NULL; | 952 | hashtable_t* ref_table = NULL; |
| 867 | struct serialize_s ser_s; | 953 | struct serialize_s ser_s; |
| 868 | uint8_t offset_size = 0; | 954 | uint8_t offset_size = 0; |
| 869 | uint8_t dict_param_size = 0; | 955 | uint8_t dict_param_size = 0; |
| 870 | uint64_t num_objects = 0; | 956 | uint64_t num_objects = 0; |
| 871 | uint64_t root_object = 0; | 957 | uint64_t root_object = 0; |
| 872 | uint64_t offset_table_index = 0; | 958 | uint64_t offset_table_index = 0; |
| 873 | GByteArray *bplist_buff = NULL; | 959 | bytearray_t *bplist_buff = NULL; |
| 874 | uint64_t i = 0; | 960 | uint64_t i = 0; |
| 875 | uint8_t *buff = NULL; | 961 | uint8_t *buff = NULL; |
| 876 | uint64_t *offsets = NULL; | 962 | uint64_t *offsets = NULL; |
| 877 | uint8_t pad[6] = { 0, 0, 0, 0, 0, 0 }; | 963 | uint8_t pad[6] = { 0, 0, 0, 0, 0, 0 }; |
| 878 | uint8_t trailer[BPLIST_TRL_SIZE]; | 964 | uint8_t trailer[BPLIST_TRL_SIZE]; |
| 879 | //for string | 965 | //for string |
| 880 | glong len = 0; | 966 | long len = 0; |
| 881 | int type = 0; | 967 | int type = 0; |
| 882 | glong items_read = 0; | 968 | long items_read = 0; |
| 883 | glong items_written = 0; | 969 | long items_written = 0; |
| 884 | GError *error = NULL; | 970 | uint16_t *unicodestr = NULL; |
| 885 | gunichar2 *unicodestr = NULL; | ||
| 886 | 971 | ||
| 887 | //check for valid input | 972 | //check for valid input |
| 888 | if (!plist || !plist_bin || *plist_bin || !length) | 973 | if (!plist || !plist_bin || *plist_bin || !length) |
| 889 | return; | 974 | return; |
| 890 | 975 | ||
| 891 | //list of objects | 976 | //list of objects |
| 892 | objects = g_ptr_array_new(); | 977 | objects = ptr_array_new(256); |
| 893 | //hashtable to write only once same nodes | 978 | //hashtable to write only once same nodes |
| 894 | ref_table = g_hash_table_new(plist_data_hash, plist_data_compare); | 979 | ref_table = hash_table_new(plist_data_hash, plist_data_compare); |
| 895 | 980 | ||
| 896 | //serialize plist | 981 | //serialize plist |
| 897 | ser_s.objects = objects; | 982 | ser_s.objects = objects; |
| @@ -906,18 +991,18 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 906 | offset_table_index = 0; //unknown yet | 991 | offset_table_index = 0; //unknown yet |
| 907 | 992 | ||
| 908 | //setup a dynamic bytes array to store bplist in | 993 | //setup a dynamic bytes array to store bplist in |
| 909 | bplist_buff = g_byte_array_new(); | 994 | bplist_buff = byte_array_new(); |
| 910 | 995 | ||
| 911 | //set magic number and version | 996 | //set magic number and version |
| 912 | g_byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); | 997 | byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); |
| 913 | g_byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE); | 998 | byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE); |
| 914 | 999 | ||
| 915 | //write objects and table | 1000 | //write objects and table |
| 916 | offsets = (uint64_t *) malloc(num_objects * sizeof(uint64_t)); | 1001 | offsets = (uint64_t *) malloc(num_objects * sizeof(uint64_t)); |
| 917 | for (i = 0; i < num_objects; i++) | 1002 | for (i = 0; i < num_objects; i++) |
| 918 | { | 1003 | { |
| 919 | 1004 | ||
| 920 | plist_data_t data = plist_get_data(g_ptr_array_index(objects, i)); | 1005 | plist_data_t data = plist_get_data(ptr_array_index(objects, i)); |
| 921 | offsets[i] = bplist_buff->len; | 1006 | offsets[i] = bplist_buff->len; |
| 922 | 1007 | ||
| 923 | switch (data->type) | 1008 | switch (data->type) |
| @@ -925,7 +1010,7 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 925 | case PLIST_BOOLEAN: | 1010 | case PLIST_BOOLEAN: |
| 926 | buff = (uint8_t *) malloc(sizeof(uint8_t)); | 1011 | buff = (uint8_t *) malloc(sizeof(uint8_t)); |
| 927 | buff[0] = data->boolval ? BPLIST_TRUE : BPLIST_FALSE; | 1012 | buff[0] = data->boolval ? BPLIST_TRUE : BPLIST_FALSE; |
| 928 | g_byte_array_append(bplist_buff, buff, sizeof(uint8_t)); | 1013 | byte_array_append(bplist_buff, buff, sizeof(uint8_t)); |
| 929 | free(buff); | 1014 | free(buff); |
| 930 | break; | 1015 | break; |
| 931 | 1016 | ||
| @@ -946,21 +1031,21 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 946 | } | 1031 | } |
| 947 | else | 1032 | else |
| 948 | { | 1033 | { |
| 949 | unicodestr = g_utf8_to_utf16(data->strval, len, &items_read, &items_written, &error); | 1034 | unicodestr = plist_utf8_to_utf16(data->strval, len, &items_read, &items_written); |
| 950 | write_unicode(bplist_buff, unicodestr, items_written); | 1035 | write_unicode(bplist_buff, unicodestr, items_written); |
| 951 | g_free(unicodestr); | 1036 | free(unicodestr); |
| 952 | } | 1037 | } |
| 953 | break; | 1038 | break; |
| 954 | case PLIST_DATA: | 1039 | case PLIST_DATA: |
| 955 | write_data(bplist_buff, data->buff, data->length); | 1040 | write_data(bplist_buff, data->buff, data->length); |
| 956 | case PLIST_ARRAY: | 1041 | case PLIST_ARRAY: |
| 957 | write_array(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); | 1042 | write_array(bplist_buff, ptr_array_index(objects, i), ref_table, dict_param_size); |
| 958 | break; | 1043 | break; |
| 959 | case PLIST_DICT: | 1044 | case PLIST_DICT: |
| 960 | write_dict(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); | 1045 | write_dict(bplist_buff, ptr_array_index(objects, i), ref_table, dict_param_size); |
| 961 | break; | 1046 | break; |
| 962 | case PLIST_DATE: | 1047 | case PLIST_DATE: |
| 963 | write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / G_USEC_PER_SEC); | 1048 | write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / 1000000); |
| 964 | break; | 1049 | break; |
| 965 | default: | 1050 | default: |
| 966 | break; | 1051 | break; |
| @@ -968,9 +1053,9 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 968 | } | 1053 | } |
| 969 | 1054 | ||
| 970 | //free intermediate objects | 1055 | //free intermediate objects |
| 971 | g_hash_table_foreach_remove(ref_table, free_index, NULL); | 1056 | //hash_table_foreach_remove(ref_table, free_index, NULL); |
| 972 | g_ptr_array_free(objects, TRUE); | 1057 | ptr_array_free(objects); |
| 973 | g_hash_table_destroy(ref_table); | 1058 | hash_table_destroy(ref_table); |
| 974 | 1059 | ||
| 975 | //write offsets | 1060 | //write offsets |
| 976 | offset_size = get_needed_bytes(bplist_buff->len); | 1061 | 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) | |||
| 979 | { | 1064 | { |
| 980 | uint8_t *offsetbuff = (uint8_t *) malloc(offset_size); | 1065 | uint8_t *offsetbuff = (uint8_t *) malloc(offset_size); |
| 981 | 1066 | ||
| 982 | #if G_BYTE_ORDER == G_BIG_ENDIAN | 1067 | #if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN |
| 983 | offsets[i] = offsets[i] << ((sizeof(uint64_t) - offset_size) * 8); | 1068 | offsets[i] = offsets[i] << ((sizeof(uint64_t) - offset_size) * 8); |
| 984 | #endif | 1069 | #endif |
| 985 | 1070 | ||
| 986 | memcpy(offsetbuff, &offsets[i], offset_size); | 1071 | memcpy(offsetbuff, &offsets[i], offset_size); |
| 987 | byte_convert(offsetbuff, offset_size); | 1072 | byte_convert(offsetbuff, offset_size); |
| 988 | g_byte_array_append(bplist_buff, offsetbuff, offset_size); | 1073 | byte_array_append(bplist_buff, offsetbuff, offset_size); |
| 989 | free(offsetbuff); | 1074 | free(offsetbuff); |
| 990 | } | 1075 | } |
| 991 | 1076 | ||
| 992 | //experimental pad to reflect apple's files | 1077 | //experimental pad to reflect apple's files |
| 993 | g_byte_array_append(bplist_buff, pad, 6); | 1078 | byte_array_append(bplist_buff, pad, 6); |
| 994 | 1079 | ||
| 995 | //setup trailer | 1080 | //setup trailer |
| 996 | num_objects = GUINT64_FROM_BE(num_objects); | 1081 | num_objects = be64toh(num_objects); |
| 997 | root_object = GUINT64_FROM_BE(root_object); | 1082 | root_object = be64toh(root_object); |
| 998 | offset_table_index = GUINT64_FROM_BE(offset_table_index); | 1083 | offset_table_index = be64toh(offset_table_index); |
| 999 | 1084 | ||
| 1000 | memcpy(trailer + BPLIST_TRL_OFFSIZE_IDX, &offset_size, sizeof(uint8_t)); | 1085 | memcpy(trailer + BPLIST_TRL_OFFSIZE_IDX, &offset_size, sizeof(uint8_t)); |
| 1001 | memcpy(trailer + BPLIST_TRL_PARMSIZE_IDX, &dict_param_size, sizeof(uint8_t)); | 1086 | 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) | |||
| 1003 | memcpy(trailer + BPLIST_TRL_ROOTOBJ_IDX, &root_object, sizeof(uint64_t)); | 1088 | memcpy(trailer + BPLIST_TRL_ROOTOBJ_IDX, &root_object, sizeof(uint64_t)); |
| 1004 | memcpy(trailer + BPLIST_TRL_OFFTAB_IDX, &offset_table_index, sizeof(uint64_t)); | 1089 | memcpy(trailer + BPLIST_TRL_OFFTAB_IDX, &offset_table_index, sizeof(uint64_t)); |
| 1005 | 1090 | ||
| 1006 | g_byte_array_append(bplist_buff, trailer, BPLIST_TRL_SIZE); | 1091 | byte_array_append(bplist_buff, trailer, BPLIST_TRL_SIZE); |
| 1007 | 1092 | ||
| 1008 | //duplicate buffer | 1093 | //duplicate buffer |
| 1009 | *plist_bin = (char *) malloc(bplist_buff->len); | 1094 | *plist_bin = (char *) malloc(bplist_buff->len); |
| 1010 | memcpy(*plist_bin, bplist_buff->data, bplist_buff->len); | 1095 | memcpy(*plist_bin, bplist_buff->data, bplist_buff->len); |
| 1011 | *length = bplist_buff->len; | 1096 | *length = bplist_buff->len; |
| 1012 | 1097 | ||
| 1013 | g_byte_array_free(bplist_buff, TRUE); | 1098 | byte_array_free(bplist_buff); |
| 1014 | free(offsets); | 1099 | free(offsets); |
| 1015 | } | 1100 | } |
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 @@ | |||
| 1 | /* | ||
| 2 | * bytearray.c | ||
| 3 | * simple byte array implementation | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | #include <string.h> | ||
| 22 | #include "bytearray.h" | ||
| 23 | |||
| 24 | bytearray_t *byte_array_new() | ||
| 25 | { | ||
| 26 | bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t)); | ||
| 27 | a->data = malloc(256); | ||
| 28 | a->len = 0; | ||
| 29 | a->capacity = 256; | ||
| 30 | return a; | ||
| 31 | } | ||
| 32 | |||
| 33 | void byte_array_free(bytearray_t *ba) | ||
| 34 | { | ||
| 35 | if (!ba) return; | ||
| 36 | if (ba->data) { | ||
| 37 | free(ba->data); | ||
| 38 | } | ||
| 39 | free(ba); | ||
| 40 | } | ||
| 41 | |||
| 42 | void byte_array_append(bytearray_t *ba, void *buf, size_t len) | ||
| 43 | { | ||
| 44 | if (!ba || !ba->data || (len <= 0)) return; | ||
| 45 | size_t remaining = ba->capacity-ba->len; | ||
| 46 | if (len > remaining) { | ||
| 47 | ba->data = realloc(ba->data, ba->capacity + (len - remaining)); | ||
| 48 | ba->capacity += (len - remaining); | ||
| 49 | } | ||
| 50 | memcpy(ba->data+ba->len, buf, len); | ||
| 51 | ba->len += len; | ||
| 52 | } | ||
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 @@ | |||
| 1 | /* | ||
| 2 | * bytearray.h | ||
| 3 | * header file for simple byte array implementation | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | #ifndef BYTEARRAY_H | ||
| 22 | #define BYTEARRAY_H | ||
| 23 | #include <stdlib.h> | ||
| 24 | #include "common.h" | ||
| 25 | |||
| 26 | typedef struct bytearray_t { | ||
| 27 | void *data; | ||
| 28 | size_t len; | ||
| 29 | size_t capacity; | ||
| 30 | } bytearray_t; | ||
| 31 | |||
| 32 | _PLIST_INTERNAL bytearray_t *byte_array_new(); | ||
| 33 | _PLIST_INTERNAL void byte_array_free(bytearray_t *ba); | ||
| 34 | _PLIST_INTERNAL void byte_array_append(bytearray_t *ba, void *buf, size_t len); | ||
| 35 | |||
| 36 | #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 @@ | |||
| 1 | #ifndef COMMON_H | ||
| 2 | #define COMMON_H | ||
| 3 | |||
| 4 | #define PLIST_LITTLE_ENDIAN 0 | ||
| 5 | #define PLIST_BIG_ENDIAN 1 | ||
| 6 | |||
| 7 | #if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__CYGWIN__) | ||
| 8 | # define _PLIST_INTERNAL __attribute__((visibility("hidden"))) | ||
| 9 | #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) | ||
| 10 | # define _PLIST_INTERNAL __hidden | ||
| 11 | #else /* not gcc >= 4 and not Sun Studio >= 8 */ | ||
| 12 | # define _PLIST_INTERNAL | ||
| 13 | #endif /* GNUC >= 4 */ | ||
| 14 | |||
| 15 | #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 @@ | |||
| 1 | /* | ||
| 2 | * hashtable.c | ||
| 3 | * really simple hash table implementation | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | #include "hashtable.h" | ||
| 22 | |||
| 23 | hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func) | ||
| 24 | { | ||
| 25 | hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t)); | ||
| 26 | int i; | ||
| 27 | for (i = 0; i < 256; i++) { | ||
| 28 | ht->entries[i] = NULL; | ||
| 29 | } | ||
| 30 | ht->count = 0; | ||
| 31 | ht->hash_func = hash_func; | ||
| 32 | ht->compare_func = compare_func; | ||
| 33 | return ht; | ||
| 34 | } | ||
| 35 | |||
| 36 | void hash_table_destroy(hashtable_t *ht) | ||
| 37 | { | ||
| 38 | if (!ht) return; | ||
| 39 | |||
| 40 | int i = 0; | ||
| 41 | for (i = 0; i < 256; i++) { | ||
| 42 | if (ht->entries[i]) { | ||
| 43 | hashentry_t* e = ht->entries[i]; | ||
| 44 | while (e) { | ||
| 45 | free(e->value); | ||
| 46 | hashentry_t* old = e; | ||
| 47 | e = e->next; | ||
| 48 | free(old); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
| 52 | free(ht); | ||
| 53 | } | ||
| 54 | |||
| 55 | void hash_table_insert(hashtable_t* ht, void *key, void *value) | ||
| 56 | { | ||
| 57 | if (!ht || !key) return; | ||
| 58 | int i; | ||
| 59 | |||
| 60 | unsigned int hash = ht->hash_func(key); | ||
| 61 | |||
| 62 | int idx0 = hash & 0xFF; | ||
| 63 | |||
| 64 | // get the idx0 list | ||
| 65 | hashentry_t* e = ht->entries[idx0]; | ||
| 66 | while (e) { | ||
| 67 | if (ht->compare_func(e->key, key)) { | ||
| 68 | // element already present. replace value. | ||
| 69 | e->value = value; | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | e = e->next; | ||
| 73 | } | ||
| 74 | |||
| 75 | // if we get here, the element is not yet in the list. | ||
| 76 | |||
| 77 | // make a new entry. | ||
| 78 | hashentry_t* entry = (hashentry_t*)malloc(sizeof(hashentry_t)); | ||
| 79 | entry->key = key; | ||
| 80 | entry->value = value; | ||
| 81 | if (!ht->entries[idx0]) { | ||
| 82 | // first entry | ||
| 83 | entry->next = NULL; | ||
| 84 | } else { | ||
| 85 | // add to list | ||
| 86 | entry->next = ht->entries[idx0]; | ||
| 87 | } | ||
| 88 | ht->entries[idx0] = entry; | ||
| 89 | ht->count++; | ||
| 90 | } | ||
| 91 | |||
| 92 | void* hash_table_lookup(hashtable_t* ht, void *key) | ||
| 93 | { | ||
| 94 | if (!ht || !key) return NULL; | ||
| 95 | unsigned int hash = ht->hash_func(key); | ||
| 96 | |||
| 97 | int idx0 = hash & 0xFF; | ||
| 98 | |||
| 99 | hashentry_t* e = ht->entries[idx0]; | ||
| 100 | while (e) { | ||
| 101 | if (ht->compare_func(e->key, key)) { | ||
| 102 | return e->value; | ||
| 103 | } | ||
| 104 | e = e->next; | ||
| 105 | } | ||
| 106 | return NULL; | ||
| 107 | } | ||
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 @@ | |||
| 1 | /* | ||
| 2 | * hashtable.h | ||
| 3 | * header file for really simple hash table implementation | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | #ifndef HASHTABLE_H | ||
| 22 | #define HASHTABLE_H | ||
| 23 | #include <stdlib.h> | ||
| 24 | #include "common.h" | ||
| 25 | |||
| 26 | typedef struct hashentry_t { | ||
| 27 | void *key; | ||
| 28 | void *value; | ||
| 29 | void *next; | ||
| 30 | } hashentry_t; | ||
| 31 | |||
| 32 | typedef unsigned int(*hash_func_t)(const void* key); | ||
| 33 | typedef int (*compare_func_t)(const void *a, const void *b); | ||
| 34 | |||
| 35 | typedef struct hashtable_t { | ||
| 36 | hashentry_t *entries[256]; | ||
| 37 | size_t count; | ||
| 38 | hash_func_t hash_func; | ||
| 39 | compare_func_t compare_func; | ||
| 40 | } hashtable_t; | ||
| 41 | |||
| 42 | _PLIST_INTERNAL hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func); | ||
| 43 | _PLIST_INTERNAL void hash_table_destroy(hashtable_t *ht); | ||
| 44 | |||
| 45 | _PLIST_INTERNAL void hash_table_insert(hashtable_t* ht, void *key, void *value); | ||
| 46 | _PLIST_INTERNAL void* hash_table_lookup(hashtable_t* ht, void *key); | ||
| 47 | |||
| 48 | #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 @@ | |||
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | #include <stdio.h> | 27 | #include <stdio.h> |
| 28 | 28 | ||
| 29 | #include <node.h> | ||
| 30 | #include <node_iterator.h> | ||
| 31 | |||
| 29 | plist_t plist_new_node(plist_data_t data) | 32 | plist_t plist_new_node(plist_data_t data) |
| 30 | { | 33 | { |
| 31 | return (plist_t) g_node_new(data); | 34 | return (plist_t) node_create(NULL, data); |
| 32 | } | 35 | } |
| 33 | 36 | ||
| 34 | plist_data_t plist_get_data(const plist_t node) | 37 | plist_data_t plist_get_data(const plist_t node) |
| 35 | { | 38 | { |
| 36 | if (!node) | 39 | if (!node) |
| 37 | return NULL; | 40 | return NULL; |
| 38 | return ((GNode *) node)->data; | 41 | return ((node_t*)node)->data; |
| 39 | } | 42 | } |
| 40 | 43 | ||
| 41 | plist_data_t plist_new_plist_data(void) | 44 | plist_data_t plist_new_plist_data(void) |
| @@ -64,15 +67,22 @@ static void plist_free_data(plist_data_t data) | |||
| 64 | } | 67 | } |
| 65 | } | 68 | } |
| 66 | 69 | ||
| 67 | static void plist_free_node(GNode * node, gpointer none) | 70 | static void plist_free_node(node_t* node) |
| 68 | { | 71 | { |
| 69 | plist_data_t data = NULL; | 72 | plist_data_t data = NULL; |
| 70 | g_node_unlink(node); | 73 | node_detach(node->parent, node); |
| 71 | data = plist_get_data(node); | 74 | data = plist_get_data(node); |
| 72 | plist_free_data(data); | 75 | plist_free_data(data); |
| 73 | node->data = NULL; | 76 | node->data = NULL; |
| 74 | g_node_children_foreach(node, G_TRAVERSE_ALL, plist_free_node, NULL); | 77 | |
| 75 | g_node_destroy(node); | 78 | node_iterator_t *ni = node_iterator_create(node->children); |
| 79 | node_t *ch; | ||
| 80 | while ((ch = node_iterator_next(ni))) { | ||
| 81 | plist_free_node(ch); | ||
| 82 | } | ||
| 83 | node_iterator_destroy(ni); | ||
| 84 | |||
| 85 | node_destroy(node); | ||
| 76 | } | 86 | } |
| 77 | 87 | ||
| 78 | plist_t plist_new_dict(void) | 88 | plist_t plist_new_dict(void) |
| @@ -151,7 +161,7 @@ plist_t plist_new_date(int32_t sec, int32_t usec) | |||
| 151 | data->type = PLIST_DATE; | 161 | data->type = PLIST_DATE; |
| 152 | data->timeval.tv_sec = sec; | 162 | data->timeval.tv_sec = sec; |
| 153 | data->timeval.tv_usec = usec; | 163 | data->timeval.tv_usec = usec; |
| 154 | data->length = sizeof(GTimeVal); | 164 | data->length = sizeof(struct timeval); |
| 155 | return plist_new_node(data); | 165 | return plist_new_node(data); |
| 156 | } | 166 | } |
| 157 | 167 | ||
| @@ -159,11 +169,11 @@ void plist_free(plist_t plist) | |||
| 159 | { | 169 | { |
| 160 | if (plist) | 170 | if (plist) |
| 161 | { | 171 | { |
| 162 | plist_free_node(plist, NULL); | 172 | plist_free_node(plist); |
| 163 | } | 173 | } |
| 164 | } | 174 | } |
| 165 | 175 | ||
| 166 | static void plist_copy_node(GNode * node, gpointer parent_node_ptr) | 176 | static void plist_copy_node(node_t *node, void *parent_node_ptr) |
| 167 | { | 177 | { |
| 168 | plist_type node_type = PLIST_NONE; | 178 | plist_type node_type = PLIST_NONE; |
| 169 | plist_t newnode = NULL; | 179 | plist_t newnode = NULL; |
| @@ -195,14 +205,19 @@ static void plist_copy_node(GNode * node, gpointer parent_node_ptr) | |||
| 195 | 205 | ||
| 196 | if (*(plist_t*)parent_node_ptr) | 206 | if (*(plist_t*)parent_node_ptr) |
| 197 | { | 207 | { |
| 198 | g_node_append(*(plist_t*)parent_node_ptr, newnode); | 208 | node_attach(*(plist_t*)parent_node_ptr, newnode); |
| 199 | } | 209 | } |
| 200 | else | 210 | else |
| 201 | { | 211 | { |
| 202 | *(plist_t*)parent_node_ptr = newnode; | 212 | *(plist_t*)parent_node_ptr = newnode; |
| 203 | } | 213 | } |
| 204 | 214 | ||
| 205 | g_node_children_foreach(node, G_TRAVERSE_ALL, plist_copy_node, &newnode); | 215 | node_iterator_t *ni = node_iterator_create(node->children); |
| 216 | node_t *ch; | ||
| 217 | while ((ch = node_iterator_next(ni))) { | ||
| 218 | plist_copy_node(ch, &newnode); | ||
| 219 | } | ||
| 220 | node_iterator_destroy(ni); | ||
| 206 | } | 221 | } |
| 207 | 222 | ||
| 208 | plist_t plist_copy(plist_t node) | 223 | plist_t plist_copy(plist_t node) |
| @@ -217,7 +232,7 @@ uint32_t plist_array_get_size(plist_t node) | |||
| 217 | uint32_t ret = 0; | 232 | uint32_t ret = 0; |
| 218 | if (node && PLIST_ARRAY == plist_get_node_type(node)) | 233 | if (node && PLIST_ARRAY == plist_get_node_type(node)) |
| 219 | { | 234 | { |
| 220 | ret = g_node_n_children(node); | 235 | ret = node_n_children(node); |
| 221 | } | 236 | } |
| 222 | return ret; | 237 | return ret; |
| 223 | } | 238 | } |
| @@ -227,7 +242,7 @@ plist_t plist_array_get_item(plist_t node, uint32_t n) | |||
| 227 | plist_t ret = NULL; | 242 | plist_t ret = NULL; |
| 228 | if (node && PLIST_ARRAY == plist_get_node_type(node)) | 243 | if (node && PLIST_ARRAY == plist_get_node_type(node)) |
| 229 | { | 244 | { |
| 230 | ret = (plist_t)g_node_nth_child(node, n); | 245 | ret = (plist_t)node_nth_child(node, n); |
| 231 | } | 246 | } |
| 232 | return ret; | 247 | return ret; |
| 233 | } | 248 | } |
| @@ -237,7 +252,7 @@ uint32_t plist_array_get_item_index(plist_t node) | |||
| 237 | plist_t father = plist_get_parent(node); | 252 | plist_t father = plist_get_parent(node); |
| 238 | if (PLIST_ARRAY == plist_get_node_type(father)) | 253 | if (PLIST_ARRAY == plist_get_node_type(father)) |
| 239 | { | 254 | { |
| 240 | return g_node_child_position(father, node); | 255 | return node_child_position(father, node); |
| 241 | } | 256 | } |
| 242 | return 0; | 257 | return 0; |
| 243 | } | 258 | } |
| @@ -249,7 +264,7 @@ void plist_array_set_item(plist_t node, plist_t item, uint32_t n) | |||
| 249 | plist_t old_item = plist_array_get_item(node, n); | 264 | plist_t old_item = plist_array_get_item(node, n); |
| 250 | if (old_item) | 265 | if (old_item) |
| 251 | { | 266 | { |
| 252 | plist_free_node(old_item, NULL); | 267 | plist_free_node(old_item); |
| 253 | old_item = NULL; | 268 | old_item = NULL; |
| 254 | plist_copy_node(item, &old_item); | 269 | plist_copy_node(item, &old_item); |
| 255 | } | 270 | } |
| @@ -261,7 +276,7 @@ void plist_array_append_item(plist_t node, plist_t item) | |||
| 261 | { | 276 | { |
| 262 | if (node && PLIST_ARRAY == plist_get_node_type(node)) | 277 | if (node && PLIST_ARRAY == plist_get_node_type(node)) |
| 263 | { | 278 | { |
| 264 | g_node_append(node, item); | 279 | node_attach(node, item); |
| 265 | } | 280 | } |
| 266 | return; | 281 | return; |
| 267 | } | 282 | } |
| @@ -270,7 +285,7 @@ void plist_array_insert_item(plist_t node, plist_t item, uint32_t n) | |||
| 270 | { | 285 | { |
| 271 | if (node && PLIST_ARRAY == plist_get_node_type(node)) | 286 | if (node && PLIST_ARRAY == plist_get_node_type(node)) |
| 272 | { | 287 | { |
| 273 | g_node_insert(node, n, item); | 288 | node_insert(node, n, item); |
| 274 | } | 289 | } |
| 275 | return; | 290 | return; |
| 276 | } | 291 | } |
| @@ -293,7 +308,7 @@ uint32_t plist_dict_get_size(plist_t node) | |||
| 293 | uint32_t ret = 0; | 308 | uint32_t ret = 0; |
| 294 | if (node && PLIST_DICT == plist_get_node_type(node)) | 309 | if (node && PLIST_DICT == plist_get_node_type(node)) |
| 295 | { | 310 | { |
| 296 | ret = g_node_n_children(node) / 2; | 311 | ret = node_n_children(node) / 2; |
| 297 | } | 312 | } |
| 298 | return ret; | 313 | return ret; |
| 299 | } | 314 | } |
| @@ -321,17 +336,17 @@ void plist_dict_next_item(plist_t node, plist_dict_iter iter, char **key, plist_ | |||
| 321 | *val = NULL; | 336 | *val = NULL; |
| 322 | } | 337 | } |
| 323 | 338 | ||
| 324 | if (node && PLIST_DICT == plist_get_node_type(node) && *iter_int < g_node_n_children(node)) | 339 | if (node && PLIST_DICT == plist_get_node_type(node) && *iter_int < node_n_children(node)) |
| 325 | { | 340 | { |
| 326 | 341 | ||
| 327 | if (key) | 342 | if (key) |
| 328 | { | 343 | { |
| 329 | plist_get_key_val((plist_t)g_node_nth_child(node, *iter_int), key); | 344 | plist_get_key_val((plist_t)node_nth_child(node, *iter_int), key); |
| 330 | } | 345 | } |
| 331 | 346 | ||
| 332 | if (val) | 347 | if (val) |
| 333 | { | 348 | { |
| 334 | *val = (plist_t) g_node_nth_child(node, *iter_int + 1); | 349 | *val = (plist_t) node_nth_child(node, *iter_int + 1); |
| 335 | } | 350 | } |
| 336 | 351 | ||
| 337 | *iter_int += 2; | 352 | *iter_int += 2; |
| @@ -344,7 +359,7 @@ void plist_dict_get_item_key(plist_t node, char **key) | |||
| 344 | plist_t father = plist_get_parent(node); | 359 | plist_t father = plist_get_parent(node); |
| 345 | if (PLIST_DICT == plist_get_node_type(father)) | 360 | if (PLIST_DICT == plist_get_node_type(father)) |
| 346 | { | 361 | { |
| 347 | plist_get_key_val( (plist_t) g_node_prev_sibling(node), key); | 362 | plist_get_key_val( (plist_t) node_prev_sibling(node), key); |
| 348 | } | 363 | } |
| 349 | } | 364 | } |
| 350 | 365 | ||
| @@ -356,9 +371,9 @@ plist_t plist_dict_get_item(plist_t node, const char* key) | |||
| 356 | { | 371 | { |
| 357 | 372 | ||
| 358 | plist_t current = NULL; | 373 | plist_t current = NULL; |
| 359 | for (current = (plist_t)g_node_first_child(node); | 374 | for (current = (plist_t)node_first_child(node); |
| 360 | current; | 375 | current; |
| 361 | current = (plist_t)g_node_next_sibling(g_node_next_sibling(current))) | 376 | current = (plist_t)node_next_sibling(node_next_sibling(current))) |
| 362 | { | 377 | { |
| 363 | 378 | ||
| 364 | plist_data_t data = plist_get_data(current); | 379 | plist_data_t data = plist_get_data(current); |
| @@ -366,7 +381,7 @@ plist_t plist_dict_get_item(plist_t node, const char* key) | |||
| 366 | 381 | ||
| 367 | if (data && !strcmp(key, data->strval)) | 382 | if (data && !strcmp(key, data->strval)) |
| 368 | { | 383 | { |
| 369 | ret = (plist_t)g_node_next_sibling(current); | 384 | ret = (plist_t)node_next_sibling(current); |
| 370 | break; | 385 | break; |
| 371 | } | 386 | } |
| 372 | } | 387 | } |
| @@ -381,7 +396,7 @@ void plist_dict_set_item(plist_t node, const char* key, plist_t item) | |||
| 381 | plist_t old_item = plist_dict_get_item(node, key); | 396 | plist_t old_item = plist_dict_get_item(node, key); |
| 382 | if (old_item) | 397 | if (old_item) |
| 383 | { | 398 | { |
| 384 | plist_free_node(old_item, NULL); | 399 | plist_free_node(old_item); |
| 385 | old_item = NULL; | 400 | old_item = NULL; |
| 386 | plist_copy_node(item, &old_item); | 401 | plist_copy_node(item, &old_item); |
| 387 | } | 402 | } |
| @@ -393,8 +408,8 @@ void plist_dict_insert_item(plist_t node, const char* key, plist_t item) | |||
| 393 | { | 408 | { |
| 394 | if (node && PLIST_DICT == plist_get_node_type(node)) | 409 | if (node && PLIST_DICT == plist_get_node_type(node)) |
| 395 | { | 410 | { |
| 396 | g_node_append(node, plist_new_key(key)); | 411 | node_attach(node, plist_new_key(key)); |
| 397 | g_node_append(node, item); | 412 | node_attach(node, item); |
| 398 | } | 413 | } |
| 399 | return; | 414 | return; |
| 400 | } | 415 | } |
| @@ -406,7 +421,7 @@ void plist_dict_remove_item(plist_t node, const char* key) | |||
| 406 | plist_t old_item = plist_dict_get_item(node, key); | 421 | plist_t old_item = plist_dict_get_item(node, key); |
| 407 | if (old_item) | 422 | if (old_item) |
| 408 | { | 423 | { |
| 409 | plist_t key_node = g_node_prev_sibling(old_item); | 424 | plist_t key_node = node_prev_sibling(old_item); |
| 410 | plist_free(key_node); | 425 | plist_free(key_node); |
| 411 | plist_free(old_item); | 426 | plist_free(old_item); |
| 412 | } | 427 | } |
| @@ -482,8 +497,8 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu | |||
| 482 | break; | 497 | break; |
| 483 | case PLIST_DATE: | 498 | case PLIST_DATE: |
| 484 | //exception : here we use memory on the stack since it is just a temporary buffer | 499 | //exception : here we use memory on the stack since it is just a temporary buffer |
| 485 | ((GTimeVal *) value)->tv_sec = data->timeval.tv_sec; | 500 | ((struct timeval*) value)->tv_sec = data->timeval.tv_sec; |
| 486 | ((GTimeVal *) value)->tv_usec = data->timeval.tv_usec; | 501 | ((struct timeval*) value)->tv_usec = data->timeval.tv_usec; |
| 487 | break; | 502 | break; |
| 488 | case PLIST_ARRAY: | 503 | case PLIST_ARRAY: |
| 489 | case PLIST_DICT: | 504 | case PLIST_DICT: |
| @@ -494,7 +509,7 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu | |||
| 494 | 509 | ||
| 495 | plist_t plist_get_parent(plist_t node) | 510 | plist_t plist_get_parent(plist_t node) |
| 496 | { | 511 | { |
| 497 | return node ? (plist_t) ((GNode *) node)->parent : NULL; | 512 | return node ? (plist_t) ((node_t*) node)->parent : NULL; |
| 498 | } | 513 | } |
| 499 | 514 | ||
| 500 | plist_type plist_get_node_type(plist_t node) | 515 | 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) | |||
| 564 | { | 579 | { |
| 565 | plist_type type = plist_get_node_type(node); | 580 | plist_type type = plist_get_node_type(node); |
| 566 | uint64_t length = 0; | 581 | uint64_t length = 0; |
| 567 | GTimeVal val = { 0, 0 }; | 582 | struct timeval val = { 0, 0 }; |
| 568 | if (PLIST_DATE == type) | 583 | if (PLIST_DATE == type) |
| 569 | plist_get_type_and_value(node, &type, (void *) &val, &length); | 584 | plist_get_type_and_value(node, &type, (void *) &val, &length); |
| 570 | assert(length == sizeof(GTimeVal)); | 585 | assert(length == sizeof(struct timeval)); |
| 571 | *sec = val.tv_sec; | 586 | *sec = val.tv_sec; |
| 572 | *usec = val.tv_usec; | 587 | *usec = val.tv_usec; |
| 573 | } | 588 | } |
| 574 | 589 | ||
| 575 | gboolean plist_data_compare(gconstpointer a, gconstpointer b) | 590 | int plist_data_compare(const void *a, const void *b) |
| 576 | { | 591 | { |
| 577 | plist_data_t val_a = NULL; | 592 | plist_data_t val_a = NULL; |
| 578 | plist_data_t val_b = NULL; | 593 | plist_data_t val_b = NULL; |
| @@ -580,7 +595,7 @@ gboolean plist_data_compare(gconstpointer a, gconstpointer b) | |||
| 580 | if (!a || !b) | 595 | if (!a || !b) |
| 581 | return FALSE; | 596 | return FALSE; |
| 582 | 597 | ||
| 583 | if (!((GNode *) a)->data || !((GNode *) b)->data) | 598 | if (!((node_t*) a)->data || !((node_t*) b)->data) |
| 584 | return FALSE; | 599 | return FALSE; |
| 585 | 600 | ||
| 586 | val_a = plist_get_data((plist_t) a); | 601 | val_a = plist_get_data((plist_t) a); |
| @@ -620,7 +635,7 @@ gboolean plist_data_compare(gconstpointer a, gconstpointer b) | |||
| 620 | return FALSE; | 635 | return FALSE; |
| 621 | break; | 636 | break; |
| 622 | case PLIST_DATE: | 637 | case PLIST_DATE: |
| 623 | if (!memcmp(&(val_a->timeval), &(val_b->timeval), sizeof(GTimeVal))) | 638 | if (!memcmp(&(val_a->timeval), &(val_b->timeval), sizeof(struct timeval))) |
| 624 | return TRUE; | 639 | return TRUE; |
| 625 | else | 640 | else |
| 626 | return FALSE; | 641 | return FALSE; |
| @@ -681,8 +696,8 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val | |||
| 681 | memcpy(data->buff, value, length); | 696 | memcpy(data->buff, value, length); |
| 682 | break; | 697 | break; |
| 683 | case PLIST_DATE: | 698 | case PLIST_DATE: |
| 684 | data->timeval.tv_sec = ((GTimeVal *) value)->tv_sec; | 699 | data->timeval.tv_sec = ((struct timeval*) value)->tv_sec; |
| 685 | data->timeval.tv_usec = ((GTimeVal *) value)->tv_usec; | 700 | data->timeval.tv_usec = ((struct timeval*) value)->tv_usec; |
| 686 | break; | 701 | break; |
| 687 | case PLIST_ARRAY: | 702 | case PLIST_ARRAY: |
| 688 | case PLIST_DICT: | 703 | case PLIST_DICT: |
| @@ -693,7 +708,7 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val | |||
| 693 | 708 | ||
| 694 | void plist_set_type(plist_t node, plist_type type) | 709 | void plist_set_type(plist_t node, plist_type type) |
| 695 | { | 710 | { |
| 696 | if ( g_node_n_children(node) == 0 ) | 711 | if ( node_n_children(node) == 0 ) |
| 697 | { | 712 | { |
| 698 | plist_data_t data = plist_get_data(node); | 713 | plist_data_t data = plist_get_data(node); |
| 699 | plist_free_data( data ); | 714 | plist_free_data( data ); |
| @@ -711,7 +726,7 @@ void plist_set_type(plist_t node, plist_type type) | |||
| 711 | data->length = sizeof(double); | 726 | data->length = sizeof(double); |
| 712 | break; | 727 | break; |
| 713 | case PLIST_DATE: | 728 | case PLIST_DATE: |
| 714 | data->length = sizeof(GTimeVal); | 729 | data->length = sizeof(struct timeval); |
| 715 | break; | 730 | break; |
| 716 | default: | 731 | default: |
| 717 | data->length = 0; | 732 | data->length = 0; |
| @@ -752,7 +767,7 @@ void plist_set_data_val(plist_t node, const char *val, uint64_t length) | |||
| 752 | 767 | ||
| 753 | void plist_set_date_val(plist_t node, int32_t sec, int32_t usec) | 768 | void plist_set_date_val(plist_t node, int32_t sec, int32_t usec) |
| 754 | { | 769 | { |
| 755 | GTimeVal val = { sec, usec }; | 770 | struct timeval val = { sec, usec }; |
| 756 | plist_set_element_val(node, PLIST_DATE, &val, sizeof(GTimeVal)); | 771 | plist_set_element_val(node, PLIST_DATE, &val, sizeof(struct timeval)); |
| 757 | } | 772 | } |
| 758 | 773 | ||
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 @@ | |||
| 23 | #define PLIST_H | 23 | #define PLIST_H |
| 24 | 24 | ||
| 25 | #include "plist/plist.h" | 25 | #include "plist/plist.h" |
| 26 | 26 | #include "common.h" | |
| 27 | 27 | ||
| 28 | #include <sys/types.h> | 28 | #include <sys/types.h> |
| 29 | #include <sys/stat.h> | 29 | #include <sys/stat.h> |
| 30 | #include <glib.h> | ||
| 31 | 30 | ||
| 32 | #ifdef _MSC_VER | 31 | #ifdef _MSC_VER |
| 33 | #pragma warning(disable:4996) | 32 | #pragma warning(disable:4996) |
| @@ -44,7 +43,7 @@ struct plist_data_s | |||
| 44 | double realval; | 43 | double realval; |
| 45 | char *strval; | 44 | char *strval; |
| 46 | uint8_t *buff; | 45 | uint8_t *buff; |
| 47 | GTimeVal timeval; | 46 | struct timeval timeval; |
| 48 | }; | 47 | }; |
| 49 | uint64_t length; | 48 | uint64_t length; |
| 50 | plist_type type; | 49 | plist_type type; |
| @@ -52,10 +51,10 @@ struct plist_data_s | |||
| 52 | 51 | ||
| 53 | typedef struct plist_data_s *plist_data_t; | 52 | typedef struct plist_data_s *plist_data_t; |
| 54 | 53 | ||
| 55 | G_GNUC_INTERNAL plist_t plist_new_node(plist_data_t data); | 54 | _PLIST_INTERNAL plist_t plist_new_node(plist_data_t data); |
| 56 | G_GNUC_INTERNAL plist_data_t plist_get_data(const plist_t node); | 55 | _PLIST_INTERNAL plist_data_t plist_get_data(const plist_t node); |
| 57 | G_GNUC_INTERNAL plist_data_t plist_new_plist_data(void); | 56 | _PLIST_INTERNAL plist_data_t plist_new_plist_data(void); |
| 58 | G_GNUC_INTERNAL gboolean plist_data_compare(gconstpointer a, gconstpointer b); | 57 | _PLIST_INTERNAL int plist_data_compare(const void *a, const void *b); |
| 59 | 58 | ||
| 60 | 59 | ||
| 61 | #endif | 60 | #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 @@ | |||
| 1 | /* | ||
| 2 | * ptrarray.c | ||
| 3 | * simple pointer array implementation | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | #include "ptrarray.h" | ||
| 22 | |||
| 23 | ptrarray_t *ptr_array_new(int capacity) | ||
| 24 | { | ||
| 25 | ptrarray_t *pa = (ptrarray_t*)malloc(sizeof(ptrarray_t)); | ||
| 26 | pa->pdata = (void**)malloc(sizeof(void*) * capacity); | ||
| 27 | pa->capacity = capacity; | ||
| 28 | pa->capacity_step = (capacity > 64) ? 64 : capacity; | ||
| 29 | pa->len = 0; | ||
| 30 | return pa; | ||
| 31 | } | ||
| 32 | |||
| 33 | void ptr_array_free(ptrarray_t *pa) | ||
| 34 | { | ||
| 35 | if (!pa) return; | ||
| 36 | if (pa->pdata) { | ||
| 37 | free(pa->pdata); | ||
| 38 | } | ||
| 39 | free(pa); | ||
| 40 | } | ||
| 41 | |||
| 42 | void ptr_array_add(ptrarray_t *pa, void *data) | ||
| 43 | { | ||
| 44 | if (!pa || !pa->pdata || !data) return; | ||
| 45 | size_t remaining = pa->capacity-pa->len; | ||
| 46 | if (remaining == 0) { | ||
| 47 | pa->pdata = realloc(pa->pdata, sizeof(void*) * (pa->capacity + pa->capacity_step)); | ||
| 48 | pa->capacity += pa->capacity_step; | ||
| 49 | } | ||
| 50 | pa->pdata[pa->len] = data; | ||
| 51 | pa->len++; | ||
| 52 | } | ||
| 53 | |||
| 54 | void* ptr_array_index(ptrarray_t *pa, size_t index) | ||
| 55 | { | ||
| 56 | if (!pa) return NULL; | ||
| 57 | if (index >= pa->len) { | ||
| 58 | return NULL; | ||
| 59 | } | ||
| 60 | return pa->pdata[index]; | ||
| 61 | } | ||
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 @@ | |||
| 1 | /* | ||
| 2 | * ptrarray.h | ||
| 3 | * header file for simple pointer array implementation | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | #ifndef PTRARRAY_H | ||
| 22 | #define PTRARRAY_H | ||
| 23 | #include <stdlib.h> | ||
| 24 | #include "common.h" | ||
| 25 | |||
| 26 | typedef struct ptrarray_t { | ||
| 27 | void **pdata; | ||
| 28 | size_t len; | ||
| 29 | size_t capacity; | ||
| 30 | size_t capacity_step; | ||
| 31 | } ptrarray_t; | ||
| 32 | |||
| 33 | _PLIST_INTERNAL ptrarray_t *ptr_array_new(int capacity); | ||
| 34 | _PLIST_INTERNAL void ptr_array_free(ptrarray_t *pa); | ||
| 35 | _PLIST_INTERNAL void ptr_array_add(ptrarray_t *pa, void *data); | ||
| 36 | _PLIST_INTERNAL void* ptr_array_index(ptrarray_t *pa, size_t index); | ||
| 37 | #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 @@ | |||
| 24 | #include <assert.h> | 24 | #include <assert.h> |
| 25 | #include <stdlib.h> | 25 | #include <stdlib.h> |
| 26 | #include <stdio.h> | 26 | #include <stdio.h> |
| 27 | #include <time.h> | ||
| 27 | 28 | ||
| 28 | #include <inttypes.h> | 29 | #include <inttypes.h> |
| 29 | #include <locale.h> | 30 | #include <locale.h> |
| @@ -31,7 +32,12 @@ | |||
| 31 | #include <libxml/parser.h> | 32 | #include <libxml/parser.h> |
| 32 | #include <libxml/tree.h> | 33 | #include <libxml/tree.h> |
| 33 | 34 | ||
| 35 | #include <node.h> | ||
| 36 | #include <node_list.h> | ||
| 37 | #include <node_iterator.h> | ||
| 38 | |||
| 34 | #include "plist.h" | 39 | #include "plist.h" |
| 40 | #include "base64.h" | ||
| 35 | 41 | ||
| 36 | #define XPLIST_TEXT BAD_CAST("text") | 42 | #define XPLIST_TEXT BAD_CAST("text") |
| 37 | #define XPLIST_KEY BAD_CAST("key") | 43 | #define XPLIST_KEY BAD_CAST("key") |
| @@ -61,18 +67,22 @@ static const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ | |||
| 61 | * | 67 | * |
| 62 | * @return The formatted string. | 68 | * @return The formatted string. |
| 63 | */ | 69 | */ |
| 64 | static gchar *format_string(const char *buf, int cols, int depth) | 70 | static char *format_string(const char *buf, size_t len, int cols, int depth) |
| 65 | { | 71 | { |
| 72 | if (!buf || !(len > 0)) return NULL; | ||
| 66 | int colw = depth + cols + 1; | 73 | int colw = depth + cols + 1; |
| 67 | int len = strlen(buf); | ||
| 68 | int nlines = len / cols + 1; | 74 | int nlines = len / cols + 1; |
| 69 | gchar *new_buf = (gchar *) g_malloc0(nlines * colw + depth + 1); | 75 | char *new_buf = NULL; |
| 70 | int i = 0; | 76 | int i = 0; |
| 71 | int j = 0; | 77 | int j = 0; |
| 72 | 78 | ||
| 73 | assert(cols >= 0); | 79 | assert(cols >= 0); |
| 74 | assert(depth >= 0); | 80 | assert(depth >= 0); |
| 75 | 81 | ||
| 82 | new_buf = (char*) malloc(nlines * colw + depth + 1); | ||
| 83 | assert(new_buf != 0); | ||
| 84 | memset(new_buf, 0, nlines * colw + depth + 1); | ||
| 85 | |||
| 76 | // Inserts new lines and tabs at appropriate locations | 86 | // Inserts new lines and tabs at appropriate locations |
| 77 | for (i = 0; i < nlines; i++) | 87 | for (i = 0; i < nlines; i++) |
| 78 | { | 88 | { |
| @@ -116,7 +126,7 @@ static xmlDocPtr new_xml_plist(void) | |||
| 116 | return plist_xml; | 126 | return plist_xml; |
| 117 | } | 127 | } |
| 118 | 128 | ||
| 119 | static void node_to_xml(GNode * node, gpointer xml_struct) | 129 | static void node_to_xml(node_t* node, void *xml_struct) |
| 120 | { | 130 | { |
| 121 | struct xml_node *xstruct = NULL; | 131 | struct xml_node *xstruct = NULL; |
| 122 | plist_data_t node_data = NULL; | 132 | plist_data_t node_data = NULL; |
| @@ -125,10 +135,10 @@ static void node_to_xml(GNode * node, gpointer xml_struct) | |||
| 125 | char isStruct = FALSE; | 135 | char isStruct = FALSE; |
| 126 | 136 | ||
| 127 | const xmlChar *tag = NULL; | 137 | const xmlChar *tag = NULL; |
| 128 | gchar *val = NULL; | 138 | char *val = NULL; |
| 129 | 139 | ||
| 130 | //for base64 | 140 | //for base64 |
| 131 | gchar *valtmp = NULL; | 141 | char *valtmp = NULL; |
| 132 | 142 | ||
| 133 | uint32_t i = 0; | 143 | uint32_t i = 0; |
| 134 | 144 | ||
| @@ -151,31 +161,32 @@ static void node_to_xml(GNode * node, gpointer xml_struct) | |||
| 151 | 161 | ||
| 152 | case PLIST_UINT: | 162 | case PLIST_UINT: |
| 153 | tag = XPLIST_INT; | 163 | tag = XPLIST_INT; |
| 154 | val = g_strdup_printf("%"PRIu64, node_data->intval); | 164 | (void)asprintf(&val, "%"PRIu64, node_data->intval); |
| 155 | break; | 165 | break; |
| 156 | 166 | ||
| 157 | case PLIST_REAL: | 167 | case PLIST_REAL: |
| 158 | tag = XPLIST_REAL; | 168 | tag = XPLIST_REAL; |
| 159 | val = g_strdup_printf("%f", node_data->realval); | 169 | (void)asprintf(&val, "%f", node_data->realval); |
| 160 | break; | 170 | break; |
| 161 | 171 | ||
| 162 | case PLIST_STRING: | 172 | case PLIST_STRING: |
| 163 | tag = XPLIST_STRING; | 173 | tag = XPLIST_STRING; |
| 164 | val = g_strdup(node_data->strval); | 174 | val = strdup(node_data->strval); |
| 165 | break; | 175 | break; |
| 166 | 176 | ||
| 167 | case PLIST_KEY: | 177 | case PLIST_KEY: |
| 168 | tag = XPLIST_KEY; | 178 | tag = XPLIST_KEY; |
| 169 | val = g_strdup((gchar *) node_data->strval); | 179 | val = strdup((char*) node_data->strval); |
| 170 | break; | 180 | break; |
| 171 | 181 | ||
| 172 | case PLIST_DATA: | 182 | case PLIST_DATA: |
| 173 | tag = XPLIST_DATA; | 183 | tag = XPLIST_DATA; |
| 174 | if (node_data->length) | 184 | if (node_data->length) |
| 175 | { | 185 | { |
| 176 | valtmp = g_base64_encode(node_data->buff, node_data->length); | 186 | size_t len = node_data->length; |
| 177 | val = format_string(valtmp, 68, xstruct->depth); | 187 | valtmp = base64encode(node_data->buff, &len); |
| 178 | g_free(valtmp); | 188 | val = format_string(valtmp, len, 68, xstruct->depth); |
| 189 | free(valtmp); | ||
| 179 | } | 190 | } |
| 180 | break; | 191 | break; |
| 181 | case PLIST_ARRAY: | 192 | case PLIST_ARRAY: |
| @@ -188,7 +199,18 @@ static void node_to_xml(GNode * node, gpointer xml_struct) | |||
| 188 | break; | 199 | break; |
| 189 | case PLIST_DATE: | 200 | case PLIST_DATE: |
| 190 | tag = XPLIST_DATE; | 201 | tag = XPLIST_DATE; |
| 191 | val = g_time_val_to_iso8601(&node_data->timeval); | 202 | { |
| 203 | time_t time = (time_t)node_data->timeval.tv_sec; | ||
| 204 | struct tm *btime = localtime(&time); | ||
| 205 | if (btime) { | ||
| 206 | val = (char*)malloc(24); | ||
| 207 | memset(val, 0, 24); | ||
| 208 | if (strftime(val, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) { | ||
| 209 | free (val); | ||
| 210 | val = NULL; | ||
| 211 | } | ||
| 212 | } | ||
| 213 | } | ||
| 192 | break; | 214 | break; |
| 193 | default: | 215 | default: |
| 194 | break; | 216 | break; |
| @@ -205,7 +227,9 @@ static void node_to_xml(GNode * node, gpointer xml_struct) | |||
| 205 | } else | 227 | } else |
| 206 | child_node = xmlNewChild(xstruct->xml, NULL, tag, BAD_CAST(val)); | 228 | child_node = xmlNewChild(xstruct->xml, NULL, tag, BAD_CAST(val)); |
| 207 | xmlNodeAddContent(xstruct->xml, BAD_CAST("\n")); | 229 | xmlNodeAddContent(xstruct->xml, BAD_CAST("\n")); |
| 208 | g_free(val); | 230 | if (val) { |
| 231 | free(val); | ||
| 232 | } | ||
| 209 | 233 | ||
| 210 | //add return for structured types | 234 | //add return for structured types |
| 211 | if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT) | 235 | 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) | |||
| 214 | if (isStruct) | 238 | if (isStruct) |
| 215 | { | 239 | { |
| 216 | struct xml_node child = { child_node, xstruct->depth + 1 }; | 240 | struct xml_node child = { child_node, xstruct->depth + 1 }; |
| 217 | g_node_children_foreach(node, G_TRAVERSE_ALL, node_to_xml, &child); | 241 | node_iterator_t *ni = node_iterator_create(node->children); |
| 242 | node_t *ch; | ||
| 243 | while ((ch = node_iterator_next(ni))) { | ||
| 244 | node_to_xml(ch, &child); | ||
| 245 | } | ||
| 246 | node_iterator_destroy(ni); | ||
| 218 | } | 247 | } |
| 219 | //fix indent for structured types | 248 | //fix indent for structured types |
| 220 | if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT) | 249 | 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) | |||
| 236 | plist_t subnode = NULL; | 265 | plist_t subnode = NULL; |
| 237 | 266 | ||
| 238 | //for string | 267 | //for string |
| 239 | glong len = 0; | 268 | long len = 0; |
| 240 | int type = 0; | 269 | int type = 0; |
| 241 | 270 | ||
| 242 | if (!xml_node) | 271 | if (!xml_node) |
| @@ -253,7 +282,7 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) | |||
| 253 | data = plist_new_plist_data(); | 282 | data = plist_new_plist_data(); |
| 254 | subnode = plist_new_node(data); | 283 | subnode = plist_new_node(data); |
| 255 | if (*plist_node) | 284 | if (*plist_node) |
| 256 | g_node_append(*plist_node, subnode); | 285 | node_attach(*plist_node, subnode); |
| 257 | else | 286 | else |
| 258 | *plist_node = subnode; | 287 | *plist_node = subnode; |
| 259 | 288 | ||
| @@ -276,7 +305,7 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) | |||
| 276 | if (!xmlStrcmp(node->name, XPLIST_INT)) | 305 | if (!xmlStrcmp(node->name, XPLIST_INT)) |
| 277 | { | 306 | { |
| 278 | xmlChar *strval = xmlNodeGetContent(node); | 307 | xmlChar *strval = xmlNodeGetContent(node); |
| 279 | data->intval = g_ascii_strtoull((char *) strval, NULL, 0); | 308 | data->intval = strtoull((char*)strval, NULL, 0); |
| 280 | data->type = PLIST_UINT; | 309 | data->type = PLIST_UINT; |
| 281 | data->length = 8; | 310 | data->length = 8; |
| 282 | xmlFree(strval); | 311 | xmlFree(strval); |
| @@ -296,9 +325,17 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) | |||
| 296 | if (!xmlStrcmp(node->name, XPLIST_DATE)) | 325 | if (!xmlStrcmp(node->name, XPLIST_DATE)) |
| 297 | { | 326 | { |
| 298 | xmlChar *strval = xmlNodeGetContent(node); | 327 | xmlChar *strval = xmlNodeGetContent(node); |
| 299 | g_time_val_from_iso8601((char *) strval, &data->timeval); | 328 | time_t time = 0; |
| 329 | if (strlen(strval) >= 11) { | ||
| 330 | struct tm btime; | ||
| 331 | memset(&btime, 0, sizeof(struct tm)); | ||
| 332 | strptime((char*)strval, "%Y-%m-%dT%H:%M:%SZ", &btime); | ||
| 333 | time = mktime(&btime); | ||
| 334 | } | ||
| 335 | data->timeval.tv_sec = (long)time; | ||
| 336 | data->timeval.tv_usec = 0; | ||
| 300 | data->type = PLIST_DATE; | 337 | data->type = PLIST_DATE; |
| 301 | data->length = sizeof(GTimeVal); | 338 | data->length = sizeof(struct timeval); |
| 302 | xmlFree(strval); | 339 | xmlFree(strval); |
| 303 | continue; | 340 | continue; |
| 304 | } | 341 | } |
| @@ -332,11 +369,11 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) | |||
| 332 | if (!xmlStrcmp(node->name, XPLIST_DATA)) | 369 | if (!xmlStrcmp(node->name, XPLIST_DATA)) |
| 333 | { | 370 | { |
| 334 | xmlChar *strval = xmlNodeGetContent(node); | 371 | xmlChar *strval = xmlNodeGetContent(node); |
| 335 | gsize size = 0; | 372 | size_t size = 0; |
| 336 | guchar *dec = g_base64_decode((char *) strval, &size); | 373 | unsigned char *dec = base64decode((char*)strval, &size); |
| 337 | data->buff = (uint8_t *) malloc(size * sizeof(uint8_t)); | 374 | data->buff = (uint8_t *) malloc(size * sizeof(uint8_t)); |
| 338 | memcpy(data->buff, dec, size * sizeof(uint8_t)); | 375 | memcpy(data->buff, dec, size * sizeof(uint8_t)); |
| 339 | g_free(dec); | 376 | free(dec); |
| 340 | data->length = size; | 377 | data->length = size; |
| 341 | data->type = PLIST_DATA; | 378 | data->type = PLIST_DATA; |
| 342 | xmlFree(strval); | 379 | 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 @@ | |||
| 1 | 1 | ||
| 2 | #build the test executable | 2 | #build the test executable |
| 3 | INCLUDE_DIRECTORIES( ${GLIB2_INCLUDE_DIR} ) | 3 | INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/libcnary/include ) |
| 4 | 4 | ||
| 5 | SET(plist_test_SRC | 5 | SET(plist_test_SRC |
| 6 | plist_test.c) | 6 | 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 @@ | |||
| 27 | #include <string.h> | 27 | #include <string.h> |
| 28 | #include <sys/stat.h> | 28 | #include <sys/stat.h> |
| 29 | 29 | ||
| 30 | #include <glib.h> | 30 | #include <node.h> |
| 31 | 31 | ||
| 32 | #ifdef _MSC_VER | 32 | #ifdef _MSC_VER |
| 33 | #pragma warning(disable:4996) | 33 | #pragma warning(disable:4996) |
| @@ -35,12 +35,12 @@ | |||
| 35 | 35 | ||
| 36 | static plist_t plist_get_first_child(plist_t node) | 36 | static plist_t plist_get_first_child(plist_t node) |
| 37 | { | 37 | { |
| 38 | return (plist_t) g_node_first_child((GNode *) node); | 38 | return (plist_t) node_first_child((node_t*) node); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | static plist_t plist_get_next_sibling(plist_t node) | 41 | static plist_t plist_get_next_sibling(plist_t node) |
| 42 | { | 42 | { |
| 43 | return (plist_t) g_node_next_sibling((GNode *) node); | 43 | return (plist_t) node_next_sibling((node_t*) node); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | static char compare_plist(plist_t node_l, plist_t node_r) | 46 | static char compare_plist(plist_t node_l, plist_t node_r) |
