2 #include <msp/core/maputils.h>
3 #include "binarywriter.h"
12 BinaryWriter::BinaryWriter(IO::Base &o):
18 dict[DictEntry("__kwd", "iss")] = -1;
19 dict[DictEntry("__str", "is")] = -2;
20 dict[DictEntry("__flt", "i")] = -3;
23 void BinaryWriter::set_float_precision(unsigned fp)
25 if(fp<16 || fp>64 || fp%8)
26 throw invalid_argument("BinaryWriter::set_float_precision");
29 fst.keyword = "__flt";
30 fst.args.push_back(float_precision);
34 void BinaryWriter::write(const Statement &st)
40 void BinaryWriter::write_(const Statement &st)
42 int id = get_item(dict, DictEntry(st.keyword, st.get_signature()));
45 for(Statement::Arguments::const_iterator j = st.args.begin(); j!=st.args.end(); ++j)
46 switch(j->get_signature())
48 case IntType::signature: write_int (j->get<IntType::Store>()); break;
49 case StringType::signature: write_string(j->get<StringType::Store>()); break;
50 case BoolType::signature: write_int (j->get<BoolType::Store>()); break;
51 case FloatType::signature: write_float (j->get<FloatType::Store>()); break;
52 case SymbolType::signature: write_symbol(j->get<SymbolType::Store>()); break;
55 write_int(st.sub.size());
56 for(list<Statement>::const_iterator j = st.sub.begin(); j!=st.sub.end(); ++j)
60 void BinaryWriter::collect_keywords(const Statement &st)
62 DictEntry de(st.keyword, st.get_signature());
67 kst.keyword = "__kwd";
68 kst.args.push_back(next_kwd_id);
69 kst.args.push_back(de.keyword);
70 kst.args.push_back(de.args);
73 dict[de] = next_kwd_id++;
76 for(ValueArray::const_iterator i = st.args.begin(); i!=st.args.end(); ++i)
78 char sig = i->get_signature();
80 if(sig==SymbolType::signature)
81 str = i->get<Symbol>().name;
82 else if(sig==StringType::signature)
84 str = i->get<string>();
91 if(strings.count(str))
95 sst.keyword = "__str";
96 sst.args.push_back(next_str_id);
97 sst.args.push_back(str);
100 strings[str] = next_str_id++;
103 for(list<Statement>::const_iterator i = st.sub.begin(); i!=st.sub.end(); ++i)
104 collect_keywords(*i);
107 void BinaryWriter::write_int(IntType::Store n)
109 unsigned i = sizeof(IntType::Store)-1;
112 for(; (i>0 && (n>>(i*7-1))==0); --i) ;
114 for(; (i>0 && (n>>(i*7-1))==-1); --i) ;
117 out.put((n>>(i*7) & 0x7F) | (i?0x80:0));
120 void BinaryWriter::write_string(const StringType::Store &s)
122 StringMap::const_iterator i = strings.find(s);
124 write_int(-static_cast<int>(i->second));
128 out.write(s.data(), s.size());
132 void BinaryWriter::write_float(FloatType::Store f)
136 if(numeric_limits<FloatType::Store>::is_iec559)
137 bf = BinFloat::explode_iec559(f);
140 /* The structure of the float is unknown, so we must use arithmetic to
141 reduce it to components. */
156 for(unsigned i=0; i<64; ++i)
169 UInt64 encoded = bf.compose(float_precision);
170 for(unsigned i=float_precision/8; i--; )
171 out.put((encoded>>(i*8))&0xFF);
174 void BinaryWriter::write_symbol(const SymbolType::Store &s)
176 write_int(get_item(strings, s.name));
179 } // namespace DataFile