encode.h revision 8fc5a7f51e62cb4ae44a27bdf4176d04adc80ede
1105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// encode.h 2105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// 3105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// Licensed under the Apache License, Version 2.0 (the "License"); 4105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// you may not use this file except in compliance with the License. 5105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// You may obtain a copy of the License at 6105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// 7105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// http://www.apache.org/licenses/LICENSE-2.0 8105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// 9105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// Unless required by applicable law or agreed to in writing, software 10105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// distributed under the License is distributed on an "AS IS" BASIS, 11105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// See the License for the specific language governing permissions and 13105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// limitations under the License. 14105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// 15105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// 16105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// \file 17105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// Class to encode and decoder an fst. 18105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 19105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project#ifndef FST_LIB_ENCODE_H__ 20105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project#define FST_LIB_ENCODE_H__ 21105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 22105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project#include "fst/lib/map.h" 23105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project#include "fst/lib/rmfinalepsilon.h" 24105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 25105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectnamespace fst { 26105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 27105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectstatic const uint32 kEncodeLabels = 0x00001; 28105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectstatic const uint32 kEncodeWeights = 0x00002; 29105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 30105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectenum EncodeType { ENCODE = 1, DECODE = 2 }; 31105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 32105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// Identifies stream data as an encode table (and its endianity) 33105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectstatic const int32 kEncodeMagicNumber = 2129983209; 34105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 35105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 36105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// The following class encapsulates implementation details for the 37105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// encoding and decoding of label/weight tuples used for encoding 38105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// and decoding of Fsts. The EncodeTable is bidirectional. I.E it 39105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// stores both the Tuple of encode labels and weights to a unique 40105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project// label, and the reverse. 41105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projecttemplate <class A> class EncodeTable { 42105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public: 43105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project typedef typename A::Label Label; 44105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project typedef typename A::Weight Weight; 45105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 46105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Encoded data consists of arc input/output labels and arc weight 47105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project struct Tuple { 48105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Tuple() {} 49105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Tuple(Label ilabel_, Label olabel_, Weight weight_) 50105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project : ilabel(ilabel_), olabel(olabel_), weight(weight_) {} 51105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Tuple(const Tuple& tuple) 52105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project : ilabel(tuple.ilabel), olabel(tuple.olabel), weight(tuple.weight) {} 53105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 54105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Label ilabel; 55105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Label olabel; 56105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Weight weight; 57105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project }; 58105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 59105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Comparison object for hashing EncodeTable Tuple(s). 60105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project class TupleEqual { 61105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public: 62105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project bool operator()(const Tuple* x, const Tuple* y) const { 63105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return (x->ilabel == y->ilabel && 64105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project x->olabel == y->olabel && 65105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project x->weight == y->weight); 66105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 67105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project }; 68105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 69105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Hash function for EncodeTabe Tuples. Based on the encode flags 70105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // we either hash the labels, weights or compbination of them. 71105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project class TupleKey { 72105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project static const int kPrime = 7853; 73105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project public: 74105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project TupleKey() 75105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project : encode_flags_(kEncodeLabels | kEncodeWeights) {} 76105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 77105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project TupleKey(const TupleKey& key) 78105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project : encode_flags_(key.encode_flags_) {} 79806cdd82f0b5b1f720ee26ef3f20c8c1ec034f12Yu Shan Emily Lau 80105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project explicit TupleKey(uint32 encode_flags) 81105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project : encode_flags_(encode_flags) {} 82105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 83105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project size_t operator()(const Tuple* x) const { 84105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project int lshift = x->ilabel % kPrime; 85c8c7ca7bd769df9288575b322e10ebf1fb22e4a5Brett Chabot int rshift = sizeof(size_t) - lshift; 86c8c7ca7bd769df9288575b322e10ebf1fb22e4a5Brett Chabot size_t hash = x->ilabel << lshift; 87105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (encode_flags_ & kEncodeLabels) hash ^= x->olabel >> rshift; 88806cdd82f0b5b1f720ee26ef3f20c8c1ec034f12Yu Shan Emily Lau if (encode_flags_ & kEncodeWeights) hash ^= x->weight.Hash(); 89105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return hash; 90105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 91105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 92105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private: 93105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project int32 encode_flags_; 94105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project }; 95105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 96105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project typedef hash_map<const Tuple*, 97105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Label, 98105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project TupleKey, 99105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project TupleEqual> EncodeHash; 100105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 101105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project explicit EncodeTable(uint32 encode_flags) 102105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project : flags_(encode_flags), 103105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project encode_hash_(1024, TupleKey(encode_flags)) {} 104105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 105105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project ~EncodeTable() { 106105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project for (size_t i = 0; i < encode_tuples_.size(); ++i) { 107105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project delete encode_tuples_[i]; 108105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 109105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 110105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 111105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Given an arc encode either input/ouptut labels or input/costs or both 112105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Label Encode(const A &arc) { 113105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project const Tuple tuple(arc.ilabel, 114105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project flags_ & kEncodeLabels ? arc.olabel : 0, 115105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project flags_ & kEncodeWeights ? arc.weight : Weight::One()); 116105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project typename EncodeHash::const_iterator it = encode_hash_.find(&tuple); 117105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (it == encode_hash_.end()) { 118105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project encode_tuples_.push_back(new Tuple(tuple)); 119105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project encode_hash_[encode_tuples_.back()] = encode_tuples_.size(); 120105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return encode_tuples_.size(); 121105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } else { 122105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return it->second; 123105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 124105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 125105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 126105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // Given an encode arc Label decode back to input/output labels and costs 127105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project const Tuple* Decode(Label key) { 128105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return key <= (Label)encode_tuples_.size() ? encode_tuples_[key - 1] : 0; 129105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 130105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 131105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project bool Write(ostream &strm, const string &source) const { 132105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project WriteType(strm, kEncodeMagicNumber); 133105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project WriteType(strm, flags_); 134105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project int64 size = encode_tuples_.size(); 135105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project WriteType(strm, size); 136105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project for (size_t i = 0; i < size; ++i) { 137105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project const Tuple* tuple = encode_tuples_[i]; 138105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project WriteType(strm, tuple->ilabel); 139 WriteType(strm, tuple->olabel); 140 tuple->weight.Write(strm); 141 } 142 strm.flush(); 143 if (!strm) 144 LOG(ERROR) << "EncodeTable::Write: write failed: " << source; 145 return strm; 146 } 147 148 bool Read(istream &strm, const string &source) { 149 encode_tuples_.clear(); 150 encode_hash_.clear(); 151 int32 magic_number = 0; 152 ReadType(strm, &magic_number); 153 if (magic_number != kEncodeMagicNumber) { 154 LOG(ERROR) << "EncodeTable::Read: Bad encode table header: " << source; 155 return false; 156 } 157 ReadType(strm, &flags_); 158 int64 size; 159 ReadType(strm, &size); 160 if (!strm) { 161 LOG(ERROR) << "EncodeTable::Read: read failed: " << source; 162 return false; 163 } 164 for (size_t i = 0; i < size; ++i) { 165 Tuple* tuple = new Tuple(); 166 ReadType(strm, &tuple->ilabel); 167 ReadType(strm, &tuple->olabel); 168 tuple->weight.Read(strm); 169 encode_tuples_.push_back(tuple); 170 encode_hash_[encode_tuples_.back()] = encode_tuples_.size(); 171 } 172 if (!strm) 173 LOG(ERROR) << "EncodeTable::Read: read failed: " << source; 174 return strm; 175 } 176 177 const uint32 flags() const { return flags_; } 178 private: 179 uint32 flags_; 180 vector<Tuple*> encode_tuples_; 181 EncodeHash encode_hash_; 182 183 DISALLOW_EVIL_CONSTRUCTORS(EncodeTable); 184}; 185 186 187// A mapper to encode/decode weighted transducers. Encoding of an 188// Fst is useful for performing classical determinization or minimization 189// on a weighted transducer by treating it as an unweighted acceptor over 190// encoded labels. 191// 192// The Encode mapper stores the encoding in a local hash table (EncodeTable) 193// This table is shared (and reference counted) between the encoder and 194// decoder. A decoder has read only access to the EncodeTable. 195// 196// The EncodeMapper allows on the fly encoding of the machine. As the 197// EncodeTable is generated the same table may by used to decode the machine 198// on the fly. For example in the following sequence of operations 199// 200// Encode -> Determinize -> Decode 201// 202// we will use the encoding table generated during the encode step in the 203// decode, even though the encoding is not complete. 204// 205template <class A> class EncodeMapper { 206 typedef typename A::Weight Weight; 207 typedef typename A::Label Label; 208 public: 209 EncodeMapper(uint32 flags, EncodeType type) 210 : ref_count_(1), flags_(flags), type_(type), 211 table_(new EncodeTable<A>(flags)) {} 212 213 EncodeMapper(const EncodeMapper& mapper) 214 : ref_count_(mapper.ref_count_ + 1), 215 flags_(mapper.flags_), 216 type_(mapper.type_), 217 table_(mapper.table_) { } 218 219 // Copy constructor but setting the type, typically to DECODE 220 EncodeMapper(const EncodeMapper& mapper, EncodeType type) 221 : ref_count_(mapper.ref_count_ + 1), 222 flags_(mapper.flags_), 223 type_(type), 224 table_(mapper.table_) { } 225 226 ~EncodeMapper() { 227 if (--ref_count_ == 0) delete table_; 228 } 229 230 A operator()(const A &arc) { 231 if (type_ == ENCODE) { // labels and/or weights to single label 232 if ((arc.nextstate == kNoStateId && !(flags_ & kEncodeWeights)) || 233 (arc.nextstate == kNoStateId && (flags_ & kEncodeWeights) && 234 arc.weight == Weight::Zero())) { 235 return arc; 236 } else { 237 Label label = table_->Encode(arc); 238 return A(label, 239 flags_ & kEncodeLabels ? label : arc.olabel, 240 flags_ & kEncodeWeights ? Weight::One() : arc.weight, 241 arc.nextstate); 242 } 243 } else { 244 if (arc.nextstate == kNoStateId) { 245 return arc; 246 } else { 247 const typename EncodeTable<A>::Tuple* tuple = 248 table_->Decode(arc.ilabel); 249 return A(tuple->ilabel, 250 flags_ & kEncodeLabels ? tuple->olabel : arc.olabel, 251 flags_ & kEncodeWeights ? tuple->weight : arc.weight, 252 arc.nextstate);; 253 } 254 } 255 } 256 257 uint64 Properties(uint64 props) { 258 uint64 mask = kFstProperties; 259 if (flags_ & kEncodeLabels) 260 mask &= kILabelInvariantProperties & kOLabelInvariantProperties; 261 if (flags_ & kEncodeWeights) 262 mask &= kILabelInvariantProperties & kWeightInvariantProperties & 263 (type_ == ENCODE ? kAddSuperFinalProperties : 264 kRmSuperFinalProperties); 265 return props & mask; 266 } 267 268 269 MapFinalAction FinalAction() const { 270 return (type_ == ENCODE && (flags_ & kEncodeWeights)) ? 271 MAP_REQUIRE_SUPERFINAL : MAP_NO_SUPERFINAL; 272 } 273 274 const uint32 flags() const { return flags_; } 275 const EncodeType type() const { return type_; } 276 277 bool Write(ostream &strm, const string& source) { 278 return table_->Write(strm, source); 279 } 280 281 bool Write(const string& filename) { 282 ofstream strm(filename.c_str()); 283 if (!strm) { 284 LOG(ERROR) << "EncodeMap: Can't open file: " << filename; 285 return false; 286 } 287 return Write(strm, filename); 288 } 289 290 static EncodeMapper<A> *Read(istream &strm, 291 const string& source, EncodeType type) { 292 EncodeTable<A> *table = new EncodeTable<A>(0); 293 bool r = table->Read(strm, source); 294 return r ? new EncodeMapper(table->flags(), type, table) : 0; 295 } 296 297 static EncodeMapper<A> *Read(const string& filename, EncodeType type) { 298 ifstream strm(filename.c_str()); 299 if (!strm) { 300 LOG(ERROR) << "EncodeMap: Can't open file: " << filename; 301 return false; 302 } 303 return Read(strm, filename, type); 304 } 305 306 private: 307 uint32 ref_count_; 308 uint32 flags_; 309 EncodeType type_; 310 EncodeTable<A>* table_; 311 312 explicit EncodeMapper(uint32 flags, EncodeType type, EncodeTable<A> *table) 313 : ref_count_(1), flags_(flags), type_(type), table_(table) {} 314 void operator=(const EncodeMapper &); // Disallow. 315}; 316 317 318// Complexity: O(nstates + narcs) 319template<class A> inline 320void Encode(MutableFst<A> *fst, EncodeMapper<A>* mapper) { 321 Map(fst, mapper); 322} 323 324 325template<class A> inline 326void Decode(MutableFst<A>* fst, const EncodeMapper<A>& mapper) { 327 Map(fst, EncodeMapper<A>(mapper, DECODE)); 328 RmFinalEpsilon(fst); 329} 330 331 332// On the fly label and/or weight encoding of input Fst 333// 334// Complexity: 335// - Constructor: O(1) 336// - Traversal: O(nstates_visited + narcs_visited), assuming constant 337// time to visit an input state or arc. 338template <class A> 339class EncodeFst : public MapFst<A, A, EncodeMapper<A> > { 340 public: 341 typedef A Arc; 342 typedef EncodeMapper<A> C; 343 344 EncodeFst(const Fst<A> &fst, EncodeMapper<A>* encoder) 345 : MapFst<A, A, C>(fst, encoder, MapFstOptions()) {} 346 347 EncodeFst(const Fst<A> &fst, const EncodeMapper<A>& encoder) 348 : MapFst<A, A, C>(fst, encoder, MapFstOptions()) {} 349 350 EncodeFst(const EncodeFst<A> &fst) 351 : MapFst<A, A, C>(fst) {} 352 353 virtual EncodeFst<A> *Copy() const { return new EncodeFst(*this); } 354}; 355 356 357// On the fly label and/or weight encoding of input Fst 358// 359// Complexity: 360// - Constructor: O(1) 361// - Traversal: O(nstates_visited + narcs_visited), assuming constant 362// time to visit an input state or arc. 363template <class A> 364class DecodeFst : public MapFst<A, A, EncodeMapper<A> > { 365 public: 366 typedef A Arc; 367 typedef EncodeMapper<A> C; 368 369 DecodeFst(const Fst<A> &fst, const EncodeMapper<A>& encoder) 370 : MapFst<A, A, C>(fst, 371 EncodeMapper<A>(encoder, DECODE), 372 MapFstOptions()) {} 373 374 DecodeFst(const EncodeFst<A> &fst) 375 : MapFst<A, A, C>(fst) {} 376 377 virtual DecodeFst<A> *Copy() const { return new DecodeFst(*this); } 378}; 379 380 381// Specialization for EncodeFst. 382template <class A> 383class StateIterator< EncodeFst<A> > 384 : public StateIterator< MapFst<A, A, EncodeMapper<A> > > { 385 public: 386 explicit StateIterator(const EncodeFst<A> &fst) 387 : StateIterator< MapFst<A, A, EncodeMapper<A> > >(fst) {} 388}; 389 390 391// Specialization for EncodeFst. 392template <class A> 393class ArcIterator< EncodeFst<A> > 394 : public ArcIterator< MapFst<A, A, EncodeMapper<A> > > { 395 public: 396 ArcIterator(const EncodeFst<A> &fst, typename A::StateId s) 397 : ArcIterator< MapFst<A, A, EncodeMapper<A> > >(fst, s) {} 398}; 399 400 401// Specialization for DecodeFst. 402template <class A> 403class StateIterator< DecodeFst<A> > 404 : public StateIterator< MapFst<A, A, EncodeMapper<A> > > { 405 public: 406 explicit StateIterator(const DecodeFst<A> &fst) 407 : StateIterator< MapFst<A, A, EncodeMapper<A> > >(fst) {} 408}; 409 410 411// Specialization for DecodeFst. 412template <class A> 413class ArcIterator< DecodeFst<A> > 414 : public ArcIterator< MapFst<A, A, EncodeMapper<A> > > { 415 public: 416 ArcIterator(const DecodeFst<A> &fst, typename A::StateId s) 417 : ArcIterator< MapFst<A, A, EncodeMapper<A> > >(fst, s) {} 418}; 419 420 421// Useful aliases when using StdArc. 422typedef EncodeFst<StdArc> StdEncodeFst; 423 424typedef DecodeFst<StdArc> StdDecodeFst; 425 426} 427 428#endif // FST_LIB_ENCODE_H__ 429