2 #include <msp/core/maputils.h>
3 #include "binarywriter.h"
13 BinaryWriter::BinaryWriter(Output &o):
19 dict[StatementKey("__kwd", "iss")] = -1;
20 dict[StatementKey("__str", "is")] = -2;
21 dict[StatementKey("__flt", "i")] = -3;
24 void BinaryWriter::set_float_precision(unsigned fp)
26 if(fp<16 || fp>64 || fp%8)
27 throw invalid_argument("BinaryWriter::set_float_precision");
30 fst.keyword = "__flt";
31 fst.args.push_back(float_precision);
35 void BinaryWriter::write(const Statement &st)
41 void BinaryWriter::write_(const Statement &st)
43 int id = get_item(dict, StatementKey(st.keyword, st.get_signature()));
46 for(Statement::Arguments::const_iterator j = st.args.begin(); j!=st.args.end(); ++j)
47 switch(j->get_signature())
49 case IntType::signature: write_int (j->get<IntType::Store>()); break;
50 case StringType::signature: write_string(j->get<StringType::Store>()); break;
51 case BoolType::signature: write_int (j->get<BoolType::Store>()); break;
52 case FloatType::signature: write_float (j->get<FloatType::Store>()); break;
53 case SymbolType::signature: write_symbol(j->get<SymbolType::Store>()); break;
56 write_int(st.sub.size());
57 for(list<Statement>::const_iterator j = st.sub.begin(); j!=st.sub.end(); ++j)
61 void BinaryWriter::collect_keywords(const Statement &st)
63 StatementKey key(st.keyword, st.get_signature());
68 kst.keyword = "__kwd";
69 kst.args.push_back(next_kwd_id);
70 kst.args.push_back(key.keyword);
71 kst.args.push_back(key.signature);
74 dict[key] = next_kwd_id++;
77 for(vector<Value>::const_iterator i = st.args.begin(); i!=st.args.end(); ++i)
79 char sig = i->get_signature();
81 if(sig==SymbolType::signature)
82 str = i->get<Symbol>().name;
83 else if(sig==StringType::signature)
85 str = i->get<string>();
92 if(strings.count(str))
96 sst.keyword = "__str";
97 sst.args.push_back(next_str_id);
98 sst.args.push_back(str);
101 strings[str] = next_str_id++;
104 for(list<Statement>::const_iterator i = st.sub.begin(); i!=st.sub.end(); ++i)
105 collect_keywords(*i);
108 void BinaryWriter::write_int(IntType::Store n)
110 unsigned i = sizeof(IntType::Store)-1;
113 for(; (i>0 && (n>>(i*7-1))==0); --i) ;
115 for(; (i>0 && (n>>(i*7-1))==-1); --i) ;
118 out.put((n>>(i*7) & 0x7F) | (i?0x80:0));
121 void BinaryWriter::write_string(const StringType::Store &s)
123 StringMap::const_iterator i = strings.find(s);
125 write_int(-static_cast<int>(i->second));
133 void BinaryWriter::write_float(FloatType::Store f)
137 if(numeric_limits<FloatType::Store>::is_iec559)
138 bf = BinFloat::explode_iec559(f);
141 /* The structure of the float is unknown, so we must use arithmetic to
142 reduce it to components. */
157 for(unsigned i=0; i<64; ++i)
170 UInt64 encoded = bf.compose(float_precision);
171 for(unsigned i=float_precision/8; i--; )
172 out.put((encoded>>(i*8))&0xFF);
175 void BinaryWriter::write_symbol(const SymbolType::Store &s)
177 write_int(get_item(strings, s.name));
180 } // namespace DataFile