summaryrefslogtreecommitdiffstats
path: root/tools/plistutil.c
diff options
context:
space:
mode:
authorGravatar Calil Khalil2026-02-21 10:39:24 -0300
committerGravatar Nikias Bassen2026-03-20 17:12:47 +0100
commit3edac28498d883f1f768699ee15ce85a82bb2a7b (patch)
treeb350517a84a671fc500d943168f973e7c97aa93e /tools/plistutil.c
parent6e03a1df6d1aa87c8f9e2b35f1a2ca60feca1c0e (diff)
downloadlibplist-3edac28498d883f1f768699ee15ce85a82bb2a7b.tar.gz
libplist-3edac28498d883f1f768699ee15ce85a82bb2a7b.tar.bz2
Add JSON coercion support for non-JSON plist types
- Add PLIST_OPT_COERCE option to coerce PLIST_DATE, PLIST_DATA, and PLIST_UID to JSON-compatible types (ISO 8601 strings, Base64 strings, and integers) - Add plist_to_json_with_options() function to allow passing coercion options (and others) - Update plist_write_to_string() and plist_write_to_stream() to support coercion option - Add --coerce flag to plistutil for JSON output - Create plist2json symlink that automatically enables coercion when invoked
Diffstat (limited to 'tools/plistutil.c')
-rw-r--r--tools/plistutil.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/tools/plistutil.c b/tools/plistutil.c
index bdf195e..fef72b7 100644
--- a/tools/plistutil.c
+++ b/tools/plistutil.c
@@ -52,6 +52,7 @@ typedef struct _options
52#define OPT_DEBUG (1 << 0) 52#define OPT_DEBUG (1 << 0)
53#define OPT_COMPACT (1 << 1) 53#define OPT_COMPACT (1 << 1)
54#define OPT_SORT (1 << 2) 54#define OPT_SORT (1 << 2)
55#define OPT_COERCE (1 << 3)
55 56
56static void print_usage(int argc, char *argv[]) 57static void print_usage(int argc, char *argv[])
57{ 58{
@@ -74,6 +75,10 @@ static void print_usage(int argc, char *argv[])
74 printf(" -n, --nodepath PATH Restrict output to nodepath defined by PATH.\n"); 75 printf(" -n, --nodepath PATH Restrict output to nodepath defined by PATH.\n");
75 printf(" -c, --compact JSON and OpenStep only: Print output in compact form.\n"); 76 printf(" -c, --compact JSON and OpenStep only: Print output in compact form.\n");
76 printf(" By default, the output will be pretty-printed.\n"); 77 printf(" By default, the output will be pretty-printed.\n");
78 printf(" -C, --coerce JSON only: Coerce non-JSON plist types to JSON-compatible\n");
79 printf(" representations. Date values become ISO 8601 strings,\n");
80 printf(" data values become Base64-encoded strings, and UID values\n");
81 printf(" become integers. Implied when invoked as plist2json.\n");
77 printf(" -s, --sort Sort all dictionary nodes lexicographically by key\n"); 82 printf(" -s, --sort Sort all dictionary nodes lexicographically by key\n");
78 printf(" before converting to the output format.\n"); 83 printf(" before converting to the output format.\n");
79 printf(" -d, --debug Enable extended debug output\n"); 84 printf(" -d, --debug Enable extended debug output\n");
@@ -96,6 +101,7 @@ static options_t *parse_arguments(int argc, char *argv[])
96 { "outfile", required_argument, 0, 'o' }, 101 { "outfile", required_argument, 0, 'o' },
97 { "format", required_argument, 0, 'f' }, 102 { "format", required_argument, 0, 'f' },
98 { "compact", no_argument, 0, 'c' }, 103 { "compact", no_argument, 0, 'c' },
104 { "coerce", no_argument, 0, 'C' },
99 { "sort", no_argument, 0, 's' }, 105 { "sort", no_argument, 0, 's' },
100 { "print", required_argument, 0, 'p' }, 106 { "print", required_argument, 0, 'p' },
101 { "nodepath", required_argument, 0, 'n' }, 107 { "nodepath", required_argument, 0, 'n' },
@@ -106,7 +112,7 @@ static options_t *parse_arguments(int argc, char *argv[])
106 }; 112 };
107 113
108 int c; 114 int c;
109 while ((c = getopt_long(argc, argv, "i:o:f:csp:n:dhv", long_options, NULL)) != -1) 115 while ((c = getopt_long(argc, argv, "i:o:f:cCsp:n:dhv", long_options, NULL)) != -1)
110 { 116 {
111 switch (c) 117 switch (c)
112 { 118 {
@@ -154,6 +160,10 @@ static options_t *parse_arguments(int argc, char *argv[])
154 options->flags |= OPT_COMPACT; 160 options->flags |= OPT_COMPACT;
155 break; 161 break;
156 162
163 case 'C':
164 options->flags |= OPT_COERCE;
165 break;
166
157 case 's': 167 case 's':
158 options->flags |= OPT_SORT; 168 options->flags |= OPT_SORT;
159 break; 169 break;
@@ -230,6 +240,18 @@ int main(int argc, char *argv[])
230 return 0; 240 return 0;
231 } 241 }
232 242
243 // detect invocation as plist2json symlink
244 {
245 char *progname = strrchr(argv[0], '/');
246 progname = progname ? progname + 1 : argv[0];
247 if (!strcmp(progname, "plist2json")) {
248 if (options->out_fmt == 0) {
249 options->out_fmt = PLIST_FORMAT_JSON;
250 }
251 options->flags |= OPT_COERCE;
252 }
253 }
254
233 if (options->flags & OPT_DEBUG) 255 if (options->flags & OPT_DEBUG)
234 { 256 {
235 plist_set_debug(1); 257 plist_set_debug(1);
@@ -404,7 +426,10 @@ int main(int argc, char *argv[])
404 } else if (options->out_fmt == PLIST_FORMAT_XML) { 426 } else if (options->out_fmt == PLIST_FORMAT_XML) {
405 output_res = plist_to_xml(root_node, &plist_out, &size); 427 output_res = plist_to_xml(root_node, &plist_out, &size);
406 } else if (options->out_fmt == PLIST_FORMAT_JSON) { 428 } else if (options->out_fmt == PLIST_FORMAT_JSON) {
407 output_res = plist_to_json(root_node, &plist_out, &size, !(options->flags & OPT_COMPACT)); 429 plist_write_options_t wropts = PLIST_OPT_NONE;
430 if (options->flags & OPT_COMPACT) wropts |= PLIST_OPT_COMPACT;
431 if (options->flags & OPT_COERCE) wropts |= PLIST_OPT_COERCE;
432 output_res = plist_to_json_with_options(root_node, &plist_out, &size, wropts);
408 } else if (options->out_fmt == PLIST_FORMAT_OSTEP) { 433 } else if (options->out_fmt == PLIST_FORMAT_OSTEP) {
409 output_res = plist_to_openstep(root_node, &plist_out, &size, !(options->flags & OPT_COMPACT)); 434 output_res = plist_to_openstep(root_node, &plist_out, &size, !(options->flags & OPT_COMPACT));
410 } else { 435 } else {