namespace Msp {
namespace DataFile {
-BinaryWriter::BinaryWriter(ostream &o):
+BinaryWriter::BinaryWriter(IO::Base &o):
WriterMode(o),
- next_st_id(3),
- next_enum_id(1)
+ next_kwd_id(3),
+ next_str_id(1)
{
- dict[DictEntry("__kw", "iss")]=1;
- dict[DictEntry("__enum", "is")]=1;
+ dict[DictEntry("__kwd", "iss")] = 1;
+ dict[DictEntry("__str", "is")] = 2;
}
void BinaryWriter::write(const Statement &st)
void BinaryWriter::write_(const Statement &st)
{
- Dictionary::iterator i=dict.find(create_entry(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)
+ for(ValueArray::const_iterator j = st.args.begin(); j!=st.args.end(); ++j)
switch(j->get_type())
{
case INTEGER: write_int (j->get<long long>()); break;
}
write_int(st.sub.size());
- for(list<Statement>::const_iterator j=st.sub.begin(); j!=st.sub.end(); ++j)
+ for(list<Statement>::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";
+ static const char types[] = "ifsbe";
string args;
- for(ValueArray::const_iterator i=st.args.begin(); i!=st.args.end(); ++i)
+ 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()];
+ args += types[i->get_type()];
}
return DictEntry(st.keyword, args);
void BinaryWriter::collect_keywords(const Statement &st)
{
- DictEntry de=create_entry(st);
+ DictEntry de = create_entry(st);
if(!dict.count(de))
{
Statement kst;
- kst.keyword="__kw";
- kst.args.push_back(next_st_id);
+ kst.keyword = "__kwd";
+ kst.args.push_back(next_kwd_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;
+ dict[de] = next_kwd_id++;
}
- for(ValueArray::const_iterator i=st.args.begin(); i!=st.args.end(); ++i)
- if(i->get_type()==ENUM && !enums.count(i->get_raw()))
+ for(ValueArray::const_iterator i = st.args.begin(); i!=st.args.end(); ++i)
+ {
+ const Type t = i->get_type();
+ const string &r = i->get_raw();
+ if((t==ENUM || (t==STRING && r.size()<32)) && !strings.count(r))
{
- Statement est;
- est.keyword="__enum";
- est.args.push_back(next_enum_id);
- est.args.push_back(i->get_raw());
- write_(est);
+ Statement sst;
+ sst.keyword = "__str";
+ sst.args.push_back(next_str_id);
+ sst.args.push_back(r);
+ write_(sst);
- enums[i->get_raw()]=next_enum_id++;
+ strings[r] = next_str_id++;
}
+ }
- for(list<Statement>::const_iterator i=st.sub.begin(); i!=st.sub.end(); ++i)
+ for(list<Statement>::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));
+ unsigned i = sizeof(long long)-1;
+
+ if(n>=0)
+ for(; (i>0 && (n>>(i*7-1))==0); --i) ;
+ else
+ for(; (i>0 && (n>>(i*7-1))==-1); --i) ;
+
+ for(++i; 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());
+ StringMap::const_iterator i = strings.find(s);
+ if(i!=strings.end())
+ write_int(-static_cast<int>(i->second));
+ else
+ {
+ write_int(s.size());
+ out.write(s.data(), s.size());
+ }
}
void BinaryWriter::write_float(float f)
char d[sizeof(float)];
};
- v=f;
+ v = f;
#if BYTE_ORDER == LITTLE_ENDIAN
- for(unsigned i=sizeof(float); i--;)
+ for(unsigned i = sizeof(float); i--;)
out.put(d[i]);
#else
- for(unsigned i=0; i<sizeof(float); ++i)
+ for(unsigned i = 0; i<sizeof(float); ++i)
out.put(d[i]);
#endif
}
void BinaryWriter::write_enum(const string &e)
{
- EnumMap::const_iterator i=enums.find(e);
- if(i==enums.end())
+ StringMap::const_iterator i = strings.find(e);
+ if(i==strings.end())
throw InvalidParameterValue("Unknown enum");
write_int(i->second);
}