9bb9e9bf2d418bd2a550b7d19bc5d4bb6205d258
[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 <stdio.h>
46 #include <unistd.h>
47
48 #include <json-c/json.h>
49
50 #define oom(x) do{if(!(x)){fprintf(stderr,"out of memory\n");exit(1);}}while(0)
51
52 /**
53  * root of the JSON being parsed
54  */
55 struct json_object *root = NULL;
56
57 char *make_desc(struct json_object *o)
58 {
59         const char *a, *b;
60         char *desc, c, buf[3];
61         size_t len;
62         int i, pos, e;
63
64         a = b = json_object_to_json_string_ext(root, 0);
65         len = 1;
66         while((c = *b++)) {
67                 len += 1 + ('"' == c);
68         }
69
70         len += 7 * (1 + len / 72);
71         desc = malloc(len);
72         oom(desc);
73
74         len = pos = 0;
75         b = a;
76         while((c = *b++)) {
77                 if (c == '"') {
78                         buf[0] = '\\';
79                         buf[1] = '"';
80                         buf[2] = 0;
81                 }
82                 else if (c == '\\') {
83                         switch ((c = *b++)) {
84                         case '/':
85                                 buf[0] = '/';
86                                 buf[1] = 0;
87                                 break;
88                         case 0:
89                                 b--;
90                                 /*@fallthrough@*/
91                         default:
92                                 buf[0] = '\\';
93                                 buf[1] = c;
94                                 buf[2] = 0;
95                                 break;
96                         }
97                 }
98                 else {
99                         buf[0] = c;
100                         buf[1] = 0;
101                 }
102                 i = e = 0;
103                 while (buf[i]) {
104                         if (pos >= 77 && !e) {
105                                 desc[len++] = '"';
106                                 desc[len++] = '\n';
107                                 pos = 0;
108                         }
109                         if (pos == 0) {
110                                 desc[len++] = ' ';
111                                 desc[len++] = ' ';
112                                 desc[len++] = ' ';
113                                 desc[len++] = ' ';
114                                 desc[len++] = '"';
115                                 pos = 5;
116                         }
117                         c = buf[i++];
118                         desc[len++] = c;
119                         e = !e && c == '\\';
120                         pos++;
121                 }
122         }
123         desc[len++] = '"';
124         desc[len++] = '\n';
125         desc[len] = 0;
126         return desc;
127 }
128
129 /**
130  * process a file and prints its expansion on stdout
131  */
132 void process(char *filename)
133 {
134         char *desc;
135
136         /* translate - */
137         if (!strcmp(filename, "-"))
138                 filename = "/dev/stdin";
139
140         /* check access */
141         if (access(filename, R_OK)) {
142                 fprintf(stderr, "can't access file %s\n", filename);
143                 exit(1);
144         }
145
146         /* read the file */
147         root = json_object_from_file(filename);
148         if (!root) {
149                 fprintf(stderr, "reading file %s produced null\n", filename);
150                 exit(1);
151         }
152
153         /* create the description */
154         desc = make_desc(root);
155
156         printf("%s", desc);
157
158         /* clean up */
159         json_object_put(root);
160         free(desc);
161 }
162
163 /** process the list of files or stdin if none */
164 int main(int ac, char **av)
165 {
166         if (!*++av)
167                 process("-");
168         else {
169                 do { process(*av); } while(*++av);
170         }
171         return 0;
172 }
173
174