3 #include <msp/core/maputils.h>
4 #include <msp/strings/format.h>
5 #include "argumentstore.h"
6 #include "binaryparser.h"
9 #include "loaderaction.h"
16 class bad_definition: public runtime_error
19 bad_definition(const std::string &w):
23 virtual ~bad_definition() throw() { }
26 class nesting_error: public logic_error
29 nesting_error(const std::string &w):
33 virtual ~nesting_error() throw() { }
37 BinaryParser::BinaryParser(Input &i, const string &s):
42 dict[-1] = StatementInfo("__kwd", "iss");
43 dict[-2] = StatementInfo("__str", "is");
44 dict[-3] = StatementInfo("__flt", "i");
47 Statement BinaryParser::parse()
49 const StatementKey *key;
61 key = &get_item(dict, id).key;
65 result.keyword = key->keyword;
68 for(unsigned j=0; j<key->signature.size(); ++j)
70 switch(key->signature[j])
72 case IntType::signature:
73 result.args.push_back(parse_int());
75 case FloatType::signature:
76 result.args.push_back(parse_float());
78 case StringType::signature:
79 result.args.push_back(parse_string());
81 case BoolType::signature:
82 result.args.push_back(parse_bool());
84 case SymbolType::signature:
85 result.args.push_back(parse_symbol());
90 unsigned upper_nsub = (sub_remaining.empty() ? 0 : sub_remaining.back());
92 unsigned nsub = parse_int();
93 for(unsigned j = 0; j<nsub; ++j)
94 result.sub.push_back(parse());
97 sub_remaining.back() = upper_nsub-1;
104 void BinaryParser::process_control_statement(const Statement &st)
106 if(st.keyword=="__kwd")
108 int id = st.args[0].get<int>();
110 throw bad_definition("__kwd");
112 const string &kw = st.args[1].get<const string &>();
113 const string &args = st.args[2].get<const string &>();
114 for(string::const_iterator i=args.begin(); i!=args.end(); ++i)
115 for(unsigned j=0; valid_signatures[j]!=*i; ++j)
116 if(!valid_signatures[j])
117 throw bad_definition("__kwd");
119 dict[id] = StatementInfo(kw, args);
121 else if(st.keyword=="__str")
123 int id = st.args[0].get<int>();
125 throw bad_definition("__str");
127 strings[id] = st.args[1].get<const string &>();
129 else if(st.keyword=="__flt")
130 float_precision = st.args[0].get<unsigned>();
133 const StatementKey *BinaryParser::peek(unsigned level)
135 if(level>sub_remaining.size())
136 throw nesting_error("bad level");
137 while(level<sub_remaining.size())
139 // Discard any substatements that haven't been parsed yet
140 for(unsigned i=sub_remaining.back(); i-->0; )
142 sub_remaining.pop_back();
146 if(!sub_remaining.empty() && sub_remaining.back()==0)
148 // No more substatements on this level
154 return &cur_info->key;
156 int id = parse_int();
160 cur_info = &get_item(dict, id);
161 return &cur_info->key;
164 bool BinaryParser::parse_and_load(unsigned level, Loader &ldr, const LoaderAction &act)
166 if(!cur_info && !peek(level))
169 ArgumentStore args(*cur_info);
170 for(unsigned i=0; i<cur_info->key.signature.size(); ++i)
171 switch(cur_info->key.signature[i])
173 case IntType::signature:
174 args.set(i, parse_int());
176 case FloatType::signature:
177 args.set(i, parse_float());
179 case BoolType::signature:
180 args.set(i, parse_bool());
182 case StringType::signature:
183 args.set(i, parse_string());
185 case SymbolType::signature:
186 args.set(i, parse_symbol());
190 if(!sub_remaining.empty())
191 --sub_remaining.back();
192 sub_remaining.push_back(parse_int());
195 act.execute(ldr, args);
200 IntType::Store BinaryParser::parse_int()
202 IntType::Store result = 0;
209 result = (result<<7) | (c&0x7F);
216 const IntType::Store mask = 1LL<<(bits-1);
217 result = (result^mask)-mask;
222 FloatType::Store BinaryParser::parse_float()
225 for(unsigned i=0; i<float_precision; i+=8)
228 encoded = (encoded<<8) | (c&0xFF);
231 BinFloat bf = BinFloat::explode(encoded, float_precision);
233 if(numeric_limits<FloatType::Store>::is_iec559)
234 return bf.compose_iec559<FloatType::Store>();
237 /* Put the float together with arithmetic since we don't know its
239 FloatType::Store f = 0;
242 if(numeric_limits<FloatType::Store>::has_infinity)
243 f = numeric_limits<FloatType::Store>::infinity();
245 f = numeric_limits<FloatType::Store>::max();
249 for(unsigned i=0; i<64; ++i)
256 for(int i=0; i<bf.exponent; ++i)
258 for(int i=0; i>bf.exponent; --i)
267 BoolType::Store BinaryParser::parse_bool()
272 StringType::Store BinaryParser::parse_string()
274 int len = parse_int();
279 for(int i = 0; i<len; ++i)
284 return get_item(strings, -len);
287 SymbolType::Store BinaryParser::parse_symbol()
289 return get_item(strings, parse_int());
292 } // namespace DataFile