summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2023-04-19 17:49:07 +0200
committerGravatar Nikias Bassen2023-04-19 17:49:07 +0200
commitce9ce43efd707a85cc792ff2cc417603a53d4d1d (patch)
tree64c471946cc9e2da8a373db1c1c85fb41bc84265
parent3aa5f6a3a663a5f2694ec6fc8cdf9744b616e15e (diff)
downloadlibplist-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.h23
-rw-r--r--src/plist.c52
-rw-r--r--test/plist_cmp.c46
-rw-r--r--tools/plistutil.c2
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"
#include <stdint.h>
#endif
+/*{{{ deprecation macros */
#ifdef __llvm__
#if defined(__has_extension)
#if (__has_extension(attribute_deprecated_with_message))
@@ -72,6 +73,7 @@ extern "C"
#define PLIST_WARN_DEPRECATED(x)
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#endif
+/*}}}*/
#include <sys/types.h>
#include <stdarg.h>
@@ -819,7 +821,8 @@ extern "C"
/**
* Import the #plist_t structure from memory data.
- * This method will look at the first bytes of plist_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
@@ -831,9 +834,25 @@ extern "C"
* @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_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_read_from_data() 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_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist);
+ 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.
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)
#define FIND_NEXT(blob, pos, len, chr) \
while (pos < len && (blob[pos] != chr)) pos++;
-PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist)
+PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t *plist, plist_format_t *format)
{
int res = -1;
if (!plist) {
@@ -207,8 +207,11 @@ PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length,
if (!plist_data || length == 0) {
return PLIST_ERR_INVALID_ARG;
}
+ plist_format_t fmt = 0;
+ if (format) *format = 0;
if (plist_is_binary(plist_data, length)) {
res = plist_from_bin(plist_data, length, plist);
+ fmt = PLIST_FORMAT_BINARY;
} else {
uint32_t pos = 0;
int is_json = 0;
@@ -248,12 +251,59 @@ PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length,
}
if (is_xml) {
res = plist_from_xml(plist_data, length, plist);
+ fmt = PLIST_FORMAT_XML;
} else if (is_json) {
res = plist_from_json(plist_data, length, plist);
+ fmt = PLIST_FORMAT_JSON;
} else {
res = plist_from_openstep(plist_data, length, plist);
+ fmt = PLIST_FORMAT_OSTEP;
}
}
+ if (format && res == PLIST_ERR_SUCCESS) {
+ *format = fmt;
+ }
+ return res;
+}
+
+PLIST_API plist_err_t plist_read_from_file(const char *filename, plist_t *plist, plist_format_t *format)
+{
+ if (!filename || !plist) {
+ return PLIST_ERR_INVALID_ARG;
+ }
+ FILE *f = fopen(filename, "rb");
+ if (!f) {
+ return PLIST_ERR_IO;
+ }
+ struct stat fst;
+ fstat(fileno(f), &fst);
+ if (fst.st_size > UINT32_MAX) {
+ return PLIST_ERR_NO_MEM;
+ }
+ uint32_t total = (uint32_t)fst.st_size;
+ if (total == 0) {
+ return PLIST_ERR_PARSE;
+ }
+ char *buf = malloc(total);
+ if (!buf) {
+ fclose(f);
+ return PLIST_ERR_NO_MEM;
+ }
+ uint32_t done = 0;
+ while (done < total) {
+ ssize_t r = fread(buf + done, 1, total - done, f);
+ if (r <= 0) {
+ break;
+ }
+ done += r;
+ }
+ fclose(f);
+ if (done < total) {
+ free(buf);
+ return PLIST_ERR_IO;
+ }
+ plist_err_t res = plist_from_memory(buf, total, plist, format);
+ free(buf);
return res;
}
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)
int main(int argc, char *argv[])
{
- FILE *iplist1 = NULL;
- FILE *iplist2 = NULL;
plist_t root_node1 = NULL;
plist_t root_node2 = NULL;
- char *plist_1 = NULL;
- char *plist_2 = NULL;
- int size_in1 = 0;
- int size_in2 = 0;
char *file_in1 = NULL;
char *file_in2 = NULL;
int res = 0;
- struct stat *filestats1 = (struct stat *) malloc(sizeof(struct stat));
- struct stat *filestats2 = (struct stat *) malloc(sizeof(struct stat));
-
if (argc!= 3)
{
printf("Wrong input\n");
@@ -99,36 +90,8 @@ int main(int argc, char *argv[])
file_in1 = argv[1];
file_in2 = argv[2];
- //read input file
- iplist1 = fopen(file_in1, "rb");
- iplist2 = fopen(file_in2, "rb");
-
- if (!iplist1 || !iplist2)
- {
- printf("File does not exists\n");
- return 2;
- }
-
- stat(file_in1, filestats1);
- stat(file_in2, filestats2);
-
- size_in1 = filestats1->st_size;
- size_in2 = filestats2->st_size;
-
- plist_1 = (char *) malloc(sizeof(char) * (size_in1 + 1));
- plist_2 = (char *) malloc(sizeof(char) * (size_in2 + 1));
-
- fread(plist_1, sizeof(char), size_in1, iplist1);
- fread(plist_2, sizeof(char), size_in2, iplist2);
-
- fclose(iplist1);
- fclose(iplist2);
-
- plist_1[size_in1] = '\0';
- plist_2[size_in2] = '\0';
-
- plist_from_memory(plist_1, size_in1, &root_node1);
- plist_from_memory(plist_2, size_in2, &root_node2);
+ plist_read_from_file(file_in1, &root_node1, NULL);
+ plist_read_from_file(file_in2, &root_node2, NULL);
if (!root_node1 || !root_node2)
{
@@ -142,11 +105,6 @@ int main(int argc, char *argv[])
plist_free(root_node1);
plist_free(root_node2);
- free(plist_1);
- free(plist_2);
- free(filestats1);
- free(filestats2);
-
return !res;
}
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[])
}
else
{
- input_res = plist_from_memory(plist_entire, read_size, &root_node);
+ input_res = plist_from_memory(plist_entire, read_size, &root_node, NULL);
if (input_res == PLIST_ERR_SUCCESS) {
if (options->flags & OPT_SORT) {
plist_sort(root_node);