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