diff options
| -rw-r--r-- | cython/plist.pxd | 3 | ||||
| -rw-r--r-- | cython/plist.pyx | 55 | ||||
| -rw-r--r-- | include/plist/Integer.h | 8 | ||||
| -rw-r--r-- | include/plist/plist.h | 79 | ||||
| -rw-r--r-- | src/Integer.cpp | 35 | ||||
| -rw-r--r-- | src/Key.cpp | 2 | ||||
| -rw-r--r-- | src/Node.cpp | 4 | ||||
| -rw-r--r-- | src/Real.cpp | 2 | ||||
| -rw-r--r-- | src/String.cpp | 2 | ||||
| -rw-r--r-- | src/bplist.c | 24 | ||||
| -rw-r--r-- | src/jplist.c | 12 | ||||
| -rw-r--r-- | src/oplist.c | 4 | ||||
| -rw-r--r-- | src/plist.c | 68 | ||||
| -rw-r--r-- | src/xplist.c | 6 | ||||
| -rw-r--r-- | test/Makefile.am | 5 | ||||
| -rw-r--r-- | test/integer_set.c | 130 | ||||
| -rwxr-xr-x | test/integer_set.test | 5 | 
17 files changed, 382 insertions, 62 deletions
| diff --git a/cython/plist.pxd b/cython/plist.pxd index b11d80d..5a41bf8 100644 --- a/cython/plist.pxd +++ b/cython/plist.pxd @@ -19,7 +19,8 @@ cdef class Bool(Node):  cdef class Integer(Node):      cpdef set_value(self, object value) -    cpdef uint64_t get_value(self) +    cpdef get_value(self) +    cpdef bint is_negative(self)  cdef class Uid(Node):      cpdef set_value(self, object value) diff --git a/cython/plist.pyx b/cython/plist.pyx index 38415f9..5481308 100644 --- a/cython/plist.pyx +++ b/cython/plist.pyx @@ -5,7 +5,7 @@ from libc.stdint cimport *  cdef extern from *:      ctypedef enum plist_type:          PLIST_BOOLEAN, -        PLIST_UINT, +        PLIST_INT,          PLIST_REAL,          PLIST_STRING,          PLIST_ARRAY, @@ -14,6 +14,7 @@ cdef extern from *:          PLIST_DATA,          PLIST_KEY,          PLIST_UID, +        PLIST_NULL,          PLIST_NONE      plist_t plist_new_bool(uint8_t val) @@ -24,6 +25,10 @@ cdef extern from *:      void plist_get_uint_val(plist_t node, uint64_t *val)      void plist_set_uint_val(plist_t node, uint64_t val) +    plist_t plist_new_int(int64_t val) +    void plist_get_int_val(plist_t node, int64_t *val) +    void plist_set_int_val(plist_t node, int64_t val) +      plist_t plist_new_real(double val)      void plist_get_real_val(plist_t node, double *val)      void plist_set_real_val(plist_t node, double val) @@ -47,6 +52,8 @@ cdef extern from *:      void plist_get_data_val(plist_t node, char **val, uint64_t * length)      void plist_set_data_val(plist_t node, char *val, uint64_t length) +    plist_t plist_new_null(); +      plist_t plist_new_dict()      int plist_dict_get_size(plist_t node)      plist_t plist_dict_get_item(plist_t node, char* key) @@ -77,6 +84,8 @@ cdef extern from *:      void plist_from_xml(char *plist_xml, uint32_t length, plist_t * plist)      void plist_from_bin(char *plist_bin, uint32_t length, plist_t * plist) +    int plist_int_val_is_negative(plist_t node); +  cdef class Node:      def __init__(self, *args, **kwargs):          self._c_managed = True @@ -177,13 +186,15 @@ cdef Bool Bool_factory(plist_t c_node, bint managed=True):  cdef class Integer(Node):      def __cinit__(self, object value=None, *args, **kwargs):          if value is None: -            self._c_node = plist_new_uint(0) +            self._c_node = plist_new_int(0)          else: -            self._c_node = plist_new_uint(int(value)) +            if value < 0 or value <= INT64_MAX: +                self._c_node = plist_new_int(int(value)) +            else: +                self._c_node = plist_new_uint(int(value))      def __repr__(self): -        cdef uint64_t i = self.get_value() -        return '<Integer: %s>' % i +        return '<Integer: %s>' % self.get_value()      def __int__(self):          return self.get_value() @@ -210,10 +221,18 @@ cdef class Integer(Node):      cpdef set_value(self, object value):          plist_set_uint_val(self._c_node, int(value)) -    cpdef uint64_t get_value(self): -        cdef uint64_t value -        plist_get_uint_val(self._c_node, &value) -        return value +    cpdef get_value(self): +        cdef int64_t ivalue +        cdef uint64_t uvalue +        if self.is_negative(): +            plist_get_int_val(self._c_node, &ivalue) +            return int(ivalue) +        else: +            plist_get_uint_val(self._c_node, &uvalue) +            return int(uvalue) + +    cpdef bint is_negative(self): +        return plist_int_val_is_negative(self._c_node);  cdef Integer Integer_factory(plist_t c_node, bint managed=True):      cdef Integer instance = Integer.__new__(Integer) @@ -314,6 +333,20 @@ cdef Uid Uid_factory(plist_t c_node, bint managed=True):      instance._c_node = c_node      return instance +cdef class Null(Node): +    def __cinit__(self, object value=None, *args, **kwargs): +        self._c_node = plist_new_null() + +    def __repr__(self): +        cdef uint64_t i = self.get_value() +        return '<Null>' + +cdef Null Null_factory(plist_t c_node, bint managed=True): +    cdef Null instance = Null.__new__(Null) +    instance._c_managed = managed +    instance._c_node = c_node +    return instance +  from cpython cimport PY_MAJOR_VERSION  cdef class Key(Node): @@ -833,7 +866,7 @@ cdef object plist_t_to_node(plist_t c_plist, bint managed=True):      cdef plist_type t = plist_get_node_type(c_plist)      if t == PLIST_BOOLEAN:          return Bool_factory(c_plist, managed) -    if t == PLIST_UINT: +    if t == PLIST_INT:          return Integer_factory(c_plist, managed)      if t == PLIST_KEY:          return Key_factory(c_plist, managed) @@ -851,6 +884,8 @@ cdef object plist_t_to_node(plist_t c_plist, bint managed=True):          return Data_factory(c_plist, managed)      if t == PLIST_UID:          return Uid_factory(c_plist, managed) +    if t == PLIST_NULL: +        return Null_factory(c_plist, managed)      if t == PLIST_NONE:          return None diff --git a/include/plist/Integer.h b/include/plist/Integer.h index bdabc6f..1a4d980 100644 --- a/include/plist/Integer.h +++ b/include/plist/Integer.h @@ -35,12 +35,18 @@ public :      Integer(const Integer& i);      Integer& operator=(const Integer& i);      Integer(uint64_t i); +    Integer(int64_t i);      virtual ~Integer();      Node* Clone() const; +    void SetValue(int64_t i);      void SetValue(uint64_t i); -    uint64_t GetValue() const; +    void SetUnsignedValue(uint64_t i); +    int64_t GetValue() const; +    uint64_t GetUnsignedValue() const; + +    bool isNegative() const;  };  }; diff --git a/include/plist/plist.h b/include/plist/plist.h index 0ae8889..2bb947f 100644 --- a/include/plist/plist.h +++ b/include/plist/plist.h @@ -3,7 +3,7 @@   * @brief Main include of libplist   * \internal   * - * Copyright (c) 2012-2019 Nikias Bassen, 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 @@ -104,7 +104,7 @@ extern "C"      typedef enum      {          PLIST_BOOLEAN,  /**< Boolean, scalar type */ -        PLIST_UINT,     /**< Unsigned integer, scalar type */ +        PLIST_INT,      /**< Integer, scalar type */          PLIST_REAL,     /**< Real, scalar type */          PLIST_STRING,   /**< ASCII string, scalar type */          PLIST_ARRAY,    /**< Ordered array, structured type */ @@ -117,6 +117,9 @@ extern "C"          PLIST_NONE      /**< No type */      } plist_type; +    /* for backwards compatibility */ +    #define PLIST_UINT PLIST_INT +      /**       * libplist error values       */ @@ -171,15 +174,28 @@ extern "C"      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_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_t plist_new_int(int64_t val); + +    /**       * Create a new plist_t type #PLIST_REAL       *       * @param val the real value @@ -509,8 +525,8 @@ extern "C"      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. @@ -518,6 +534,15 @@ extern "C"      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. +     */ +    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       * @@ -607,7 +632,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 @@ -616,6 +641,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 +     */ +    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 @@ -823,7 +857,7 @@ extern "C"      /* Helper macros for the different plist types */      #define PLIST_IS_BOOLEAN(__plist) _PLIST_IS_TYPE(__plist, BOOLEAN) -    #define PLIST_IS_UINT(__plist)    _PLIST_IS_TYPE(__plist, UINT) +    #define PLIST_IS_INT(__plist)     _PLIST_IS_TYPE(__plist, INT)      #define PLIST_IS_REAL(__plist)    _PLIST_IS_TYPE(__plist, REAL)      #define PLIST_IS_STRING(__plist)  _PLIST_IS_TYPE(__plist, STRING)      #define PLIST_IS_ARRAY(__plist)   _PLIST_IS_TYPE(__plist, ARRAY) @@ -832,21 +866,42 @@ extern "C"      #define PLIST_IS_DATA(__plist)    _PLIST_IS_TYPE(__plist, DATA)      #define PLIST_IS_KEY(__plist)     _PLIST_IS_TYPE(__plist, KEY)      #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, 0 if FALSE, -     *   or -1 if the node is not of type PLIST_BOOL +     * @return 1 if the boolean node has a value of TRUE or 0 if FALSE.       */      int plist_bool_val_is_true(plist_t boolnode);      /** -     * Helper function to compare the value of a PLIST_UINT node against -     * a given value. +     * 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. +     */ +    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. +     */ +    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_UINT +     * @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, diff --git a/src/Integer.cpp b/src/Integer.cpp index a40d026..7fa0f93 100644 --- a/src/Integer.cpp +++ b/src/Integer.cpp @@ -24,7 +24,7 @@  namespace PList  { -Integer::Integer(Node* parent) : Node(PLIST_UINT, parent) +Integer::Integer(Node* parent) : Node(PLIST_INT, parent)  {  } @@ -32,7 +32,7 @@ Integer::Integer(plist_t node, Node* parent) : Node(node, parent)  {  } -Integer::Integer(const PList::Integer& i) : Node(PLIST_UINT) +Integer::Integer(const PList::Integer& i) : Node(PLIST_INT)  {      plist_set_uint_val(_node, i.GetValue());  } @@ -44,11 +44,16 @@ Integer& Integer::operator=(const PList::Integer& i)      return *this;  } -Integer::Integer(uint64_t i) : Node(PLIST_UINT) +Integer::Integer(uint64_t i) : Node(PLIST_INT)  {      plist_set_uint_val(_node, i);  } +Integer::Integer(int64_t i) : Node(PLIST_INT) +{ +    plist_set_int_val(_node, i); +} +  Integer::~Integer()  {  } @@ -58,16 +63,38 @@ Node* Integer::Clone() const      return new Integer(*this);  } +void Integer::SetValue(int64_t i) +{ +    plist_set_int_val(_node, i); +} +  void Integer::SetValue(uint64_t i)  {      plist_set_uint_val(_node, i);  } -uint64_t Integer::GetValue() const +void Integer::SetUnsignedValue(uint64_t i) +{ +    plist_set_uint_val(_node, i); +} + +int64_t Integer::GetValue() const +{ +    int64_t i = 0; +    plist_get_int_val(_node, &i); +    return i; +} + +uint64_t Integer::GetUnsignedValue() const  {      uint64_t i = 0;      plist_get_uint_val(_node, &i);      return i;  } +bool Integer::isNegative() const +{ +    return plist_int_val_is_negative(_node); +} +  }  // namespace PList diff --git a/src/Key.cpp b/src/Key.cpp index 5d7d372..5f8d205 100644 --- a/src/Key.cpp +++ b/src/Key.cpp @@ -32,7 +32,7 @@ Key::Key(plist_t node, Node* parent) : Node(node, parent)  {  } -Key::Key(const PList::Key& k) : Node(PLIST_UINT) +Key::Key(const PList::Key& k) : Node(PLIST_INT)  {      plist_set_key_val(_node, k.GetValue().c_str());  } diff --git a/src/Node.cpp b/src/Node.cpp index fb79911..08a91b0 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -52,7 +52,7 @@ Node::Node(plist_type type, Node* parent) : _parent(parent)      case PLIST_BOOLEAN:          _node = plist_new_bool(0);          break; -    case PLIST_UINT: +    case PLIST_INT:          _node = plist_new_uint(0);          break;      case PLIST_REAL: @@ -134,7 +134,7 @@ Node* Node::FromPlist(plist_t node, Node* parent)          case PLIST_BOOLEAN:              ret = new Boolean(node, parent);              break; -        case PLIST_UINT: +        case PLIST_INT:              ret = new Integer(node, parent);              break;          case PLIST_REAL: diff --git a/src/Real.cpp b/src/Real.cpp index 6bdb920..02d1d9b 100644 --- a/src/Real.cpp +++ b/src/Real.cpp @@ -32,7 +32,7 @@ Real::Real(plist_t node, Node* parent) : Node(node, parent)  {  } -Real::Real(const PList::Real& d) : Node(PLIST_UINT) +Real::Real(const PList::Real& d) : Node(PLIST_INT)  {      plist_set_real_val(_node, d.GetValue());  } diff --git a/src/String.cpp b/src/String.cpp index 06b61ba..aee2358 100644 --- a/src/String.cpp +++ b/src/String.cpp @@ -32,7 +32,7 @@ String::String(plist_t node, Node* parent) : Node(node, parent)  {  } -String::String(const PList::String& s) : Node(PLIST_UINT) +String::String(const PList::String& s) : Node(PLIST_INT)  {      plist_set_string_val(_node, s.GetValue().c_str());  } diff --git a/src/bplist.c b/src/bplist.c index 851ecd6..8927de6 100644 --- a/src/bplist.c +++ b/src/bplist.c @@ -62,7 +62,7 @@ enum      BPLIST_FALSE = 0x08,      BPLIST_TRUE = 0x09,      BPLIST_FILL = 0x0F,			/* will be used for length grabbing */ -    BPLIST_UINT = 0x10, +    BPLIST_INT = 0x10,      BPLIST_REAL = 0x20,      BPLIST_DATE = 0x30,      BPLIST_DATA = 0x40, @@ -229,7 +229,7 @@ void plist_bin_deinit(void)  static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node_index); -static plist_t parse_uint_node(const char **bnode, uint8_t size) +static plist_t parse_int_node(const char **bnode, uint8_t size)  {      plist_data_t data = plist_new_plist_data(); @@ -254,7 +254,7 @@ static plist_t parse_uint_node(const char **bnode, uint8_t size)      data->intval = UINT_TO_HOST(*bnode, size);      (*bnode) += size; -    data->type = PLIST_UINT; +    data->type = PLIST_INT;      return node_create(NULL, data);  } @@ -583,8 +583,8 @@ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object)          case BPLIST_DICT:          {              uint16_t next_size = **object & BPLIST_FILL; -            if ((**object & BPLIST_MASK) != BPLIST_UINT) { -                PLIST_BIN_ERR("%s: invalid size node type for node type 0x%02x: found 0x%02x, expected 0x%02x\n", __func__, type, **object & BPLIST_MASK, BPLIST_UINT); +            if ((**object & BPLIST_MASK) != BPLIST_INT) { +                PLIST_BIN_ERR("%s: invalid size node type for node type 0x%02x: found 0x%02x, expected 0x%02x\n", __func__, type, **object & BPLIST_MASK, BPLIST_INT);                  return NULL;              }              (*object)++; @@ -641,12 +641,12 @@ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object)              return NULL;          } -    case BPLIST_UINT: +    case BPLIST_INT:          if (pobject + (uint64_t)(1 << size) > poffset_table) { -            PLIST_BIN_ERR("%s: BPLIST_UINT data bytes point outside of valid range\n", __func__); +            PLIST_BIN_ERR("%s: BPLIST_INT data bytes point outside of valid range\n", __func__);              return NULL;          } -        return parse_uint_node(object, size); +        return parse_int_node(object, size);      case BPLIST_REAL:          if (pobject + (uint64_t)(1 << size) > poffset_table) { @@ -896,7 +896,7 @@ static unsigned int plist_data_hash(const void* key)      switch (data->type)      {      case PLIST_BOOLEAN: -    case PLIST_UINT: +    case PLIST_INT:      case PLIST_REAL:      case PLIST_DATE:      case PLIST_UID: @@ -973,7 +973,7 @@ static void write_int(bytearray_t * bplist, uint64_t val)      //do not write 3bytes int node      if (size == 3)          size++; -    sz = BPLIST_UINT | Log2(size); +    sz = BPLIST_INT | Log2(size);      val = be64toh(val);      byte_array_append(bplist, &sz, 1); @@ -982,7 +982,7 @@ static void write_int(bytearray_t * bplist, uint64_t val)  static void write_uint(bytearray_t * bplist, uint64_t val)  { -    uint8_t sz = BPLIST_UINT | 4; +    uint8_t sz = BPLIST_INT | 4;      uint64_t zero = 0;      val = be64toh(val); @@ -1346,7 +1346,7 @@ PLIST_API plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * l              byte_array_append(bplist_buff, &b, 1);              break;          } -        case PLIST_UINT: +        case PLIST_INT:              if (data->length == 16) {                  write_uint(bplist_buff, data->intval);              } else { diff --git a/src/jplist.c b/src/jplist.c index f4adf2f..7817b1c 100644 --- a/src/jplist.c +++ b/src/jplist.c @@ -131,7 +131,7 @@ static int node_to_json(node_t* node, bytearray_t **outbuf, uint32_t depth, int          str_buf_append(*outbuf, "null", 4);  	break; -    case PLIST_UINT: +    case PLIST_INT:          val = (char*)malloc(64);          if (node_data->length == 16) {              val_len = snprintf(val, 64, "%"PRIu64, node_data->intval); @@ -349,7 +349,7 @@ static int node_estimate_size(node_t *node, uint64_t *size, uint32_t depth, int              *size += data->length;              *size += 2;              break; -        case PLIST_UINT: +        case PLIST_INT:              if (data->length == 16) {                  *size += num_digits_u(data->intval);              } else { @@ -501,10 +501,15 @@ static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index)          val = plist_new_node(data);      } else if (isdigit(str_val[0]) || (str_val[0] == '-' && str_val+1 < str_end && isdigit(str_val[1]))) {          char* endp = (char*)str_val; +        int is_neg = (str_val[0] == '-');          int64_t intpart = parse_decimal(str_val, str_end, &endp);          if (endp >= str_end) {              /* integer */ -            val = plist_new_uint((uint64_t)intpart); +            if (is_neg || intpart <= INT64_MAX) { +                val = plist_new_int(intpart); +            } 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)))))) {              /* floating point */              double dval = (double)intpart; @@ -513,7 +518,6 @@ static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index)              do {                  if (*endp == '.') {                      fendp++; -                    int is_neg = (str_val[0] == '-');                      double frac = 0;                      double p = 0.1;                      while (fendp < str_end && isdigit(*fendp)) { diff --git a/src/oplist.c b/src/oplist.c index 122440f..8936cce 100644 --- a/src/oplist.c +++ b/src/oplist.c @@ -146,7 +146,7 @@ static int node_to_openstep(node_t* node, bytearray_t **outbuf, uint32_t depth,      switch (node_data->type)      { -    case PLIST_UINT: +    case PLIST_INT:          val = (char*)malloc(64);          if (node_data->length == 16) {              val_len = snprintf(val, 64, "%"PRIu64, node_data->intval); @@ -393,7 +393,7 @@ static int node_estimate_size(node_t *node, uint64_t *size, uint32_t depth, int              *size += data->length;              *size += 2;              break; -        case PLIST_UINT: +        case PLIST_INT:              if (data->length == 16) {                  *size += num_digits_u(data->intval);              } else { diff --git a/src/plist.c b/src/plist.c index e696f70..5d06311 100644 --- a/src/plist.c +++ b/src/plist.c @@ -2,7 +2,7 @@   * plist.c   * Builds plist XML structures   * - * Copyright (c) 2009-2019 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2009-2023 Nikias Bassen, All Rights Reserved.   * Copyright (c) 2010-2015 Martin Szulecki, All Rights Reserved.   * Copyright (c) 2008 Zach C., All Rights Reserved.   * @@ -390,7 +390,16 @@ PLIST_API plist_t plist_new_bool(uint8_t val)  PLIST_API plist_t plist_new_uint(uint64_t val)  {      plist_data_t data = plist_new_plist_data(); -    data->type = PLIST_UINT; +    data->type = PLIST_INT; +    data->intval = val; +    data->length = (val > INT_MAX) ? sizeof(uint64_t)*2 : sizeof(uint64_t); +    return plist_new_node(data); +} + +PLIST_API plist_t plist_new_int(int64_t val) +{ +    plist_data_t data = plist_new_plist_data(); +    data->type = PLIST_INT;      data->intval = val;      data->length = sizeof(uint64_t);      return plist_new_node(data); @@ -926,7 +935,7 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu      case PLIST_BOOLEAN:          *((char *) value) = data->boolval;          break; -    case PLIST_UINT: +    case PLIST_INT:      case PLIST_UID:          *((uint64_t *) value) = data->intval;          break; @@ -1024,12 +1033,17 @@ PLIST_API void plist_get_uint_val(plist_t node, uint64_t * val)          return;      plist_type type = plist_get_node_type(node);      uint64_t length = 0; -    if (PLIST_UINT != type) +    if (PLIST_INT != type)          return;      plist_get_type_and_value(node, &type, (void *) val, &length);      assert(length == sizeof(uint64_t) || length == 16);  } +PLIST_API void plist_get_int_val(plist_t node, int64_t * val) +{ +    plist_get_uint_val(node, (uint64_t*)val); +} +  PLIST_API void plist_get_uid_val(plist_t node, uint64_t * val)  {      if (!node || !val) @@ -1116,7 +1130,7 @@ int plist_data_compare(const void *a, const void *b)      switch (val_a->type)      {      case PLIST_BOOLEAN: -    case PLIST_UINT: +    case PLIST_INT:      case PLIST_REAL:      case PLIST_DATE:      case PLIST_UID: @@ -1180,7 +1194,7 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val      case PLIST_BOOLEAN:          data->boolval = *((char *) value);          break; -    case PLIST_UINT: +    case PLIST_INT:      case PLIST_UID:          data->intval = *((uint64_t *) value);          break; @@ -1225,7 +1239,12 @@ PLIST_API void plist_set_bool_val(plist_t node, uint8_t val)  PLIST_API void plist_set_uint_val(plist_t node, uint64_t val)  { -    plist_set_element_val(node, PLIST_UINT, &val, sizeof(uint64_t)); +    plist_set_element_val(node, PLIST_INT, &val, (val > INT64_MAX) ? sizeof(uint64_t)*2 : sizeof(uint64_t)); +} + +PLIST_API void plist_set_int_val(plist_t node, int64_t val) +{ +    plist_set_element_val(node, PLIST_INT, &val, sizeof(uint64_t));  }  PLIST_API void plist_set_uid_val(plist_t node, uint64_t val) @@ -1259,9 +1278,42 @@ PLIST_API int plist_bool_val_is_true(plist_t boolnode)      return (bv == 1);  } +PLIST_API int plist_int_val_is_negative(plist_t intnode) +{ +    if (!PLIST_IS_INT(intnode)) { +        return 0; +    } +    plist_data_t data = plist_get_data(intnode); +    if (data->length == 16) { +        return 0; +    } +    if ((int64_t)data->intval < 0) { +        return 1; +    } +    return 0; +} + +PLIST_API int plist_int_val_compare(plist_t uintnode, int64_t cmpval) +{ +    if (!PLIST_IS_INT(uintnode)) { +        return -1; +    } +    int64_t uintval = 0; +    plist_get_int_val(uintnode, &uintval); +    if (uintval == cmpval) { +        return 0; +    } + +    if (uintval < cmpval) { +        return -1; +    } + +    return 1; +} +  PLIST_API int plist_uint_val_compare(plist_t uintnode, uint64_t cmpval)  { -    if (!PLIST_IS_UINT(uintnode)) { +    if (!PLIST_IS_INT(uintnode)) {          return -1;      }      uint64_t uintval = 0; diff --git a/src/xplist.c b/src/xplist.c index d8f6458..cf5d818 100644 --- a/src/xplist.c +++ b/src/xplist.c @@ -162,7 +162,7 @@ static int node_to_xml(node_t* node, bytearray_t **outbuf, uint32_t depth)      }      break; -    case PLIST_UINT: +    case PLIST_INT:          tag = XPLIST_INT;          tag_len = XPLIST_INT_LEN;          val = (char*)malloc(64); @@ -479,7 +479,7 @@ static int node_estimate_size(node_t *node, uint64_t *size, uint32_t depth)              *size += data->length;              *size += (XPLIST_KEY_LEN << 1) + 6;              break; -        case PLIST_UINT: +        case PLIST_INT:              if (data->length == 16) {                  *size += num_digits_u(data->intval);              } else { @@ -1194,7 +1194,7 @@ static int node_from_xml(parse_ctx ctx, plist_t *plist)                      data->intval = 0;                      data->length = 8;                  } -                data->type = PLIST_UINT; +                data->type = PLIST_INT;              } else if (!strcmp(tag, XPLIST_REAL)) {                  if (!is_empty) {                      text_part_t first_part = { NULL, 0, 0, NULL }; diff --git a/test/Makefile.am b/test/Makefile.am index 66543ea..5326317 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -8,6 +8,7 @@ AM_LDFLAGS =  noinst_PROGRAMS = \  	plist_cmp \  	plist_test \ +	integer_set_test \  	plist_btest \  	plist_jtest \  	plist_otest @@ -20,6 +21,9 @@ plist_cmp_LDADD = \  plist_test_SOURCES = plist_test.c  plist_test_LDADD = $(top_builddir)/src/libplist-2.0.la +integer_set_test_SOURCES = integer_set.c +integer_set_test_LDADD = $(top_builddir)/src/libplist-2.0.la +  plist_btest_SOURCES = plist_btest.c  plist_btest_LDADD = $(top_builddir)/src/libplist-2.0.la @@ -54,6 +58,7 @@ TESTS = \  	refsize.test \  	malformed_dict.test \  	uid.test \ +	integer_set.test \  	json1.test \  	json2.test \  	json3.test \ diff --git a/test/integer_set.c b/test/integer_set.c new file mode 100644 index 0000000..e25648f --- /dev/null +++ b/test/integer_set.c @@ -0,0 +1,130 @@ +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> +#include <stdlib.h> + +#include <string.h> +#include <plist/plist.h> + +void print_plist(plist_t pl) +{ +	char *xml = NULL; +	uint32_t xlen = 0; +	plist_to_xml(pl, &xml, &xlen); +	if (xml) { +		printf("%s\n", xml); +	} +	free(xml); +} + +int main(int argc, char** argv) +{ +	int err = 0; +	char *xml = NULL; +	uint32_t xlen = 0; +	plist_t iii = plist_new_int(0); + +	/* test 1 */ +	plist_set_uint_val(iii, 0x8000000000000000LL); +	plist_to_xml(iii, &xml, &xlen); +	const char* match1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +		"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +		"<plist version=\"1.0\">\n" +		"<integer>9223372036854775808</integer>\n" +		"</plist>\n"; +	if (strcmp(xml, match1) != 0) { +		printf("ERROR: plist_set_uint_val with 0x8000000000000000LL failed\n"); +		err++; +	} else { +		printf("SUCCESS: plist_set_uint_val with 0x8000000000000000LL\n"); +	} +	free(xml); +	xml = NULL; + +	/* test 2 */ +	plist_set_int_val(iii, 0x8000000000000000LL); +	plist_to_xml(iii, &xml, &xlen); +	const char* match2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +		"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +		"<plist version=\"1.0\">\n" +		"<integer>-9223372036854775808</integer>\n" +		"</plist>\n"; +	if (strcmp(xml, match2) != 0) { +		printf("ERROR: plist_set_int_val with 0x8000000000000000LL failed\n"); +		err++; +	} else { +		printf("SUCCESS: plist_set_int_val with 0x8000000000000000LL\n"); +	} +	free(xml); +	xml = NULL; + +	/* test 3 */ +	plist_set_uint_val(iii, (uint64_t)-1LL); +	plist_to_xml(iii, &xml, &xlen); +	const char* match3 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +		"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +		"<plist version=\"1.0\">\n" +		"<integer>18446744073709551615</integer>\n" +		"</plist>\n"; +	if (strcmp(xml, match3) != 0) { +		printf("ERROR: plist_set_uint_val with (uint64_t)-1LL failed\n"); +		err++; +	} else { +		printf("SUCCESS: plist_set_uint_val with (uint64_t)-1LL\n"); +	} +	free(xml); +	xml = NULL; + +	/* test 4 */ +	plist_set_int_val(iii, -1LL); +	plist_to_xml(iii, &xml, &xlen); +	const char* match4 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +		"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +		"<plist version=\"1.0\">\n" +		"<integer>-1</integer>\n" +		"</plist>\n"; +	if (strcmp(xml, match4) != 0) { +		printf("ERROR: plist_set_int_val with -1LL failed\n"); +		err++; +	} else { +		printf("SUCCESS: plist_set_int_val with -1LL\n"); +	} +	free(xml); +	xml = NULL; + +	/* test 5 */ +	plist_set_uint_val(iii, 0x8000000000000001LL); +	plist_to_xml(iii, &xml, &xlen); +	const char* match5 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +		"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +		"<plist version=\"1.0\">\n" +		"<integer>9223372036854775809</integer>\n" +		"</plist>\n"; +	if (strcmp(xml, match5) != 0) { +		printf("ERROR: plist_set_uint_val with 0x8000000000000001LL failed\n"); +		err++; +	} else { +		printf("SUCCESS: plist_set_uint_val with 0x8000000000000001LL\n"); +	} +	free(xml); +	xml = NULL; + +	/* test 6 */ +	plist_set_uint_val(iii, 18446744073709551615uLL); +	plist_to_xml(iii, &xml, &xlen); +	const char* match6 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +		"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +		"<plist version=\"1.0\">\n" +		"<integer>18446744073709551615</integer>\n" +		"</plist>\n"; +	if (strcmp(xml, match6) != 0) { +		printf("ERROR: plist_set_uint_val with 0x8000000000000001LL failed\n"); +		err++; +	} else { +		printf("SUCCESS: plist_set_uint_val with 0x8000000000000001LL\n"); +	} +	free(xml); +	xml = NULL; + +	return (err > 0) ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/test/integer_set.test b/test/integer_set.test new file mode 100755 index 0000000..b917663 --- /dev/null +++ b/test/integer_set.test @@ -0,0 +1,5 @@ +## -*- sh -*- + +set -e + +$top_builddir/test/integer_set_test | 
