X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbinarywriter.cpp;h=0fbf8ce503058f5aaa89734250856777e083409e;hb=HEAD;hp=c1e53fb5f23e7ca3622697c4e5e829383aeafd2f;hpb=5fd2c13c3036ea6a767802fdc9a2ab809ef8ec17;p=libs%2Fdatafile.git diff --git a/source/binarywriter.cpp b/source/binarywriter.cpp index c1e53fb..87111f0 100644 --- a/source/binarywriter.cpp +++ b/source/binarywriter.cpp @@ -1,5 +1,8 @@ +#include #include #include "binarywriter.h" +#include "binfloat.h" +#include "output.h" #include "statement.h" using namespace std; @@ -7,13 +10,23 @@ using namespace std; namespace Msp { namespace DataFile { -BinaryWriter::BinaryWriter(IO::Base &o): - WriterMode(o), - next_kwd_id(3), - next_str_id(1) +BinaryWriter::BinaryWriter(Output &o): + WriterMode(o) { - dict[DictEntry("__kwd", "iss")] = 1; - dict[DictEntry("__str", "is")] = 2; + dict[StatementKey("__kwd", "iss")] = -1; + dict[StatementKey("__str", "is")] = -2; + dict[StatementKey("__flt", "i")] = -3; +} + +void BinaryWriter::set_float_precision(unsigned fp) +{ + if(fp<16 || fp>64 || fp%8) + throw invalid_argument("BinaryWriter::set_float_precision"); + float_precision = fp; + Statement fst; + fst.keyword = "__flt"; + fst.args.push_back(float_precision); + write_(fst); } void BinaryWriter::write(const Statement &st) @@ -24,49 +37,49 @@ void BinaryWriter::write(const Statement &st) void BinaryWriter::write_(const Statement &st) { - unsigned id = get_item(dict, DictEntry(st.keyword, st.get_signature())); + int id = get_item(dict, StatementKey(st.keyword, st.get_signature())); write_int(id); - for(Statement::Arguments::const_iterator j = st.args.begin(); j!=st.args.end(); ++j) - switch(j->get_signature()) + for(const Value &a: st.args) + switch(a.get_signature()) { - case IntType::signature: write_int (j->get()); break; - case StringType::signature: write_string(j->get()); break; - case BoolType::signature: write_int (j->get()); break; - case FloatType::signature: write_float (j->get()); break; - case SymbolType::signature: write_symbol(j->get()); break; + case IntType::signature: write_int (a.get()); break; + case StringType::signature: write_string(a.get()); break; + case BoolType::signature: write_int (a.get()); break; + case FloatType::signature: write_float (a.get()); break; + case SymbolType::signature: write_symbol(a.get()); break; } write_int(st.sub.size()); - for(list::const_iterator j = st.sub.begin(); j!=st.sub.end(); ++j) - write(*j); + for(const Statement &s: st.sub) + write(s); } void BinaryWriter::collect_keywords(const Statement &st) { - DictEntry de(st.keyword, st.get_signature()); + StatementKey key(st.keyword, st.get_signature()); - if(!dict.count(de)) + if(!dict.count(key)) { Statement kst; kst.keyword = "__kwd"; kst.args.push_back(next_kwd_id); - kst.args.push_back(de.keyword); - kst.args.push_back(de.args); + kst.args.push_back(key.keyword); + kst.args.push_back(key.signature); write_(kst); - dict[de] = next_kwd_id++; + dict[key] = next_kwd_id++; } - for(ValueArray::const_iterator i = st.args.begin(); i!=st.args.end(); ++i) + for(const Value &a: st.args) { - char sig = i->get_signature(); + char sig = a.get_signature(); string str; if(sig==SymbolType::signature) - str = i->get().name; + str = a.get().name; else if(sig==StringType::signature) { - str = i->get(); + str = a.get(); if(str.size()>32) continue; } @@ -85,8 +98,8 @@ void BinaryWriter::collect_keywords(const Statement &st) strings[str] = next_str_id++; } - for(list::const_iterator i = st.sub.begin(); i!=st.sub.end(); ++i) - collect_keywords(*i); + for(const Statement &s: st.sub) + collect_keywords(s); } void BinaryWriter::write_int(IntType::Store n) @@ -110,26 +123,50 @@ void BinaryWriter::write_string(const StringType::Store &s) else { write_int(s.size()); - out.write(s.data(), s.size()); + out.write(s); } } void BinaryWriter::write_float(FloatType::Store f) { - union + BinFloat bf; + + if(numeric_limits::is_iec559) + bf = BinFloat::explode_iec559(f); + else { - float v; - char d[sizeof(float)]; - }; - - v = f; -#if BYTE_ORDER == LITTLE_ENDIAN - for(unsigned i = sizeof(float); i--;) - out.put(d[i]); -#else - for(unsigned i = 0; if)) + bf.infinity = true; + else if(f!=0) + { + for(; f<1; f*=2) + --bf.exponent; + for(; f>=2; f/=2) + ++bf.exponent; + for(unsigned i=0; i<64; ++i) + { + bf.mantissa <<= 1; + if(f>=1) + { + bf.mantissa |= 1; + f -= 1; + } + f *= 2; + } + } + } + + uint64_t encoded = bf.compose(float_precision); + for(unsigned i=float_precision/8; i--; ) + out.put((encoded>>(i*8))&0xFF); } void BinaryWriter::write_symbol(const SymbolType::Store &s)