3 This file is part of libmspdatafile
4 Copyright © 2007-2008 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
9 #include <msp/strings/formatter.h>
10 #include "binaryparser.h"
18 BinaryParser::BinaryParser(Input &i, const string &s):
22 dict[1] = DictEntry("__kwd", "iss");
23 dict[2] = DictEntry("__str", "is");
26 Statement BinaryParser::parse()
30 Statement st = parse_statement();
31 if(st.keyword=="__kwd")
34 throw_at(TypeError("Keyword definition must have three arguments"), src);
36 const unsigned id = st.args[0].get<unsigned>();
37 const string &kw = st.args[1].get<const string &>();
38 const string &args = st.args[2].get<const string &>();
39 dict[id] = DictEntry(kw, args);
41 else if(st.keyword=="__str")
44 throw_at(TypeError("String definition must have two arguments"), src);
46 const unsigned id = st.args[0].get<unsigned>();
47 strings[id] = st.args[1].get<const string &>();
54 Statement BinaryParser::parse_statement()
56 while(first && in.peek()=='\n')
60 unsigned id = parse_int();
64 Dictionary::const_iterator i = dict.find(id);
66 throw_at(KeyError("Unknown statement ID", lexical_cast(id)), src);
67 const DictEntry &de = i->second;
70 result.keyword = de.keyword;
73 for(unsigned j = 0; j<de.args.size(); ++j)
77 case IntType::signature:
78 result.args.push_back(parse_int());
80 case FloatType::signature:
81 result.args.push_back(parse_float());
83 case StringType::signature:
84 result.args.push_back(parse_string());
86 case BoolType::signature:
87 result.args.push_back(parse_bool());
89 case SymbolType::signature:
90 result.args.push_back(Symbol(parse_enum()));
95 unsigned nsub = parse_int();
96 for(unsigned j = 0; j<nsub; ++j)
97 result.sub.push_back(parse());
104 long long BinaryParser::parse_int()
106 long long result = 0;
113 result = (result<<7) | (c&0x7F);
120 const long long mask = 1LL<<(bits-1);
121 result = (result^mask)-mask;
126 float BinaryParser::parse_float()
131 char d[sizeof(float)];
134 #if BYTE_ORDER == LITTLE_ENDIAN
135 for(unsigned i = sizeof(float); i--;)
138 for(unsigned i = 0; i<sizeof(float); ++i)
145 bool BinaryParser::parse_bool()
150 string BinaryParser::parse_string()
152 int len = parse_int();
157 for(int i = 0; i<len; ++i)
162 return lookup_string(-len);
165 string BinaryParser::parse_enum()
167 return lookup_string(parse_int());
170 const string &BinaryParser::lookup_string(unsigned id) const
172 StringMap::const_iterator i = strings.find(id);
174 throw_at(KeyError("Unknown string", lexical_cast(id)), src);
178 } // namespace DataFile