diff options
author | Nikias Bassen | 2023-04-19 17:49:07 +0200 |
---|---|---|
committer | Nikias Bassen | 2023-04-19 17:49:07 +0200 |
commit | ce9ce43efd707a85cc792ff2cc417603a53d4d1d (patch) | |
tree | 64c471946cc9e2da8a373db1c1c85fb41bc84265 /src | |
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).
Diffstat (limited to 'src')
-rw-r--r-- | src/plist.c | 52 |
1 files changed, 51 insertions, 1 deletions
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; } |