2 #include <msp/core/maputils.h>
3 #include <msp/strings/format.h>
4 #include "argumentstore.h"
5 #include "binaryparser.h"
9 #include "loaderaction.h"
16 BinaryParser::BinaryParser(Input &i, const string &s):
21 dict[-1] = StatementInfo("__kwd", "iss");
22 dict[-2] = StatementInfo("__str", "is");
23 dict[-3] = StatementInfo("__flt", "i");
26 Statement BinaryParser::parse()
28 const StatementKey *key;
40 key = &get_item(dict, id).key;
44 result.keyword = key->keyword;
47 for(unsigned j=0; j<key->signature.size(); ++j)
49 switch(key->signature[j])
51 case IntType::signature:
52 result.args.push_back(parse_int());
54 case FloatType::signature:
55 result.args.push_back(parse_float());
57 case StringType::signature:
58 result.args.push_back(parse_string());
60 case BoolType::signature:
61 result.args.push_back(parse_bool());
63 case SymbolType::signature:
64 result.args.push_back(Value(parse_symbol()));
69 unsigned upper_nsub = (sub_remaining.empty() ? 0 : sub_remaining.back());
71 unsigned nsub = parse_int();
72 for(unsigned j = 0; j<nsub; ++j)
73 result.sub.push_back(parse());
76 sub_remaining.back() = upper_nsub-1;
83 void BinaryParser::process_control_statement(const Statement &st)
85 if(st.keyword=="__kwd")
87 int id = st.args[0].get<int>();
89 throw bad_definition("__kwd");
91 const string &kw = st.args[1].get<const string &>();
92 const string &args = st.args[2].get<const string &>();
94 for(unsigned j=0; valid_signatures[j]!=c; ++j)
95 if(!valid_signatures[j])
96 throw bad_definition("__kwd");
98 dict[id] = StatementInfo(kw, args);
100 else if(st.keyword=="__str")
102 int id = st.args[0].get<int>();
104 throw bad_definition("__str");
106 strings[id] = st.args[1].get<const string &>();
108 else if(st.keyword=="__flt")
109 float_precision = st.args[0].get<unsigned>();
112 const StatementKey *BinaryParser::peek(unsigned level)
114 if(level>sub_remaining.size())
115 throw nesting_error("bad level");
116 while(level<sub_remaining.size())
118 // Discard any substatements that haven't been parsed yet
119 for(unsigned i=sub_remaining.back(); i-->0; )
121 sub_remaining.pop_back();
125 if(!sub_remaining.empty() && sub_remaining.back()==0)
127 // No more substatements on this level
133 return &cur_info->key;
135 int id = parse_int();
139 cur_info = &get_item(dict, id);
140 return &cur_info->key;
143 bool BinaryParser::parse_and_load(unsigned level, Loader &ldr, const LoaderAction &act)
145 if(!cur_info && !peek(level))
148 ArgumentStore args(*cur_info);
149 for(unsigned i=0; i<cur_info->key.signature.size(); ++i)
150 switch(cur_info->key.signature[i])
152 case IntType::signature:
153 args.set(i, parse_int());
155 case FloatType::signature:
156 args.set(i, parse_float());
158 case BoolType::signature:
159 args.set(i, parse_bool());
161 case StringType::signature:
162 args.set(i, parse_string());
164 case SymbolType::signature:
165 args.set(i, parse_symbol());
169 if(!sub_remaining.empty())
170 --sub_remaining.back();
171 sub_remaining.push_back(parse_int());
174 act.execute(ldr, args);
179 IntType::Store BinaryParser::parse_int()
181 IntType::Store result = 0;
188 result = (result<<7) | (c&0x7F);
195 const IntType::Store mask = 1LL<<(bits-1);
196 result = (result^mask)-mask;
201 FloatType::Store BinaryParser::parse_float()
203 uint64_t encoded = 0;
204 for(unsigned i=0; i<float_precision; i+=8)
207 encoded = (encoded<<8) | (c&0xFF);
210 BinFloat bf = BinFloat::explode(encoded, float_precision);
212 if(numeric_limits<FloatType::Store>::is_iec559)
213 return bf.compose_iec559<FloatType::Store>();
216 /* Put the float together with arithmetic since we don't know its
218 FloatType::Store f = 0;
221 if(numeric_limits<FloatType::Store>::has_infinity)
222 f = numeric_limits<FloatType::Store>::infinity();
224 f = numeric_limits<FloatType::Store>::max();
228 for(unsigned i=0; i<64; ++i)
235 for(int i=0; i<bf.exponent; ++i)
237 for(int i=0; i>bf.exponent; --i)
246 BoolType::Store BinaryParser::parse_bool()
251 StringType::Store BinaryParser::parse_string()
253 int len = parse_int();
258 for(int i = 0; i<len; ++i)
263 return get_item(strings, -len);
266 SymbolType::Store BinaryParser::parse_symbol()
268 return get_item(strings, parse_int());
271 } // namespace DataFile