diff options
| author | 2023-04-19 17:49:07 +0200 | |
|---|---|---|
| committer | 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;  } | 
