X-Git-Url: http://git.tdb.fi/?p=libs%2Fdatafile.git;a=blobdiff_plain;f=source%2Fbinaryparser.cpp;h=fa99a7e47708ba3c1d4991c16d605d9ae77c7b28;hp=ed1d71c8b197db64366e5e858b35ff032bc9b8df;hb=19179a622c1de88de5ed7047643eec79f285bf2a;hpb=cbd0ddd6ee033e46646bfb85d19232c816ea1eda diff --git a/source/binaryparser.cpp b/source/binaryparser.cpp index ed1d71c..fa99a7e 100644 --- a/source/binaryparser.cpp +++ b/source/binaryparser.cpp @@ -1,13 +1,9 @@ -/* $Id$ - -This file is part of libmspdatafile -Copyright © 2007-2008 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - +#include #include -#include +#include +#include #include "binaryparser.h" +#include "binfloat.h" #include "input.h" using namespace std; @@ -15,12 +11,25 @@ using namespace std; namespace Msp { namespace DataFile { +class bad_definition: public runtime_error +{ +public: + bad_definition(const std::string &w): + runtime_error(w) + { } + + virtual ~bad_definition() throw() { } +}; + + 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() @@ -31,9 +40,9 @@ Statement BinaryParser::parse() if(st.keyword=="__kwd") { if(st.args.size()!=3) - throw_at(TypeError("Keyword definition must have three arguments"), src); + throw bad_definition("__kwd"); - const unsigned id = st.args[0].get(); + const int id = st.args[0].get(); const string &kw = st.args[1].get(); const string &args = st.args[2].get(); dict[id] = DictEntry(kw, args); @@ -41,11 +50,13 @@ Statement BinaryParser::parse() else if(st.keyword=="__str") { if(st.args.size()!=2) - throw_at(TypeError("String definition must have two arguments"), src); + throw bad_definition("__str"); const unsigned id = st.args[0].get(); strings[id] = st.args[1].get(); } + else if(st.keyword=="__flt") + float_precision = st.args[0].get(); else return st; } @@ -57,14 +68,11 @@ Statement BinaryParser::parse_statement() in.get(); first = false; - unsigned id = parse_int(); + int id = parse_int(); if(!in) return Statement(); - Dictionary::const_iterator i = dict.find(id); - if(i==dict.end()) - throw_at(KeyError("Unknown statement ID", lexical_cast(id)), src); - const DictEntry &de = i->second; + const DictEntry &de = get_item(dict, id); Statement result; result.keyword = de.keyword; @@ -74,20 +82,20 @@ Statement BinaryParser::parse_statement() { switch(de.args[j]) { - case 'i': + case IntType::signature: result.args.push_back(parse_int()); break; - case 'f': + case FloatType::signature: result.args.push_back(parse_float()); break; - case 's': + case StringType::signature: result.args.push_back(parse_string()); break; - case 'b': + case BoolType::signature: result.args.push_back(parse_bool()); break; - case 'e': - result.args.push_back(Value(ENUM, parse_enum())); + case SymbolType::signature: + result.args.push_back(parse_symbol()); break; } } @@ -101,9 +109,9 @@ Statement BinaryParser::parse_statement() 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) @@ -117,37 +125,63 @@ long long BinaryParser::parse_int() 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::is_iec559) + return bf.compose_iec559(); + 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::has_infinity) + f = numeric_limits::infinity(); + else + f = numeric_limits::max(); + } + else + { + for(unsigned i=0; i<64; ++i) + { + f /= 2; + if(bf.mantissa&1) + f += 1; + bf.mantissa >>= 1; + } + for(int i=0; ibf.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) @@ -159,20 +193,12 @@ string BinaryParser::parse_string() return result; } else - return lookup_string(-len); -} - -string BinaryParser::parse_enum() -{ - return lookup_string(parse_int()); + return get_item(strings, -len); } -const string &BinaryParser::lookup_string(unsigned id) const +SymbolType::Store BinaryParser::parse_symbol() { - StringMap::const_iterator i = strings.find(id); - if(i==strings.end()) - throw_at(KeyError("Unknown string", lexical_cast(id)), src); - return i->second; + return get_item(strings, parse_int()); } } // namespace DataFile