summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2016-09-19 01:49:05 +0200
committerGravatar Nikias Bassen2016-09-19 01:49:05 +0200
commit912cb45928f03355ca162a2f1286ca49eb58155c (patch)
tree2069bf08b56c04b3e194a3ac7515e897e2e12880 /src
parenta348ba9aa866e7e97fd7bf819af38c8c9107ebb5 (diff)
downloadlibplist-912cb45928f03355ca162a2f1286ca49eb58155c.tar.gz
libplist-912cb45928f03355ca162a2f1286ca49eb58155c.tar.bz2
Change internal storage of PLIST_DATE values from struct timeval to double
This removes the timeval union member from the plist_data_t structure. Since struct timeval is 2x64bit on 64bit platforms this member unnecessarily grew the union size to 16 bytes while a size of 8 bytes is sufficient. Also, on 32bit platforms struct timeval is only 2x32bit of size, limiting the range of possible time values. In addition the binary property list format also stores PLIST_DATE nodes as double.
Diffstat (limited to 'src')
-rw-r--r--src/bplist.c11
-rw-r--r--src/plist.c33
-rw-r--r--src/plist.h1
-rw-r--r--src/xplist.c7
4 files changed, 16 insertions, 36 deletions
diff --git a/src/bplist.c b/src/bplist.c
index bb73b31..fbe1b63 100644
--- a/src/bplist.c
+++ b/src/bplist.c
@@ -284,11 +284,7 @@ static plist_t parse_date_node(const char **bnode, uint8_t size)
284 plist_t node = parse_real_node(bnode, size); 284 plist_t node = parse_real_node(bnode, size);
285 plist_data_t data = plist_get_data(node); 285 plist_data_t data = plist_get_data(node);
286 286
287 double time_real = data->realval;
288 data->timeval.tv_sec = (long) time_real;
289 data->timeval.tv_usec = (time_real - (long) time_real) * 1000000;
290 data->type = PLIST_DATE; 287 data->type = PLIST_DATE;
291 data->length = sizeof(struct timeval);
292 288
293 return node; 289 return node;
294} 290}
@@ -728,6 +724,7 @@ static unsigned int plist_data_hash(const void* key)
728 case PLIST_BOOLEAN: 724 case PLIST_BOOLEAN:
729 case PLIST_UINT: 725 case PLIST_UINT:
730 case PLIST_REAL: 726 case PLIST_REAL:
727 case PLIST_DATE:
731 case PLIST_UID: 728 case PLIST_UID:
732 buff = (char *) &data->intval; //works also for real as we use an union 729 buff = (char *) &data->intval; //works also for real as we use an union
733 size = 8; 730 size = 8;
@@ -744,10 +741,6 @@ static unsigned int plist_data_hash(const void* key)
744 buff = (char *) &key; 741 buff = (char *) &key;
745 size = sizeof(const void*); 742 size = sizeof(const void*);
746 break; 743 break;
747 case PLIST_DATE:
748 buff = (char *) &(data->timeval);
749 size = data->length;
750 break;
751 default: 744 default:
752 break; 745 break;
753 } 746 }
@@ -1183,7 +1176,7 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1183 write_dict(bplist_buff, ptr_array_index(objects, i), ref_table, dict_param_size); 1176 write_dict(bplist_buff, ptr_array_index(objects, i), ref_table, dict_param_size);
1184 break; 1177 break;
1185 case PLIST_DATE: 1178 case PLIST_DATE:
1186 write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / 1000000); 1179 write_date(bplist_buff, data->realval);
1187 break; 1180 break;
1188 case PLIST_UID: 1181 case PLIST_UID:
1189 write_uid(bplist_buff, data->intval); 1182 write_uid(bplist_buff, data->intval);
diff --git a/src/plist.c b/src/plist.c
index ef1d7a2..af64ed1 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -27,6 +27,7 @@
27#include "plist.h" 27#include "plist.h"
28#include <stdlib.h> 28#include <stdlib.h>
29#include <stdio.h> 29#include <stdio.h>
30#include <math.h>
30 31
31#include <node.h> 32#include <node.h>
32#include <node_iterator.h> 33#include <node_iterator.h>
@@ -214,9 +215,8 @@ PLIST_API plist_t plist_new_date(int32_t sec, int32_t usec)
214{ 215{
215 plist_data_t data = plist_new_plist_data(); 216 plist_data_t data = plist_new_plist_data();
216 data->type = PLIST_DATE; 217 data->type = PLIST_DATE;
217 data->timeval.tv_sec = sec; 218 data->realval = (double)sec + (double)usec / 1000000;
218 data->timeval.tv_usec = usec; 219 data->length = sizeof(double);
219 data->length = sizeof(struct timeval);
220 return plist_new_node(data); 220 return plist_new_node(data);
221} 221}
222 222
@@ -567,6 +567,7 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu
567 *((uint64_t *) value) = data->intval; 567 *((uint64_t *) value) = data->intval;
568 break; 568 break;
569 case PLIST_REAL: 569 case PLIST_REAL:
570 case PLIST_DATE:
570 *((double *) value) = data->realval; 571 *((double *) value) = data->realval;
571 break; 572 break;
572 case PLIST_KEY: 573 case PLIST_KEY:
@@ -577,11 +578,6 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu
577 *((uint8_t **) value) = (uint8_t *) malloc(*length * sizeof(uint8_t)); 578 *((uint8_t **) value) = (uint8_t *) malloc(*length * sizeof(uint8_t));
578 memcpy(*((uint8_t **) value), data->buff, *length * sizeof(uint8_t)); 579 memcpy(*((uint8_t **) value), data->buff, *length * sizeof(uint8_t));
579 break; 580 break;
580 case PLIST_DATE:
581 //exception : here we use memory on the stack since it is just a temporary buffer
582 ((struct timeval*) value)->tv_sec = data->timeval.tv_sec;
583 ((struct timeval*) value)->tv_usec = data->timeval.tv_usec;
584 break;
585 case PLIST_ARRAY: 581 case PLIST_ARRAY:
586 case PLIST_DICT: 582 case PLIST_DICT:
587 default: 583 default:
@@ -670,12 +666,12 @@ PLIST_API void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec)
670{ 666{
671 plist_type type = plist_get_node_type(node); 667 plist_type type = plist_get_node_type(node);
672 uint64_t length = 0; 668 uint64_t length = 0;
673 struct timeval val = { 0, 0 }; 669 double val = 0;
674 if (PLIST_DATE == type) 670 if (PLIST_DATE == type)
675 plist_get_type_and_value(node, &type, (void *) &val, &length); 671 plist_get_type_and_value(node, &type, (void *) &val, &length);
676 assert(length == sizeof(struct timeval)); 672 assert(length == sizeof(double));
677 *sec = val.tv_sec; 673 *sec = (int32_t)val;
678 *usec = val.tv_usec; 674 *usec = (int32_t)fabs((val - (int64_t)val) * 1000000);
679} 675}
680 676
681int plist_data_compare(const void *a, const void *b) 677int plist_data_compare(const void *a, const void *b)
@@ -700,6 +696,7 @@ int plist_data_compare(const void *a, const void *b)
700 case PLIST_BOOLEAN: 696 case PLIST_BOOLEAN:
701 case PLIST_UINT: 697 case PLIST_UINT:
702 case PLIST_REAL: 698 case PLIST_REAL:
699 case PLIST_DATE:
703 case PLIST_UID: 700 case PLIST_UID:
704 if (val_a->length != val_b->length) 701 if (val_a->length != val_b->length)
705 return FALSE; 702 return FALSE;
@@ -730,11 +727,6 @@ int plist_data_compare(const void *a, const void *b)
730 else 727 else
731 return FALSE; 728 return FALSE;
732 break; 729 break;
733 case PLIST_DATE:
734 if (!memcmp(&(val_a->timeval), &(val_b->timeval), sizeof(struct timeval)))
735 return TRUE;
736 else
737 return FALSE;
738 default: 730 default:
739 break; 731 break;
740 } 732 }
@@ -782,6 +774,7 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val
782 data->intval = *((uint64_t *) value); 774 data->intval = *((uint64_t *) value);
783 break; 775 break;
784 case PLIST_REAL: 776 case PLIST_REAL:
777 case PLIST_DATE:
785 data->realval = *((double *) value); 778 data->realval = *((double *) value);
786 break; 779 break;
787 case PLIST_KEY: 780 case PLIST_KEY:
@@ -792,10 +785,6 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val
792 data->buff = (uint8_t *) malloc(length); 785 data->buff = (uint8_t *) malloc(length);
793 memcpy(data->buff, value, length); 786 memcpy(data->buff, value, length);
794 break; 787 break;
795 case PLIST_DATE:
796 data->timeval.tv_sec = ((struct timeval*) value)->tv_sec;
797 data->timeval.tv_usec = ((struct timeval*) value)->tv_usec;
798 break;
799 case PLIST_ARRAY: 788 case PLIST_ARRAY:
800 case PLIST_DICT: 789 case PLIST_DICT:
801 default: 790 default:
@@ -840,7 +829,7 @@ PLIST_API void plist_set_data_val(plist_t node, const char *val, uint64_t length
840 829
841PLIST_API void plist_set_date_val(plist_t node, int32_t sec, int32_t usec) 830PLIST_API void plist_set_date_val(plist_t node, int32_t sec, int32_t usec)
842{ 831{
843 struct timeval val = { sec, usec }; 832 double val = (double)sec + (double)usec / 1000000;
844 plist_set_element_val(node, PLIST_DATE, &val, sizeof(struct timeval)); 833 plist_set_element_val(node, PLIST_DATE, &val, sizeof(struct timeval));
845} 834}
846 835
diff --git a/src/plist.h b/src/plist.h
index ad65dea..da8f9ca 100644
--- a/src/plist.h
+++ b/src/plist.h
@@ -56,7 +56,6 @@ struct plist_data_s
56 double realval; 56 double realval;
57 char *strval; 57 char *strval;
58 uint8_t *buff; 58 uint8_t *buff;
59 struct timeval timeval;
60 }; 59 };
61 uint64_t length; 60 uint64_t length;
62 plist_type type; 61 plist_type type;
diff --git a/src/xplist.c b/src/xplist.c
index 8fe3604..e55a094 100644
--- a/src/xplist.c
+++ b/src/xplist.c
@@ -258,7 +258,7 @@ static void node_to_xml(node_t* node, void *xml_struct)
258 case PLIST_DATE: 258 case PLIST_DATE:
259 tag = XPLIST_DATE; 259 tag = XPLIST_DATE;
260 { 260 {
261 time_t timev = (time_t)node_data->timeval.tv_sec + MAC_EPOCH; 261 time_t timev = (time_t)node_data->realval + MAC_EPOCH;
262 struct tm *btime = gmtime(&timev); 262 struct tm *btime = gmtime(&timev);
263 if (btime) { 263 if (btime) {
264 val = (char*)malloc(24); 264 val = (char*)malloc(24);
@@ -462,10 +462,9 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node)
462 tm_utc = gmtime(&timev); 462 tm_utc = gmtime(&timev);
463 timev -= (mktime(tm_utc) - timev); 463 timev -= (mktime(tm_utc) - timev);
464 } 464 }
465 data->timeval.tv_sec = (long)(timev - MAC_EPOCH); 465 data->realval = (double)(timev - MAC_EPOCH);
466 data->timeval.tv_usec = 0;
467 data->type = PLIST_DATE; 466 data->type = PLIST_DATE;
468 data->length = sizeof(struct timeval); 467 data->length = sizeof(double);
469 xmlFree(strval); 468 xmlFree(strval);
470 continue; 469 continue;
471 } 470 }