1 /* 2 * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $ 3 * 4 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 * Michael Clark <michael@metaparadigm.com> 6 * 7 * This library is free software; you can redistribute it and/or modify 8 * it under the terms of the MIT license. See COPYING for details. 9 * 10 */ 11 12 #include "config.h" 13 #undef realloc 14 15 #include "strerror_override.h" 16 17 #include <ctype.h> 18 #include <limits.h> 19 #include <stdarg.h> 20 #include <stddef.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 25 #ifdef HAVE_SYS_TYPES_H 26 #include <sys/types.h> 27 #endif /* HAVE_SYS_TYPES_H */ 28 29 #ifdef HAVE_SYS_STAT_H 30 #include <sys/stat.h> 31 #endif /* HAVE_SYS_STAT_H */ 32 33 #ifdef HAVE_FCNTL_H 34 #include <fcntl.h> 35 #endif /* HAVE_FCNTL_H */ 36 37 #ifdef HAVE_UNISTD_H 38 #include <unistd.h> 39 #endif /* HAVE_UNISTD_H */ 40 41 #ifdef WIN32 42 #define WIN32_LEAN_AND_MEAN 43 #include <io.h> 44 #include <windows.h> 45 #endif /* defined(WIN32) */ 46 47 #if !defined(HAVE_OPEN) && defined(WIN32) 48 #define open _open 49 #endif 50 51 #include "snprintf_compat.h" 52 53 #include "debug.h" 54 #include "json_inttypes.h" 55 #include "json_object.h" 56 #include "json_tokener.h" 57 #include "json_util.h" 58 #include "printbuf.h" 59 60 static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename); 61 62 static char _last_err[256] = ""; 63 64 const char *json_util_get_last_err() 65 { 66 if (_last_err[0] == '\0') 67 return NULL; 68 return _last_err; 69 } 70 71 void _json_c_set_last_err(const char *err_fmt, ...) 72 { 73 va_list ap; 74 va_start(ap, err_fmt); 75 // Ignore (attempted) overruns from snprintf 76 (void)vsnprintf(_last_err, sizeof(_last_err), err_fmt, ap); 77 va_end(ap); 78 } 79 80 struct json_object *json_object_from_fd(int fd) 81 { 82 return json_object_from_fd_ex(fd, -1); 83 } 84 struct json_object *json_object_from_fd_ex(int fd, int in_depth) 85 { 86 struct printbuf *pb; 87 struct json_object *obj; 88 char buf[JSON_FILE_BUF_SIZE]; 89 int ret; 90 int depth = JSON_TOKENER_DEFAULT_DEPTH; 91 json_tokener *tok; 92 93 if (!(pb = printbuf_new())) 94 { 95 _json_c_set_last_err("json_object_from_file: printbuf_new failed\n"); 96 return NULL; 97 } 98 99 if (in_depth != -1) 100 depth = in_depth; 101 tok = json_tokener_new_ex(depth); 102 if (!tok) 103 { 104 _json_c_set_last_err( 105 "json_object_from_fd: unable to allocate json_tokener(depth=%d): %s\n", depth, 106 strerror(errno)); 107 printbuf_free(pb); 108 return NULL; 109 } 110 111 while ((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) 112 { 113 printbuf_memappend(pb, buf, ret); 114 } 115 if (ret < 0) 116 { 117 _json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd, 118 strerror(errno)); 119 json_tokener_free(tok); 120 printbuf_free(pb); 121 return NULL; 122 } 123 124 obj = json_tokener_parse_ex(tok, pb->buf, printbuf_length(pb)); 125 if (obj == NULL) 126 _json_c_set_last_err("json_tokener_parse_ex failed: %s\n", 127 json_tokener_error_desc(json_tokener_get_error(tok))); 128 129 json_tokener_free(tok); 130 printbuf_free(pb); 131 return obj; 132 } 133 134 struct json_object *json_object_from_file(const char *filename) 135 { 136 struct json_object *obj; 137 int fd; 138 139 if ((fd = open(filename, O_RDONLY)) < 0) 140 { 141 _json_c_set_last_err("json_object_from_file: error opening file %s: %s\n", filename, 142 strerror(errno)); 143 return NULL; 144 } 145 obj = json_object_from_fd(fd); 146 close(fd); 147 return obj; 148 } 149 150 /* extended "format and write to file" function */ 151 152 int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags) 153 { 154 int fd, ret; 155 int saved_errno; 156 157 if (!obj) 158 { 159 _json_c_set_last_err("json_object_to_file: object is null\n"); 160 return -1; 161 } 162 163 if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) 164 { 165 _json_c_set_last_err("json_object_to_file: error opening file %s: %s\n", filename, 166 strerror(errno)); 167 return -1; 168 } 169 ret = _json_object_to_fd(fd, obj, flags, filename); 170 saved_errno = errno; 171 close(fd); 172 errno = saved_errno; 173 return ret; 174 } 175 176 int json_object_to_fd(int fd, struct json_object *obj, int flags) 177 { 178 if (!obj) 179 { 180 _json_c_set_last_err("json_object_to_fd: object is null\n"); 181 return -1; 182 } 183 184 return _json_object_to_fd(fd, obj, flags, NULL); 185 } 186 static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename) 187 { 188 int ret; 189 const char *json_str; 190 unsigned int wpos, wsize; 191 192 filename = filename ? filename : "(fd)"; 193 194 if (!(json_str = json_object_to_json_string_ext(obj, flags))) 195 { 196 return -1; 197 } 198 199 /* CAW: probably unnecessary, but the most 64bit safe */ 200 wsize = (unsigned int)(strlen(json_str) & UINT_MAX); 201 wpos = 0; 202 while (wpos < wsize) 203 { 204 if ((ret = write(fd, json_str + wpos, wsize - wpos)) < 0) 205 { 206 _json_c_set_last_err("json_object_to_file: error writing file %s: %s\n", 207 filename, strerror(errno)); 208 return -1; 209 } 210 211 /* because of the above check for ret < 0, we can safely cast and add */ 212 wpos += (unsigned int)ret; 213 } 214 215 return 0; 216 } 217 218 // backwards compatible "format and write to file" function 219 220 int json_object_to_file(const char *filename, struct json_object *obj) 221 { 222 return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN); 223 } 224 225 // Deprecated json_parse_double function. See json_tokener_parse_double instead. 226 int json_parse_double(const char *buf, double *retval) 227 { 228 char *end; 229 *retval = strtod(buf, &end); 230 return end == buf ? 1 : 0; 231 } 232 233 int json_parse_int64(const char *buf, int64_t *retval) 234 { 235 char *end = NULL; 236 int64_t val; 237 238 errno = 0; 239 val = strtoll(buf, &end, 10); 240 if (end != buf) 241 *retval = val; 242 return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0; 243 } 244 245 int json_parse_uint64(const char *buf, uint64_t *retval) 246 { 247 char *end = NULL; 248 uint64_t val; 249 250 errno = 0; 251 while (*buf == ' ') 252 buf++; 253 if (*buf == '-') 254 return 1; /* error: uint cannot be negative */ 255 256 val = strtoull(buf, &end, 10); 257 if (end != buf) 258 *retval = val; 259 return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0; 260 } 261 262 #ifndef HAVE_REALLOC 263 void *rpl_realloc(void *p, size_t n) 264 { 265 if (n == 0) 266 n = 1; 267 if (p == 0) 268 return malloc(n); 269 return realloc(p, n); 270 } 271 #endif 272 273 #define NELEM(a) (sizeof(a) / sizeof(a[0])) 274 /* clang-format off */ 275 static const char *json_type_name[] = { 276 /* If you change this, be sure to update the enum json_type definition too */ 277 "null", 278 "boolean", 279 "double", 280 "int", 281 "object", 282 "array", 283 "string", 284 }; 285 /* clang-format on */ 286 287 const char *json_type_to_name(enum json_type o_type) 288 { 289 int o_type_int = (int)o_type; 290 if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name)) 291 { 292 _json_c_set_last_err("json_type_to_name: type %d is out of range [0,%d]\n", o_type, 293 NELEM(json_type_name)); 294 return NULL; 295 } 296 return json_type_name[o_type]; 297 } 298
This page was automatically generated by LXR 0.3.1. • OpenWrt