summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2025-05-13 18:34:32 +0200
committerGravatar Nikias Bassen2025-05-13 18:34:32 +0200
commitcb76e4da84c61609c13e84c922f14a27b8348a36 (patch)
tree6f0057efd11780ec38da6e8b686726f51bd10f30
parentd7fe479707af57aeedf7e41c08e7fb698cd2e2a3 (diff)
downloadlibplist-cb76e4da84c61609c13e84c922f14a27b8348a36.tar.gz
libplist-cb76e4da84c61609c13e84c922f14a27b8348a36.tar.bz2
Add plist_new_unix_date, plist_get_unix_date_val, plist_set_unix_date_val functions
These functions work with int64_t values representing a UNIX timestamp instead of using the 'MAC epoch'. They should be used instead of plist_new_date, plist_get_date_val, and plist_set_date_val, which are now marked deprecated and might be removed in a future version of libplist.
-rw-r--r--cython/plist.pyx48
-rw-r--r--cython/plist_util.c31
-rw-r--r--cython/plist_util.h4
-rw-r--r--include/plist/Date.h6
-rw-r--r--include/plist/plist.h84
-rw-r--r--src/Date.cpp22
-rw-r--r--src/Node.cpp2
-rw-r--r--src/plist.c49
8 files changed, 174 insertions, 72 deletions
diff --git a/cython/plist.pyx b/cython/plist.pyx
index 4d1f8aa..29c1181 100644
--- a/cython/plist.pyx
+++ b/cython/plist.pyx
@@ -33,9 +33,9 @@ cdef extern from *:
33 void plist_get_real_val(plist_t node, double *val) 33 void plist_get_real_val(plist_t node, double *val)
34 void plist_set_real_val(plist_t node, double val) 34 void plist_set_real_val(plist_t node, double val)
35 35
36 plist_t plist_new_date(int32_t sec, int32_t usec) 36 plist_t plist_new_unix_date(int64_t sec)
37 void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec) 37 void plist_get_unix_date_val(plist_t node, int64_t *sec)
38 void plist_set_date_val(plist_t node, int32_t sec, int32_t usec) 38 void plist_set_unix_date_val(plist_t node, int64_t sec)
39 39
40 void plist_get_key_val(plist_t node, char **val) 40 void plist_get_key_val(plist_t node, char **val)
41 void plist_set_key_val(plist_t node, char *val) 41 void plist_set_key_val(plist_t node, char *val)
@@ -488,23 +488,21 @@ cdef String String_factory(plist_t c_node, bint managed=True):
488 instance._c_node = c_node 488 instance._c_node = c_node
489 return instance 489 return instance
490 490
491MAC_EPOCH = 978307200
492
493cdef extern from "plist_util.h": 491cdef extern from "plist_util.h":
494 void datetime_to_ints(object obj, int32_t* sec, int32_t* usec) 492 int64_t datetime_to_timestamp(object obj)
495 object ints_to_datetime(int32_t sec, int32_t usec) 493 object timestamp_to_datetime(int64_t sec)
496 int check_datetime(object obj) 494 int check_datetime(object obj)
497 495
498cdef plist_t create_date_plist(value=None): 496cdef plist_t create_date_plist(value=None):
499 cdef plist_t node = NULL 497 cdef plist_t node = NULL
500 cdef int32_t secs
501 cdef int32_t usecs
502 if value is None: 498 if value is None:
503 node = plist_new_date(0, 0) 499 node = plist_new_unix_date(0)
500 elif isinstance(value, int):
501 node = plist_new_unix_date(value)
502 elif isinstance(value, float):
503 node = plist_new_unix_date(int(value))
504 elif check_datetime(value): 504 elif check_datetime(value):
505 datetime_to_ints(value, &secs, &usecs) 505 node = plist_new_unix_date(datetime_to_timestamp(value))
506 secs -= MAC_EPOCH
507 node = plist_new_date(secs, usecs)
508 return node 506 return node
509 507
510cdef class Date(Node): 508cdef class Date(Node):
@@ -531,19 +529,21 @@ cdef class Date(Node):
531 return d >= other 529 return d >= other
532 530
533 cpdef object get_value(self): 531 cpdef object get_value(self):
534 cdef int32_t secs = 0 532 cdef int64_t secs = 0
535 cdef int32_t usecs = 0 533 plist_get_unix_date_val(self._c_node, &secs)
536 plist_get_date_val(self._c_node, &secs, &usecs) 534 return timestamp_to_datetime(secs)
537 secs += MAC_EPOCH
538 return ints_to_datetime(secs, usecs)
539 535
540 cpdef set_value(self, object value): 536 cpdef set_value(self, object value):
541 cdef int32_t secs 537 cdef int64_t secs = 0
542 cdef int32_t usecs 538 if isinstance(value, int):
543 if not check_datetime(value): 539 secs = value
544 raise ValueError("Expected a datetime") 540 elif isinstance(value, float):
545 datetime_to_ints(value, &secs, &usecs) 541 secs = int(value)
546 plist_set_date_val(self._c_node, secs, usecs) 542 elif check_datetime(value):
543 secs = datetime_to_timestamp(value)
544 else:
545 raise ValueError("Expected int or datetime")
546 plist_set_unix_date_val(self._c_node, secs)
547 547
548cdef Date Date_factory(plist_t c_node, bint managed=True): 548cdef Date Date_factory(plist_t c_node, bint managed=True):
549 cdef Date instance = Date.__new__(Date) 549 cdef Date instance = Date.__new__(Date)
diff --git a/cython/plist_util.c b/cython/plist_util.c
index 4f922e5..27084fa 100644
--- a/cython/plist_util.c
+++ b/cython/plist_util.c
@@ -3,13 +3,11 @@
3#include <time.h> 3#include <time.h>
4#include <datetime.h> 4#include <datetime.h>
5 5
6void datetime_to_ints(PyObject* obj, int32_t* sec, int32_t* usec) { 6int64_t datetime_to_timestamp(PyObject* obj) {
7 PyDateTime_IMPORT; 7 PyDateTime_IMPORT;
8 if (!PyDateTime_Check(obj)) { 8 if (!PyDateTime_Check(obj)) {
9 PyErr_SetString(PyExc_ValueError,"Expected a datetime"); 9 PyErr_SetString(PyExc_ValueError,"Expected a datetime");
10 sec = NULL; 10 return 0;
11 usec = NULL;
12 return;
13 } 11 }
14 struct tm t; 12 struct tm t;
15 memset(&t, 0, sizeof(t)); 13 memset(&t, 0, sizeof(t));
@@ -19,22 +17,21 @@ void datetime_to_ints(PyObject* obj, int32_t* sec, int32_t* usec) {
19 t.tm_mday = PyDateTime_GET_DAY(obj); 17 t.tm_mday = PyDateTime_GET_DAY(obj);
20 t.tm_mon = PyDateTime_GET_MONTH(obj)-1; 18 t.tm_mon = PyDateTime_GET_MONTH(obj)-1;
21 t.tm_year = PyDateTime_GET_YEAR(obj)-1900; 19 t.tm_year = PyDateTime_GET_YEAR(obj)-1900;
22 *sec = (int32_t)mktime(&t); 20 return mktime(&t);
23 *usec = PyDateTime_DATE_GET_MICROSECOND(obj);
24} 21}
25PyObject* ints_to_datetime(int32_t sec, int32_t usec) { 22PyObject* timestamp_to_datetime(int64_t sec) {
26 time_t sec_tt = sec; 23 time_t sec_tt = sec;
27 struct tm* t = gmtime(&sec_tt); 24 struct tm* t = gmtime(&sec_tt);
28 if(t){ 25 if(t){
29 PyDateTime_IMPORT; 26 PyDateTime_IMPORT;
30 return PyDateTime_FromDateAndTime(t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, usec); 27 return PyDateTime_FromDateAndTime(t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, 0);
31 } 28 }
32 return NULL; 29 return NULL;
33} 30}
34int check_datetime(PyObject* ob) { 31int check_datetime(PyObject* ob) {
35 if(ob){ 32 if(ob){
36 PyDateTime_IMPORT; 33 PyDateTime_IMPORT;
37 return PyDateTime_Check(ob); 34 return PyDateTime_Check(ob);
38 } 35 }
39 return 0; 36 return 0;
40} 37}
diff --git a/cython/plist_util.h b/cython/plist_util.h
index fbf56b6..e0a84b5 100644
--- a/cython/plist_util.h
+++ b/cython/plist_util.h
@@ -1,5 +1,5 @@
1#include <Python.h> 1#include <Python.h>
2 2
3void datetime_to_ints(PyObject* obj, int32_t* sec, int32_t* usec); 3int64_t datetime_to_timestamp(PyObject* obj);
4PyObject* ints_to_datetime(int32_t sec, int32_t usec); 4PyObject* timestamp_to_datetime(int64_t sec);
5int check_datetime(PyObject* obj); 5int check_datetime(PyObject* obj);
diff --git a/include/plist/Date.h b/include/plist/Date.h
index 5113cf3..7026699 100644
--- a/include/plist/Date.h
+++ b/include/plist/Date.h
@@ -40,13 +40,13 @@ public :
40 Date(plist_t node, Node* parent = NULL); 40 Date(plist_t node, Node* parent = NULL);
41 Date(const Date& d); 41 Date(const Date& d);
42 Date& operator=(const Date& d); 42 Date& operator=(const Date& d);
43 Date(timeval t); 43 Date(int64_t t);
44 virtual ~Date(); 44 virtual ~Date();
45 45
46 Node* Clone() const; 46 Node* Clone() const;
47 47
48 void SetValue(timeval t); 48 void SetValue(int64_t t);
49 timeval GetValue() const; 49 int64_t GetValue() const;
50}; 50};
51 51
52}; 52};
diff --git a/include/plist/plist.h b/include/plist/plist.h
index aff81e9..41af8ce 100644
--- a/include/plist/plist.h
+++ b/include/plist/plist.h
@@ -263,12 +263,11 @@ extern "C"
263 /** 263 /**
264 * Create a new plist_t type #PLIST_DATE 264 * Create a new plist_t type #PLIST_DATE
265 * 265 *
266 * @param sec the number of seconds since 01/01/2001 266 * @param sec The number of seconds since 01/01/1970 (UNIX timestamp)
267 * @param usec the number of microseconds
268 * @return the created item 267 * @return the created item
269 * @sa #plist_type 268 * @sa #plist_type
270 */ 269 */
271 PLIST_API plist_t plist_new_date(int32_t sec, int32_t usec); 270 PLIST_API plist_t plist_new_unix_date(int64_t sec);
272 271
273 /** 272 /**
274 * Create a new plist_t type #PLIST_UID 273 * Create a new plist_t type #PLIST_UID
@@ -775,10 +774,9 @@ extern "C"
775 * This function does nothing if node is not of type #PLIST_DATE 774 * This function does nothing if node is not of type #PLIST_DATE
776 * 775 *
777 * @param node the node 776 * @param node the node
778 * @param sec a pointer to an int32_t variable. Represents the number of seconds since 01/01/2001. 777 * @param sec a pointer to an int64_t variable. Represents the number of seconds since 01/01/1970 (UNIX timestamp).
779 * @param usec a pointer to an int32_t variable. Represents the number of microseconds
780 */ 778 */
781 PLIST_API void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec); 779 PLIST_API void plist_get_unix_date_val(plist_t node, int64_t *sec);
782 780
783 /** 781 /**
784 * Get the value of a #PLIST_UID node. 782 * Get the value of a #PLIST_UID node.
@@ -867,10 +865,9 @@ extern "C"
867 * Forces type of node to #PLIST_DATE 865 * Forces type of node to #PLIST_DATE
868 * 866 *
869 * @param node the node 867 * @param node the node
870 * @param sec the number of seconds since 01/01/2001 868 * @param sec the number of seconds since 01/01/1970 (UNIX timestamp)
871 * @param usec the number of microseconds
872 */ 869 */
873 PLIST_API void plist_set_date_val(plist_t node, int32_t sec, int32_t usec); 870 PLIST_API void plist_set_unix_date_val(plist_t node, int64_t sec);
874 871
875 /** 872 /**
876 * Set the value of a node. 873 * Set the value of a node.
@@ -1213,16 +1210,15 @@ extern "C"
1213 1210
1214 /** 1211 /**
1215 * Helper function to compare the value of a PLIST_DATE node against 1212 * Helper function to compare the value of a PLIST_DATE node against
1216 * a given set of seconds and fraction of a second since epoch. 1213 * a given number of seconds since epoch (UNIX timestamp).
1217 * 1214 *
1218 * @param datenode node of type PLIST_DATE 1215 * @param datenode node of type PLIST_DATE
1219 * @param cmpsec number of seconds since epoch to compare against 1216 * @param cmpval Number of seconds to compare against (UNIX timestamp)
1220 * @param cmpusec fraction of a second in microseconds to compare against
1221 * @return 0 if the node's date is equal to the supplied values, 1217 * @return 0 if the node's date is equal to the supplied values,
1222 * 1 if the node's date is greater than the supplied values, 1218 * 1 if the node's date is greater than the supplied values,
1223 * or -1 if the node's date is less than the supplied values. 1219 * or -1 if the node's date is less than the supplied values.
1224 */ 1220 */
1225 PLIST_API int plist_date_val_compare(plist_t datenode, int32_t cmpsec, int32_t cmpusec); 1221 PLIST_API int plist_unix_date_val_compare(plist_t datenode, int64_t cmpval);
1226 1222
1227 /** 1223 /**
1228 * Helper function to compare the value of a PLIST_STRING node against 1224 * Helper function to compare the value of a PLIST_STRING node against
@@ -1382,6 +1378,68 @@ extern "C"
1382 */ 1378 */
1383 PLIST_API const char* libplist_version(); 1379 PLIST_API const char* libplist_version();
1384 1380
1381
1382 /********************************************
1383 * *
1384 * Deprecated API *
1385 * *
1386 ********************************************/
1387
1388 /**
1389 * Create a new plist_t type #PLIST_DATE
1390 *
1391 * @deprecated Deprecated. Use plist_new_unix_date instead.
1392 *
1393 * @param sec the number of seconds since 01/01/2001
1394 * @param usec the number of microseconds
1395 * @return the created item
1396 * @sa #plist_type
1397 */
1398 PLIST_WARN_DEPRECATED("use plist_new_unix_date instead")
1399 PLIST_API plist_t plist_new_date(int32_t sec, int32_t usec);
1400
1401 /**
1402 * Get the value of a #PLIST_DATE node.
1403 * This function does nothing if node is not of type #PLIST_DATE
1404 *
1405 * @deprecated Deprecated. Use plist_get_unix_date_val instead.
1406 *
1407 * @param node the node
1408 * @param sec a pointer to an int32_t variable. Represents the number of seconds since 01/01/2001.
1409 * @param usec a pointer to an int32_t variable. Represents the number of microseconds
1410 */
1411 PLIST_WARN_DEPRECATED("use plist_get_unix_date_val instead")
1412 PLIST_API void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec);
1413
1414 /**
1415 * Set the value of a node.
1416 * Forces type of node to #PLIST_DATE
1417 *
1418 * @deprecated Deprecated. Use plist_set_unix_date_val instead.
1419 *
1420 * @param node the node
1421 * @param sec the number of seconds since 01/01/2001
1422 * @param usec the number of microseconds
1423 */
1424 PLIST_WARN_DEPRECATED("use plist_set_unix_date_val instead")
1425 PLIST_API void plist_set_date_val(plist_t node, int32_t sec, int32_t usec);
1426
1427 /**
1428 * Helper function to compare the value of a PLIST_DATE node against
1429 * a given set of seconds and fraction of a second since epoch.
1430 *
1431 * @deprecated Deprecated. Use plist_unix_date_val_compare instead.
1432 *
1433 * @param datenode node of type PLIST_DATE
1434 * @param cmpsec number of seconds since epoch to compare against
1435 * @param cmpusec fraction of a second in microseconds to compare against
1436 * @return 0 if the node's date is equal to the supplied values,
1437 * 1 if the node's date is greater than the supplied values,
1438 * or -1 if the node's date is less than the supplied values.
1439 */
1440 PLIST_WARN_DEPRECATED("use plist_unix_date_val_compare instead")
1441 PLIST_API int plist_date_val_compare(plist_t datenode, int32_t cmpsec, int32_t cmpusec);
1442
1385 /*@}*/ 1443 /*@}*/
1386 1444
1387#ifdef __cplusplus 1445#ifdef __cplusplus
diff --git a/src/Date.cpp b/src/Date.cpp
index 8b8e650..cbfa123 100644
--- a/src/Date.cpp
+++ b/src/Date.cpp
@@ -34,8 +34,8 @@ Date::Date(plist_t node, Node* parent) : Node(node, parent)
34 34
35Date::Date(const PList::Date& d) : Node(PLIST_DATE) 35Date::Date(const PList::Date& d) : Node(PLIST_DATE)
36{ 36{
37 timeval t = d.GetValue(); 37 int64_t t = d.GetValue();
38 plist_set_date_val(_node, t.tv_sec, t.tv_usec); 38 plist_set_unix_date_val(_node, t);
39} 39}
40 40
41Date& Date::operator=(const PList::Date& d) 41Date& Date::operator=(const PList::Date& d)
@@ -45,9 +45,9 @@ Date& Date::operator=(const PList::Date& d)
45 return *this; 45 return *this;
46} 46}
47 47
48Date::Date(timeval t) : Node(PLIST_DATE) 48Date::Date(int64_t t) : Node(PLIST_DATE)
49{ 49{
50 plist_set_date_val(_node, t.tv_sec, t.tv_usec); 50 plist_set_unix_date_val(_node, t);
51} 51}
52 52
53Date::~Date() 53Date::~Date()
@@ -59,18 +59,16 @@ Node* Date::Clone() const
59 return new Date(*this); 59 return new Date(*this);
60} 60}
61 61
62void Date::SetValue(timeval t) 62void Date::SetValue(int64_t t)
63{ 63{
64 plist_set_date_val(_node, t.tv_sec, t.tv_usec); 64 plist_set_unix_date_val(_node, t);
65} 65}
66 66
67timeval Date::GetValue() const 67int64_t Date::GetValue() const
68{ 68{
69 int32_t tv_sec = 0; 69 int64_t sec = 0;
70 int32_t tv_usec = 0; 70 plist_get_unix_date_val(_node, &sec);
71 plist_get_date_val(_node, &tv_sec, &tv_usec); 71 return sec;
72 timeval t = {tv_sec, tv_usec};
73 return t;
74} 72}
75 73
76} // namespace PList 74} // namespace PList
diff --git a/src/Node.cpp b/src/Node.cpp
index 0bd428a..1043b31 100644
--- a/src/Node.cpp
+++ b/src/Node.cpp
@@ -73,7 +73,7 @@ Node::Node(plist_type type, Node* parent) : _parent(parent)
73 _node = plist_new_data(NULL,0); 73 _node = plist_new_data(NULL,0);
74 break; 74 break;
75 case PLIST_DATE: 75 case PLIST_DATE:
76 _node = plist_new_date(0,0); 76 _node = plist_new_unix_date(0);
77 break; 77 break;
78 case PLIST_ARRAY: 78 case PLIST_ARRAY:
79 _node = plist_new_array(); 79 _node = plist_new_array();
diff --git a/src/plist.c b/src/plist.c
index 3f86105..4fc2f00 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -46,6 +46,8 @@
46#include <hashtable.h> 46#include <hashtable.h>
47#include <ptrarray.h> 47#include <ptrarray.h>
48 48
49#define MAC_EPOCH 978307200
50
49#ifdef _MSC_VER 51#ifdef _MSC_VER
50typedef SSIZE_T ssize_t; 52typedef SSIZE_T ssize_t;
51#endif 53#endif
@@ -528,6 +530,15 @@ plist_t plist_new_date(int32_t sec, int32_t usec)
528 return plist_new_node(data); 530 return plist_new_node(data);
529} 531}
530 532
533plist_t plist_new_unix_date(int64_t sec)
534{
535 plist_data_t data = plist_new_plist_data();
536 data->type = PLIST_DATE;
537 data->realval = (double)sec - MAC_EPOCH;
538 data->length = sizeof(double);
539 return plist_new_node(data);
540}
541
531plist_t plist_new_null(void) 542plist_t plist_new_null(void)
532{ 543{
533 plist_data_t data = plist_new_plist_data(); 544 plist_data_t data = plist_new_plist_data();
@@ -1392,6 +1403,20 @@ void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec)
1392 } 1403 }
1393} 1404}
1394 1405
1406void plist_get_unix_date_val(plist_t node, int64_t *sec)
1407{
1408 if (!node || !sec)
1409 return;
1410 plist_type type = plist_get_node_type(node);
1411 uint64_t length = 0;
1412 double val = 0;
1413 if (PLIST_DATE != type)
1414 return;
1415 plist_get_type_and_value(node, &type, (void *) &val, &length);
1416 assert(length == sizeof(double));
1417 *sec = (int64_t)val + MAC_EPOCH;
1418}
1419
1395int plist_data_compare(const void *a, const void *b) 1420int plist_data_compare(const void *a, const void *b)
1396{ 1421{
1397 plist_data_t val_a = NULL; 1422 plist_data_t val_a = NULL;
@@ -1551,6 +1576,12 @@ void plist_set_date_val(plist_t node, int32_t sec, int32_t usec)
1551 plist_set_element_val(node, PLIST_DATE, &val, sizeof(double)); 1576 plist_set_element_val(node, PLIST_DATE, &val, sizeof(double));
1552} 1577}
1553 1578
1579void plist_set_unix_date_val(plist_t node, int64_t sec)
1580{
1581 double val = (double)(sec - MAC_EPOCH);
1582 plist_set_element_val(node, PLIST_DATE, &val, sizeof(double));
1583}
1584
1554int plist_bool_val_is_true(plist_t boolnode) 1585int plist_bool_val_is_true(plist_t boolnode)
1555{ 1586{
1556 if (!PLIST_IS_BOOLEAN(boolnode)) { 1587 if (!PLIST_IS_BOOLEAN(boolnode)) {
@@ -1686,6 +1717,24 @@ int plist_date_val_compare(plist_t datenode, int32_t cmpsec, int32_t cmpusec)
1686 return 1; 1717 return 1;
1687} 1718}
1688 1719
1720int plist_unix_date_val_compare(plist_t datenode, int64_t cmpval)
1721{
1722 if (!PLIST_IS_DATE(datenode)) {
1723 return -1;
1724 }
1725 int64_t dateval = 0;
1726 plist_get_unix_date_val(datenode, &dateval);
1727 if (dateval == cmpval) {
1728 return 0;
1729 }
1730
1731 if (dateval < cmpval) {
1732 return -1;
1733 }
1734
1735 return 1;
1736}
1737
1689int plist_string_val_compare(plist_t strnode, const char* cmpval) 1738int plist_string_val_compare(plist_t strnode, const char* cmpval)
1690{ 1739{
1691 if (!PLIST_IS_STRING(strnode)) { 1740 if (!PLIST_IS_STRING(strnode)) {