+ add C-to-Json serializer
[citadel] / libcitadel / lib / json.c
1 /*
2  * $Id: wildfire.c 6962 2009-01-18 19:33:45Z dothebart $
3  */
4 /**
5  * \defgroup Subst Variable substitution type stuff
6  * \ingroup CitadelConfig
7  */
8
9 /*@{*/
10
11 #include "sysdep.h"
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
15 #include <dirent.h>
16 #include <errno.h>
17 #include <stdio.h>
18 #include <stdarg.h>
19 #include <string.h>
20
21 #include "libcitadel.h"
22
23
24 #define JSON_STRING 0
25 #define JSON_NUM 1
26 #define JSON_NULL 2
27 #define JSON_BOOL 3
28 #define JSON_ARRAY 4
29 #define JSON_OBJECT 7
30
31 struct JsonValue {
32         int Type;
33         StrBuf *Name;
34         StrBuf *Value;
35         HashList *SubValues;
36 };
37
38
39 void DeleteJSONValue(void *vJsonValue)
40 {
41         JsonValue *Val = (JsonValue*) vJsonValue;
42         FreeStrBuf(&Val->Name);
43         FreeStrBuf(&Val->Value);
44         DeleteHash(&Val->SubValues);
45         free(Val);
46 }
47
48 JsonValue *NewJsonObject(const char *Key, long keylen)
49 {
50         JsonValue *Ret;
51
52         Ret = (JsonValue*) malloc(sizeof(JsonValue));
53         memset(Ret, 0, sizeof(JsonValue));
54         Ret->Type = JSON_OBJECT;
55         if (Key != NULL)
56                 Ret->Name = NewStrBufPlain(Key, keylen);
57         Ret->SubValues = NewHash(1, NULL);
58         return Ret;
59 }
60
61 JsonValue *NewJsonArray(const char *Key, long keylen)
62 {
63         JsonValue *Ret;
64
65         Ret = (JsonValue*) malloc(sizeof(JsonValue));
66         memset(Ret, 0, sizeof(JsonValue));
67         Ret->Type = JSON_ARRAY;
68         if (Key != NULL)
69                 Ret->Name = NewStrBufPlain(Key, keylen);
70         Ret->SubValues = NewHash(1, Flathash);
71         return Ret;
72 }
73
74
75 JsonValue *NewJsonNumber(const char *Key, long keylen, long Number)
76 {
77         JsonValue *Ret;
78
79         Ret = (JsonValue*) malloc(sizeof(JsonValue));
80         memset(Ret, 0, sizeof(JsonValue));
81         Ret->Type = JSON_NUM;
82         if (Key != NULL)
83                 Ret->Name = NewStrBufPlain(Key, keylen);
84         Ret->Value = NewStrBufPlain(NULL, 64);
85         StrBufPrintf(Ret->Value, "%ld", Number);
86         return Ret;
87 }
88
89
90
91 JsonValue *NewJsonBigNumber(const char *Key, long keylen, double Number)
92 {
93         JsonValue *Ret;
94
95         Ret = (JsonValue*) malloc(sizeof(JsonValue));
96         memset(Ret, 0, sizeof(JsonValue));
97         Ret->Type = JSON_NUM;
98         if (Key != NULL)
99                 Ret->Name = NewStrBufPlain(Key, keylen);
100         Ret->Value = NewStrBufPlain(NULL, 128);
101         StrBufPrintf(Ret->Value, "%f", Number);
102         return Ret;
103 }
104
105 JsonValue *NewJsonString(const char *Key, long keylen, StrBuf *CopyMe)
106 {
107         JsonValue *Ret;
108
109         Ret = (JsonValue*) malloc(sizeof(JsonValue));
110         memset(Ret, 0, sizeof(JsonValue));
111         Ret->Type = JSON_STRING;
112         if (Key != NULL)
113                 Ret->Name = NewStrBufPlain(Key, keylen);
114         Ret->Value = NewStrBufDup(CopyMe);
115         return Ret;
116 }
117
118 JsonValue *NewJsonPlainString(const char *Key, long keylen, const char *CopyMe, long len)
119 {
120         JsonValue *Ret;
121
122         Ret = (JsonValue*) malloc(sizeof(JsonValue));
123         memset(Ret, 0, sizeof(JsonValue));
124         Ret->Type = JSON_STRING;
125         if (Key != NULL)
126                 Ret->Name = NewStrBufPlain(Key, keylen);
127         Ret->Value = NewStrBufPlain(CopyMe, len);
128         return Ret;
129 }
130
131 JsonValue *NewJsonNull(const char *Key, long keylen)
132 {
133         JsonValue *Ret;
134
135         Ret = (JsonValue*) malloc(sizeof(JsonValue));
136         memset(Ret, 0, sizeof(JsonValue));
137         Ret->Type = JSON_NULL;
138         if (Key != NULL)
139                 Ret->Name = NewStrBufPlain(Key, keylen);
140         Ret->Value = NewStrBufPlain(HKEY("nulll"));
141         return Ret;
142 }
143
144 JsonValue *NewJsonBool(const char *Key, long keylen, int value)
145 {
146         JsonValue *Ret;
147
148         Ret = (JsonValue*) malloc(sizeof(JsonValue));
149         memset(Ret, 0, sizeof(JsonValue));
150         Ret->Type = JSON_BOOL;
151         if (Key != NULL)
152                 Ret->Name = NewStrBufPlain(Key, keylen);
153         if (value)
154                 Ret->Value = NewStrBufPlain(HKEY("true"));
155         else
156                 Ret->Value = NewStrBufPlain(HKEY("false"));
157         return Ret;
158 }
159
160 void JsonArrayAppend(JsonValue *Array, JsonValue *Val)
161 {
162         long n;
163         if (Array->Type != JSON_ARRAY)
164                 return; /* todo assert! */
165
166         n = GetCount(Array->SubValues);
167         Put(Array->SubValues, (const char*) &n, sizeof(n), Val, DeleteJSONValue);
168 }
169
170 void JsonObjectAppend(JsonValue *Array, JsonValue *Val)
171 {
172         if ((Array->Type != JSON_OBJECT) || (Val->Name == NULL))
173                 return; /* todo assert! */
174
175         Put(Array->SubValues, SKEY(Val->Name), Val, DeleteJSONValue);
176 }
177
178
179
180
181
182 void SerializeJson(StrBuf *Target, JsonValue *Val)
183 {
184         void *vValue, *vPrevious;
185         JsonValue *SubVal;
186         HashPos *It;
187         const char *Key;
188         long keylen;
189
190
191         switch (Val->Type) {
192         case JSON_STRING:
193                 StrBufAppendBufPlain(Target, HKEY("\""), 0);
194                 StrECMAEscAppend(Target, Val->Value, NULL);
195                 StrBufAppendBufPlain(Target, HKEY("\""), 0);
196                 break;
197         case JSON_NUM:
198                 StrBufAppendBuf(Target, Val->Value, 0);
199                 break;
200         case JSON_BOOL:
201                 StrBufAppendBuf(Target, Val->Value, 0);
202                 break;
203         case JSON_NULL:
204                 StrBufAppendBuf(Target, Val->Value, 0);
205                 break;
206         case JSON_ARRAY:
207                 vPrevious = NULL;
208                 StrBufAppendBufPlain(Target, HKEY("["), 0);
209                 It = GetNewHashPos(Val->SubValues, 0);
210                 while (GetNextHashPos(Val->SubValues, 
211                                       It,
212                                       &keylen, &Key, 
213                                       &vValue)){
214                         if (vPrevious != NULL) 
215                                 StrBufAppendBufPlain(Target, HKEY(","), 0);
216
217                         SubVal = (JsonValue*) vValue;
218                         SerializeJson(Target, SubVal);
219                         vPrevious = vValue;
220                 }
221                 StrBufAppendBufPlain(Target, HKEY("]"), 0);
222                 break;
223         case JSON_OBJECT:
224                 vPrevious = NULL;
225                 StrBufAppendBufPlain(Target, HKEY("{"), 0);
226                 It = GetNewHashPos(Val->SubValues, 0);
227                 while (GetNextHashPos(Val->SubValues, 
228                                       It,
229                                       &keylen, &Key, 
230                                       &vValue)){
231                         SubVal = (JsonValue*) vValue;
232
233                         if (vPrevious != NULL) {
234                                 StrBufAppendBufPlain(Target, HKEY(","), 0);
235                         }
236                         StrBufAppendBufPlain(Target, HKEY("\""), 0);
237                         StrBufAppendBuf(Target, SubVal->Name, 0);
238                         StrBufAppendBufPlain(Target, HKEY("\":"), 0);
239
240                         SerializeJson(Target, SubVal);
241                         vPrevious = vValue;
242                 }
243                 StrBufAppendBufPlain(Target, HKEY("}"), 0);
244                 break;
245         }
246
247 }
248
249