X-Git-Url: http://git.tdb.fi/?p=libs%2Fdatafile.git;a=blobdiff_plain;f=source%2Fbinaryparser.cpp;h=4ed2877a4424c2389c890473a0e71918418516ba;hp=c3d53d7241d4aaa069aeee617f98b16f6a504cb8;hb=ed78b585cfc4ecb44972e346857e887b183fd7a7;hpb=2f79370bffe0bac865dc97c5114dc87c1936fbb4 diff --git a/source/binaryparser.cpp b/source/binaryparser.cpp index c3d53d7..4ed2877 100644 --- a/source/binaryparser.cpp +++ b/source/binaryparser.cpp @@ -1,14 +1,13 @@ -/* $Id$ - -This file is part of libmspdatafile -Copyright © 2007 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - +#include #include -#include +#include +#include +#include "argumentstore.h" #include "binaryparser.h" +#include "binfloat.h" +#include "except.h" #include "input.h" +#include "loaderaction.h" using namespace std; @@ -17,153 +16,257 @@ namespace DataFile { BinaryParser::BinaryParser(Input &i, const string &s): ParserMode(i, s), - first(true) + float_precision(32), + cur_info(0) { - dict[1]=DictEntry("__st", "iss"); - dict[2]=DictEntry("__enum", "is"); + dict[-1] = StatementInfo("__kwd", "iss"); + dict[-2] = StatementInfo("__str", "is"); + dict[-3] = StatementInfo("__flt", "i"); } Statement BinaryParser::parse() { - while(1) + const StatementKey *key; + if(cur_info) { - Statement st=parse_statement(); - if(st.keyword=="__st") - { - if(st.args.size()!=3) - throw TypeError(src+": Keyword definition must have three arguments"); - - const unsigned id=st.args[0].get(); - const string &kw=st.args[1].get(); - const string &args=st.args[2].get(); - dict[id]=DictEntry(kw, args); - } - else if(st.keyword=="__enum") - { - if(st.args.size()!=2) - throw TypeError(src+": Enum definition must have three arguments"); - - const unsigned id=st.args[0].get(); - enums[id]=st.args[1].get(); - } - else - return st; + key = &cur_info->key; + cur_info = 0; } -} - -Statement BinaryParser::parse_statement() -{ - while(first && in.peek()=='\n') - in.get(); - first=false; - - unsigned id=parse_int(); - if(!in) - return Statement(); + else + { + int id = parse_int(); + if(!in) + return Statement(); - Dictionary::const_iterator i=dict.find(id); - if(i==dict.end()) - throw ParseError(format("%s: Unknown statement ID %d", src, id), src, 0); - const DictEntry &de=i->second; + key = &get_item(dict, id).key; + } Statement result; - result.keyword=de.keyword; - result.source=src; + result.keyword = key->keyword; + result.source = src; - for(unsigned j=0; jsignature.size(); ++j) { - switch(de.args[j]) + switch(key->signature[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; } } - unsigned nsub=parse_int(); - for(unsigned j=0; j0) + sub_remaining.back() = upper_nsub-1; + + result.valid = true; return result; } -long long BinaryParser::parse_int() +void BinaryParser::process_control_statement(const Statement &st) { - long long result=0; - unsigned bits=0; + if(st.keyword=="__kwd") + { + int id = st.args[0].get(); + if(id<=0) + throw bad_definition("__kwd"); + + const string &kw = st.args[1].get(); + const string &args = st.args[2].get(); + 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] = StatementInfo(kw, args); + } + else if(st.keyword=="__str") + { + int id = st.args[0].get(); + if(id<=0) + throw bad_definition("__str"); + + strings[id] = st.args[1].get(); + } + else if(st.keyword=="__flt") + float_precision = st.args[0].get(); +} + +const StatementKey *BinaryParser::peek(unsigned level) +{ + if(level>sub_remaining.size()) + throw nesting_error("bad level"); + while(level0; ) + parse(); + sub_remaining.pop_back(); + cur_info = 0; + } + + if(!sub_remaining.empty() && sub_remaining.back()==0) + { + // No more substatements on this level + cur_info = 0; + return 0; + } + + if(cur_info) + return &cur_info->key; + + int id = parse_int(); + if(!in) + return 0; + + cur_info = &get_item(dict, id); + return &cur_info->key; +} + +bool BinaryParser::parse_and_load(unsigned level, Loader &ldr, const LoaderAction &act) +{ + if(!cur_info && !peek(level)) + return false; + + ArgumentStore args(*cur_info); + for(unsigned i=0; ikey.signature.size(); ++i) + switch(cur_info->key.signature[i]) + { + case IntType::signature: + args.set(i, parse_int()); + break; + case FloatType::signature: + args.set(i, parse_float()); + break; + case BoolType::signature: + args.set(i, parse_bool()); + break; + case StringType::signature: + args.set(i, parse_string()); + break; + case SymbolType::signature: + args.set(i, parse_symbol()); + break; + } + + if(!sub_remaining.empty()) + --sub_remaining.back(); + sub_remaining.push_back(parse_int()); + cur_info = 0; + + act.execute(ldr, args); + + return true; +} + +IntType::Store BinaryParser::parse_int() +{ + IntType::Store result = 0; + unsigned bits = 0; while(in) { - int c=in.get(); + int c = in.get(); - result=result<<7 | c&0x7F; - bits+=7; + result = (result<<7) | (c&0x7F); + bits += 7; if(!(c&0x80)) break; } - const long long mask=1<<(bits-1); - result=(result^mask)-mask; + 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() { - unsigned len=parse_int(); - string result; - result.reserve(len); - for(unsigned i=0; i=0) + { + string result; + result.reserve(len); + for(int i = 0; isecond; + return get_item(strings, parse_int()); } } // namespace DataFile