Commit 024e755d authored by Nikias Bassen's avatar Nikias Bassen

Make libplist glib free

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