devtools: Refactoring, bug fix, new IDL
[src/app-framework-binder.git] / src / devtools / json2c.c
1 /*
2  * Copyright (C) 2016-2019 "IoT.bzh"
3  * Author José Bollo <jose.bollo@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 /*
18  * This simple program expands the object { "$ref": "#/path/to/a/target" }
19  *
20  * For example:
21  *
22  *  {
23  *    "type":{
24  *      "a": "int",
25  *      "b": { "$ref": "#/type/a" }
26  *    }
27  *  }
28  *
29  * will be exapanded to
30  *
31  *  {
32  *    "type":{
33  *      "a": "int",
34  *      "b": "int"
35  *    }
36  *  }
37  *
38  * Invocation:   program  [file|-]...
39  *
40  * without arguments, it reads the input.
41  */
42
43 #define _GNU_SOURCE
44 #include <string.h>
45 #include <limits.h>
46 #include <assert.h>
47 #include <stdio.h>
48
49 #include <json-c/json.h>
50
51 static size_t s2c(const char *str, const char *prefix, int width, int lprf, char *out)
52 {
53         char c, buf[4];
54         size_t len;
55         int i, pos;
56
57 #define P(x) do{ if (out) out[len] = (x); len++; pos++; }while(0)
58         /* translate the string */
59         len = pos = 0;
60         for(;;) {
61                 /* get the char to convert */
62                 c = *str++;
63
64                 /* set buf with next char */
65                 switch(c) {
66                 case '\\':
67                         c = *str++;
68                         if (c) {
69                                 if (c == '/') {
70                                         /* remove ugly \/ put by json-c */
71                                         buf[0] = '/';
72                                         buf[1] = 0;
73                                 } else {
74                                         buf[0] = '\\';
75                                         buf[1] = c;
76                                         buf[2] = 0;
77                                 }
78                                 break;
79                         }
80                         /*@fallthrough@*/
81                 case 0:
82                         if (!len) P('"');
83                         if (!len || pos) {
84                                 P('"');
85                                 if (prefix) P('\n');
86                         }
87                         P(0);
88                         return len;
89                 case '"':
90                         buf[0] = '\\';
91                         buf[1] = '"';
92                         buf[2] = 0;
93                         break;
94                 case '\n':
95                         buf[0] = '\\';
96                         buf[1] = 'n';
97                         buf[2] = 0;
98                         break;
99                 case '\t':
100                         buf[0] = '\\';
101                         buf[1] = 't';
102                         buf[2] = 0;
103                         break;
104                 default:
105                         if (0 < c && c < ' ') {
106                                 buf[0] = '\\';
107                                 buf[1] = (char)('0' + ((c >> 3) & 7));
108                                 buf[2] = (char)('0' + ((c >> 0) & 7));
109                                 buf[3] = 0;
110                         } else {
111                                 buf[0] = c;
112                                 buf[1] = 0;
113                                 break;
114                         }
115                         break;
116                 }
117                 /* add the char in the output */
118                 if (pos == 0) {
119                         for(i = 0 ; i < lprf ; i++)
120                                 P(prefix[i]);
121                         P('"');
122                 }
123                 for(i = 0 ; buf[i] ; i++)
124                         P(buf[i]);
125                 if (pos >= width - 1) {
126                         P('"');
127                         P('\n');
128                         pos = 0;
129                 }
130         }
131         while(c);
132 #undef P
133 }
134
135 char *str2c(const char *str, const char *prefix, int width)
136 {
137         size_t len;
138         int lprf;
139         char *out;
140
141         /* ensure defaults */
142         len = prefix ? strlen(prefix) : 0;
143         lprf = len > INT_MAX ? INT_MAX : (int)len;
144         width = width <= 0 || width - 2 <= lprf ? INT_MAX : width;
145
146         /* compute final size*/
147         len = s2c(str, prefix, width, lprf, NULL);
148
149         /* allocate the memory */
150         out = malloc(len);
151         if (!out)
152                 return NULL;
153
154         /* make the output */
155         s2c(str, prefix, width, lprf, out);
156         return out;
157 }
158
159 char *str2c_std(const char *str)
160 {
161         return str2c(str, "\t", 71);
162 }
163
164 char *str2c_inl(const char *str)
165 {
166         return str2c(str, 0, 0);
167 }
168
169 char *json2c(struct json_object *object, const char *prefix, int width)
170 {
171         return str2c(json_object_to_json_string_ext(object, 0), prefix, width);
172 }
173
174 char *json2c_std(struct json_object *object)
175 {
176         return str2c_std(json_object_to_json_string_ext(object, 0));
177 }
178
179 char *json2c_inl(struct json_object *object)
180 {
181         return str2c_inl(json_object_to_json_string_ext(object, 0));
182 }