db10cad1cfdfb4e9426e7c839be1d016d646f2d4
[citadel.git] / libcitadel / lib / json.c
1 /**
2  * \defgroup Subst Variable substitution type stuff
3  * \ingroup CitadelConfig
4  *
5  * Copyright (c) 1987-2011 by the citadel.org team
6  *
7  * This program is open source software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21
22 /*@{*/
23
24 #include "sysdep.h"
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <dirent.h>
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <string.h>
33
34 #include "libcitadel.h"
35
36
37 #define JSON_STRING 0
38 #define JSON_NUM 1
39 #define JSON_NULL 2
40 #define JSON_BOOL 3
41 #define JSON_ARRAY 4
42 #define JSON_OBJECT 7
43
44 struct JsonValue {
45         int Type;
46         StrBuf *Name;
47         StrBuf *Value;
48         HashList *SubValues;
49 };
50
51
52 void DeleteJSONValue(void *vJsonValue)
53 {
54         JsonValue *Val = (JsonValue*) vJsonValue;
55         FreeStrBuf(&Val->Name);
56         FreeStrBuf(&Val->Value);
57         DeleteHash(&Val->SubValues);
58         free(Val);
59 }
60
61 JsonValue *NewJsonObject(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_OBJECT;
68         if (Key != NULL)
69                 Ret->Name = NewStrBufPlain(Key, keylen);
70         Ret->SubValues = NewHash(1, NULL);
71         return Ret;
72 }
73
74 JsonValue *NewJsonArray(const char *Key, long keylen)
75 {
76         JsonValue *Ret;
77
78         Ret = (JsonValue*) malloc(sizeof(JsonValue));
79         memset(Ret, 0, sizeof(JsonValue));
80         Ret->Type = JSON_ARRAY;
81         if (Key != NULL)
82                 Ret->Name = NewStrBufPlain(Key, keylen);
83         Ret->SubValues = NewHash(1, Flathash);
84         return Ret;
85 }
86
87
88 JsonValue *NewJsonNumber(const char *Key, long keylen, long Number)
89 {
90         JsonValue *Ret;
91
92         Ret = (JsonValue*) malloc(sizeof(JsonValue));
93         memset(Ret, 0, sizeof(JsonValue));
94         Ret->Type = JSON_NUM;
95         if (Key != NULL)
96                 Ret->Name = NewStrBufPlain(Key, keylen);
97         Ret->Value = NewStrBufPlain(NULL, 64);
98         StrBufPrintf(Ret->Value, "%ld", Number);
99         return Ret;
100 }
101
102
103
104 JsonValue *NewJsonBigNumber(const char *Key, long keylen, double Number)
105 {
106         JsonValue *Ret;
107
108         Ret = (JsonValue*) malloc(sizeof(JsonValue));
109         memset(Ret, 0, sizeof(JsonValue));
110         Ret->Type = JSON_NUM;
111         if (Key != NULL)
112                 Ret->Name = NewStrBufPlain(Key, keylen);
113         Ret->Value = NewStrBufPlain(NULL, 128);
114         StrBufPrintf(Ret->Value, "%f", Number);
115         return Ret;
116 }
117
118 JsonValue *NewJsonString(const char *Key, long keylen, StrBuf *CopyMe)
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 = NewStrBufDup(CopyMe);
128         return Ret;
129 }
130
131 JsonValue *NewJsonPlainString(const char *Key, long keylen, const char *CopyMe, long len)
132 {
133         JsonValue *Ret;
134
135         Ret = (JsonValue*) malloc(sizeof(JsonValue));
136         memset(Ret, 0, sizeof(JsonValue));
137         Ret->Type = JSON_STRING;
138         if (Key != NULL)
139                 Ret->Name = NewStrBufPlain(Key, keylen);
140         Ret->Value = NewStrBufPlain(CopyMe, len);
141         return Ret;
142 }
143
144 JsonValue *NewJsonNull(const char *Key, long keylen)
145 {
146         JsonValue *Ret;
147
148         Ret = (JsonValue*) malloc(sizeof(JsonValue));
149         memset(Ret, 0, sizeof(JsonValue));
150         Ret->Type = JSON_NULL;
151         if (Key != NULL)
152                 Ret->Name = NewStrBufPlain(Key, keylen);
153         Ret->Value = NewStrBufPlain(HKEY("nulll"));
154         return Ret;
155 }
156
157 JsonValue *NewJsonBool(const char *Key, long keylen, int value)
158 {
159         JsonValue *Ret;
160
161         Ret = (JsonValue*) malloc(sizeof(JsonValue));
162         memset(Ret, 0, sizeof(JsonValue));
163         Ret->Type = JSON_BOOL;
164         if (Key != NULL)
165                 Ret->Name = NewStrBufPlain(Key, keylen);
166         if (value)
167                 Ret->Value = NewStrBufPlain(HKEY("true"));
168         else
169                 Ret->Value = NewStrBufPlain(HKEY("false"));
170         return Ret;
171 }
172
173 void JsonArrayAppend(JsonValue *Array, JsonValue *Val)
174 {
175         long n;
176         if (Array->Type != JSON_ARRAY)
177                 return; /* todo assert! */
178
179         n = GetCount(Array->SubValues);
180         Put(Array->SubValues, (const char*) &n, sizeof(n), Val, DeleteJSONValue);
181 }
182
183 void JsonObjectAppend(JsonValue *Array, JsonValue *Val)
184 {
185         if ((Array->Type != JSON_OBJECT) || (Val->Name == NULL))
186                 return; /* todo assert! */
187
188         Put(Array->SubValues, SKEY(Val->Name), Val, DeleteJSONValue);
189 }
190
191
192
193
194
195 void SerializeJson(StrBuf *Target, JsonValue *Val, int FreeVal)
196 {
197         void *vValue, *vPrevious;
198         JsonValue *SubVal;
199         HashPos *It;
200         const char *Key;
201         long keylen;
202
203
204         switch (Val->Type) {
205         case JSON_STRING:
206                 StrBufAppendBufPlain(Target, HKEY("\""), 0);
207                 StrECMAEscAppend(Target, Val->Value, NULL);
208                 StrBufAppendBufPlain(Target, HKEY("\""), 0);
209                 break;
210         case JSON_NUM:
211                 StrBufAppendBuf(Target, Val->Value, 0);
212                 break;
213         case JSON_BOOL:
214                 StrBufAppendBuf(Target, Val->Value, 0);
215                 break;
216         case JSON_NULL:
217                 StrBufAppendBuf(Target, Val->Value, 0);
218                 break;
219         case JSON_ARRAY:
220                 vPrevious = NULL;
221                 StrBufAppendBufPlain(Target, HKEY("["), 0);
222                 It = GetNewHashPos(Val->SubValues, 0);
223                 while (GetNextHashPos(Val->SubValues, 
224                                       It,
225                                       &keylen, &Key, 
226                                       &vValue)){
227                         if (vPrevious != NULL) 
228                                 StrBufAppendBufPlain(Target, HKEY(","), 0);
229
230                         SubVal = (JsonValue*) vValue;
231                         SerializeJson(Target, SubVal, 0);
232                         vPrevious = vValue;
233                 }
234                 StrBufAppendBufPlain(Target, HKEY("]"), 0);
235                 DeleteHashPos(&It);
236                 break;
237         case JSON_OBJECT:
238                 vPrevious = NULL;
239                 StrBufAppendBufPlain(Target, HKEY("{"), 0);
240                 It = GetNewHashPos(Val->SubValues, 0);
241                 while (GetNextHashPos(Val->SubValues, 
242                                       It,
243                                       &keylen, &Key, 
244                                       &vValue)){
245                         SubVal = (JsonValue*) vValue;
246
247                         if (vPrevious != NULL) {
248                                 StrBufAppendBufPlain(Target, HKEY(","), 0);
249                         }
250                         StrBufAppendBufPlain(Target, HKEY("\""), 0);
251                         StrBufAppendBuf(Target, SubVal->Name, 0);
252                         StrBufAppendBufPlain(Target, HKEY("\":"), 0);
253
254                         SerializeJson(Target, SubVal, 0);
255                         vPrevious = vValue;
256                 }
257                 StrBufAppendBufPlain(Target, HKEY("}"), 0);
258                 DeleteHashPos(&It);
259                 break;
260         }
261         if(FreeVal) {
262                 DeleteJSONValue(Val);
263         }
264 }
265
266