Skip to content

Commit

Permalink
Add plist_read_from_file() to interface, update plist_from_memory()
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
nikias committed Apr 19, 2023
1 parent 3aa5f6a commit ce9ce43
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 48 deletions.
23 changes: 21 additions & 2 deletions include/plist/plist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down
52 changes: 51 additions & 1 deletion src/plist.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
46 changes: 2 additions & 44 deletions test/plist_cmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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)
{
Expand All @@ -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;
}

2 changes: 1 addition & 1 deletion tools/plistutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit ce9ce43

Please sign in to comment.