X-Git-Url: http://git.tdb.fi/?p=libs%2Fdatafile.git;a=blobdiff_plain;f=source%2Fbinarywriter.cpp;fp=source%2Fbinarywriter.cpp;h=e89def35a8eeac9dc7cab2c55202ef251e8701b8;hp=0000000000000000000000000000000000000000;hb=27630d44298cb67e075c166f4421288cc8ca117e;hpb=c4930d8d15a5a248ca921e0ed3f9bca8aa18b322 diff --git a/source/binarywriter.cpp b/source/binarywriter.cpp new file mode 100644 index 0000000..e89def3 --- /dev/null +++ b/source/binarywriter.cpp @@ -0,0 +1,141 @@ +/* $Id$ + +This file is part of libmspdatafile +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include "binarywriter.h" +#include "statement.h" + +using namespace std; + +namespace Msp { +namespace DataFile { + +BinaryWriter::BinaryWriter(ostream &o): + WriterMode(o), + next_st_id(3), + next_enum_id(1) +{ + dict[DictEntry("__kw", "iss")]=1; + dict[DictEntry("__enum", "is")]=1; +} + +void BinaryWriter::write(const Statement &st) +{ + collect_keywords(st); + write_(st); +} + +void BinaryWriter::write_(const Statement &st) +{ + Dictionary::iterator i=dict.find(create_entry(st)); + if(i==dict.end()) + throw InvalidParameterValue("Unknown statement"); + + write_int(i->second); + for(ValueArray::const_iterator j=st.args.begin(); j!=st.args.end(); ++j) + switch(j->get_type()) + { + case INTEGER: write_int (j->get()); break; + case STRING: write_string(j->get()); break; + case BOOLEAN: write_int (j->get()); break; + case FLOAT: write_float (j->get()); break; + case ENUM: write_enum (j->get_raw()); break; + } + + write_int(st.sub.size()); + for(list::const_iterator j=st.sub.begin(); j!=st.sub.end(); ++j) + write(*j); +} + +DictEntry BinaryWriter::create_entry(const Statement &st) +{ + static const char types[]="ifsbe"; + + string args; + for(ValueArray::const_iterator i=st.args.begin(); i!=st.args.end(); ++i) + { + if(i->get_type()>=5) + throw InvalidParameterValue("Invalid argument type"); + args+=types[i->get_type()]; + } + + return DictEntry(st.keyword, args); +} + +void BinaryWriter::collect_keywords(const Statement &st) +{ + DictEntry de=create_entry(st); + + if(!dict.count(de)) + { + Statement kst; + kst.keyword="__kw"; + kst.args.push_back(next_st_id); + kst.args.push_back(de.keyword); + kst.args.push_back(de.args); + write_(kst); + + dict.insert(Dictionary::value_type(de, next_st_id++)).first; + } + + for(ValueArray::const_iterator i=st.args.begin(); i!=st.args.end(); ++i) + if(i->get_type()==ENUM && !enums.count(i->get_raw())) + { + Statement est; + est.keyword="__enum"; + est.args.push_back(next_enum_id); + est.args.push_back(i->get_raw()); + write_(est); + + enums[i->get_raw()]=next_enum_id++; + } + + for(list::const_iterator i=st.sub.begin(); i!=st.sub.end(); ++i) + collect_keywords(*i); +} + +void BinaryWriter::write_int(long long n) +{ + unsigned i=1; + for(; n>>(i*7); ++i); + for(; i--;) + out.put(n>>(i*7) & 0x7F | (i?0x80:0)); +} + +void BinaryWriter::write_string(const string &s) +{ + write_int(s.size()); + out.write(s.data(), s.size()); +} + +void BinaryWriter::write_float(float f) +{ + union + { + 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; isecond); +} + +} // namespace DataFile +} // namespace Msp