]> git.cworth.org Git - apitrace/blob - json.hpp
Dump the enabled textures.
[apitrace] / json.hpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 /*
27  * Trace writing functions.
28  */
29
30 #ifndef _JSON_HPP_
31 #define _JSON_HPP_
32
33 #include <assert.h>
34 #include <stddef.h>
35 #include <wchar.h>
36
37 #include <ostream>
38 #include <iomanip>
39
40
41 class JSONWriter
42 {
43 private:
44     std::ostream &os;
45
46     int level;
47     bool value;
48     char space;
49
50     void newline(void) {
51         os << "\n";
52         for (int i = 0; i < level; ++i) 
53             os << "  ";
54     }
55
56     void separator(void) {
57         if (value) {
58             os << ",";
59             switch (space) {
60             case '\0':
61                 break;
62             case '\n':
63                 newline();
64                 break;
65             default:
66                 os << space;
67                 break;
68             }
69         }
70     }
71
72     void escapeAsciiString(const char *str) {
73         os << "\"";
74
75         const unsigned char *src = (const unsigned char *)str;
76         unsigned char c;
77         while ((c = *src++)) {
78             if ((c == '\"') ||
79                 (c == '\\')) {
80                 // escape character
81                 os << '\\' << (unsigned char)c;
82             } else if ((c >= 0x20 && c <= 0x7e) ||
83                         c == '\t' ||
84                         c == '\r' ||
85                         c == '\n') {
86                 // pass-through character
87                 os << (unsigned char)c;
88             } else {
89                 assert(0);
90                 os << "?";
91             }
92         }
93
94         os << "\"";
95     }
96
97     void escapeUnicodeString(const char *str) {
98         os << "\"";
99
100         const char *locale = setlocale(LC_CTYPE, "");
101         const char *src = str;
102         mbstate_t state;
103
104         memset(&state, 0, sizeof state);
105
106         do {
107             // Convert characters one at a time in order to recover from
108             // conversion errors
109             wchar_t c;
110             size_t written = mbsrtowcs(&c, &src, 1, &state);
111             if (written == 0) {
112                 // completed
113                 break;
114             } if (written == (size_t)-1) {
115                 // conversion error -- skip 
116                 os << "?";
117                 do {
118                     ++src;
119                 } while (*src & 0x80);
120             } else if ((c == '\"') ||
121                        (c == '\\')) {
122                 // escape character
123                 os << '\\' << (unsigned char)c;
124             } else if ((c >= 0x20 && c <= 0x7e) ||
125                         c == '\t' ||
126                         c == '\r' ||
127                         c == '\n') {
128                 // pass-through character
129                 os << (unsigned char)c;
130             } else {
131                 // unicode
132                 os << "\\u" << std::setfill('0') << std::hex << std::setw(4) << (unsigned)c;
133                 os << std::dec;
134             }
135         } while (src);
136
137         setlocale(LC_CTYPE, locale);
138
139         os << "\"";
140     }
141
142 public:
143     JSONWriter(std::ostream &_os) : 
144         os(_os), 
145         level(0),
146         value(false),
147         space(0)
148     {
149         beginObject();
150     }
151
152     ~JSONWriter() {
153         endObject();
154         newline();
155     }
156
157     inline void beginObject() {
158         separator();
159         os << "{";
160         ++level;
161         value = false;
162     }
163
164     inline void endObject() {
165         --level;
166         if (value)
167             newline();
168         os << "}";
169         value = true;
170         space = '\n';
171     }
172
173     inline void beginMember(const char * name) {
174         space = 0;
175         separator();
176         newline();
177         escapeAsciiString(name);
178         os << ": ";
179         value = false;
180     }
181
182     inline void endMember(void) {
183         assert(value);
184         value = true;
185         space = 0;
186     }
187
188     inline void beginArray() {
189         separator();
190         os << "[";
191         ++level;
192         value = false;
193     }
194
195     inline void endArray(void) {
196         --level;
197         os << "]";
198         value = true;
199         space = '\n';
200     }
201
202     inline void writeString(const char *s) {
203         separator();
204         escapeUnicodeString(s);
205         value = true;
206         space = ' ';
207     }
208
209     inline void writeNull(void) {
210         separator();
211         os << "null";
212         value = true;
213         space = ' ';
214     }
215
216     inline void writeBool(bool b) {
217         separator();
218         os << (b ? "true" : "false");
219         value = true;
220         space = ' ';
221     }
222
223     template<class T>
224     void writeNumber(T n) {
225         separator();
226         os << std::dec << n;
227         value = true;
228         space = ' ';
229     }
230 };
231
232 #endif /* _JSON_HPP_ */