+#include <limits>
#include <sys/param.h>
#include <msp/core/maputils.h>
#include <msp/strings/format.h>
#include "binaryparser.h"
+#include "binfloat.h"
#include "input.h"
using namespace std;
BinaryParser::BinaryParser(Input &i, const string &s):
ParserMode(i, s),
- first(true)
+ first(true),
+ float_precision(32)
{
- dict[1] = DictEntry("__kwd", "iss");
- dict[2] = DictEntry("__str", "is");
+ dict[-1] = DictEntry("__kwd", "iss");
+ dict[-2] = DictEntry("__str", "is");
+ dict[-3] = DictEntry("__flt", "i");
}
Statement BinaryParser::parse()
Statement st = parse_statement();
if(st.keyword=="__kwd")
{
- if(st.args.size()!=3)
+ int id = st.args[0].get<int>();
+ if(id<=0)
throw bad_definition("__kwd");
- const unsigned id = st.args[0].get<unsigned>();
const string &kw = st.args[1].get<const string &>();
const string &args = st.args[2].get<const string &>();
+ for(string::const_iterator i=args.begin(); i!=args.end(); ++i)
+ for(unsigned j=0; valid_signatures[j]!=*i; ++j)
+ if(!valid_signatures[j])
+ throw bad_definition("__kwd");
+
dict[id] = DictEntry(kw, args);
}
else if(st.keyword=="__str")
{
- if(st.args.size()!=2)
+ int id = st.args[0].get<int>();
+ if(id<=0)
throw bad_definition("__str");
- const unsigned id = st.args[0].get<unsigned>();
strings[id] = st.args[1].get<const string &>();
}
+ else if(st.keyword=="__flt")
+ float_precision = st.args[0].get<unsigned>();
else
return st;
}
in.get();
first = false;
- unsigned id = parse_int();
+ int id = parse_int();
if(!in)
return Statement();
result.args.push_back(parse_bool());
break;
case SymbolType::signature:
- result.args.push_back(Symbol(parse_enum()));
+ result.args.push_back(parse_symbol());
break;
}
}
return result;
}
-long long BinaryParser::parse_int()
+IntType::Store BinaryParser::parse_int()
{
- long long result = 0;
+ IntType::Store result = 0;
unsigned bits = 0;
while(in)
break;
}
- const long long mask = 1LL<<(bits-1);
+ const IntType::Store mask = 1LL<<(bits-1);
result = (result^mask)-mask;
return result;
}
-float BinaryParser::parse_float()
+FloatType::Store BinaryParser::parse_float()
{
- union
+ UInt64 encoded = 0;
+ for(unsigned i=0; i<float_precision; i+=8)
+ {
+ int c = in.get();
+ encoded = (encoded<<8) | (c&0xFF);
+ }
+
+ BinFloat bf = BinFloat::explode(encoded, float_precision);
+
+ if(numeric_limits<FloatType::Store>::is_iec559)
+ return bf.compose_iec559<FloatType::Store>();
+ else
{
- float f;
- char d[sizeof(float)];
- };
-
-#if BYTE_ORDER == LITTLE_ENDIAN
- for(unsigned i = sizeof(float); i--;)
- d[i] = in.get();
-#else
- for(unsigned i = 0; i<sizeof(float); ++i)
- d[i] = in.get();
-#endif
-
- return f;
+ /* Put the float together with arithmetic since we don't know its
+ internal layout */
+ FloatType::Store f = 0;
+ if(bf.infinity)
+ {
+ if(numeric_limits<FloatType::Store>::has_infinity)
+ f = numeric_limits<FloatType::Store>::infinity();
+ else
+ f = numeric_limits<FloatType::Store>::max();
+ }
+ else
+ {
+ for(unsigned i=0; i<64; ++i)
+ {
+ f /= 2;
+ if(bf.mantissa&1)
+ f += 1;
+ bf.mantissa >>= 1;
+ }
+ for(int i=0; i<bf.exponent; ++i)
+ f *= 2;
+ for(int i=0; i>bf.exponent; --i)
+ f /= 2;
+ }
+ if(bf.sign)
+ f = -f;
+ return f;
+ }
}
-bool BinaryParser::parse_bool()
+BoolType::Store BinaryParser::parse_bool()
{
return in.get();
}
-string BinaryParser::parse_string()
+StringType::Store BinaryParser::parse_string()
{
int len = parse_int();
if(len>=0)
return get_item(strings, -len);
}
-string BinaryParser::parse_enum()
+SymbolType::Store BinaryParser::parse_symbol()
{
return get_item(strings, parse_int());
}