]> git.cworth.org Git - apitrace/blob - trace_parser.hpp
Rename GL spec parser.
[apitrace] / trace_parser.hpp
1 /**************************************************************************
2  *
3  * Copyright 2010 VMware, Inc.
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 #ifndef _TRACE_PARSER_HPP_
27 #define _TRACE_PARSER_HPP_
28
29
30 #include <cassert>
31
32 #include <iostream>
33 #include <map>
34 #include <string>
35
36 #include <zlib.h>
37
38 #include "trace_format.hpp"
39 #include "trace_model.hpp"
40
41
42 namespace Trace {
43
44
45 class Parser
46 {
47 protected:
48    gzFile file;
49
50    typedef std::map<size_t, std::string> namemap;
51    namemap names;
52
53 public:
54    Parser() {
55       file = NULL;
56    }
57
58    ~Parser() {
59       close();
60    }
61
62    bool open(const char *filename) {
63       unsigned long long version;
64
65       file = gzopen(filename, "rb");
66       if (!file) {
67          return false;
68       }
69
70       version = read_uint();
71       if (version != TRACE_VERSION) {
72          std::cerr << "error: unsupported format version" << version << "\n";
73          return false;
74       }
75
76       return true;
77    }
78
79    void close(void) {
80       if (file) {
81          gzclose(file);
82          file = NULL;
83       }
84    }
85
86    Call *parse_call(void) {
87       Call *call = new Call;
88       call->name = read_name();
89       do {
90          int c = read_byte();
91          switch(c) {
92          case Trace::CALL_END:
93             return call;
94          case Trace::CALL_ARG:
95             parse_arg(call);
96             break;
97          case Trace::CALL_RET:
98             call->ret = parse_value();
99             break;
100          default:
101             std::cerr << "error: unknown call detail " << c << "\n";
102             assert(0);
103             /* fallthrough */
104          case -1:
105             delete call;
106             return NULL;
107          }
108       } while(true);
109    }
110    
111    void parse_arg(Call *call) {
112       unsigned index = read_uint();
113       std::string name = read_name();
114       Value *value = parse_value();
115       if (index >= call->args.size()) {
116           call->args.resize(index + 1);
117       }
118       call->args[index] = Arg(name, value);
119    }
120    
121    Value *parse_value(void) {
122       int c;
123       c = read_byte();
124       switch(c) {
125       case Trace::TYPE_NULL:
126          return new Null;
127       case Trace::TYPE_FALSE:
128          return new Bool(false);
129       case Trace::TYPE_TRUE:
130          return new Bool(true);
131       case Trace::TYPE_SINT:
132          return parse_sint();
133       case Trace::TYPE_UINT:
134          return parse_uint();
135       case Trace::TYPE_FLOAT:
136          return parse_float();
137       case Trace::TYPE_DOUBLE:
138          return parse_double();
139       case Trace::TYPE_STRING:
140          return parse_string();
141       case Trace::TYPE_CONST:
142          return parse_const();
143       case Trace::TYPE_BITMASK:
144          return parse_bitmask();
145       case Trace::TYPE_ARRAY:
146          return parse_array();
147       case Trace::TYPE_STRUCT:
148          return parse_struct();
149       case Trace::TYPE_BLOB:
150          return parse_blob();
151       case Trace::TYPE_OPAQUE:
152          return parse_opaque();
153       default:
154          std::cerr << "error: unknown type " << c << "\n";
155          assert(0);
156          return NULL;
157       }
158    }
159
160    Value *parse_sint() {
161       return new SInt(-read_uint());
162    }
163    
164    Value *parse_uint() {
165       return new UInt(read_uint());
166    }
167    
168    Value *parse_float() {
169       float value;
170       gzread(file, &value, sizeof value);
171       return new Float(value);
172    }
173    
174    Value *parse_double() {
175       double value;
176       gzread(file, &value, sizeof value);
177       return new Float(value);
178    }
179    
180    Value *parse_string() {
181       return new String(read_string());
182    }
183    
184    Value *parse_const() {
185       std::string name = read_name();
186       Value *value = parse_value();
187       return new Const(name, value);
188    }
189    
190    Value *parse_bitmask() {
191       unsigned long long value = 0;
192       int c;
193       do {
194          c = read_byte();
195          switch(c) {
196          case Trace::TYPE_SINT:
197             value |= -read_uint();
198             break;
199          case Trace::TYPE_UINT:
200             value |= read_uint();
201             break;
202          case Trace::TYPE_CONST:
203             read_name();
204             break;
205          case Trace::TYPE_NULL:
206             goto done;
207          default:
208             std::cerr << "error: uexpected type " << c << "\n";
209             assert(0);
210             return NULL;
211          }
212       } while(true);
213 done:
214       return new UInt(value);
215    }
216
217    Value *parse_array(void) {
218       size_t len = read_uint();
219       Array *array = new Array(len);
220       for (size_t i = 0; i < len; ++i) {
221          array->values[i] = parse_value();
222       }
223       return array;
224    }
225    
226    Value *parse_blob(void) {
227       size_t size = read_uint();
228       Blob *blob = new Blob(size);
229       if (size) {
230           gzread(file, blob->buf, size);
231       }
232       return blob;
233    }
234    
235    Value *parse_struct() {
236       size_t length = read_uint();
237       /* XXX */
238       for (size_t i; i < length; ++i) {
239          std::string name = read_name();
240          Value *value = parse_value();
241          std::cout << "  " << name << " = " << value << "\n";
242       }
243       return NULL;
244    }
245    
246    Value *parse_opaque() {
247       unsigned long long addr;
248       addr = read_uint();
249       /* XXX */
250       return new UInt(addr);
251    }
252
253    std::string read_name(void) {
254        std::string name;
255        size_t id = read_uint();
256        if (id >= names.size()) {
257            name = read_string();
258            names[id] = name;
259            return name;
260        } else {
261            return names[id];
262        }
263    }
264    
265    std::string read_string(void) {
266       size_t len = read_uint();
267       if (!len) {
268          return std::string();
269       }
270       char * buf = new char[len];
271       gzread(file, buf, len);
272       std::string value(buf, len);
273       delete [] buf;
274 #ifdef TRACE_VERBOSE
275       std::cerr << '"' << value << '"' << "\n";
276 #endif
277       return value;
278    }
279
280    unsigned long long read_uint(void) {
281       unsigned long long value = 0;
282       int c;
283       unsigned shift = 0;
284       do {
285          c = gzgetc(file);
286          if (c == -1) {
287             break;
288          }
289          value |= (unsigned long long)(c & 0x7f) << shift;
290          shift += 7;
291       } while(c & 0x80);
292 #ifdef TRACE_VERBOSE
293       std::cerr << value << "\n";
294 #endif
295       return value;
296    }
297
298    int read_byte(void) {
299       int c = gzgetc(file);
300 #ifdef TRACE_VERBOSE
301       if (c < 0)
302          std::cerr << "EOF" << "\n";
303       else
304          std::cerr << "0x" << std::hex << c << "\n";
305 #endif
306       return c;
307    }
308 };
309
310
311 } /* namespace Trace */
312
313 #endif /* _TRACE_PARSER_HPP_ */