diff options
| author | 2023-04-19 17:49:07 +0200 | |
|---|---|---|
| committer | 2023-04-19 17:49:07 +0200 | |
| commit | ce9ce43efd707a85cc792ff2cc417603a53d4d1d (patch) | |
| tree | 64c471946cc9e2da8a373db1c1c85fb41bc84265 | |
| parent | 3aa5f6a3a663a5f2694ec6fc8cdf9744b616e15e (diff) | |
| download | libplist-ce9ce43efd707a85cc792ff2cc417603a53d4d1d.tar.gz libplist-ce9ce43efd707a85cc792ff2cc417603a53d4d1d.tar.bz2 | |
Add plist_read_from_file() to interface, update plist_from_memory()
plist_read_from_file() is a convenience function that will open a
given file, checks its size, allocates a buffer large enough to
hold the full contents, and reads from file to fill the buffer.
Then, it calls plist_from_memory() to convert the data to plist
format.
A (breaking) change had to be made so that plist_from_memory() will
also return the parsed format in its 4th argument (if non-NULL).
| -rw-r--r-- | include/plist/plist.h | 23 | ||||
| -rw-r--r-- | src/plist.c | 52 | ||||
| -rw-r--r-- | test/plist_cmp.c | 46 | ||||
| -rw-r--r-- | tools/plistutil.c | 2 |
4 files changed, 75 insertions, 48 deletions
diff --git a/include/plist/plist.h b/include/plist/plist.h index b635996..9b16c58 100644 --- a/include/plist/plist.h +++ b/include/plist/plist.h | |||
| @@ -44,6 +44,7 @@ extern "C" | |||
| 44 | #include <stdint.h> | 44 | #include <stdint.h> |
| 45 | #endif | 45 | #endif |
| 46 | 46 | ||
| 47 | /*{{{ deprecation macros */ | ||
| 47 | #ifdef __llvm__ | 48 | #ifdef __llvm__ |
| 48 | #if defined(__has_extension) | 49 | #if defined(__has_extension) |
| 49 | #if (__has_extension(attribute_deprecated_with_message)) | 50 | #if (__has_extension(attribute_deprecated_with_message)) |
| @@ -72,6 +73,7 @@ extern "C" | |||
| 72 | #define PLIST_WARN_DEPRECATED(x) | 73 | #define PLIST_WARN_DEPRECATED(x) |
| 73 | #pragma message("WARNING: You need to implement DEPRECATED for this compiler") | 74 | #pragma message("WARNING: You need to implement DEPRECATED for this compiler") |
| 74 | #endif | 75 | #endif |
| 76 | /*}}}*/ | ||
| 75 | 77 | ||
| 76 | #include <sys/types.h> | 78 | #include <sys/types.h> |
| 77 | #include <stdarg.h> | 79 | #include <stdarg.h> |
| @@ -819,7 +821,8 @@ extern "C" | |||
| 819 | 821 | ||
| 820 | /** | 822 | /** |
| 821 | * Import the #plist_t structure from memory data. | 823 | * Import the #plist_t structure from memory data. |
| 822 | * This method will look at the first bytes of plist_data | 824 | * |
| 825 | * This function will look at the first bytes of plist_data | ||
| 823 | * to determine if plist_data contains a binary, JSON, OpenStep, or XML plist | 826 | * to determine if plist_data contains a binary, JSON, OpenStep, or XML plist |
| 824 | * and tries to parse the data in the appropriate format. | 827 | * and tries to parse the data in the appropriate format. |
| 825 | * @note This is just a convenience function and the format detection is | 828 | * @note This is just a convenience function and the format detection is |
| @@ -831,9 +834,25 @@ extern "C" | |||
| 831 | * @param plist_data A pointer to the memory buffer containing plist data. | 834 | * @param plist_data A pointer to the memory buffer containing plist data. |
| 832 | * @param length Length of the buffer to read. | 835 | * @param length Length of the buffer to read. |
| 833 | * @param plist A pointer to the imported plist. | 836 | * @param plist A pointer to the imported plist. |
| 837 | * @param format If non-NULL, the #plist_format_t value pointed to will be set to the parsed format. | ||
| 838 | * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure | ||
| 839 | */ | ||
| 840 | plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t *plist, plist_format_t *format); | ||
| 841 | |||
| 842 | /** | ||
| 843 | * Import the #plist_t structure directly from file. | ||
| 844 | * | ||
| 845 | * This function will look at the first bytes of the file data | ||
| 846 | * to determine if it contains a binary, JSON, OpenStep, or XML plist | ||
| 847 | * and tries to parse the data in the appropriate format. | ||
| 848 | * Uses #plist_read_from_data() internally. | ||
| 849 | * | ||
| 850 | * @param filename The name of the file to parse. | ||
| 851 | * @param plist A pointer to the imported plist. | ||
| 852 | * @param format If non-NULL, the #plist_format_t value pointed to will be set to the parsed format. | ||
| 834 | * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure | 853 | * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure |
| 835 | */ | 854 | */ |
| 836 | plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist); | 855 | plist_err_t plist_read_from_file(const char *filename, plist_t *plist, plist_format_t *format); |
| 837 | 856 | ||
| 838 | /** | 857 | /** |
| 839 | * Write the #plist_t structure to a NULL-terminated string using the given format and options. | 858 | * Write the #plist_t structure to a NULL-terminated string using the given format and options. |
diff --git a/src/plist.c b/src/plist.c index 01e44df..48b012b 100644 --- a/src/plist.c +++ b/src/plist.c | |||
| @@ -197,7 +197,7 @@ PLIST_API int plist_is_binary(const char *plist_data, uint32_t length) | |||
| 197 | #define FIND_NEXT(blob, pos, len, chr) \ | 197 | #define FIND_NEXT(blob, pos, len, chr) \ |
| 198 | while (pos < len && (blob[pos] != chr)) pos++; | 198 | while (pos < len && (blob[pos] != chr)) pos++; |
| 199 | 199 | ||
| 200 | PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist) | 200 | PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t *plist, plist_format_t *format) |
| 201 | { | 201 | { |
| 202 | int res = -1; | 202 | int res = -1; |
| 203 | if (!plist) { | 203 | if (!plist) { |
| @@ -207,8 +207,11 @@ PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, | |||
| 207 | if (!plist_data || length == 0) { | 207 | if (!plist_data || length == 0) { |
| 208 | return PLIST_ERR_INVALID_ARG; | 208 | return PLIST_ERR_INVALID_ARG; |
| 209 | } | 209 | } |
| 210 | plist_format_t fmt = 0; | ||
| 211 | if (format) *format = 0; | ||
| 210 | if (plist_is_binary(plist_data, length)) { | 212 | if (plist_is_binary(plist_data, length)) { |
| 211 | res = plist_from_bin(plist_data, length, plist); | 213 | res = plist_from_bin(plist_data, length, plist); |
| 214 | fmt = PLIST_FORMAT_BINARY; | ||
| 212 | } else { | 215 | } else { |
| 213 | uint32_t pos = 0; | 216 | uint32_t pos = 0; |
| 214 | int is_json = 0; | 217 | int is_json = 0; |
| @@ -248,12 +251,59 @@ PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, | |||
| 248 | } | 251 | } |
| 249 | if (is_xml) { | 252 | if (is_xml) { |
| 250 | res = plist_from_xml(plist_data, length, plist); | 253 | res = plist_from_xml(plist_data, length, plist); |
| 254 | fmt = PLIST_FORMAT_XML; | ||
| 251 | } else if (is_json) { | 255 | } else if (is_json) { |
| 252 | res = plist_from_json(plist_data, length, plist); | 256 | res = plist_from_json(plist_data, length, plist); |
| 257 | fmt = PLIST_FORMAT_JSON; | ||
| 253 | } else { | 258 | } else { |
| 254 | res = plist_from_openstep(plist_data, length, plist); | 259 | res = plist_from_openstep(plist_data, length, plist); |
| 260 | fmt = PLIST_FORMAT_OSTEP; | ||
| 255 | } | 261 | } |
| 256 | } | 262 | } |
| 263 | if (format && res == PLIST_ERR_SUCCESS) { | ||
| 264 | *format = fmt; | ||
| 265 | } | ||
| 266 | return res; | ||
| 267 | } | ||
| 268 | |||
| 269 | PLIST_API plist_err_t plist_read_from_file(const char *filename, plist_t *plist, plist_format_t *format) | ||
| 270 | { | ||
| 271 | if (!filename || !plist) { | ||
| 272 | return PLIST_ERR_INVALID_ARG; | ||
| 273 | } | ||
| 274 | FILE *f = fopen(filename, "rb"); | ||
| 275 | if (!f) { | ||
| 276 | return PLIST_ERR_IO; | ||
| 277 | } | ||
| 278 | struct stat fst; | ||
| 279 | fstat(fileno(f), &fst); | ||
| 280 | if (fst.st_size > UINT32_MAX) { | ||
| 281 | return PLIST_ERR_NO_MEM; | ||
| 282 | } | ||
| 283 | uint32_t total = (uint32_t)fst.st_size; | ||
| 284 | if (total == 0) { | ||
| 285 | return PLIST_ERR_PARSE; | ||
| 286 | } | ||
| 287 | char *buf = malloc(total); | ||
| 288 | if (!buf) { | ||
| 289 | fclose(f); | ||
| 290 | return PLIST_ERR_NO_MEM; | ||
| 291 | } | ||
| 292 | uint32_t done = 0; | ||
| 293 | while (done < total) { | ||
| 294 | ssize_t r = fread(buf + done, 1, total - done, f); | ||
| 295 | if (r <= 0) { | ||
| 296 | break; | ||
| 297 | } | ||
| 298 | done += r; | ||
| 299 | } | ||
| 300 | fclose(f); | ||
| 301 | if (done < total) { | ||
| 302 | free(buf); | ||
| 303 | return PLIST_ERR_IO; | ||
| 304 | } | ||
| 305 | plist_err_t res = plist_from_memory(buf, total, plist, format); | ||
| 306 | free(buf); | ||
| 257 | return res; | 307 | return res; |
| 258 | } | 308 | } |
| 259 | 309 | ||
diff --git a/test/plist_cmp.c b/test/plist_cmp.c index 4947276..c452032 100644 --- a/test/plist_cmp.c +++ b/test/plist_cmp.c | |||
| @@ -75,21 +75,12 @@ static char compare_plist(plist_t node_l, plist_t node_r) | |||
| 75 | 75 | ||
| 76 | int main(int argc, char *argv[]) | 76 | int main(int argc, char *argv[]) |
| 77 | { | 77 | { |
| 78 | FILE *iplist1 = NULL; | ||
| 79 | FILE *iplist2 = NULL; | ||
| 80 | plist_t root_node1 = NULL; | 78 | plist_t root_node1 = NULL; |
| 81 | plist_t root_node2 = NULL; | 79 | plist_t root_node2 = NULL; |
| 82 | char *plist_1 = NULL; | ||
| 83 | char *plist_2 = NULL; | ||
| 84 | int size_in1 = 0; | ||
| 85 | int size_in2 = 0; | ||
| 86 | char *file_in1 = NULL; | 80 | char *file_in1 = NULL; |
| 87 | char *file_in2 = NULL; | 81 | char *file_in2 = NULL; |
| 88 | int res = 0; | 82 | int res = 0; |
| 89 | 83 | ||
| 90 | struct stat *filestats1 = (struct stat *) malloc(sizeof(struct stat)); | ||
| 91 | struct stat *filestats2 = (struct stat *) malloc(sizeof(struct stat)); | ||
| 92 | |||
| 93 | if (argc!= 3) | 84 | if (argc!= 3) |
| 94 | { | 85 | { |
| 95 | printf("Wrong input\n"); | 86 | printf("Wrong input\n"); |
| @@ -99,36 +90,8 @@ int main(int argc, char *argv[]) | |||
| 99 | file_in1 = argv[1]; | 90 | file_in1 = argv[1]; |
| 100 | file_in2 = argv[2]; | 91 | file_in2 = argv[2]; |
| 101 | 92 | ||
| 102 | //read input file | 93 | plist_read_from_file(file_in1, &root_node1, NULL); |
| 103 | iplist1 = fopen(file_in1, "rb"); | 94 | plist_read_from_file(file_in2, &root_node2, NULL); |
| 104 | iplist2 = fopen(file_in2, "rb"); | ||
| 105 | |||
| 106 | if (!iplist1 || !iplist2) | ||
| 107 | { | ||
| 108 | printf("File does not exists\n"); | ||
| 109 | return 2; | ||
| 110 | } | ||
| 111 | |||
| 112 | stat(file_in1, filestats1); | ||
| 113 | stat(file_in2, filestats2); | ||
| 114 | |||
| 115 | size_in1 = filestats1->st_size; | ||
| 116 | size_in2 = filestats2->st_size; | ||
| 117 | |||
| 118 | plist_1 = (char *) malloc(sizeof(char) * (size_in1 + 1)); | ||
| 119 | plist_2 = (char *) malloc(sizeof(char) * (size_in2 + 1)); | ||
| 120 | |||
| 121 | fread(plist_1, sizeof(char), size_in1, iplist1); | ||
| 122 | fread(plist_2, sizeof(char), size_in2, iplist2); | ||
| 123 | |||
| 124 | fclose(iplist1); | ||
| 125 | fclose(iplist2); | ||
| 126 | |||
| 127 | plist_1[size_in1] = '\0'; | ||
| 128 | plist_2[size_in2] = '\0'; | ||
| 129 | |||
| 130 | plist_from_memory(plist_1, size_in1, &root_node1); | ||
| 131 | plist_from_memory(plist_2, size_in2, &root_node2); | ||
| 132 | 95 | ||
| 133 | if (!root_node1 || !root_node2) | 96 | if (!root_node1 || !root_node2) |
| 134 | { | 97 | { |
| @@ -142,11 +105,6 @@ int main(int argc, char *argv[]) | |||
| 142 | plist_free(root_node1); | 105 | plist_free(root_node1); |
| 143 | plist_free(root_node2); | 106 | plist_free(root_node2); |
| 144 | 107 | ||
| 145 | free(plist_1); | ||
| 146 | free(plist_2); | ||
| 147 | free(filestats1); | ||
| 148 | free(filestats2); | ||
| 149 | |||
| 150 | return !res; | 108 | return !res; |
| 151 | } | 109 | } |
| 152 | 110 | ||
diff --git a/tools/plistutil.c b/tools/plistutil.c index e339b8b..6da53e4 100644 --- a/tools/plistutil.c +++ b/tools/plistutil.c | |||
| @@ -284,7 +284,7 @@ int main(int argc, char *argv[]) | |||
| 284 | } | 284 | } |
| 285 | else | 285 | else |
| 286 | { | 286 | { |
| 287 | input_res = plist_from_memory(plist_entire, read_size, &root_node); | 287 | input_res = plist_from_memory(plist_entire, read_size, &root_node, NULL); |
| 288 | if (input_res == PLIST_ERR_SUCCESS) { | 288 | if (input_res == PLIST_ERR_SUCCESS) { |
| 289 | if (options->flags & OPT_SORT) { | 289 | if (options->flags & OPT_SORT) { |
| 290 | plist_sort(root_node); | 290 | plist_sort(root_node); |
