]> git.cworth.org Git - apitrace/blob - json.hpp
Dump all texture units, not just the first.
[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         } else {
70             if (space == '\n') {
71                 newline();
72             }
73         }
74     }
75
76     void escapeAsciiString(const char *str) {
77         os << "\"";
78
79         const unsigned char *src = (const unsigned char *)str;
80         unsigned char c;
81         while ((c = *src++)) {
82             if ((c == '\"') ||
83                 (c == '\\')) {
84                 // escape character
85                 os << '\\' << (unsigned char)c;
86             } else if ((c >= 0x20 && c <= 0x7e) ||
87                         c == '\t' ||
88                         c == '\r' ||
89                         c == '\n') {
90                 // pass-through character
91                 os << (unsigned char)c;
92             } else {
93                 assert(0);
94                 os << "?";
95             }
96         }
97
98         os << "\"";
99     }
100
101     void escapeUnicodeString(const char *str) {
102         os << "\"";
103
104         const char *locale = setlocale(LC_CTYPE, "");
105         const char *src = str;
106         mbstate_t state;
107
108         memset(&state, 0, sizeof state);
109
110         do {
111             // Convert characters one at a time in order to recover from
112             // conversion errors
113             wchar_t c;
114             size_t written = mbsrtowcs(&c, &src, 1, &state);
115             if (written == 0) {
116                 // completed
117                 break;
118             } if (written == (size_t)-1) {
119                 // conversion error -- skip 
120                 os << "?";
121                 do {
122                     ++src;
123                 } while (*src & 0x80);
124             } else if ((c == '\"') ||
125                        (c == '\\')) {
126                 // escape character
127                 os << '\\' << (unsigned char)c;
128             } else if ((c >= 0x20 && c <= 0x7e) ||
129                         c == '\t' ||
130                         c == '\r' ||
131                         c == '\n') {
132                 // pass-through character
133                 os << (unsigned char)c;
134             } else {
135                 // unicode
136                 os << "\\u" << std::setfill('0') << std::hex << std::setw(4) << (unsigned)c;
137                 os << std::dec;
138             }
139         } while (src);
140
141         setlocale(LC_CTYPE, locale);
142
143         os << "\"";
144     }
145
146 public:
147     JSONWriter(std::ostream &_os) : 
148         os(_os), 
149         level(0),
150         value(false),
151         space(0)
152     {
153         beginObject();
154     }
155
156     ~JSONWriter() {
157         endObject();
158         newline();
159     }
160
161     inline void beginObject() {
162         separator();
163         os << "{";
164         ++level;
165         value = false;
166     }
167
168     inline void endObject() {
169         --level;
170         if (value)
171             newline();
172         os << "}";
173         value = true;
174         space = '\n';
175     }
176
177     inline void beginMember(const char * name) {
178         space = 0;
179         separator();
180         newline();
181         escapeAsciiString(name);
182         os << ": ";
183         value = false;
184     }
185
186     inline void endMember(void) {
187         assert(value);
188         value = true;
189         space = 0;
190     }
191
192     inline void beginArray() {
193         separator();
194         os << "[";
195         ++level;
196         value = false;
197         space = 0;
198     }
199
200     inline void endArray(void) {
201         --level;
202         if (space == '\n') {
203             newline();
204         }
205         os << "]";
206         value = true;
207         space = '\n';
208     }
209
210     inline void writeString(const char *s) {
211         separator();
212         escapeUnicodeString(s);
213         value = true;
214         space = ' ';
215     }
216
217     inline void writeNull(void) {
218         separator();
219         os << "null";
220         value = true;
221         space = ' ';
222     }
223
224     inline void writeBool(bool b) {
225         separator();
226         os << (b ? "true" : "false");
227         value = true;
228         space = ' ';
229     }
230
231     template<class T>
232     void writeNumber(T n) {
233         separator();
234         os << std::dec << n;
235         value = true;
236         space = ' ';
237     }
238 };
239
240 #endif /* _JSON_HPP_ */