]> git.cworth.org Git - apitrace/blob - trace_parser.hpp
Handle null more consistently.
[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    bool parse(const char *filename) {
53       unsigned long long version;
54
55       file = gzopen(filename, "rb");
56       if (!file) {
57          return false;
58       }
59
60       version = read_uint();
61       if (version != TRACE_VERSION) {
62          std::cerr << "error: unsupported format version" << version << "\n";
63          return false;
64       }
65
66       while (!gzeof(file)) {
67          parse_call();
68       }
69
70       return true;
71    }
72
73    void parse_call(void) {
74       Call call;
75       call.name = read_string();
76       int c;
77       do {
78          c = gzgetc(file);
79          if (c == Trace::CALL_END || c == -1) {
80             break;
81          }
82          switch(c) {
83          case Trace::CALL_END:
84             return;
85          case Trace::CALL_ARG:
86             call.args.push_back(parse_arg());
87             break;
88          case Trace::CALL_RET:
89             call.ret = parse_value();
90             break;
91          default:
92             std::cerr << "error: unknown call detail " << c << "\n";
93             assert(0);
94             break;
95          }
96       } while(true);
97       handle_call(call);
98    }
99    
100    virtual void handle_call(Call &call) {
101       std::cout << call;
102    }
103
104    Arg parse_arg(void) {
105       std::string name = read_string();
106       Value *value = parse_value();
107       return Arg(name, value);
108    }
109    
110    Value *parse_value(void) {
111       int c;
112       c = gzgetc(file);
113       switch(c) {
114       case Trace::TYPE_FALSE:
115          return new Bool(false);
116       case Trace::TYPE_TRUE:
117          return new Bool(true);
118       case Trace::TYPE_SINT:
119          return parse_sint();
120       case Trace::TYPE_UINT:
121          return parse_uint();
122       case Trace::TYPE_FLOAT:
123          return parse_float();
124       case Trace::TYPE_DOUBLE:
125          return parse_double();
126       case Trace::TYPE_STRING:
127          return parse_string();
128       case Trace::TYPE_CONST:
129          return parse_const();
130       case Trace::TYPE_BITMASK:
131          return parse_bitmask();
132       case Trace::TYPE_ARRAY:
133          return parse_array();
134       case Trace::TYPE_BLOB:
135          return parse_blob();
136       case Trace::TYPE_POINTER:
137          return parse_pointer();
138       case Trace::TYPE_NULL:
139          return new Null;
140       default:
141          std::cerr << "error: unknown type " << c << "\n";
142          assert(0);
143          return NULL;
144       }
145    }
146
147    Value *parse_bool() {
148       int c;
149       c = gzgetc(file);
150       return new Bool(c);
151    }
152    
153    Value *parse_sint() {
154       return new SInt(-read_uint());
155    }
156    
157    Value *parse_uint() {
158       return new UInt(read_uint());
159    }
160    
161    Value *parse_float() {
162       float value;
163       gzread(file, &value, sizeof value);
164       return new Float(value);
165    }
166    
167    Value *parse_double() {
168       double value;
169       gzread(file, &value, sizeof value);
170       return new Float(value);
171    }
172    
173    Value *parse_string() {
174       return new String(read_string());
175    }
176    
177    Value *parse_const() {
178       std::string name = read_string();
179       Value *value = parse_value();
180       return new Const(name, value);
181    }
182    
183    Value *parse_bitmask() {
184       unsigned long long value = 0;
185       int c;
186       do {
187          c = gzgetc(file);
188          switch(c) {
189          case Trace::TYPE_SINT:
190             value |= -read_uint();
191             break;
192          case Trace::TYPE_UINT:
193             value |= read_uint();
194             break;
195          case Trace::TYPE_CONST:
196             read_string();
197             break;
198          case Trace::TYPE_NULL:
199             goto done;
200          default:
201             std::cerr << "error: uexpected type " << c << "\n";
202             assert(0);
203             return NULL;
204          }
205       } while(true);
206 done:
207       return new UInt(value);
208    }
209
210    Value *parse_array(void) {
211       size_t len = read_uint();
212       Array *array = new Array(len);
213       for (size_t i = 0; i < len; ++i) {
214          array->values[i] = parse_value();
215       }
216       return array;
217    }
218    
219    Value *parse_blob(void) {
220       size_t size = read_uint();
221       Blob *blob = new Blob(size);
222       if (size) {
223           gzread(file, blob->buf, size);
224       }
225       return blob;
226    }
227    
228    Value *parse_pointer() {
229       unsigned long long addr;
230       Value *value;
231       addr = read_uint();
232       value = parse_value();
233       if (!value)
234          value = new UInt(addr);
235       return value;
236    }
237    
238    std::string read_string(void) {
239       size_t len = read_uint();
240       char * buf = new char[len];
241       gzread(file, buf, len);
242       std::string value(buf, len);
243       delete [] buf;
244       return value;
245    }
246
247    unsigned long long read_uint(void) {
248       unsigned long long value = 0;
249       int c;
250       unsigned shift = 0;
251       do {
252          c = gzgetc(file);
253          if (c == -1) {
254             break;
255          }
256          value |= (unsigned long long)(c & 0x7f) << shift;
257          shift += 7;
258       } while(c & 0x80);
259       return value;
260    }
261 };
262
263
264 } /* namespace Trace */
265
266 #endif /* _TRACE_PARSER_HPP_ */