diff options
| author | 2023-01-08 05:29:22 +0100 | |
|---|---|---|
| committer | 2023-01-08 05:29:22 +0100 | |
| commit | 60d291941fadb72b66d11502710add5899e21a2d (patch) | |
| tree | a7ecccf74cd8fb7e2596fd3531fd9cccefa39dcd /src/plist.c | |
| parent | 3f9360e33c13c22648036da42e36f8668e29fb60 (diff) | |
| download | libplist-60d291941fadb72b66d11502710add5899e21a2d.tar.gz libplist-60d291941fadb72b66d11502710add5899e21a2d.tar.bz2 | |
Add support for OpenStep plist format
Diffstat (limited to 'src/plist.c')
| -rw-r--r-- | src/plist.c | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/src/plist.c b/src/plist.c index 37edfa4..e696f70 100644 --- a/src/plist.c +++ b/src/plist.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <assert.h> | 34 | #include <assert.h> |
| 35 | #include <limits.h> | 35 | #include <limits.h> |
| 36 | #include <float.h> | 36 | #include <float.h> |
| 37 | #include <ctype.h> | ||
| 37 | 38 | ||
| 38 | #ifdef WIN32 | 39 | #ifdef WIN32 |
| 39 | #include <windows.h> | 40 | #include <windows.h> |
| @@ -51,12 +52,15 @@ extern void plist_bin_init(void); | |||
| 51 | extern void plist_bin_deinit(void); | 52 | extern void plist_bin_deinit(void); |
| 52 | extern void plist_json_init(void); | 53 | extern void plist_json_init(void); |
| 53 | extern void plist_json_deinit(void); | 54 | extern void plist_json_deinit(void); |
| 55 | extern void plist_ostep_init(void); | ||
| 56 | extern void plist_ostep_deinit(void); | ||
| 54 | 57 | ||
| 55 | static void internal_plist_init(void) | 58 | static void internal_plist_init(void) |
| 56 | { | 59 | { |
| 57 | plist_bin_init(); | 60 | plist_bin_init(); |
| 58 | plist_xml_init(); | 61 | plist_xml_init(); |
| 59 | plist_json_init(); | 62 | plist_json_init(); |
| 63 | plist_ostep_init(); | ||
| 60 | } | 64 | } |
| 61 | 65 | ||
| 62 | static void internal_plist_deinit(void) | 66 | static void internal_plist_deinit(void) |
| @@ -64,6 +68,7 @@ static void internal_plist_deinit(void) | |||
| 64 | plist_bin_deinit(); | 68 | plist_bin_deinit(); |
| 65 | plist_xml_deinit(); | 69 | plist_xml_deinit(); |
| 66 | plist_json_deinit(); | 70 | plist_json_deinit(); |
| 71 | plist_ostep_deinit(); | ||
| 67 | } | 72 | } |
| 68 | 73 | ||
| 69 | #ifdef WIN32 | 74 | #ifdef WIN32 |
| @@ -186,6 +191,10 @@ PLIST_API int plist_is_binary(const char *plist_data, uint32_t length) | |||
| 186 | return (memcmp(plist_data, "bplist00", 8) == 0); | 191 | return (memcmp(plist_data, "bplist00", 8) == 0); |
| 187 | } | 192 | } |
| 188 | 193 | ||
| 194 | #define SKIP_WS(blob, pos, len) \ | ||
| 195 | while (pos < len && ((blob[pos] == ' ') || (blob[pos] == '\t') || (blob[pos] == '\r') || (blob[pos] == '\n'))) pos++; | ||
| 196 | #define FIND_NEXT(blob, pos, len, chr) \ | ||
| 197 | while (pos < len && (blob[pos] != chr)) pos++; | ||
| 189 | 198 | ||
| 190 | PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist) | 199 | PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist) |
| 191 | { | 200 | { |
| @@ -194,19 +203,54 @@ PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, | |||
| 194 | return PLIST_ERR_INVALID_ARG; | 203 | return PLIST_ERR_INVALID_ARG; |
| 195 | } | 204 | } |
| 196 | *plist = NULL; | 205 | *plist = NULL; |
| 197 | if (!plist_data || length < 8) { | 206 | if (!plist_data || length == 0) { |
| 198 | return PLIST_ERR_INVALID_ARG; | 207 | return PLIST_ERR_INVALID_ARG; |
| 199 | } | 208 | } |
| 200 | if (plist_is_binary(plist_data, length)) { | 209 | if (plist_is_binary(plist_data, length)) { |
| 201 | res = plist_from_bin(plist_data, length, plist); | 210 | res = plist_from_bin(plist_data, length, plist); |
| 202 | } else { | 211 | } else { |
| 203 | /* skip whitespace before checking */ | ||
| 204 | uint32_t pos = 0; | 212 | uint32_t pos = 0; |
| 205 | while (pos < length && ((plist_data[pos] == ' ') || (plist_data[pos] == '\t') || (plist_data[pos] == '\r') || (plist_data[pos] == '\n'))) pos++; | 213 | int is_json = 0; |
| 206 | if (plist_data[pos] == '[' || plist_data[pos] == '{') { | 214 | int is_xml = 0; |
| 215 | /* skip whitespace */ | ||
| 216 | SKIP_WS(plist_data, pos, length); | ||
| 217 | if (plist_data[pos] == '<' && (length-pos > 3) && !isxdigit(plist_data[pos+1]) && !isxdigit(plist_data[pos+2]) && !isxdigit(plist_data[pos+3])) { | ||
| 218 | is_xml = 1; | ||
| 219 | } else if (plist_data[pos] == '[') { | ||
| 220 | /* only valid for json */ | ||
| 221 | is_json = 1; | ||
| 222 | } else if (plist_data[pos] == '(') { | ||
| 223 | /* only valid for openstep */ | ||
| 224 | } else if (plist_data[pos] == '{') { | ||
| 225 | /* this could be json or openstep */ | ||
| 226 | pos++; | ||
| 227 | SKIP_WS(plist_data, pos, length); | ||
| 228 | if (plist_data[pos] == '"') { | ||
| 229 | /* still could be both */ | ||
| 230 | pos++; | ||
| 231 | do { | ||
| 232 | FIND_NEXT(plist_data, pos, length, '"'); | ||
| 233 | if (plist_data[pos-1] != '\\') { | ||
| 234 | break; | ||
| 235 | } | ||
| 236 | pos++; | ||
| 237 | } while (pos < length); | ||
| 238 | if (plist_data[pos] == '"') { | ||
| 239 | pos++; | ||
| 240 | SKIP_WS(plist_data, pos, length); | ||
| 241 | if (plist_data[pos] == ':') { | ||
| 242 | /* this is definitely json */ | ||
| 243 | is_json = 1; | ||
| 244 | } | ||
| 245 | } | ||
| 246 | } | ||
| 247 | } | ||
| 248 | if (is_xml) { | ||
| 249 | res = plist_from_xml(plist_data, length, plist); | ||
| 250 | } else if (is_json) { | ||
| 207 | res = plist_from_json(plist_data, length, plist); | 251 | res = plist_from_json(plist_data, length, plist); |
| 208 | } else { | 252 | } else { |
| 209 | res = plist_from_xml(plist_data, length, plist); | 253 | res = plist_from_openstep(plist_data, length, plist); |
| 210 | } | 254 | } |
| 211 | } | 255 | } |
| 212 | return res; | 256 | return res; |
