Install json_object_private.h file
[platform/upstream/json-c.git] / json_util.c
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 <stdarg.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stddef.h>
21 #include <limits.h>
22 #include <string.h>
23 #include <ctype.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 # if MSC_VER < 1800
43 /* strtoll is available only since Visual Studio 2013 */
44 #  define strtoll _strtoi64
45 # endif
46 # define WIN32_LEAN_AND_MEAN
47 # include <windows.h>
48 # include <io.h>
49 #endif /* defined(WIN32) */
50
51 #if !defined(HAVE_OPEN) && defined(WIN32)
52 # define open _open
53 #endif
54
55 #include "snprintf_compat.h"
56
57 #include "debug.h"
58 #include "printbuf.h"
59 #include "json_inttypes.h"
60 #include "json_object.h"
61 #include "json_tokener.h"
62 #include "json_util.h"
63
64 static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename);
65
66 static char _last_err[256] = "";
67
68 const char *json_util_get_last_err()
69 {
70         if (_last_err[0] == '\0')
71                 return NULL;
72         return _last_err;
73 }
74
75 void _json_c_set_last_err(const char *err_fmt, ...)
76 {
77         va_list ap;
78         va_start(ap, err_fmt);
79         // Ignore (attempted) overruns from snprintf
80         (void)vsnprintf(_last_err, sizeof(_last_err), err_fmt, ap);
81         va_end(ap);
82 }
83
84 struct json_object* json_object_from_fd(int fd)
85 {
86   struct printbuf *pb;
87   struct json_object *obj;
88   char buf[JSON_FILE_BUF_SIZE];
89   int ret;
90
91   if(!(pb = printbuf_new())) {
92     _json_c_set_last_err("json_object_from_file: printbuf_new failed\n");
93     return NULL;
94   }
95   while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
96     printbuf_memappend(pb, buf, ret);
97   }
98   if(ret < 0) {
99     _json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd, strerror(errno));
100     printbuf_free(pb);
101     return NULL;
102   }
103   obj = json_tokener_parse(pb->buf);
104   printbuf_free(pb);
105   return obj;
106 }
107
108 struct json_object* json_object_from_file(const char *filename)
109 {
110   struct json_object *obj;
111   int fd;
112
113   if((fd = open(filename, O_RDONLY)) < 0) {
114     _json_c_set_last_err("json_object_from_file: error opening file %s: %s\n",
115              filename, strerror(errno));
116     return NULL;
117   }
118   obj = json_object_from_fd(fd);
119   close(fd);
120   return obj;
121 }
122
123 /* extended "format and write to file" function */
124
125 int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags)
126 {
127         int fd, ret;
128         int saved_errno;
129
130         if (!obj) {
131                 _json_c_set_last_err("json_object_to_file: object is null\n");
132                 return -1;
133         }
134
135         if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
136                 _json_c_set_last_err("json_object_to_file: error opening file %s: %s\n",
137                               filename, strerror(errno));
138                 return -1;
139         }
140         ret = _json_object_to_fd(fd, obj, flags, filename);
141         saved_errno = errno;
142         close(fd);
143         errno = saved_errno;
144         return ret;
145 }
146
147 int json_object_to_fd(int fd, struct json_object *obj, int flags)
148 {
149         if (!obj) {
150                 _json_c_set_last_err("json_object_to_fd: object is null\n");
151                 return -1;
152         }
153
154         return _json_object_to_fd(fd, obj, flags, NULL);
155 }
156 static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename)
157 {
158         int ret;
159         const char *json_str;
160         unsigned int wpos, wsize;
161
162         filename = filename ? filename : "(fd)";
163
164         if (!(json_str = json_object_to_json_string_ext(obj,flags))) {
165                 return -1;
166         }
167
168         wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
169         wpos = 0;
170         while(wpos < wsize) {
171                 if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
172                   _json_c_set_last_err("json_object_to_file: error writing file %s: %s\n",
173                          filename, strerror(errno));
174                   return -1;
175                 }
176
177                 /* because of the above check for ret < 0, we can safely cast and add */
178                 wpos += (unsigned int)ret;
179         }
180
181         return 0;
182 }
183
184 // backwards compatible "format and write to file" function
185
186 int json_object_to_file(const char *filename, struct json_object *obj)
187 {
188   return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
189 }
190
191 int json_parse_double(const char *buf, double *retval)
192 {
193   char *end;
194   *retval = strtod(buf, &end);
195   return end == buf ? 1 : 0;
196 }
197
198 int json_parse_int64(const char *buf, int64_t *retval)
199 {
200         char *end = NULL;
201         int64_t val;
202
203         errno = 0;
204         val = strtoll(buf, &end, 10);
205         if (end != buf)
206                 *retval = val;
207         return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0;
208 }
209
210 #ifndef HAVE_REALLOC
211 void* rpl_realloc(void* p, size_t n)
212 {
213         if (n == 0)
214                 n = 1;
215         if (p == 0)
216                 return malloc(n);
217         return realloc(p, n);
218 }
219 #endif
220
221 #define NELEM(a)        (sizeof(a) / sizeof(a[0]))
222 static const char* json_type_name[] = {
223   /* If you change this, be sure to update the enum json_type definition too */
224   "null",
225   "boolean",
226   "double",
227   "int",
228   "object",
229   "array",
230   "string",
231 };
232
233 const char *json_type_to_name(enum json_type o_type)
234 {
235         int o_type_int = (int)o_type;
236         if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name))
237         {
238                 _json_c_set_last_err("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name));
239                 return NULL;
240         }
241         return json_type_name[o_type];
242 }
243