diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Array.cpp | 49 | ||||
-rw-r--r-- | src/Data.cpp | 11 | ||||
-rw-r--r-- | src/Date.cpp | 22 | ||||
-rw-r--r-- | src/Dictionary.cpp | 8 | ||||
-rw-r--r-- | src/Integer.cpp | 3 | ||||
-rw-r--r-- | src/Key.cpp | 2 | ||||
-rw-r--r-- | src/Node.cpp | 2 | ||||
-rw-r--r-- | src/String.cpp | 23 | ||||
-rw-r--r-- | src/Structure.cpp | 27 | ||||
-rw-r--r-- | src/bplist.c | 78 | ||||
-rw-r--r-- | src/jplist.c | 10 | ||||
-rw-r--r-- | src/oplist.c | 4 | ||||
-rw-r--r-- | src/plist.c | 412 |
13 files changed, 523 insertions, 128 deletions
diff --git a/src/Array.cpp b/src/Array.cpp index bc448d3..49b8924 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -40,7 +40,9 @@ static void array_fill(Array *_this, std::vector<Node*> &array, plist_t node) do { subnode = NULL; plist_array_next_item(node, iter, &subnode); - array.push_back( Node::FromPlist(subnode, _this) ); + if (subnode) { + array.push_back( Node::FromPlist(subnode, _this) ); + } } while (subnode); free(iter); } @@ -51,7 +53,7 @@ Array::Array(plist_t node, Node* parent) : Structure(parent) array_fill(this, _array, _node); } -Array::Array(const PList::Array& a) +Array::Array(const PList::Array& a) : Structure(a.GetParent()) { _array.clear(); _node = plist_copy(a.GetPlist()); @@ -88,6 +90,26 @@ Node* Array::operator[](unsigned int array_index) return _array.at(array_index); } +Node* Array::Back() +{ + return _array.back(); +} + +Node* Array::back() +{ + return _array.back(); +} + +Node* Array::Front() +{ + return _array.front(); +} + +Node* Array::front() +{ + return _array.front(); +} + Array::iterator Array::Begin() { return _array.begin(); @@ -132,7 +154,7 @@ size_t Array::size() const { return _array.size(); } -void Array::Append(Node* node) +void Array::Append(const Node* node) { if (node) { @@ -143,7 +165,12 @@ void Array::Append(Node* node) } } -void Array::Insert(Node* node, unsigned int pos) +void Array::Append(const Node& node) +{ + Append(&node); +} + +void Array::Insert(const Node* node, unsigned int pos) { if (node) { @@ -156,6 +183,11 @@ void Array::Insert(Node* node, unsigned int pos) } } +void Array::Insert(const Node &node, unsigned int pos) +{ + Insert(&node, pos); +} + void Array::Remove(Node* node) { if (node) @@ -168,7 +200,7 @@ void Array::Remove(Node* node) std::vector<Node*>::iterator it = _array.begin(); it += pos; _array.erase(it); - delete node; + free(node); } } @@ -181,10 +213,15 @@ void Array::Remove(unsigned int pos) _array.erase(it); } -unsigned int Array::GetNodeIndex(Node* node) const +unsigned int Array::GetNodeIndex(const Node* node) const { std::vector<Node*>::const_iterator it = std::find(_array.begin(), _array.end(), node); return std::distance (_array.begin(), it); } +unsigned int Array::GetNodeIndex(const Node& node) const +{ + return GetNodeIndex(&node); +} + } // namespace PList diff --git a/src/Data.cpp b/src/Data.cpp index a96fc50..56b2d6b 100644 --- a/src/Data.cpp +++ b/src/Data.cpp @@ -50,6 +50,11 @@ Data::Data(const std::vector<char>& buff) : Node(PLIST_DATA) plist_set_data_val(_node, &buff[0], buff.size()); } +Data::Data(const char* buff, uint64_t size) : Node(PLIST_DATA) +{ + plist_set_data_val(_node, buff, size); +} + Data::~Data() { } @@ -66,14 +71,10 @@ void Data::SetValue(const std::vector<char>& buff) std::vector<char> Data::GetValue() const { - char* buff = NULL; uint64_t length = 0; - plist_get_data_val(_node, &buff, &length); + const char* buff = plist_get_data_ptr(_node, &length); std::vector<char> ret(buff, buff + length); - delete buff; return ret; } - - } // namespace PList diff --git a/src/Date.cpp b/src/Date.cpp index 8b8e650..cbfa123 100644 --- a/src/Date.cpp +++ b/src/Date.cpp @@ -34,8 +34,8 @@ Date::Date(plist_t node, Node* parent) : Node(node, parent) Date::Date(const PList::Date& d) : Node(PLIST_DATE) { - timeval t = d.GetValue(); - plist_set_date_val(_node, t.tv_sec, t.tv_usec); + int64_t t = d.GetValue(); + plist_set_unix_date_val(_node, t); } Date& Date::operator=(const PList::Date& d) @@ -45,9 +45,9 @@ Date& Date::operator=(const PList::Date& d) return *this; } -Date::Date(timeval t) : Node(PLIST_DATE) +Date::Date(int64_t t) : Node(PLIST_DATE) { - plist_set_date_val(_node, t.tv_sec, t.tv_usec); + plist_set_unix_date_val(_node, t); } Date::~Date() @@ -59,18 +59,16 @@ Node* Date::Clone() const return new Date(*this); } -void Date::SetValue(timeval t) +void Date::SetValue(int64_t t) { - plist_set_date_val(_node, t.tv_sec, t.tv_usec); + plist_set_unix_date_val(_node, t); } -timeval Date::GetValue() const +int64_t Date::GetValue() const { - int32_t tv_sec = 0; - int32_t tv_usec = 0; - plist_get_date_val(_node, &tv_sec, &tv_usec); - timeval t = {tv_sec, tv_usec}; - return t; + int64_t sec = 0; + plist_get_unix_date_val(_node, &sec); + return sec; } } // namespace PList diff --git a/src/Dictionary.cpp b/src/Dictionary.cpp index 30c20b6..0a909e5 100644 --- a/src/Dictionary.cpp +++ b/src/Dictionary.cpp @@ -40,7 +40,7 @@ static void dictionary_fill(Dictionary *_this, std::map<std::string,Node*> &map, plist_dict_next_item(node, it, &key, &subnode); if (key && subnode) map[std::string(key)] = Node::FromPlist(subnode, _this); - delete key; + free(key); } while (subnode); free(it); } @@ -51,7 +51,7 @@ Dictionary::Dictionary(plist_t node, Node* parent) : Structure(parent) dictionary_fill(this, _map, _node); } -Dictionary::Dictionary(const PList::Dictionary& d) +Dictionary::Dictionary(const PList::Dictionary& d) : Structure(d.GetParent()) { for (Dictionary::iterator it = _map.begin(); it != _map.end(); it++) { @@ -176,9 +176,9 @@ void Dictionary::Remove(Node* node) plist_dict_get_item_key(node->GetPlist(), &key); plist_dict_remove_item(_node, key); std::string skey = key; - delete key; + free(key); _map.erase(skey); - delete node; + free(node); } } diff --git a/src/Integer.cpp b/src/Integer.cpp index 30a5405..653455d 100644 --- a/src/Integer.cpp +++ b/src/Integer.cpp @@ -35,7 +35,8 @@ Integer::Integer(plist_t node, Node* parent) : Node(node, parent) Integer::Integer(const PList::Integer& i) : Node(PLIST_INT) { - plist_set_uint_val(_node, i.GetValue()); + plist_free(_node); + _node = plist_copy(i.GetPlist()); } Integer& Integer::operator=(const PList::Integer& i) diff --git a/src/Key.cpp b/src/Key.cpp index 79265d5..86a0bf8 100644 --- a/src/Key.cpp +++ b/src/Key.cpp @@ -69,7 +69,7 @@ std::string Key::GetValue() const char* s = NULL; plist_get_key_val(_node, &s); std::string ret = s ? s : ""; - delete s; + free(s); return ret; } diff --git a/src/Node.cpp b/src/Node.cpp index 0bd428a..1043b31 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -73,7 +73,7 @@ Node::Node(plist_type type, Node* parent) : _parent(parent) _node = plist_new_data(NULL,0); break; case PLIST_DATE: - _node = plist_new_date(0,0); + _node = plist_new_unix_date(0); break; case PLIST_ARRAY: _node = plist_new_array(); diff --git a/src/String.cpp b/src/String.cpp index 2ddc28b..8daec0f 100644 --- a/src/String.cpp +++ b/src/String.cpp @@ -45,11 +45,30 @@ String& String::operator=(const PList::String& s) return *this; } +String& String::operator=(const std::string& s) +{ + plist_free(_node); + _node = plist_new_string(s.c_str()); + return *this; +} + +String& String::operator=(const char* s) +{ + plist_free(_node); + _node = plist_new_string(s); + return *this; +} + String::String(const std::string& s) : Node(PLIST_STRING) { plist_set_string_val(_node, s.c_str()); } +String::String(const char *s) : Node(PLIST_STRING) +{ + plist_set_string_val(_node, s); +} + String::~String() { } @@ -66,10 +85,8 @@ void String::SetValue(const std::string& s) std::string String::GetValue() const { - char* s = NULL; - plist_get_string_val(_node, &s); + const char* s = plist_get_string_ptr(_node, NULL); std::string ret = s ? s : ""; - delete s; return ret; } diff --git a/src/Structure.cpp b/src/Structure.cpp index 670cce6..65e5ca8 100644 --- a/src/Structure.cpp +++ b/src/Structure.cpp @@ -57,7 +57,7 @@ std::string Structure::ToXml() const uint32_t length = 0; plist_to_xml(_node, &xml, &length); std::string ret(xml, xml+length); - delete xml; + free(xml); return ret; } @@ -67,7 +67,7 @@ std::vector<char> Structure::ToBin() const uint32_t length = 0; plist_to_bin(_node, &bin, &length); std::vector<char> ret(bin, bin+length); - delete bin; + free(bin); return ret; } @@ -77,7 +77,7 @@ void Structure::UpdateNodeParent(Node* node) if ( NULL != node->_parent ) { plist_type type = plist_get_node_type(node->_parent); - if (PLIST_ARRAY ==type || PLIST_DICT == type ) + if (PLIST_ARRAY == type || PLIST_DICT == type) { Structure* s = static_cast<Structure*>(node->_parent); s->Remove(node); @@ -117,8 +117,27 @@ Structure* Structure::FromBin(const std::vector<char>& bin) plist_from_bin(&bin[0], bin.size(), &root); return ImportStruct(root); +} + +Structure* Structure::FromBin(const char* bin, uint64_t size) +{ + plist_t root = NULL; + plist_from_bin(bin, size, &root); + return ImportStruct(root); } -} // namespace PList +Structure* Structure::FromMemory(const std::vector<char>& buf, plist_format_t *format) +{ + return Structure::FromMemory(&buf[0], buf.size(), format); +} +Structure* Structure::FromMemory(const char* buf, uint64_t size, plist_format_t *format) +{ + plist_t root = NULL; + plist_from_memory(buf, size, &root, format); + return ImportStruct(root); +} + + +} // namespace PList diff --git a/src/bplist.c b/src/bplist.c index 93f0bc6..85e55e2 100644 --- a/src/bplist.c +++ b/src/bplist.c @@ -87,6 +87,28 @@ union plist_uint_ptr uint64_t *u64ptr; }; +#ifdef _MSC_VER +uint64_t get_unaligned_64(uint64_t *ptr) +{ + uint64_t temp; + memcpy(&temp, ptr, sizeof(temp)); + return temp; +} + +uint32_t get_unaligned_32(uint32_t *ptr) +{ + uint32_t temp; + memcpy(&temp, ptr, sizeof(temp)); + return temp; +} + +uint16_t get_unaligned_16(uint16_t *ptr) +{ + uint16_t temp; + memcpy(&temp, ptr, sizeof(temp)); + return temp; +} +#else #define get_unaligned(ptr) \ ({ \ struct __attribute__((packed)) { \ @@ -94,6 +116,7 @@ union plist_uint_ptr } *__p = (void *) (ptr); \ __p->__v; \ }) +#endif #ifndef bswap16 @@ -148,17 +171,31 @@ union plist_uint_ptr #define beNtoh(x,n) be64toh((x) << ((8-(n)) << 3)) #endif +#ifdef _MSC_VER +static uint64_t UINT_TO_HOST(const void* x, uint8_t n) +{ + union plist_uint_ptr __up; + __up.src = (n > 8) ? (const char*)x + (n - 8) : (const char*)x; + return (n >= 8 ? be64toh( get_unaligned_64(__up.u64ptr) ) : + (n == 4 ? be32toh( get_unaligned_32(__up.u32ptr) ) : + (n == 2 ? be16toh( get_unaligned_16(__up.u16ptr) ) : + (n == 1 ? *__up.u8ptr : + beNtoh( get_unaligned_64(__up.u64ptr), n) + )))); +} +#else #define UINT_TO_HOST(x, n) \ ({ \ union plist_uint_ptr __up; \ - __up.src = ((n) > 8) ? (x) + ((n) - 8) : (x); \ + __up.src = ((n) > 8) ? (const char*)(x) + ((n) - 8) : (const char*)(x); \ ((n) >= 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \ ((n) == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \ ((n) == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \ - ((n) == 1 ? *__up.u8ptr : \ + ((n) == 1 ? *__up.u8ptr : \ beNtoh( get_unaligned(__up.u64ptr), n) \ )))); \ }) +#endif #define get_needed_bytes(x) \ ( ((uint64_t)(x)) < (1ULL << 8) ? 1 : \ @@ -168,15 +205,13 @@ union plist_uint_ptr #define get_real_bytes(x) ((x) == (float) (x) ? sizeof(float) : sizeof(double)) -#if (defined(__LITTLE_ENDIAN__) \ - && !defined(__FLOAT_WORD_ORDER__)) \ - || (defined(__FLOAT_WORD_ORDER__) \ - && __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__) -#define float_bswap64(x) bswap64(x) -#define float_bswap32(x) bswap32(x) -#else +#if (defined(__BIG_ENDIAN__) && !defined(__FLOAT_WORD_ORDER__)) \ + || (defined(__FLOAT_WORD_ORDER__) && __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__) #define float_bswap64(x) (x) #define float_bswap32(x) (x) +#else +#define float_bswap64(x) bswap64(x) +#define float_bswap32(x) bswap32(x) #endif #ifndef __has_builtin @@ -271,19 +306,30 @@ static plist_t parse_int_node(const char **bnode, uint8_t size) static plist_t parse_real_node(const char **bnode, uint8_t size) { plist_data_t data = plist_new_plist_data(); - uint8_t buf[8]; size = 1 << size; // make length less misleading switch (size) { case sizeof(uint32_t): - *(uint32_t*)buf = float_bswap32(get_unaligned((uint32_t*)*bnode)); - data->realval = *(float *) buf; - break; + { + uint32_t ival; + memcpy(&ival, *bnode, sizeof(uint32_t)); + ival = float_bswap32(ival); + float fval; + memcpy(&fval, &ival, sizeof(float)); + data->realval = fval; + } + break; + case sizeof(uint64_t): - *(uint64_t*)buf = float_bswap64(get_unaligned((uint64_t*)*bnode)); - data->realval = *(double *) buf; + { + uint64_t ival; + memcpy(&ival, *bnode, sizeof(uint64_t)); + ival = float_bswap64(ival); + memcpy(&data->realval, &ival, sizeof(double)); break; + } + default: free(data); PLIST_BIN_ERR("%s: Invalid byte size for real node\n", __func__); @@ -343,7 +389,7 @@ static char *plist_utf16be_to_utf8(uint16_t *unistr, long len, long *items_read, } while (i < len) { - wc = be16toh(get_unaligned(unistr + i)); + wc = UINT_TO_HOST(unistr + i, sizeof(wc)); i++; if (wc >= 0xD800 && wc <= 0xDBFF) { if (!read_lead_surrogate) { diff --git a/src/jplist.c b/src/jplist.c index 782d2b3..1c7a932 100644 --- a/src/jplist.c +++ b/src/jplist.c @@ -72,8 +72,10 @@ void plist_json_set_debug(int debug) } #ifndef HAVE_STRNDUP +#ifndef _MSC_VER #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" +#endif static char* strndup(const char* str, size_t len) { char *newstr = (char *)malloc(len+1); @@ -83,8 +85,10 @@ static char* strndup(const char* str, size_t len) } return newstr; } +#ifndef _MSC_VER #pragma GCC diagnostic pop #endif +#endif static size_t dtostr(char *buf, size_t bufsize, double realval) { @@ -460,6 +464,8 @@ static int64_t parse_decimal(const char* str, const char* str_end, char** endp) if (str[0] == '-') { is_neg = 1; (*endp)++; + } else if (str[0] == '+') { + (*endp)++; } if (is_neg) { MAX++; @@ -522,7 +528,7 @@ static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index) } else { val = plist_new_uint((uint64_t)intpart); } - } else if ((*endp == '.' && endp+1 < str_end && isdigit(*(endp+1))) || ((*endp == 'e' || *endp == 'E') && endp+1 < str_end && (isdigit(*(endp+1)) || ((*(endp+1) == '-') && endp+2 < str_end && isdigit(*(endp+2)))))) { + } else if ((*endp == '.' && endp+1 < str_end && isdigit(*(endp+1))) || ((*endp == 'e' || *endp == 'E') && endp+1 < str_end && (isdigit(*(endp+1)) || (((*(endp+1) == '-') || (*(endp+1) == '+')) && endp+2 < str_end && isdigit(*(endp+2)))))) { /* floating point */ double dval = (double)intpart; char* fendp = endp; @@ -546,7 +552,7 @@ static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index) if (fendp >= str_end) { break; } - if (fendp+1 < str_end && (*fendp == 'e' || *fendp == 'E') && (isdigit(*(fendp+1)) || ((*(fendp+1) == '-') && fendp+2 < str_end && isdigit(*(fendp+2))))) { + if (fendp+1 < str_end && (*fendp == 'e' || *fendp == 'E') && (isdigit(*(fendp+1)) || (((*(fendp+1) == '-') || (*(fendp+1) == '+')) && fendp+2 < str_end && isdigit(*(fendp+2))))) { int64_t exp = parse_decimal(fendp+1, str_end, &fendp); dval = dval * pow(10, (double)exp); } else { diff --git a/src/oplist.c b/src/oplist.c index 6ab6603..33896f9 100644 --- a/src/oplist.c +++ b/src/oplist.c @@ -71,8 +71,10 @@ void plist_ostep_set_debug(int debug) } #ifndef HAVE_STRNDUP +#ifndef _MSC_VER #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" +#endif static char* strndup(const char* str, size_t len) { char *newstr = (char *)malloc(len+1); @@ -82,8 +84,10 @@ static char* strndup(const char* str, size_t len) } return newstr; } +#ifndef _MSC_VER #pragma GCC diagnostic pop #endif +#endif static size_t dtostr(char *buf, size_t bufsize, double realval) { diff --git a/src/plist.c b/src/plist.c index 2078520..fe98f34 100644 --- a/src/plist.c +++ b/src/plist.c @@ -35,11 +35,10 @@ #include <limits.h> #include <float.h> #include <ctype.h> +#include <inttypes.h> #ifdef WIN32 #include <windows.h> -#else -#include <pthread.h> #endif #include <node.h> @@ -47,10 +46,92 @@ #include <hashtable.h> #include <ptrarray.h> +#define MAC_EPOCH 978307200 + #ifdef _MSC_VER typedef SSIZE_T ssize_t; #endif +#ifdef DEBUG +static int plist_debug = 0; +#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); } +#else +#define PLIST_ERR(...) +#endif + +#ifndef bswap16 +#define bswap16(x) ((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8)) +#endif + +#ifndef bswap32 +#define bswap32(x) ((((x) & 0xFF000000) >> 24) \ + | (((x) & 0x00FF0000) >> 8) \ + | (((x) & 0x0000FF00) << 8) \ + | (((x) & 0x000000FF) << 24)) +#endif + +#ifndef bswap64 +#define bswap64(x) ((((x) & 0xFF00000000000000ull) >> 56) \ + | (((x) & 0x00FF000000000000ull) >> 40) \ + | (((x) & 0x0000FF0000000000ull) >> 24) \ + | (((x) & 0x000000FF00000000ull) >> 8) \ + | (((x) & 0x00000000FF000000ull) << 8) \ + | (((x) & 0x0000000000FF0000ull) << 24) \ + | (((x) & 0x000000000000FF00ull) << 40) \ + | (((x) & 0x00000000000000FFull) << 56)) +#endif + +#ifndef le16toh +#ifdef __BIG_ENDIAN__ +#define le16toh(x) bswap16(x) +#else +#define le16toh(x) (x) +#endif +#endif + +#ifndef le32toh +#ifdef __BIG_ENDIAN__ +#define le32toh(x) bswap32(x) +#else +#define le32toh(x) (x) +#endif +#endif + +#ifndef le64toh +#ifdef __BIG_ENDIAN__ +#define le64toh(x) bswap64(x) +#else +#define le64toh(x) (x) +#endif +#endif + +// Reference: https://stackoverflow.com/a/2390626/1806760 +// Initializer/finalizer sample for MSVC and GCC/Clang. +// 2010-2016 Joe Lowe. Released into the public domain. + +#ifdef __cplusplus + #define INITIALIZER(f) \ + static void f(void); \ + struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \ + static void f(void) +#elif defined(_MSC_VER) + #pragma section(".CRT$XCU",read) + #define INITIALIZER2_(f,p) \ + static void f(void); \ + __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \ + __pragma(comment(linker,"/include:" p #f "_")) \ + static void f(void) + #ifdef _WIN64 + #define INITIALIZER(f) INITIALIZER2_(f,"") + #else + #define INITIALIZER(f) INITIALIZER2_(f,"_") + #endif +#else + #define INITIALIZER(f) \ + static void f(void) __attribute__((__constructor__)); \ + static void f(void) +#endif + extern void plist_xml_init(void); extern void plist_xml_deinit(void); extern void plist_bin_init(void); @@ -60,14 +141,6 @@ extern void plist_json_deinit(void); extern void plist_ostep_init(void); extern void plist_ostep_deinit(void); -static void internal_plist_init(void) -{ - plist_bin_init(); - plist_xml_init(); - plist_json_init(); - plist_ostep_init(); -} - static void internal_plist_deinit(void) { plist_bin_deinit(); @@ -76,66 +149,14 @@ static void internal_plist_deinit(void) plist_ostep_deinit(); } -#ifdef WIN32 -typedef volatile struct { - LONG lock; - int state; -} thread_once_t; - -static thread_once_t init_once = {0, 0}; -static thread_once_t deinit_once = {0, 0}; - -static void thread_once(thread_once_t *once_control, void (*init_routine)(void)) +INITIALIZER(internal_plist_init) { - while (InterlockedExchange(&(once_control->lock), 1) != 0) { - Sleep(1); - } - if (!once_control->state) { - once_control->state = 1; - init_routine(); - } - InterlockedExchange(&(once_control->lock), 0); -} -#else -static pthread_once_t init_once = PTHREAD_ONCE_INIT; -static pthread_once_t deinit_once = PTHREAD_ONCE_INIT; -#define thread_once pthread_once -#endif - -#ifndef HAVE_ATTRIBUTE_CONSTRUCTOR - #if defined(__llvm__) || defined(__GNUC__) - #define HAVE_ATTRIBUTE_CONSTRUCTOR - #endif -#endif - -#ifdef HAVE_ATTRIBUTE_CONSTRUCTOR -static void __attribute__((constructor)) libplist_initialize(void) -{ - thread_once(&init_once, internal_plist_init); -} - -static void __attribute__((destructor)) libplist_deinitialize(void) -{ - thread_once(&deinit_once, internal_plist_deinit); -} -#elif defined(WIN32) -BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) -{ - switch (dwReason) { - case DLL_PROCESS_ATTACH: - thread_once(&init_once, internal_plist_init); - break; - case DLL_PROCESS_DETACH: - thread_once(&deinit_once, internal_plist_deinit); - break; - default: - break; - } - return 1; + plist_bin_init(); + plist_xml_init(); + plist_json_init(); + plist_ostep_init(); + atexit(internal_plist_deinit); } -#else -#warning No compiler support for constructor/destructor attributes, some features might not be available. -#endif #ifndef HAVE_MEMMEM // see https://sourceware.org/legacy-ml/libc-alpha/2007-12/msg00000.html @@ -337,7 +358,7 @@ plist_data_t plist_get_data(plist_t node) plist_data_t plist_new_plist_data(void) { - plist_data_t data = (plist_data_t) calloc(sizeof(struct plist_data_s), 1); + plist_data_t data = (plist_data_t) calloc(1, sizeof(struct plist_data_s)); return data; } @@ -509,6 +530,15 @@ plist_t plist_new_date(int32_t sec, int32_t usec) return plist_new_node(data); } +plist_t plist_new_unix_date(int64_t sec) +{ + plist_data_t data = plist_new_plist_data(); + data->type = PLIST_DATE; + data->realval = (double)sec - MAC_EPOCH; + data->length = sizeof(double); + return plist_new_node(data); +} + plist_t plist_new_null(void) { plist_data_t data = plist_new_plist_data(); @@ -957,6 +987,195 @@ void plist_dict_merge(plist_t *target, plist_t source) free(it); } +uint8_t plist_dict_get_bool(plist_t dict, const char *key) +{ + uint8_t bval = 0; + uint64_t uintval = 0; + const char *strval = NULL; + uint64_t strsz = 0; + plist_t node = plist_dict_get_item(dict, key); + if (!node) { + return 0; + } + switch (plist_get_node_type(node)) { + case PLIST_BOOLEAN: + plist_get_bool_val(node, &bval); + break; + case PLIST_INT: + plist_get_uint_val(node, &uintval); + bval = (uintval) ? 1 : 0; + break; + case PLIST_STRING: + strval = plist_get_string_ptr(node, NULL); + if (strval) { + if (strcmp(strval, "true")) { + bval = 1; + } else if (strcmp(strval, "false")) { + bval = 0; + } else { + PLIST_ERR("%s: invalid string '%s' for string to boolean conversion\n", __func__, strval); + } + } + break; + case PLIST_DATA: + strval = (const char*)plist_get_data_ptr(node, &strsz); + if (strval) { + if (strsz == 1) { + bval = (strval[0]) ? 1 : 0; + } else { + PLIST_ERR("%s: invalid size %" PRIu64 " for data to boolean conversion\n", __func__, strsz); + } + } + break; + default: + break; + } + return bval; +} + +int64_t plist_dict_get_int(plist_t dict, const char *key) +{ + int64_t intval = 0; + const char *strval = NULL; + uint64_t strsz = 0; + plist_t node = plist_dict_get_item(dict, key); + if (!node) { + return intval; + } + switch (plist_get_node_type(node)) { + case PLIST_INT: + plist_get_int_val(node, &intval); + break; + case PLIST_STRING: + strval = plist_get_string_ptr(node, NULL); + if (strval) { + intval = strtoll(strval, NULL, 0); + } + break; + case PLIST_DATA: + strval = (const char*)plist_get_data_ptr(node, &strsz); + if (strval) { + if (strsz == 8) { + intval = le64toh(*(int64_t*)strval); + } else if (strsz == 4) { + intval = le32toh(*(int32_t*)strval); + } else if (strsz == 2) { + intval = le16toh(*(int16_t*)strval); + } else if (strsz == 1) { + intval = strval[0]; + } else { + PLIST_ERR("%s: invalid size %" PRIu64 " for data to integer conversion\n", __func__, strsz); + } + } + break; + default: + break; + } + return intval; +} + + +uint64_t plist_dict_get_uint(plist_t dict, const char *key) +{ + uint64_t uintval = 0; + const char *strval = NULL; + uint64_t strsz = 0; + plist_t node = plist_dict_get_item(dict, key); + if (!node) { + return uintval; + } + switch (plist_get_node_type(node)) { + case PLIST_INT: + plist_get_uint_val(node, &uintval); + break; + case PLIST_STRING: + strval = plist_get_string_ptr(node, NULL); + if (strval) { + uintval = strtoull(strval, NULL, 0); + } + break; + case PLIST_DATA: + strval = (const char*)plist_get_data_ptr(node, &strsz); + if (strval) { + if (strsz == 8) { + uintval = le64toh(*(uint64_t*)strval); + } else if (strsz == 4) { + uintval = le32toh(*(uint32_t*)strval); + } else if (strsz == 2) { + uintval = le16toh(*(uint16_t*)strval); + } else if (strsz == 1) { + uintval = strval[0]; + } else { + PLIST_ERR("%s: invalid size %" PRIu64 " for data to integer conversion\n", __func__, strsz); + } + } + break; + default: + break; + } + return uintval; +} + +plist_err_t plist_dict_copy_item(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) +{ + plist_t node = plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key); + if (!node) { + return PLIST_ERR_INVALID_ARG; + } + plist_dict_set_item(target_dict, key, plist_copy(node)); + return PLIST_ERR_SUCCESS; +} + +plist_err_t plist_dict_copy_bool(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) +{ + if (plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key) == NULL) { + return PLIST_ERR_INVALID_ARG; + } + uint8_t bval = plist_dict_get_bool(source_dict, (alt_source_key) ? alt_source_key : key); + plist_dict_set_item(target_dict, key, plist_new_bool(bval)); + return PLIST_ERR_SUCCESS; +} + +plist_err_t plist_dict_copy_int(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) +{ + if (plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key) == NULL) { + return PLIST_ERR_INVALID_ARG; + } + int64_t i64val = plist_dict_get_int(source_dict, (alt_source_key) ? alt_source_key : key); + plist_dict_set_item(target_dict, key, plist_new_int(i64val)); + return PLIST_ERR_SUCCESS; +} + +plist_err_t plist_dict_copy_uint(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) +{ + if (plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key) == NULL) { + return PLIST_ERR_INVALID_ARG; + } + uint64_t u64val = plist_dict_get_uint(source_dict, (alt_source_key) ? alt_source_key : key); + plist_dict_set_item(target_dict, key, plist_new_uint(u64val)); + return PLIST_ERR_SUCCESS; +} + +plist_err_t plist_dict_copy_data(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) +{ + plist_t node = plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key); + if (!PLIST_IS_DATA(node)) { + return PLIST_ERR_INVALID_ARG; + } + plist_dict_set_item(target_dict, key, plist_copy(node)); + return PLIST_ERR_SUCCESS; +} + +plist_err_t plist_dict_copy_string(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key) +{ + plist_t node = plist_dict_get_item(source_dict, (alt_source_key) ? alt_source_key : key); + if (!PLIST_IS_STRING(node)) { + return PLIST_ERR_INVALID_ARG; + } + plist_dict_set_item(target_dict, key, plist_copy(node)); + return PLIST_ERR_SUCCESS; +} + plist_t plist_access_pathv(plist_t plist, uint32_t length, va_list v) { plist_t current = plist; @@ -1184,6 +1403,20 @@ void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec) } } +void plist_get_unix_date_val(plist_t node, int64_t *sec) +{ + if (!node || !sec) + return; + plist_type type = plist_get_node_type(node); + uint64_t length = 0; + double val = 0; + if (PLIST_DATE != type) + return; + plist_get_type_and_value(node, &type, (void *) &val, &length); + assert(length == sizeof(double)); + *sec = (int64_t)val + MAC_EPOCH; +} + int plist_data_compare(const void *a, const void *b) { plist_data_t val_a = NULL; @@ -1340,7 +1573,13 @@ 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) { double val = (double)sec + (double)usec / 1000000; - plist_set_element_val(node, PLIST_DATE, &val, sizeof(struct timeval)); + plist_set_element_val(node, PLIST_DATE, &val, sizeof(double)); +} + +void plist_set_unix_date_val(plist_t node, int64_t sec) +{ + double val = (double)(sec - MAC_EPOCH); + plist_set_element_val(node, PLIST_DATE, &val, sizeof(double)); } int plist_bool_val_is_true(plist_t boolnode) @@ -1462,9 +1701,12 @@ int plist_date_val_compare(plist_t datenode, int32_t cmpsec, int32_t cmpusec) if (!PLIST_IS_DATE(datenode)) { return -1; } - int32_t sec = 0; - int32_t usec = 0; - plist_get_date_val(datenode, &sec, &usec); + plist_data_t data = plist_get_data(datenode); + assert(data->length == sizeof(double)); + double val = data->realval; + int32_t sec = (int32_t)val; + val = fabs((val - (int64_t)val) * 1000000); + int32_t usec = (int32_t)val; uint64_t dateval = ((int64_t)sec << 32) | usec; uint64_t cmpval = ((int64_t)cmpsec << 32) | cmpusec; if (dateval == cmpval) { @@ -1478,6 +1720,24 @@ int plist_date_val_compare(plist_t datenode, int32_t cmpsec, int32_t cmpusec) return 1; } +int plist_unix_date_val_compare(plist_t datenode, int64_t cmpval) +{ + if (!PLIST_IS_DATE(datenode)) { + return -1; + } + int64_t dateval = 0; + plist_get_unix_date_val(datenode, &dateval); + if (dateval == cmpval) { + return 0; + } + + if (dateval < cmpval) { + return -1; + } + + return 1; +} + int plist_string_val_compare(plist_t strnode, const char* cmpval) { if (!PLIST_IS_STRING(strnode)) { @@ -1577,6 +1837,9 @@ extern void plist_ostep_set_debug(int debug); void plist_set_debug(int debug) { +#if DEBUG + plist_debug = debug; +#endif plist_xml_set_debug(debug); plist_bin_set_debug(debug); plist_json_set_debug(debug); @@ -1597,6 +1860,9 @@ void plist_sort(plist_t plist) } else if (PLIST_IS_DICT(plist)) { node_t node = (node_t)plist; node_t ch; + if (!node_first_child(node)) { + return; + } for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { ch = node_next_sibling(ch); plist_sort((plist_t)ch); |