diff options
Diffstat (limited to 'include/plist')
| -rw-r--r-- | include/plist/Array.h | 43 | ||||
| -rw-r--r-- | include/plist/Boolean.h | 14 | ||||
| -rw-r--r-- | include/plist/Data.h | 15 | ||||
| -rw-r--r-- | include/plist/Date.h | 25 | ||||
| -rw-r--r-- | include/plist/Dictionary.h | 31 | ||||
| -rw-r--r-- | include/plist/Integer.h | 20 | ||||
| -rw-r--r-- | include/plist/Key.h | 49 | ||||
| -rw-r--r-- | include/plist/Node.h | 15 | ||||
| -rw-r--r-- | include/plist/Real.h | 14 | ||||
| -rw-r--r-- | include/plist/String.h | 17 | ||||
| -rw-r--r-- | include/plist/Structure.h | 15 | ||||
| -rw-r--r-- | include/plist/Uid.h | 48 | ||||
| -rw-r--r-- | include/plist/plist++.h | 2 | ||||
| -rw-r--r-- | include/plist/plist.h | 1150 |
14 files changed, 1297 insertions, 161 deletions
diff --git a/include/plist/Array.h b/include/plist/Array.h index fd4dea8..f4360c5 100644 --- a/include/plist/Array.h +++ b/include/plist/Array.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PLIST__ARRAY_H -#define PLIST__ARRAY_H +#ifndef PLIST_ARRAY_H +#define PLIST_ARRAY_H #include <plist/Structure.h> #include <vector> @@ -33,18 +33,43 @@ class Array : public Structure public : Array(Node* parent = NULL); Array(plist_t node, Node* parent = NULL); - Array(Array& a); - Array& operator=(Array& a); + Array(const Array& a); + Array& operator=(const Array& a); virtual ~Array(); - Node* Clone(); + Node* Clone() const; + + typedef std::vector<Node*>::iterator iterator; + typedef std::vector<Node*>::const_iterator const_iterator; Node* operator[](unsigned int index); - void Append(Node* node); - void Insert(Node* node, unsigned int pos); + Node* Back(); + Node* back(); + Node* Front(); + Node* front(); + iterator Begin(); + iterator begin(); + iterator End(); + iterator end(); + const_iterator Begin() const; + const_iterator begin() const; + const_iterator End() const; + const_iterator end() const; + size_t size() const; + void Append(const Node& node); + void Append(const Node* node); + void Insert(const Node& node, unsigned int pos); + void Insert(const Node* node, unsigned int pos); void Remove(Node* node); void Remove(unsigned int pos); - unsigned int GetNodeIndex(Node* node); + unsigned int GetNodeIndex(const Node& node) const; + unsigned int GetNodeIndex(const Node* node) const; + template <typename T> T* at(unsigned int index) { + return (T*)(_array.at(index)); + } + template <typename T> T* At(unsigned int index) { + return (T*)(_array.at(index)); + } private : std::vector<Node*> _array; @@ -52,4 +77,4 @@ private : }; -#endif // PLIST__ARRAY_H +#endif // PLIST_ARRAY_H diff --git a/include/plist/Boolean.h b/include/plist/Boolean.h index 731eb9e..9ecbc48 100644 --- a/include/plist/Boolean.h +++ b/include/plist/Boolean.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PLIST__BOOLEAN_H -#define PLIST__BOOLEAN_H +#ifndef PLIST_BOOLEAN_H +#define PLIST_BOOLEAN_H #include <plist/Node.h> @@ -32,17 +32,17 @@ class Boolean : public Node public : Boolean(Node* parent = NULL); Boolean(plist_t node, Node* parent = NULL); - Boolean(Boolean& b); - Boolean& operator=(Boolean& b); + Boolean(const Boolean& b); + Boolean& operator=(const Boolean& b); Boolean(bool b); virtual ~Boolean(); - Node* Clone(); + Node* Clone() const; void SetValue(bool b); - bool GetValue(); + bool GetValue() const; }; }; -#endif // PLIST__BOOLEAN_H +#endif // PLIST_BOOLEAN_H diff --git a/include/plist/Data.h b/include/plist/Data.h index f8ae715..1de88aa 100644 --- a/include/plist/Data.h +++ b/include/plist/Data.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PLIST__DATA_H -#define PLIST__DATA_H +#ifndef PLIST_DATA_H +#define PLIST_DATA_H #include <plist/Node.h> #include <vector> @@ -33,17 +33,18 @@ class Data : public Node public : Data(Node* parent = NULL); Data(plist_t node, Node* parent = NULL); - Data(Data& d); - Data& operator=(Data& d); + Data(const Data& d); + Data& operator=(const Data& b); Data(const std::vector<char>& buff); + Data(const char* buff, uint64_t size); virtual ~Data(); - Node* Clone(); + Node* Clone() const; void SetValue(const std::vector<char>& buff); - std::vector<char> GetValue(); + std::vector<char> GetValue() const; }; }; -#endif // PLIST__DATA_H +#endif // PLIST_DATA_H diff --git a/include/plist/Date.h b/include/plist/Date.h index 2ea830b..7026699 100644 --- a/include/plist/Date.h +++ b/include/plist/Date.h @@ -19,14 +19,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PLIST__DATE_H -#define PLIST__DATE_H +#ifndef PLIST_DATE_H +#define PLIST_DATE_H #include <plist/Node.h> #include <ctime> - -#ifdef _WIN32 -#include <Winsock2.h> +#ifdef _MSC_VER +#include <winsock2.h> +#else +#include <sys/time.h> #endif namespace PList @@ -37,17 +38,17 @@ class Date : public Node public : Date(Node* parent = NULL); Date(plist_t node, Node* parent = NULL); - Date(Date& d); - Date& operator=(Date& d); - Date(timeval t); + Date(const Date& d); + Date& operator=(const Date& d); + Date(int64_t t); virtual ~Date(); - Node* Clone(); + Node* Clone() const; - void SetValue(timeval t); - timeval GetValue(); + void SetValue(int64_t t); + int64_t GetValue() const; }; }; -#endif // PLIST__DATE_H +#endif // PLIST_DATE_H diff --git a/include/plist/Dictionary.h b/include/plist/Dictionary.h index a937bde..37ff1c9 100644 --- a/include/plist/Dictionary.h +++ b/include/plist/Dictionary.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PLIST__DICTIONARY_H -#define PLIST__DICTIONARY_H +#ifndef PLIST_DICTIONARY_H +#define PLIST_DICTIONARY_H #include <plist/Structure.h> #include <map> @@ -34,29 +34,40 @@ class Dictionary : public Structure public : Dictionary(Node* parent = NULL); Dictionary(plist_t node, Node* parent = NULL); - Dictionary(Dictionary& d); - Dictionary& operator=(Dictionary& d); + Dictionary(const Dictionary& d); + Dictionary& operator=(const Dictionary& d); virtual ~Dictionary(); - Node* Clone(); + Node* Clone() const; typedef std::map<std::string,Node*>::iterator iterator; + typedef std::map<std::string,Node*>::const_iterator const_iterator; Node* operator[](const std::string& key); iterator Begin(); + iterator begin(); iterator End(); + iterator end(); iterator Find(const std::string& key); - iterator Insert(const std::string& key, Node* node); + const_iterator Begin() const; + const_iterator begin() const; + const_iterator End() const; + const_iterator end() const; + size_t size() const; + const_iterator Find(const std::string& key) const; + iterator Set(const std::string& key, const Node* node); + iterator Set(const std::string& key, const Node& node); void Remove(Node* node); void Remove(const std::string& key); - std::string GetNodeKey(Node* key); + std::string GetNodeKey(Node* node); + template <typename T> T* Get(const std::string& key) { + return (T*)(_map[key]); + } private : std::map<std::string,Node*> _map; - - }; }; -#endif // PLIST__DICTIONARY_H +#endif // PLIST_DICTIONARY_H diff --git a/include/plist/Integer.h b/include/plist/Integer.h index 7cdf0df..1a4d980 100644 --- a/include/plist/Integer.h +++ b/include/plist/Integer.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PLIST__INTEGER_H -#define PLIST__INTEGER_H +#ifndef PLIST_INTEGER_H +#define PLIST_INTEGER_H #include <plist/Node.h> @@ -32,17 +32,23 @@ class Integer : public Node public : Integer(Node* parent = NULL); Integer(plist_t node, Node* parent = NULL); - Integer(Integer& i); - Integer& operator=(Integer& i); + Integer(const Integer& i); + Integer& operator=(const Integer& i); Integer(uint64_t i); + Integer(int64_t i); virtual ~Integer(); - Node* Clone(); + Node* Clone() const; + void SetValue(int64_t i); void SetValue(uint64_t i); - uint64_t GetValue(); + void SetUnsignedValue(uint64_t i); + int64_t GetValue() const; + uint64_t GetUnsignedValue() const; + + bool isNegative() const; }; }; -#endif // PLIST__INTEGER_H +#endif // PLIST_INTEGER_H diff --git a/include/plist/Key.h b/include/plist/Key.h new file mode 100644 index 0000000..bd5f7bc --- /dev/null +++ b/include/plist/Key.h @@ -0,0 +1,49 @@ +/* + * Key.h + * Key node type for C++ binding + * + * Copyright (c) 2012 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 PLIST_KEY_H +#define PLIST_KEY_H + +#include <plist/Node.h> +#include <string> + +namespace PList +{ + +class Key : public Node +{ +public : + Key(Node* parent = NULL); + Key(plist_t node, Node* parent = NULL); + Key(const Key& k); + Key& operator=(const Key& k); + Key(const std::string& s); + virtual ~Key(); + + Node* Clone() const; + + void SetValue(const std::string& s); + std::string GetValue() const; +}; + +}; + +#endif // PLIST_KEY_H diff --git a/include/plist/Node.h b/include/plist/Node.h index 1da9ee1..6c9ae43 100644 --- a/include/plist/Node.h +++ b/include/plist/Node.h @@ -19,10 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PLIST__NODE_H -#define PLIST__NODE_H +#ifndef PLIST_NODE_H +#define PLIST_NODE_H #include <plist/plist.h> +#include <cstddef> namespace PList { @@ -32,11 +33,11 @@ class Node public : virtual ~Node(); - virtual Node* Clone() = 0; + virtual Node* Clone() const = 0; - Node * GetParent(); - plist_type GetType(); - plist_t GetPlist(); + Node * GetParent() const; + plist_type GetType() const; + plist_t GetPlist() const; static Node* FromPlist(plist_t node, Node* parent = NULL); @@ -53,4 +54,4 @@ private: }; -#endif // PLIST__NODE_H +#endif // PLIST_NODE_H diff --git a/include/plist/Real.h b/include/plist/Real.h index 7d6f8e2..5afb0c0 100644 --- a/include/plist/Real.h +++ b/include/plist/Real.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PLIST__REAL_H -#define PLIST__REAL_H +#ifndef PLIST_REAL_H +#define PLIST_REAL_H #include <plist/Node.h> @@ -32,17 +32,17 @@ class Real : public Node public : Real(Node* parent = NULL); Real(plist_t node, Node* parent = NULL); - Real(Real& d); - Real& operator=(Real& d); + Real(const Real& d); + Real& operator=(const Real& d); Real(double d); virtual ~Real(); - Node* Clone(); + Node* Clone() const; void SetValue(double d); - double GetValue(); + double GetValue() const; }; }; -#endif // PLIST__REAL_H +#endif // PLIST_REAL_H diff --git a/include/plist/String.h b/include/plist/String.h index bd8680d..95f8dd1 100644 --- a/include/plist/String.h +++ b/include/plist/String.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PLIST__STRING_H -#define PLIST__STRING_H +#ifndef PLIST_STRING_H +#define PLIST_STRING_H #include <plist/Node.h> #include <string> @@ -33,17 +33,20 @@ class String : public Node public : String(Node* parent = NULL); String(plist_t node, Node* parent = NULL); - String(String& s); - String& operator=(String& s); + String(const String& s); + String& operator=(const String& s); + String& operator=(const std::string& s); + String& operator=(const char* s); String(const std::string& s); + String(const char *s); virtual ~String(); - Node* Clone(); + Node* Clone() const; void SetValue(const std::string& s); - std::string GetValue(); + std::string GetValue() const; }; }; -#endif // PLIST__STRING_H +#endif // PLIST_STRING_H diff --git a/include/plist/Structure.h b/include/plist/Structure.h index ace8b5c..b7fbdb5 100644 --- a/include/plist/Structure.h +++ b/include/plist/Structure.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PLIST__STRUCTURE_H -#define PLIST__STRUCTURE_H +#ifndef PLIST_STRUCTURE_H +#define PLIST_STRUCTURE_H #include <plist/Node.h> #include <string> @@ -34,15 +34,18 @@ class Structure : public Node public : virtual ~Structure(); - uint32_t GetSize(); + uint32_t GetSize() const; - std::string ToXml(); - std::vector<char> ToBin(); + std::string ToXml() const; + std::vector<char> ToBin() const; virtual void Remove(Node* node) = 0; static Structure* FromXml(const std::string& xml); static Structure* FromBin(const std::vector<char>& bin); + static Structure* FromBin(const char* bin, uint64_t size); + static Structure* FromMemory(const std::vector<char>& buf, plist_format_t* format = NULL); + static Structure* FromMemory(const char* buf, uint64_t size, plist_format_t* format = NULL); protected: Structure(Node* parent = NULL); @@ -56,4 +59,4 @@ private: }; -#endif // PLIST__STRUCTURE_H +#endif // PLIST_STRUCTURE_H diff --git a/include/plist/Uid.h b/include/plist/Uid.h new file mode 100644 index 0000000..af6e51d --- /dev/null +++ b/include/plist/Uid.h @@ -0,0 +1,48 @@ +/* + * Uid.h + * Uid node type for C++ binding + * + * Copyright (c) 2012 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 PLIST_UID_H +#define PLIST_UID_H + +#include <plist/Node.h> + +namespace PList +{ + +class Uid : public Node +{ +public : + Uid(Node* parent = NULL); + Uid(plist_t node, Node* parent = NULL); + Uid(const Uid& i); + Uid& operator=(const Uid& i); + Uid(uint64_t i); + virtual ~Uid(); + + Node* Clone() const; + + void SetValue(uint64_t i); + uint64_t GetValue() const; +}; + +}; + +#endif // PLIST_UID_H diff --git a/include/plist/plist++.h b/include/plist/plist++.h index d5eb691..b29fc76 100644 --- a/include/plist/plist++.h +++ b/include/plist/plist++.h @@ -31,6 +31,8 @@ #include "Integer.h" #include "Node.h" #include "Real.h" +#include "Key.h" +#include "Uid.h" #include "String.h" #include "Structure.h" diff --git a/include/plist/plist.h b/include/plist/plist.h index 1b1ac52..e720aac 100644 --- a/include/plist/plist.h +++ b/include/plist/plist.h @@ -3,7 +3,8 @@ * @brief Main include of libplist * \internal * - * Copyright (c) 2008 Jonathan Beck All Rights Reserved. + * Copyright (c) 2012-2023 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2008-2009 Jonathan Beck, 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 @@ -28,7 +29,7 @@ extern "C" { #endif -#ifdef _MSC_VER +#if _MSC_VER && _MSC_VER < 1700 typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; @@ -39,21 +40,57 @@ extern "C" typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; -#ifdef plist_EXPORTS -#define PLIST_API __declspec( dllexport ) #else -#define PLIST_API __declspec( dllimport ) +#include <stdint.h> #endif + +/*{{{ deprecation macros */ +#ifdef __llvm__ + #if defined(__has_extension) + #if (__has_extension(attribute_deprecated_with_message)) + #ifndef PLIST_WARN_DEPRECATED + #define PLIST_WARN_DEPRECATED(x) __attribute__((deprecated(x))) + #endif + #else + #ifndef PLIST_WARN_DEPRECATED + #define PLIST_WARN_DEPRECATED(x) __attribute__((deprecated)) + #endif + #endif + #else + #ifndef PLIST_WARN_DEPRECATED + #define PLIST_WARN_DEPRECATED(x) __attribute__((deprecated)) + #endif + #endif +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 5))) + #ifndef PLIST_WARN_DEPRECATED + #define PLIST_WARN_DEPRECATED(x) __attribute__((deprecated(x))) + #endif +#elif defined(_MSC_VER) + #ifndef PLIST_WARN_DEPRECATED + #define PLIST_WARN_DEPRECATED(x) __declspec(deprecated(x)) + #endif #else -#include <stdint.h> -#define PLIST_API + #define PLIST_WARN_DEPRECATED(x) + #pragma message("WARNING: You need to implement DEPRECATED for this compiler") +#endif +/*}}}*/ + +#ifndef PLIST_API + #ifdef LIBPLIST_STATIC + #define PLIST_API + #elif defined(_WIN32) + #define PLIST_API __declspec(dllimport) + #else + #define PLIST_API + #endif #endif #include <sys/types.h> #include <stdarg.h> +#include <stdio.h> /** - * \mainpage libplist : A library to handle Apple Property Lists + * libplist : A library to handle Apple Property Lists * \defgroup PublicAPI Public libplist API */ /*@{*/ @@ -67,25 +104,87 @@ extern "C" /** * The plist dictionary iterator. */ - typedef void *plist_dict_iter; + typedef void* plist_dict_iter; + + /** + * The plist array iterator. + */ + typedef void* plist_array_iter; /** * The enumeration of plist node types. */ typedef enum { - PLIST_BOOLEAN, /**< Boolean, scalar type */ - PLIST_UINT, /**< Unsigned integer, scalar type */ - PLIST_REAL, /**< Real, scalar type */ - PLIST_STRING, /**< ASCII string, scalar type */ - PLIST_ARRAY, /**< Ordered array, structured type */ - PLIST_DICT, /**< Unordered dictionary (key/value pair), structured type */ - PLIST_DATE, /**< Date, scalar type */ - PLIST_DATA, /**< Binary data, scalar type */ - PLIST_KEY, /**< Key in dictionaries (ASCII String), scalar type */ - PLIST_NONE /**< No type */ + PLIST_NONE =-1, /**< No type */ + PLIST_BOOLEAN, /**< Boolean, scalar type */ + PLIST_INT, /**< Integer, scalar type */ + PLIST_REAL, /**< Real, scalar type */ + PLIST_STRING, /**< ASCII string, scalar type */ + PLIST_ARRAY, /**< Ordered array, structured type */ + PLIST_DICT, /**< Unordered dictionary (key/value pair), structured type */ + PLIST_DATE, /**< Date, scalar type */ + PLIST_DATA, /**< Binary data, scalar type */ + PLIST_KEY, /**< Key in dictionaries (ASCII String), scalar type */ + PLIST_UID, /**< Special type used for 'keyed encoding' */ + PLIST_NULL, /**< NULL type */ } plist_type; + /* for backwards compatibility */ + #define PLIST_UINT PLIST_INT + + /** + * libplist error values + */ + typedef enum + { + PLIST_ERR_SUCCESS = 0, /**< operation successful */ + PLIST_ERR_INVALID_ARG = -1, /**< one or more of the parameters are invalid */ + PLIST_ERR_FORMAT = -2, /**< the plist contains nodes not compatible with the output format */ + PLIST_ERR_PARSE = -3, /**< parsing of the input format failed */ + PLIST_ERR_NO_MEM = -4, /**< not enough memory to handle the operation */ + PLIST_ERR_IO = -5, /**< I/O error */ + PLIST_ERR_CIRCULAR_REF = -6, /**< circular reference detected */ + PLIST_ERR_MAX_NESTING = -7, /**< maximum nesting depth exceeded */ + PLIST_ERR_UNKNOWN = -255 /**< an unspecified error occurred */ + } plist_err_t; + + /** + * libplist format types + */ + typedef enum + { + PLIST_FORMAT_NONE = 0, /**< No format */ + PLIST_FORMAT_XML = 1, /**< XML format */ + PLIST_FORMAT_BINARY = 2, /**< bplist00 format */ + PLIST_FORMAT_JSON = 3, /**< JSON format */ + PLIST_FORMAT_OSTEP = 4, /**< OpenStep "old-style" plist format */ + /* 5-9 are reserved for possible future use */ + PLIST_FORMAT_PRINT = 10, /**< human-readable output-only format */ + PLIST_FORMAT_LIMD = 11, /**< "libimobiledevice" output-only format (ideviceinfo) */ + PLIST_FORMAT_PLUTIL = 12, /**< plutil-style output-only format */ + } plist_format_t; + + /** + * libplist write options + */ + typedef enum + { + PLIST_OPT_NONE = 0, /**< Default value to use when none of the options is needed. */ + PLIST_OPT_COMPACT = 1 << 0, /**< Use a compact representation (non-prettified). Only valid for #PLIST_FORMAT_JSON and #PLIST_FORMAT_OSTEP. */ + PLIST_OPT_PARTIAL_DATA = 1 << 1, /**< Print 24 bytes maximum of #PLIST_DATA values. If the data is longer than 24 bytes, the first 16 and last 8 bytes will be written. Only valid for #PLIST_FORMAT_PRINT. */ + PLIST_OPT_NO_NEWLINE = 1 << 2, /**< Do not print a final newline character. Only valid for #PLIST_FORMAT_PRINT, #PLIST_FORMAT_LIMD, and #PLIST_FORMAT_PLUTIL. */ + PLIST_OPT_INDENT = 1 << 3, /**< Indent each line of output. Currently only #PLIST_FORMAT_PRINT and #PLIST_FORMAT_LIMD are supported. Use #PLIST_OPT_INDENT_BY() macro to specify the level of indentation. */ + PLIST_OPT_COERCE = 1 << 4, /**< Coerce plist types that have no native JSON representation into JSON-compatible types. + #PLIST_DATE is converted to an ISO 8601 date string, + #PLIST_DATA is converted to a Base64-encoded string, and + #PLIST_UID is converted to an integer. + Only valid for #PLIST_FORMAT_JSON. Without this option, these types cause #PLIST_ERR_FORMAT. */ + } plist_write_options_t; + + /** To be used with #PLIST_OPT_INDENT - encodes the level of indentation for OR'ing it into the #plist_write_options_t bitfield. */ + #define PLIST_OPT_INDENT_BY(x) ((x & 0xFF) << 24) + /******************************************** * * @@ -128,15 +227,28 @@ extern "C" PLIST_API plist_t plist_new_bool(uint8_t val); /** - * Create a new plist_t type #PLIST_UINT + * Create a new plist_t type #PLIST_INT with an unsigned integer value * * @param val the unsigned integer value * @return the created item * @sa #plist_type + * @note The value is always stored as uint64_t internally. + * Use #plist_get_uint_val or #plist_get_int_val to get the unsigned or signed value. */ PLIST_API plist_t plist_new_uint(uint64_t val); /** + * Create a new plist_t type #PLIST_INT with a signed integer value + * + * @param val the signed integer value + * @return the created item + * @sa #plist_type + * @note The value is always stored as uint64_t internally. + * Use #plist_get_uint_val or #plist_get_int_val to get the unsigned or signed value. + */ + PLIST_API plist_t plist_new_int(int64_t val); + + /** * Create a new plist_t type #PLIST_REAL * * @param val the real value @@ -158,12 +270,29 @@ extern "C" /** * Create a new plist_t type #PLIST_DATE * - * @param sec the number of seconds since 01/01/2001 - * @param usec the number of microseconds + * @param sec The number of seconds since 01/01/1970 (UNIX timestamp) * @return the created item * @sa #plist_type */ - PLIST_API plist_t plist_new_date(int32_t sec, int32_t usec); + PLIST_API plist_t plist_new_unix_date(int64_t sec); + + /** + * Create a new plist_t type #PLIST_UID + * + * @param val the unsigned integer value + * @return the created item + * @sa #plist_type + */ + PLIST_API plist_t plist_new_uid(uint64_t val); + + /** + * Create a new plist_t type #PLIST_NULL + * @return the created item + * @sa #plist_type + * @note This type is not valid for all formats, e.g. the XML format + * does not support it. + */ + PLIST_API plist_t plist_new_null(void); /** * Destruct a plist_t node and all its children recursively @@ -208,7 +337,7 @@ extern "C" * Get the index of an item. item must be a member of a #PLIST_ARRAY node. * * @param node the node - * @return the node index + * @return the node index or UINT_MAX if node index can't be determined */ PLIST_API uint32_t plist_array_get_item_index(plist_t node); @@ -217,36 +346,105 @@ extern "C" * The previous item at index n will be freed using #plist_free * * @param node the node of type #PLIST_ARRAY - * @param item the new item at index n - * @param n the index of the item to get. Range is [0, array_size[. Assert if n is not in range. + * @param item the new item at index n. The array is responsible for freeing item when it is no longer needed. + * @param n the index of the item to get. Range is [0, array_size[. + * + * @return + * - PLIST_ERR_SUCCESS on success. + * - PLIST_ERR_INVALID_ARG if node is not an array, item is NULL, item is already + * attached to a parent, or n is outside the valid range. + * - PLIST_ERR_NO_MEM if replacing the item fails due to memory allocation failure + * and the original array element was restored successfully. + * - PLIST_ERR_UNKNOWN if an unexpected internal error occurred, including failure + * to restore the original array element after insertion of the replacement failed. */ - PLIST_API void plist_array_set_item(plist_t node, plist_t item, uint32_t n); + PLIST_API plist_err_t plist_array_set_item(plist_t node, plist_t item, uint32_t n); /** * Append a new item at the end of a #PLIST_ARRAY node. * * @param node the node of type #PLIST_ARRAY - * @param item the new item + * @param item the new item. The array is responsible for freeing item when it is no longer needed. + * + * @return + * - PLIST_ERR_SUCCESS on success. + * - PLIST_ERR_INVALID_ARG if node is not an array, item is NULL, or item is + * already attached to a parent. + * - PLIST_ERR_NO_MEM if memory allocation failed while appending the item. + * - PLIST_ERR_UNKNOWN if an unexpected internal error occurred. */ - PLIST_API void plist_array_append_item(plist_t node, plist_t item); + PLIST_API plist_err_t plist_array_append_item(plist_t node, plist_t item); /** * Insert a new item at position n in a #PLIST_ARRAY node. * * @param node the node of type #PLIST_ARRAY - * @param item the new item to insert - * @param n The position at which the node will be stored. Range is [0, array_size[. Assert if n is not in range. + * @param item the new item to insert. The array is responsible for freeing item when it is no longer needed. + * @param n The position at which the node will be stored. Range is [0, array_size[. + * + * @return + * - PLIST_ERR_SUCCESS on success. + * - PLIST_ERR_INVALID_ARG if node is not an array, item is NULL, item is already + * attached to a parent, or n is outside the valid insertion range. + * - PLIST_ERR_NO_MEM if memory allocation failed while inserting the item. + * - PLIST_ERR_UNKNOWN if an unexpected internal error occurred. */ - PLIST_API void plist_array_insert_item(plist_t node, plist_t item, uint32_t n); + PLIST_API plist_err_t plist_array_insert_item(plist_t node, plist_t item, uint32_t n); /** * Remove an existing position in a #PLIST_ARRAY node. - * Removed position will be freed using #plist_free + * Removed position will be freed using #plist_free. * * @param node the node of type #PLIST_ARRAY - * @param n The position to remove. Range is [0, array_size[. Assert if n is not in range. + * @param n The position to remove. Range is [0, array_size[. + * + * @return + * - PLIST_ERR_SUCCESS on success. + * - PLIST_ERR_INVALID_ARG if node is not an array or n is outside the valid range. + * - PLIST_ERR_UNKNOWN if an unexpected internal error occurred while removing + * the item. + */ + PLIST_API plist_err_t plist_array_remove_item(plist_t node, uint32_t n); + + /** + * Remove a node that is a child node of a #PLIST_ARRAY node. + * node will be freed using #plist_free. + * + * @param node The node to be removed from its #PLIST_ARRAY parent. + * + * @return + * - PLIST_ERR_SUCCESS on success. + * - PLIST_ERR_INVALID_ARG if item is NULL or not a child of a #PLIST_ARRAY + * - PLIST_ERR_UNKNOWN if an unexpected internal error occurred. + */ + PLIST_API plist_err_t plist_array_item_remove(plist_t item); + + /** + * Create an iterator of a #PLIST_ARRAY node. + * The allocated iterator should be freed with the standard free function. + * + * @param node The node of type #PLIST_ARRAY + * @param iter Location to store the iterator for the array. + */ + PLIST_API void plist_array_new_iter(plist_t node, plist_array_iter *iter); + + /** + * Increment iterator of a #PLIST_ARRAY node. + * + * @param node The node of type #PLIST_ARRAY. + * @param iter Iterator of the array + * @param item Location to store the item. The caller must *not* free the + * returned item. Will be set to NULL when no more items are left + * to iterate. + */ + PLIST_API void plist_array_next_item(plist_t node, plist_array_iter iter, plist_t *item); + + /** + * Free #PLIST_ARRAY iterator. + * + * @param iter Iterator to free. */ - PLIST_API void plist_array_remove_item(plist_t node, uint32_t n); + PLIST_API void plist_array_free_iter(plist_array_iter iter); /******************************************** * * @@ -263,29 +461,39 @@ extern "C" PLIST_API uint32_t plist_dict_get_size(plist_t node); /** - * Create iterator of a #PLIST_DICT node. - * The allocated iterator shoult be freed with tandard free function + * Create an iterator of a #PLIST_DICT node. + * The allocated iterator should be freed with the standard free function. * - * @param node the node of type #PLIST_DICT - * @param iter iterator of the #PLIST_DICT node + * @param node The node of type #PLIST_DICT. + * @param iter Location to store the iterator for the dictionary. */ PLIST_API void plist_dict_new_iter(plist_t node, plist_dict_iter *iter); /** * Increment iterator of a #PLIST_DICT node. * - * @param node the node of type #PLIST_DICT - * @param iter iterator of the dictionary - * @param key a location to store the key, or NULL. - * @param val a location to store the value, or NULL. + * @param node The node of type #PLIST_DICT + * @param iter Iterator of the dictionary + * @param key Location to store the key, or NULL. The caller is responsible + * for freeing the the returned string. + * @param val Location to store the value, or NULL. The caller must *not* + * free the returned value. Will be set to NULL when no more + * key/value pairs are left to iterate. */ PLIST_API void plist_dict_next_item(plist_t node, plist_dict_iter iter, char **key, plist_t *val); /** - * Get key associated to an item. Item must be member of a dictionary + * Free #PLIST_DICT iterator. * - * @param node the node - * @param key a location to store the key. + * @param iter Iterator to free. + */ + PLIST_API void plist_dict_free_iter(plist_dict_iter iter); + + /** + * Get key associated key to an item. Item must be member of a dictionary. + * + * @param node the item + * @param key a location to store the key. The caller is responsible for freeing the returned string. */ PLIST_API void plist_dict_get_item_key(plist_t node, char **key); @@ -294,38 +502,232 @@ extern "C" * * @param node the node of type #PLIST_DICT * @param key the identifier of the item to get. - * @return the item or NULL if node is not of type #PLIST_DICT + * @return the item or NULL if node is not of type #PLIST_DICT. The caller should not free + * the returned node. */ PLIST_API plist_t plist_dict_get_item(plist_t node, const char* key); /** - * Set item identified by key in a #PLIST_DICT node. - * The previous item at index n will be freed using #plist_free + * Get key node associated to an item. Item must be member of a dictionary. * - * @param node the node of type #PLIST_DICT - * @param item the new item associated to key - * @param key the identifier of the item to get. Assert if identifier is not present. + * @param node the item + * @return the key node of the given item, or NULL. */ - PLIST_API void plist_dict_set_item(plist_t node, const char* key, plist_t item); + PLIST_API plist_t plist_dict_item_get_key(plist_t node); /** - * Insert a new item at position n in a #PLIST_DICT node. + * Set item identified by key in a #PLIST_DICT node. + * The previous item identified by key will be freed using #plist_free. + * If there is no item for the given key a new item will be inserted. * * @param node the node of type #PLIST_DICT - * @param item the new item to insert - * @param key The identifier of the item to insert. Assert if identifier already present. + * @param item the new item associated to key + * @param key the identifier of the item to set. + * + * @return + * - PLIST_ERR_SUCCESS on success. + * - PLIST_ERR_INVALID_ARG if node is not a dictionary, key is NULL, item is NULL, + * or item is already attached to a parent. + * - PLIST_ERR_NO_MEM if memory allocation failed while creating or inserting the + * key/value pair. + * - PLIST_ERR_UNKNOWN if an unexpected internal error occurred. */ - PLIST_API void plist_dict_insert_item(plist_t node, const char* key, plist_t item); + PLIST_API plist_err_t plist_dict_set_item(plist_t node, const char* key, plist_t item); /** * Remove an existing position in a #PLIST_DICT node. * Removed position will be freed using #plist_free * * @param node the node of type #PLIST_DICT - * @param key The identifier of the item to remove. Assert if identifier is not present. + * @param key The identifier of the item to remove + * + * @return + * - PLIST_ERR_SUCCESS on success. + * - PLIST_ERR_INVALID_ARG if node is not a dictionary, key is NULL, or no item + * with the given key exists. + * - PLIST_ERR_UNKNOWN if an unexpected internal error occurred while removing + * the item. + */ + PLIST_API plist_err_t plist_dict_remove_item(plist_t node, const char* key); + + /** + * Merge a dictionary into another. This will add all key/value pairs + * from the source dictionary to the target dictionary, overwriting + * any existing key/value pairs that are already present in target. + * + * @param target pointer to an existing node of type #PLIST_DICT + * @param source node of type #PLIST_DICT that should be merged into target + * + * @return + * - PLIST_ERR_SUCCESS on success. + * - PLIST_ERR_INVALID_ARG if target is NULL, source is NULL, source is not a + * dictionary, or *target is not NULL and does not point to a dictionary. + * - PLIST_ERR_NO_MEM if memory allocation failed while creating the target + * dictionary or copying items from source. + * - PLIST_ERR_UNKNOWN if an unexpected internal error occurred. + */ + PLIST_API plist_err_t plist_dict_merge(plist_t *target, plist_t source); + + /** + * Get a boolean value from a given #PLIST_DICT entry. + * + * The value node can be of type #PLIST_BOOLEAN, but also + * #PLIST_STRING (either 'true' or 'false'), + * #PLIST_INT with a numerical value of 0 or >= 1, + * or #PLIST_DATA with a single byte with a value of 0 or >= 1. + * + * @note This function returns 0 if the dictionary does not contain an + * entry for the given key, if the value node is of any other than + * the above mentioned type, or has any mismatching value. + * + * @param dict A node of type #PLIST_DICT + * @param key The key to look for in dict + * @return 0 or 1 depending on the value of the node. + */ + PLIST_API uint8_t plist_dict_get_bool(plist_t dict, const char *key); + + /** + * Get a signed integer value from a given #PLIST_DICT entry. + * The value node can be of type #PLIST_INT, but also + * #PLIST_STRING with a numerical value as string (decimal or hexadecimal), + * or #PLIST_DATA with a size of 1, 2, 4, or 8 bytes in little endian byte order. + * + * @note This function returns 0 if the dictionary does not contain an + * entry for the given key, if the value node is of any other than + * the above mentioned type, or has any mismatching value. + * + * @param dict A node of type #PLIST_DICT + * @param key The key to look for in dict + * @return Signed integer value depending on the value of the node. + */ + PLIST_API int64_t plist_dict_get_int(plist_t dict, const char *key); + + /** + * Get an unsigned integer value from a given #PLIST_DICT entry. + * The value node can be of type #PLIST_INT, but also + * #PLIST_STRING with a numerical value as string (decimal or hexadecimal), + * or #PLIST_DATA with a size of 1, 2, 4, or 8 bytes in little endian byte order. + * + * @note This function returns 0 if the dictionary does not contain an + * entry for the given key, if the value node is of any other than + * the above mentioned type, or has any mismatching value. + * + * @param dict A node of type #PLIST_DICT + * @param key The key to look for in dict + * @return Signed integer value depending on the value of the node. + */ + PLIST_API uint64_t plist_dict_get_uint(plist_t dict, const char *key); + + /** + * Copy a node from *source_dict* to *target_dict*. + * The node is looked up in *source_dict* with given *key*, unless *alt_source_key* + * is non-NULL, in which case it is looked up with *alt_source_key*. + * The entry in *target_dict* is **always** created with *key*. + * + * @param target_dict The target dictionary to copy to. + * @param source_dict The source dictionary to copy from. + * @param key The key for the node to copy. + * @param alt_source_key The alternative source key for lookup in *source_dict* or NULL. + * + * @result PLIST_ERR_SUCCESS on success or PLIST_ERR_INVALID_ARG if the source dictionary does not contain + * any entry with given key or alt_source_key. + */ + PLIST_API plist_err_t plist_dict_copy_item(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); + + /** + * Copy a boolean value from *source_dict* to *target_dict*. + * The node is looked up in *source_dict* with given *key*, unless *alt_source_key* + * is non-NULL, in which case it is looked up with *alt_source_key*. + * The entry in *target_dict* is **always** created with *key*. + * + * @note The boolean value from *source_dict* is retrieved with #plist_dict_get_bool, + * but is **always** created as #PLIST_BOOLEAN in *target_dict*. + * + * @param target_dict The target dictionary to copy to. + * @param source_dict The source dictionary to copy from. + * @param key The key for the node to copy. + * @param alt_source_key The alternative source key for lookup in *source_dict* or NULL. + * + * @result PLIST_ERR_SUCCESS on success or PLIST_ERR_INVALID_ARG if the source dictionary does not contain + * any entry with given key or alt_source_key. + */ + PLIST_API plist_err_t plist_dict_copy_bool(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); + + /** + * Copy a signed integer value from *source_dict* to *target_dict*. + * The node is looked up in *source_dict* with given *key*, unless *alt_source_key* + * is non-NULL, in which case it is looked up with *alt_source_key*. + * The entry in *target_dict* is **always** created with *key*. + * + * @note The signed integer value from *source_dict* is retrieved with #plist_dict_get_int, + * but is **always** created as #PLIST_INT. + * + * @param target_dict The target dictionary to copy to. + * @param source_dict The source dictionary to copy from. + * @param key The key for the node value to copy. + * @param alt_source_key The alternative source key for lookup in *source_dict* or NULL. + * + * @result PLIST_ERR_SUCCESS on success or PLIST_ERR_INVALID_ARG if the source dictionary does not contain + * any entry with given key or alt_source_key. */ - PLIST_API void plist_dict_remove_item(plist_t node, const char* key); + PLIST_API plist_err_t plist_dict_copy_int(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); + /** + * Copy an unsigned integer value from *source_dict* to *target_dict*. + * The node is looked up in *source_dict* with given *key*, unless *alt_source_key* + * is non-NULL, in which case it is looked up with *alt_source_key*. + * The entry in *target_dict* is **always** created with *key*. + * + * @note The unsigned integer value from *source_dict* is retrieved with #plist_dict_get_uint, + * but is **always** created as #PLIST_INT. + * + * @param target_dict The target dictionary to copy to. + * @param source_dict The source dictionary to copy from. + * @param key The key for the node value to copy. + * @param alt_source_key The alternative source key for lookup in *source_dict* or NULL. + * + * @result PLIST_ERR_SUCCESS on success or PLIST_ERR_INVALID_ARG if the source dictionary does not contain + * any entry with given key or alt_source_key. + */ + PLIST_API plist_err_t plist_dict_copy_uint(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); + + /** + * Copy a #PLIST_DATA node from *source_dict* to *target_dict*. + * The node is looked up in *source_dict* with given *key*, unless *alt_source_key* + * is non-NULL, in which case it is looked up with *alt_source_key*. + * The entry in *target_dict* is **always** created with *key*. + * + * @note This function is like #plist_dict_copy_item, except that it fails + * if the source node is not of type #PLIST_DATA. + * + * @param target_dict The target dictionary to copy to. + * @param source_dict The source dictionary to copy from. + * @param key The key for the node value to copy. + * @param alt_source_key The alternative source key for lookup in *source_dict* or NULL. + * + * @result PLIST_ERR_SUCCESS on success or PLIST_ERR_INVALID_ARG if the source dictionary does not contain + * any entry with given key or alt_source_key, or if it is not of type #PLIST_DATA. + */ + PLIST_API plist_err_t plist_dict_copy_data(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); + + /** + * Copy a #PLIST_STRING node from *source_dict* to *target_dict*. + * The node is looked up in *source_dict* with given *key*, unless *alt_source_key* + * is non-NULL, in which case it is looked up with *alt_source_key*. + * The entry in *target_dict* is **always** created with *key*. + * + * @note This function is like #plist_dict_copy_item, except that it fails + * if the source node is not of type #PLIST_STRING. + * + * @param target_dict The target dictionary to copy to. + * @param source_dict The source dictionary to copy from. + * @param key The key for the node value to copy. + * @param alt_source_key The alternative source key for lookup in *source_dict* or NULL. + * + * @result PLIST_ERR_SUCCESS on success or PLIST_ERR_INVALID_ARG if the source dictionary does not contain + * any entry with given key or alt_source_key, or if it is not of type #PLIST_STRING. + */ + PLIST_API plist_err_t plist_dict_copy_string(plist_t target_dict, plist_t source_dict, const char *key, const char *alt_source_key); /******************************************** * * @@ -355,6 +757,7 @@ extern "C" * @param node the node * @param val a pointer to a C-string. This function allocates the memory, * caller is responsible for freeing it. + * @note Use plist_mem_free() to free the allocated memory. */ PLIST_API void plist_get_key_val(plist_t node, char **val); @@ -365,10 +768,24 @@ extern "C" * @param node the node * @param val a pointer to a C-string. This function allocates the memory, * caller is responsible for freeing it. Data is UTF-8 encoded. + * @note Use plist_mem_free() to free the allocated memory. */ PLIST_API void plist_get_string_val(plist_t node, char **val); /** + * Get a pointer to the buffer of a #PLIST_STRING node. + * + * @note DO NOT MODIFY the buffer. Mind that the buffer is only available + * until the plist node gets freed. Make a copy if needed. + * + * @param node The node + * @param length If non-NULL, will be set to the length of the string + * + * @return Pointer to the NULL-terminated buffer. + */ + PLIST_API const char* plist_get_string_ptr(plist_t node, uint64_t* length); + + /** * Get the value of a #PLIST_BOOLEAN node. * This function does nothing if node is not of type #PLIST_BOOLEAN * @@ -378,8 +795,8 @@ extern "C" PLIST_API void plist_get_bool_val(plist_t node, uint8_t * val); /** - * Get the value of a #PLIST_UINT node. - * This function does nothing if node is not of type #PLIST_UINT + * Get the unsigned integer value of a #PLIST_INT node. + * This function does nothing if node is not of type #PLIST_INT * * @param node the node * @param val a pointer to a uint64_t variable. @@ -387,6 +804,15 @@ extern "C" PLIST_API void plist_get_uint_val(plist_t node, uint64_t * val); /** + * Get the signed integer value of a #PLIST_INT node. + * This function does nothing if node is not of type #PLIST_INT + * + * @param node the node + * @param val a pointer to a int64_t variable. + */ + PLIST_API void plist_get_int_val(plist_t node, int64_t * val); + + /** * Get the value of a #PLIST_REAL node. * This function does nothing if node is not of type #PLIST_REAL * @@ -403,18 +829,40 @@ extern "C" * @param val a pointer to an unallocated char buffer. This function allocates the memory, * caller is responsible for freeing it. * @param length the length of the buffer + * @note Use plist_mem_free() to free the allocated memory. */ PLIST_API void plist_get_data_val(plist_t node, char **val, uint64_t * length); /** + * Get a pointer to the data buffer of a #PLIST_DATA node. + * + * @note DO NOT MODIFY the buffer. Mind that the buffer is only available + * until the plist node gets freed. Make a copy if needed. + * + * @param node The node + * @param length Pointer to a uint64_t that will be set to the length of the buffer + * + * @return Pointer to the buffer + */ + PLIST_API const char* plist_get_data_ptr(plist_t node, uint64_t* length); + + /** * Get the value of a #PLIST_DATE node. * This function does nothing if node is not of type #PLIST_DATE * * @param node the node - * @param sec a pointer to an int32_t variable. Represents the number of seconds since 01/01/2001. - * @param usec a pointer to an int32_t variable. Represents the number of microseconds + * @param sec a pointer to an int64_t variable. Represents the number of seconds since 01/01/1970 (UNIX timestamp). */ - PLIST_API void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec); + PLIST_API void plist_get_unix_date_val(plist_t node, int64_t *sec); + + /** + * Get the value of a #PLIST_UID node. + * This function does nothing if node is not of type #PLIST_UID + * + * @param node the node + * @param val a pointer to a uint64_t variable. + */ + PLIST_API void plist_get_uid_val(plist_t node, uint64_t * val); /******************************************** @@ -424,14 +872,6 @@ extern "C" ********************************************/ /** - * Forces type of node. Changing type of structured nodes is only allowed if node is empty. - * Reset value of node; - * @param node the node - * @param type the key value - */ - PLIST_API void plist_set_type(plist_t node, plist_type type); - - /** * Set the value of a node. * Forces type of node to #PLIST_KEY * @@ -445,7 +885,8 @@ extern "C" * Forces type of node to #PLIST_STRING * * @param node the node - * @param val the string value + * @param val the string value. The string is copied when set and will be + * freed by the node. */ PLIST_API void plist_set_string_val(plist_t node, const char *val); @@ -460,7 +901,7 @@ extern "C" /** * Set the value of a node. - * Forces type of node to #PLIST_UINT + * Forces type of node to #PLIST_INT * * @param node the node * @param val the unsigned integer value @@ -469,6 +910,15 @@ extern "C" /** * Set the value of a node. + * Forces type of node to #PLIST_INT + * + * @param node the node + * @param val the signed integer value + */ + PLIST_API void plist_set_int_val(plist_t node, int64_t val); + + /** + * Set the value of a node. * Forces type of node to #PLIST_REAL * * @param node the node @@ -481,7 +931,8 @@ extern "C" * Forces type of node to #PLIST_DATA * * @param node the node - * @param val the binary buffer + * @param val the binary buffer. The buffer is copied when set and will + * be freed by the node. * @param length the length of the buffer */ PLIST_API void plist_set_data_val(plist_t node, const char *val, uint64_t length); @@ -491,10 +942,18 @@ extern "C" * Forces type of node to #PLIST_DATE * * @param node the node - * @param sec the number of seconds since 01/01/2001 - * @param usec the number of microseconds + * @param sec the number of seconds since 01/01/1970 (UNIX timestamp) */ - PLIST_API void plist_set_date_val(plist_t node, int32_t sec, int32_t usec); + PLIST_API void plist_set_unix_date_val(plist_t node, int64_t sec); + + /** + * Set the value of a node. + * Forces type of node to #PLIST_UID + * + * @param node the node + * @param val the unsigned integer value + */ + PLIST_API void plist_set_uid_val(plist_t node, uint64_t val); /******************************************** @@ -510,8 +969,10 @@ extern "C" * @param plist_xml a pointer to a C-string. This function allocates the memory, * caller is responsible for freeing it. Data is UTF-8 encoded. * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + * @note Use plist_mem_free() to free the allocated memory. */ - PLIST_API void plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length); + PLIST_API plist_err_t plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length); /** * Export the #plist_t structure to binary format. @@ -520,8 +981,84 @@ extern "C" * @param plist_bin a pointer to a char* buffer. This function allocates the memory, * caller is responsible for freeing it. * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + * @note Use plist_mem_free() to free the allocated memory. + */ + PLIST_API plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length); + + /** + * Export the #plist_t structure to JSON format. + * + * @param plist the root node to export + * @param plist_json a pointer to a char* buffer. This function allocates the memory, + * caller is responsible for freeing it. + * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. + * @param prettify pretty print the output if != 0 + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + * @note Use plist_mem_free() to free the allocated memory. + */ + PLIST_API plist_err_t plist_to_json(plist_t plist, char **plist_json, uint32_t* length, int prettify); + + /** + * Export the #plist_t structure to JSON format with extended options. + * + * When \a PLIST_OPT_COMPACT is set in \a options, the resulting JSON + * will be non-prettified. + * + * When \a PLIST_OPT_COERCE is set in \a options, plist types that have + * no native JSON representation are converted to JSON-compatible types + * instead of returning #PLIST_ERR_FORMAT: + * - #PLIST_DATE is serialized as an ISO 8601 date string + * - #PLIST_DATA is serialized as a Base64-encoded string + * - #PLIST_UID is serialized as an integer + * + * @param plist the root node to export + * @param plist_json a pointer to a char* buffer. This function allocates the memory, + * caller is responsible for freeing it. + * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. + * @param options One or more bitwise ORed values of #plist_write_options_t. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + * @note Use plist_mem_free() to free the allocated memory. + */ + PLIST_API plist_err_t plist_to_json_with_options(plist_t plist, char **plist_json, uint32_t* length, plist_write_options_t options); + + /** + * Export the #plist_t structure to OpenStep format. + * + * @param plist the root node to export + * @param plist_openstep a pointer to a char* buffer. This function allocates the memory, + * caller is responsible for freeing it. + * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. + * @param prettify pretty print the output if != 0 + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + * @note Use plist_mem_free() to free the allocated memory. + */ + PLIST_API plist_err_t plist_to_openstep(plist_t plist, char **plist_openstep, uint32_t* length, int prettify); + + /** + * Export the #plist_t structure to OpenStep format with extended options. + * + * When \a PLIST_OPT_COMPACT is set in \a options, the resulting OpenStep output + * will be non-prettified. + * + * When \a PLIST_OPT_COERCE is set in \a options, plist types that have + * no native OpenStep representation are converted to OpenStep-compatible types + * instead of returning #PLIST_ERR_FORMAT: + * - #PLIST_BOOLEAN is serialized as a 1 or 0 + * - #PLIST_DATE is serialized as an ISO 8601 date string + * - #PLIST_NULL is serialized as string 'NULL' + * - #PLIST_UID is serialized as an integer + * + * @param plist the root node to export + * @param plist_openstep a pointer to a char* buffer. This function allocates the memory, + * caller is responsible for freeing it. + * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. + * @param options One or more bitwise ORed values of #plist_write_options_t. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + * @note Use plist_mem_free() to free the allocated memory. */ - PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length); + PLIST_API plist_err_t plist_to_openstep_with_options(plist_t plist, char **plist_openstep, uint32_t* length, plist_write_options_t options); + /** * Import the #plist_t structure from XML format. @@ -529,8 +1066,9 @@ extern "C" * @param plist_xml a pointer to the xml buffer. * @param length length of the buffer to read. * @param plist a pointer to the imported plist. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure */ - PLIST_API void plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist); + PLIST_API plist_err_t plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist); /** * Import the #plist_t structure from binary format. @@ -538,9 +1076,129 @@ extern "C" * @param plist_bin a pointer to the xml buffer. * @param length length of the buffer to read. * @param plist a pointer to the imported plist. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + */ + PLIST_API plist_err_t plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist); + + /** + * Import the #plist_t structure from JSON format. + * + * @param json a pointer to the JSON buffer. + * @param length length of the buffer to read. + * @param plist a pointer to the imported plist. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + */ + PLIST_API plist_err_t plist_from_json(const char *json, uint32_t length, plist_t * plist); + + /** + * Import the #plist_t structure from OpenStep plist format. + * + * @param openstep a pointer to the OpenStep plist buffer. + * @param length length of the buffer to read. + * @param plist a pointer to the imported plist. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + */ + PLIST_API plist_err_t plist_from_openstep(const char *openstep, uint32_t length, plist_t * plist); + + /** + * Import the #plist_t structure from memory data. + * + * This function will look at the first bytes of plist_data + * to determine if plist_data contains a binary, JSON, OpenStep, or XML plist + * and tries to parse the data in the appropriate format. + * @note This is just a convenience function and the format detection is + * very basic. It checks with plist_is_binary() if the data supposedly + * contains binary plist data, if not it checks if the first bytes have + * either '{' or '[' and assumes JSON format, and XML tags will result + * in parsing as XML, otherwise it will try to parse as OpenStep. + * + * @param plist_data A pointer to the memory buffer containing plist data. + * @param length Length of the buffer to read. + * @param plist A pointer to the imported plist. + * @param format If non-NULL, the #plist_format_t value pointed to will be set to the parsed format. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + */ + PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t *plist, plist_format_t *format); + + /** + * Import the #plist_t structure directly from file. + * + * This function will look at the first bytes of the file data + * to determine if it contains a binary, JSON, OpenStep, or XML plist + * and tries to parse the data in the appropriate format. + * Uses plist_from_memory() internally. + * + * @param filename The name of the file to parse. + * @param plist A pointer to the imported plist. + * @param format If non-NULL, the #plist_format_t value pointed to will be set to the parsed format. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure */ - PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist); + PLIST_API plist_err_t plist_read_from_file(const char *filename, plist_t *plist, plist_format_t *format); + /** + * Write the #plist_t structure to a NULL-terminated string using the given format and options. + * + * @param plist The input plist structure + * @param output Pointer to a char* buffer. This function allocates the memory, + * caller is responsible for freeing it. + * @param length A pointer to a uint32_t value that will receive the lenght of the allocated buffer. + * @param format A #plist_format_t value that specifies the output format to use. + * @param options One or more bitwise ORed values of #plist_write_options_t. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure. + * @note Use plist_mem_free() to free the allocated memory. + * @note #PLIST_FORMAT_BINARY is not supported by this function. + */ + PLIST_API plist_err_t plist_write_to_string(plist_t plist, char **output, uint32_t* length, plist_format_t format, plist_write_options_t options); + + /** + * Write the #plist_t structure to a FILE* stream using the given format and options. + * + * @param plist The input plist structure + * @param stream A writeable FILE* stream that the data will be written to. + * @param format A #plist_format_t value that specifies the output format to use. + * @param options One or more bitwise ORed values of #plist_write_options_t. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure. + * @note While this function allows all formats to be written to the given stream, + * only the formats #PLIST_FORMAT_PRINT, #PLIST_FORMAT_LIMD, and #PLIST_FORMAT_PLUTIL + * (basically all output-only formats) are directly and efficiently written to the stream; + * the other formats are written to a memory buffer first. + */ + PLIST_API plist_err_t plist_write_to_stream(plist_t plist, FILE* stream, plist_format_t format, plist_write_options_t options); + + /** + * Write the #plist_t structure to a file at given path using the given format and options. + * + * @param plist The input plist structure + * @param filename The file name of the file to write to. Existing files will be overwritten. + * @param format A #plist_format_t value that specifies the output format to use. + * @param options One or more bitwise ORed values of #plist_write_options_t. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure. + * @note Use plist_mem_free() to free the allocated memory. + */ + PLIST_API plist_err_t plist_write_to_file(plist_t plist, const char *filename, plist_format_t format, plist_write_options_t options); + + /** + * Print the given plist in human-readable format to standard output. + * This is equivalent to + * <code>plist_write_to_stream(plist, stdout, PLIST_FORMAT_PRINT, PLIST_OPT_PARTIAL_DATA);</code> + * @param plist The #plist_t structure to print + * @note For #PLIST_DATA nodes, only a maximum of 24 bytes (first 16 and last 8) are written. + */ + PLIST_API void plist_print(plist_t plist); + + /** + * Test if in-memory plist data is in binary format. + * This function will look at the first bytes of plist_data to determine + * if it supposedly contains a binary plist. + * @note The function is not validating the whole memory buffer to check + * if the content is truly a plist, it is only using some heuristic on + * the first few bytes of plist_data. + * + * @param plist_data a pointer to the memory buffer containing plist data. + * @param length length of the buffer to read. + * @return 1 if the buffer is a binary plist, 0 otherwise. + */ + PLIST_API int plist_is_binary(const char *plist_data, uint32_t length); /******************************************** * * @@ -578,6 +1236,334 @@ extern "C" */ PLIST_API char plist_compare_node_value(plist_t node_l, plist_t node_r); + /** Helper macro used by PLIST_IS_* macros that will evaluate the type of a plist node. */ + #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type)) + + /* Helper macros for the different plist types */ + /** Evaluates to true if the given plist node is of type PLIST_BOOLEAN */ + #define PLIST_IS_BOOLEAN(__plist) _PLIST_IS_TYPE(__plist, BOOLEAN) + /** Evaluates to true if the given plist node is of type PLIST_INT */ + #define PLIST_IS_INT(__plist) _PLIST_IS_TYPE(__plist, INT) + /** Evaluates to true if the given plist node is of type PLIST_REAL */ + #define PLIST_IS_REAL(__plist) _PLIST_IS_TYPE(__plist, REAL) + /** Evaluates to true if the given plist node is of type PLIST_STRING */ + #define PLIST_IS_STRING(__plist) _PLIST_IS_TYPE(__plist, STRING) + /** Evaluates to true if the given plist node is of type PLIST_ARRAY */ + #define PLIST_IS_ARRAY(__plist) _PLIST_IS_TYPE(__plist, ARRAY) + /** Evaluates to true if the given plist node is of type PLIST_DICT */ + #define PLIST_IS_DICT(__plist) _PLIST_IS_TYPE(__plist, DICT) + /** Evaluates to true if the given plist node is of type PLIST_DATE */ + #define PLIST_IS_DATE(__plist) _PLIST_IS_TYPE(__plist, DATE) + /** Evaluates to true if the given plist node is of type PLIST_DATA */ + #define PLIST_IS_DATA(__plist) _PLIST_IS_TYPE(__plist, DATA) + /** Evaluates to true if the given plist node is of type PLIST_KEY */ + #define PLIST_IS_KEY(__plist) _PLIST_IS_TYPE(__plist, KEY) + /** Evaluates to true if the given plist node is of type PLIST_UID */ + #define PLIST_IS_UID(__plist) _PLIST_IS_TYPE(__plist, UID) + /* for backwards compatibility */ + #define PLIST_IS_UINT PLIST_IS_INT + + /** + * Helper function to check the value of a PLIST_BOOL node. + * + * @param boolnode node of type PLIST_BOOL + * @return 1 if the boolean node has a value of TRUE or 0 if FALSE. + */ + PLIST_API int plist_bool_val_is_true(plist_t boolnode); + + /** + * Helper function to test if a given #PLIST_INT node's value is negative + * + * @param intnode node of type PLIST_INT + * @return 1 if the node's value is negative, or 0 if positive. + */ + PLIST_API int plist_int_val_is_negative(plist_t intnode); + + /** + * Helper function to compare the value of a PLIST_INT node against + * a given signed integer value. + * + * @param uintnode node of type PLIST_INT + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are equal, + * 1 if the node's value is greater than cmpval, + * or -1 if the node's value is less than cmpval. + */ + PLIST_API int plist_int_val_compare(plist_t uintnode, int64_t cmpval); + + /** + * Helper function to compare the value of a PLIST_INT node against + * a given unsigned integer value. + * + * @param uintnode node of type PLIST_INT + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are equal, + * 1 if the node's value is greater than cmpval, + * or -1 if the node's value is less than cmpval. + */ + PLIST_API int plist_uint_val_compare(plist_t uintnode, uint64_t cmpval); + + /** + * Helper function to compare the value of a PLIST_UID node against + * a given value. + * + * @param uidnode node of type PLIST_UID + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are equal, + * 1 if the node's value is greater than cmpval, + * or -1 if the node's value is less than cmpval. + */ + PLIST_API int plist_uid_val_compare(plist_t uidnode, uint64_t cmpval); + + /** + * Helper function to compare the value of a PLIST_REAL node against + * a given value. + * + * @note WARNING: Comparing floating point values can give inaccurate + * results because of the nature of floating point values on computer + * systems. While this function is designed to be as accurate as + * possible, please don't rely on it too much. + * + * @param realnode node of type PLIST_REAL + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are (almost) equal, + * 1 if the node's value is greater than cmpval, + * or -1 if the node's value is less than cmpval. + */ + PLIST_API int plist_real_val_compare(plist_t realnode, double cmpval); + + /** + * Helper function to compare the value of a PLIST_DATE node against + * a given number of seconds since epoch (UNIX timestamp). + * + * @param datenode node of type PLIST_DATE + * @param cmpval Number of seconds to compare against (UNIX timestamp) + * @return 0 if the node's date is equal to the supplied values, + * 1 if the node's date is greater than the supplied values, + * or -1 if the node's date is less than the supplied values. + */ + PLIST_API int plist_unix_date_val_compare(plist_t datenode, int64_t cmpval); + + /** + * Helper function to compare the value of a PLIST_STRING node against + * a given value. + * This function basically behaves like strcmp. + * + * @param strnode node of type PLIST_STRING + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + PLIST_API int plist_string_val_compare(plist_t strnode, const char* cmpval); + + /** + * Helper function to compare the value of a PLIST_STRING node against + * a given value, while not comparing more than n characters. + * This function basically behaves like strncmp. + * + * @param strnode node of type PLIST_STRING + * @param cmpval value to compare against + * @param n maximum number of characters to compare + * @return 0 if the node's value and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + PLIST_API int plist_string_val_compare_with_size(plist_t strnode, const char* cmpval, size_t n); + + /** + * Helper function to match a given substring in the value of a + * PLIST_STRING node. + * + * @param strnode node of type PLIST_STRING + * @param substr value to match + * @return 1 if the node's value contains the given substring, + * or 0 if not. + */ + PLIST_API int plist_string_val_contains(plist_t strnode, const char* substr); + + /** + * Helper function to compare the value of a PLIST_KEY node against + * a given value. + * This function basically behaves like strcmp. + * + * @param keynode node of type PLIST_KEY + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + PLIST_API int plist_key_val_compare(plist_t keynode, const char* cmpval); + + /** + * Helper function to compare the value of a PLIST_KEY node against + * a given value, while not comparing more than n characters. + * This function basically behaves like strncmp. + * + * @param keynode node of type PLIST_KEY + * @param cmpval value to compare against + * @param n maximum number of characters to compare + * @return 0 if the node's value and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + PLIST_API int plist_key_val_compare_with_size(plist_t keynode, const char* cmpval, size_t n); + + /** + * Helper function to match a given substring in the value of a + * PLIST_KEY node. + * + * @param keynode node of type PLIST_KEY + * @param substr value to match + * @return 1 if the node's value contains the given substring, + * or 0 if not. + */ + PLIST_API int plist_key_val_contains(plist_t keynode, const char* substr); + + /** + * Helper function to compare the data of a PLIST_DATA node against + * a given blob and size. + * This function basically behaves like memcmp after making sure the + * size of the node's data value is equal to the size of cmpval (n), + * making this a "full match" comparison. + * + * @param datanode node of type PLIST_DATA + * @param cmpval data blob to compare against + * @param n size of data blob passed in cmpval + * @return 0 if the node's data blob and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + PLIST_API int plist_data_val_compare(plist_t datanode, const uint8_t* cmpval, size_t n); + + /** + * Helper function to compare the data of a PLIST_DATA node against + * a given blob and size, while no more than n bytes are compared. + * This function basically behaves like memcmp after making sure the + * size of the node's data value is at least n, making this a + * "starts with" comparison. + * + * @param datanode node of type PLIST_DATA + * @param cmpval data blob to compare against + * @param n size of data blob passed in cmpval + * @return 0 if the node's value and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + PLIST_API int plist_data_val_compare_with_size(plist_t datanode, const uint8_t* cmpval, size_t n); + + /** + * Helper function to match a given data blob within the value of a + * PLIST_DATA node. + * + * @param datanode node of type PLIST_KEY + * @param cmpval data blob to match + * @param n size of data blob passed in cmpval + * @return 1 if the node's value contains the given data blob + * or 0 if not. + */ + PLIST_API int plist_data_val_contains(plist_t datanode, const uint8_t* cmpval, size_t n); + + /** + * Sort all PLIST_DICT key/value pairs in a property list lexicographically + * by key. Recurses into the child nodes if necessary. + * + * @param plist The property list to perform the sorting operation on. + */ + PLIST_API void plist_sort(plist_t plist); + + /** + * Free memory allocated by relevant libplist API calls: + * - plist_to_xml() + * - plist_to_bin() + * - plist_get_key_val() + * - plist_get_string_val() + * - plist_get_data_val() + * + * @param ptr pointer to the memory to free + * + * @note Do not use this function to free plist_t nodes, use plist_free() + * instead. + */ + PLIST_API void plist_mem_free(void* ptr); + + /** + * Set debug level for the format parsers. + * @note This function does nothing if libplist was not configured with --enable-debug . + * + * @param debug Debug level. Currently, only 0 (off) and 1 (enabled) are supported. + */ + PLIST_API void plist_set_debug(int debug); + + /** + * Returns a static string of the libplist version. + * + * @return The libplist version as static ascii string + */ + PLIST_API const char* libplist_version(); + + + /******************************************** + * * + * Deprecated API * + * * + ********************************************/ + + /** + * Create a new plist_t type #PLIST_DATE + * + * @deprecated Deprecated. Use plist_new_unix_date instead. + * + * @param sec the number of seconds since 01/01/2001 + * @param usec the number of microseconds + * @return the created item + * @sa #plist_type + */ + PLIST_WARN_DEPRECATED("use plist_new_unix_date instead") + PLIST_API plist_t plist_new_date(int32_t sec, int32_t usec); + + /** + * Get the value of a #PLIST_DATE node. + * This function does nothing if node is not of type #PLIST_DATE + * + * @deprecated Deprecated. Use plist_get_unix_date_val instead. + * + * @param node the node + * @param sec a pointer to an int32_t variable. Represents the number of seconds since 01/01/2001. + * @param usec a pointer to an int32_t variable. Represents the number of microseconds + */ + PLIST_WARN_DEPRECATED("use plist_get_unix_date_val instead") + PLIST_API void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec); + + /** + * Set the value of a node. + * Forces type of node to #PLIST_DATE + * + * @deprecated Deprecated. Use plist_set_unix_date_val instead. + * + * @param node the node + * @param sec the number of seconds since 01/01/2001 + * @param usec the number of microseconds + */ + PLIST_WARN_DEPRECATED("use plist_set_unix_date_val instead") + PLIST_API void plist_set_date_val(plist_t node, int32_t sec, int32_t usec); + + /** + * Helper function to compare the value of a PLIST_DATE node against + * a given set of seconds and fraction of a second since epoch. + * + * @deprecated Deprecated. Use plist_unix_date_val_compare instead. + * + * @param datenode node of type PLIST_DATE + * @param cmpsec number of seconds since epoch to compare against + * @param cmpusec fraction of a second in microseconds to compare against + * @return 0 if the node's date is equal to the supplied values, + * 1 if the node's date is greater than the supplied values, + * or -1 if the node's date is less than the supplied values. + */ + PLIST_WARN_DEPRECATED("use plist_unix_date_val_compare instead") + PLIST_API int plist_date_val_compare(plist_t datenode, int32_t cmpsec, int32_t cmpusec); + /*@}*/ #ifdef __cplusplus |
