devtools: Refactoring, bug fix, new IDL
[src/app-framework-binder.git] / src / devtools / json2c.c
index 9bb9e9b..c26ef84 100644 (file)
 
 #define _GNU_SOURCE
 #include <string.h>
+#include <limits.h>
+#include <assert.h>
 #include <stdio.h>
-#include <unistd.h>
 
 #include <json-c/json.h>
 
-#define oom(x) do{if(!(x)){fprintf(stderr,"out of memory\n");exit(1);}}while(0)
-
-/**
- * root of the JSON being parsed
- */
-struct json_object *root = NULL;
-
-char *make_desc(struct json_object *o)
+static size_t s2c(const char *str, const char *prefix, int width, int lprf, char *out)
 {
-       const char *a, *b;
-       char *desc, c, buf[3];
+       char c, buf[4];
        size_t len;
-       int i, pos, e;
-
-       a = b = json_object_to_json_string_ext(root, 0);
-       len = 1;
-       while((c = *b++)) {
-               len += 1 + ('"' == c);
-       }
-
-       len += 7 * (1 + len / 72);
-       desc = malloc(len);
-       oom(desc);
+       int i, pos;
 
+#define P(x) do{ if (out) out[len] = (x); len++; pos++; }while(0)
+       /* translate the string */
        len = pos = 0;
-       b = a;
-       while((c = *b++)) {
-               if (c == '"') {
+       for(;;) {
+               /* get the char to convert */
+               c = *str++;
+
+               /* set buf with next char */
+               switch(c) {
+               case '\\':
+                       c = *str++;
+                       if (c) {
+                               if (c == '/') {
+                                       /* remove ugly \/ put by json-c */
+                                       buf[0] = '/';
+                                       buf[1] = 0;
+                               } else {
+                                       buf[0] = '\\';
+                                       buf[1] = c;
+                                       buf[2] = 0;
+                               }
+                               break;
+                       }
+                       /*@fallthrough@*/
+               case 0:
+                       if (!len) P('"');
+                       if (!len || pos) {
+                               P('"');
+                               if (prefix) P('\n');
+                       }
+                       P(0);
+                       return len;
+               case '"':
                        buf[0] = '\\';
                        buf[1] = '"';
                        buf[2] = 0;
-               }
-               else if (c == '\\') {
-                       switch ((c = *b++)) {
-                       case '/':
-                               buf[0] = '/';
-                               buf[1] = 0;
-                               break;
-                       case 0:
-                               b--;
-                               /*@fallthrough@*/
-                       default:
+                       break;
+               case '\n':
+                       buf[0] = '\\';
+                       buf[1] = 'n';
+                       buf[2] = 0;
+                       break;
+               case '\t':
+                       buf[0] = '\\';
+                       buf[1] = 't';
+                       buf[2] = 0;
+                       break;
+               default:
+                       if (0 < c && c < ' ') {
                                buf[0] = '\\';
-                               buf[1] = c;
-                               buf[2] = 0;
+                               buf[1] = (char)('0' + ((c >> 3) & 7));
+                               buf[2] = (char)('0' + ((c >> 0) & 7));
+                               buf[3] = 0;
+                       } else {
+                               buf[0] = c;
+                               buf[1] = 0;
                                break;
                        }
+                       break;
                }
-               else {
-                       buf[0] = c;
-                       buf[1] = 0;
+               /* add the char in the output */
+               if (pos == 0) {
+                       for(i = 0 ; i < lprf ; i++)
+                               P(prefix[i]);
+                       P('"');
                }
-               i = e = 0;
-               while (buf[i]) {
-                       if (pos >= 77 && !e) {
-                               desc[len++] = '"';
-                               desc[len++] = '\n';
-                               pos = 0;
-                       }
-                       if (pos == 0) {
-                               desc[len++] = ' ';
-                               desc[len++] = ' ';
-                               desc[len++] = ' ';
-                               desc[len++] = ' ';
-                               desc[len++] = '"';
-                               pos = 5;
-                       }
-                       c = buf[i++];
-                       desc[len++] = c;
-                       e = !e && c == '\\';
-                       pos++;
+               for(i = 0 ; buf[i] ; i++)
+                       P(buf[i]);
+               if (pos >= width - 1) {
+                       P('"');
+                       P('\n');
+                       pos = 0;
                }
        }
-       desc[len++] = '"';
-       desc[len++] = '\n';
-       desc[len] = 0;
-       return desc;
+       while(c);
+#undef P
 }
 
-/**
- * process a file and prints its expansion on stdout
- */
-void process(char *filename)
+char *str2c(const char *str, const char *prefix, int width)
 {
-       char *desc;
+       size_t len;
+       int lprf;
+       char *out;
 
-       /* translate - */
-       if (!strcmp(filename, "-"))
-               filename = "/dev/stdin";
+       /* ensure defaults */
+       len = prefix ? strlen(prefix) : 0;
+       lprf = len > INT_MAX ? INT_MAX : (int)len;
+       width = width <= 0 || width - 2 <= lprf ? INT_MAX : width;
 
-       /* check access */
-       if (access(filename, R_OK)) {
-               fprintf(stderr, "can't access file %s\n", filename);
-               exit(1);
-       }
+       /* compute final size*/
+       len = s2c(str, prefix, width, lprf, NULL);
 
-       /* read the file */
-       root = json_object_from_file(filename);
-       if (!root) {
-               fprintf(stderr, "reading file %s produced null\n", filename);
-               exit(1);
-       }
+       /* allocate the memory */
+       out = malloc(len);
+       if (!out)
+               return NULL;
 
-       /* create the description */
-       desc = make_desc(root);
+       /* make the output */
+       s2c(str, prefix, width, lprf, out);
+       return out;
+}
 
-       printf("%s", desc);
+char *str2c_std(const char *str)
+{
+       return str2c(str, "\t", 71);
+}
 
-       /* clean up */
-       json_object_put(root);
-       free(desc);
+char *str2c_inl(const char *str)
+{
+       return str2c(str, 0, 0);
 }
 
-/** process the list of files or stdin if none */
-int main(int ac, char **av)
+char *json2c(struct json_object *object, const char *prefix, int width)
 {
-       if (!*++av)
-               process("-");
-       else {
-               do { process(*av); } while(*++av);
-       }
-       return 0;
+       return str2c(json_object_to_json_string_ext(object, 0), prefix, width);
 }
 
+char *json2c_std(struct json_object *object)
+{
+       return str2c_std(json_object_to_json_string_ext(object, 0));
+}
 
+char *json2c_inl(struct json_object *object)
+{
+       return str2c_inl(json_object_to_json_string_ext(object, 0));
+}