3 #include <msp/core/maputils.h>
4 #include <msp/strings/format.h>
5 #include "argumentstore.h"
6 #include "binaryparser.h"
10 #include "loaderaction.h"
17 BinaryParser::BinaryParser(Input &i, const string &s):
22 dict[-1] = StatementInfo("__kwd", "iss");
23 dict[-2] = StatementInfo("__str", "is");
24 dict[-3] = StatementInfo("__flt", "i");
27 Statement BinaryParser::parse()
29 const StatementKey *key;
41 key = &get_item(dict, id).key;
45 result.keyword = key->keyword;
48 for(unsigned j=0; j<key->signature.size(); ++j)
50 switch(key->signature[j])
52 case IntType::signature:
53 result.args.push_back(parse_int());
55 case FloatType::signature:
56 result.args.push_back(parse_float());
58 case StringType::signature:
59 result.args.push_back(parse_string());
61 case BoolType::signature:
62 result.args.push_back(parse_bool());
64 case SymbolType::signature:
65 result.args.push_back(parse_symbol());
70 unsigned upper_nsub = (sub_remaining.empty() ? 0 : sub_remaining.back());
72 unsigned nsub = parse_int();
73 for(unsigned j = 0; j<nsub; ++j)
74 result.sub.push_back(parse());
77 sub_remaining.back() = upper_nsub-1;
84 void BinaryParser::process_control_statement(const Statement &st)
86 if(st.keyword=="__kwd")
88 int id = st.args[0].get<int>();
90 throw bad_definition("__kwd");
92 const string &kw = st.args[1].get<const string &>();
93 const string &args = st.args[2].get<const string &>();
94 for(string::const_iterator i=args.begin(); i!=args.end(); ++i)
95 for(unsigned j=0; valid_signatures[j]!=*i; ++j)
96 if(!valid_signatures[j])
97 throw bad_definition("__kwd");
99 dict[id] = StatementInfo(kw, args);
101 else if(st.keyword=="__str")
103 int id = st.args[0].get<int>();
105 throw bad_definition("__str");
107 strings[id] = st.args[1].get<const string &>();
109 else if(st.keyword=="__flt")
110 float_precision = st.args[0].get<unsigned>();
113 const StatementKey *BinaryParser::peek(unsigned level)
115 if(level>sub_remaining.size())
116 throw nesting_error("bad level");
117 while(level<sub_remaining.size())
119 // Discard any substatements that haven't been parsed yet
120 for(unsigned i=sub_remaining.back(); i-->0; )
122 sub_remaining.pop_back();
126 if(!sub_remaining.empty() && sub_remaining.back()==0)
128 // No more substatements on this level
134 return &cur_info->key;
136 int id = parse_int();
140 cur_info = &get_item(dict, id);
141 return &cur_info->key;
144 bool BinaryParser::parse_and_load(unsigned level, Loader &ldr, const LoaderAction &act)
146 if(!cur_info && !peek(level))
149 ArgumentStore args(*cur_info);
150 for(unsigned i=0; i<cur_info->key.signature.size(); ++i)
151 switch(cur_info->key.signature[i])
153 case IntType::signature:
154 args.set(i, parse_int());
156 case FloatType::signature:
157 args.set(i, parse_float());
159 case BoolType::signature:
160 args.set(i, parse_bool());
162 case StringType::signature:
163 args.set(i, parse_string());
165 case SymbolType::signature:
166 args.set(i, parse_symbol());
170 if(!sub_remaining.empty())
171 --sub_remaining.back();
172 sub_remaining.push_back(parse_int());
175 act.execute(ldr, args);
180 IntType::Store BinaryParser::parse_int()
182 IntType::Store result = 0;
189 result = (result<<7) | (c&0x7F);
196 const IntType::Store mask = 1LL<<(bits-1);
197 result = (result^mask)-mask;
202 FloatType::Store BinaryParser::parse_float()
205 for(unsigned i=0; i<float_precision; i+=8)
208 encoded = (encoded<<8) | (c&0xFF);
211 BinFloat bf = BinFloat::explode(encoded, float_precision);
213 if(numeric_limits<FloatType::Store>::is_iec559)
214 return bf.compose_iec559<FloatType::Store>();
217 /* Put the float together with arithmetic since we don't know its
219 FloatType::Store f = 0;
222 if(numeric_limits<FloatType::Store>::has_infinity)
223 f = numeric_limits<FloatType::Store>::infinity();
225 f = numeric_limits<FloatType::Store>::max();
229 for(unsigned i=0; i<64; ++i)
236 for(int i=0; i<bf.exponent; ++i)
238 for(int i=0; i>bf.exponent; --i)
247 BoolType::Store BinaryParser::parse_bool()
252 StringType::Store BinaryParser::parse_string()
254 int len = parse_int();
259 for(int i = 0; i<len; ++i)
264 return get_item(strings, -len);
267 SymbolType::Store BinaryParser::parse_symbol()
269 return get_item(strings, parse_int());
272 } // namespace DataFile