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