]> git.cworth.org Git - apitrace/blob - trace_parser.hpp
Less opaqueness.
[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             call->args.push_back(parse_arg());
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    Arg parse_arg(void) {
106       std::string name = read_string();
107       Value *value = parse_value();
108       return Arg(name, value);
109    }
110    
111    Value *parse_value(void) {
112       int c;
113       c = read_byte();
114       switch(c) {
115       case Trace::TYPE_NULL:
116          return new Null;
117       case Trace::TYPE_FALSE:
118          return new Bool(false);
119       case Trace::TYPE_TRUE:
120          return new Bool(true);
121       case Trace::TYPE_SINT:
122          return parse_sint();
123       case Trace::TYPE_UINT:
124          return parse_uint();
125       case Trace::TYPE_FLOAT:
126          return parse_float();
127       case Trace::TYPE_DOUBLE:
128          return parse_double();
129       case Trace::TYPE_STRING:
130          return parse_string();
131       case Trace::TYPE_CONST:
132          return parse_const();
133       case Trace::TYPE_BITMASK:
134          return parse_bitmask();
135       case Trace::TYPE_ARRAY:
136          return parse_array();
137       case Trace::TYPE_STRUCT:
138          return parse_struct();
139       case Trace::TYPE_BLOB:
140          return parse_blob();
141       case Trace::TYPE_POINTER:
142          return parse_pointer();
143       case Trace::TYPE_OPAQUE:
144          return parse_opaque();
145       default:
146          std::cerr << "error: unknown type " << c << "\n";
147          assert(0);
148          return NULL;
149       }
150    }
151
152    Value *parse_sint() {
153       return new SInt(-read_uint());
154    }
155    
156    Value *parse_uint() {
157       return new UInt(read_uint());
158    }
159    
160    Value *parse_float() {
161       float value;
162       gzread(file, &value, sizeof value);
163       return new Float(value);
164    }
165    
166    Value *parse_double() {
167       double value;
168       gzread(file, &value, sizeof value);
169       return new Float(value);
170    }
171    
172    Value *parse_string() {
173       return new String(read_string());
174    }
175    
176    Value *parse_const() {
177       std::string name = read_string();
178       Value *value = parse_value();
179       return new Const(name, value);
180    }
181    
182    Value *parse_bitmask() {
183       unsigned long long value = 0;
184       int c;
185       do {
186          c = read_byte();
187          switch(c) {
188          case Trace::TYPE_SINT:
189             value |= -read_uint();
190             break;
191          case Trace::TYPE_UINT:
192             value |= read_uint();
193             break;
194          case Trace::TYPE_CONST:
195             read_string();
196             break;
197          case Trace::TYPE_NULL:
198             goto done;
199          default:
200             std::cerr << "error: uexpected type " << c << "\n";
201             assert(0);
202             return NULL;
203          }
204       } while(true);
205 done:
206       return new UInt(value);
207    }
208
209    Value *parse_array(void) {
210       size_t len = read_uint();
211       Array *array = new Array(len);
212       for (size_t i = 0; i < len; ++i) {
213          array->values[i] = parse_value();
214       }
215       return array;
216    }
217    
218    Value *parse_blob(void) {
219       size_t size = read_uint();
220       Blob *blob = new Blob(size);
221       if (size) {
222           gzread(file, blob->buf, size);
223       }
224       return blob;
225    }
226    
227    Value *parse_pointer() {
228       unsigned long long addr;
229       Value *value;
230       addr = read_uint();
231       value = parse_value();
232       if (!value)
233          value = new UInt(addr);
234       return value;
235    }
236    
237    Value *parse_struct() {
238       std::string name;
239       /* XXX */
240       name = read_string();
241       while(name.length()) {
242          Value *value = parse_value();
243          std::cout << "  " << name << " = " << value << "\n";
244          name = read_string();
245       }
246       return NULL;
247    }
248    
249    Value *parse_opaque() {
250       unsigned long long addr;
251       addr = read_uint();
252       /* XXX */
253       return new UInt(addr);
254    }
255    
256    std::string read_string(void) {
257       size_t len = read_uint();
258       if (!len) {
259          return std::string();
260       }
261       char * buf = new char[len];
262       gzread(file, buf, len);
263       std::string value(buf, len);
264       delete [] buf;
265 #ifdef TRACE_VERBOSE
266       std::cerr << '"' << value << '"' << "\n";
267 #endif
268       return value;
269    }
270
271    unsigned long long read_uint(void) {
272       unsigned long long value = 0;
273       int c;
274       unsigned shift = 0;
275       do {
276          c = gzgetc(file);
277          if (c == -1) {
278             break;
279          }
280          value |= (unsigned long long)(c & 0x7f) << shift;
281          shift += 7;
282       } while(c & 0x80);
283 #ifdef TRACE_VERBOSE
284       std::cerr << value << "\n";
285 #endif
286       return value;
287    }
288
289    int read_byte(void) {
290       int c = gzgetc(file);
291 #ifdef TRACE_VERBOSE
292       if (c < 0)
293          std::cerr << "EOF" << "\n";
294       else
295          std::cerr << "0x" << std::hex << c << "\n";
296 #endif
297       return c;
298    }
299 };
300
301
302 } /* namespace Trace */
303
304 #endif /* _TRACE_PARSER_HPP_ */