Home | History | Annotate | Download | only in fst
      1 
      2 // Licensed under the Apache License, Version 2.0 (the "License");
      3 // you may not use this file except in compliance with the License.
      4 // You may obtain a copy of the License at
      5 //
      6 //     http://www.apache.org/licenses/LICENSE-2.0
      7 //
      8 // Unless required by applicable law or agreed to in writing, software
      9 // distributed under the License is distributed on an "AS IS" BASIS,
     10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     11 // See the License for the specific language governing permissions and
     12 // limitations under the License.
     13 //
     14 // Copyright 2005-2010 Google, Inc.
     15 // Author: dbikel (at) google.com (Dan Bikel)
     16 //
     17 // An \ref Fst implementation that allows non-destructive edit operations on an
     18 // existing fst.
     19 
     20 #ifndef FST_LIB_EDIT_FST_H_
     21 #define FST_LIB_EDIT_FST_H_
     22 
     23 #include <vector>
     24 using std::vector;
     25 
     26 #include <fst/cache.h>
     27 
     28 #include <tr1/unordered_map>
     29 using std::tr1::unordered_map;
     30 using std::tr1::unordered_multimap;
     31 
     32 namespace fst {
     33 
     34 // The EditFst class enables non-destructive edit operations on a wrapped
     35 // ExpandedFst. The implementation uses copy-on-write semantics at the node
     36 // level: if a user has an underlying fst on which he or she wants to perform a
     37 // relatively small number of edits (read: mutations), then this implementation
     38 // will copy the edited node to an internal MutableFst and perform any edits in
     39 // situ on that copied node. This class supports all the methods of MutableFst
     40 // except for DeleteStates(const vector<StateId> &); thus, new nodes may also be
     41 // added, and one may add transitions from existing nodes of the wrapped fst to
     42 // new nodes.
     43 //
     44 // N.B.: The documentation for Fst::Copy(true) says that its behavior is
     45 // undefined if invoked on an fst that has already been accessed.  This class
     46 // requires that the Fst implementation it wraps provides consistent, reliable
     47 // behavior when its Copy(true) method is invoked, where consistent means
     48 // the graph structure, graph properties and state numbering and do not change.
     49 // VectorFst and CompactFst, for example, are both well-behaved in this regard.
     50 
     51 // The EditFstData class is a container for all mutable data for EditFstImpl;
     52 // also, this class provides most of the actual implementation of what EditFst
     53 // does (that is, most of EditFstImpl's methods delegate to methods in this, the
     54 // EditFstData class).  Instances of this class are reference-counted and can be
     55 // shared between otherwise independent EditFstImpl instances. This scheme
     56 // allows EditFstImpl to implement the thread-safe, copy-on-write semantics
     57 // required by Fst::Copy(true).
     58 //
     59 // template parameters:
     60 //   A the type of arc to use
     61 //   WrappedFstT the type of fst wrapped by the EditFst instance that
     62 //     this EditFstData instance is backing
     63 //   MutableFstT the type of mutable fst to use internally for edited states;
     64 //     crucially, MutableFstT::Copy(false) *must* yield an fst that is
     65 //     thread-safe for reading (VectorFst, for example, has this property)
     66 template <typename A,
     67           typename WrappedFstT = ExpandedFst<A>,
     68           typename MutableFstT = VectorFst<A> >
     69 class EditFstData {
     70  public:
     71   typedef A Arc;
     72   typedef typename A::Weight Weight;
     73   typedef typename A::StateId StateId;
     74   typedef typename unordered_map<StateId, StateId>::const_iterator
     75       IdMapIterator;
     76   typedef typename unordered_map<StateId, Weight>::const_iterator
     77       FinalWeightIterator;
     78 
     79 
     80   EditFstData() : num_new_states_(0) {
     81     SetEmptyAndDeleteKeysForInternalMaps();
     82   }
     83 
     84   EditFstData(const EditFstData &other) :
     85       edits_(other.edits_),
     86       external_to_internal_ids_(other.external_to_internal_ids_),
     87       edited_final_weights_(other.edited_final_weights_),
     88       num_new_states_(other.num_new_states_) {
     89   }
     90 
     91   ~EditFstData() {
     92   }
     93 
     94   static EditFstData<A, WrappedFstT, MutableFstT> *Read(istream &strm,
     95                                                         const FstReadOptions &opts);
     96 
     97   bool Write(ostream &strm, const FstWriteOptions &opts) const {
     98     // Serialize all private data members of this class.
     99     FstWriteOptions edits_opts(opts);
    100     edits_opts.write_header = true;  // Force writing contained header.
    101     edits_.Write(strm, edits_opts);
    102     WriteType(strm, external_to_internal_ids_);
    103     WriteType(strm, edited_final_weights_);
    104     WriteType(strm, num_new_states_);
    105     if (!strm) {
    106       LOG(ERROR) << "EditFstData::Write: write failed: " << opts.source;
    107       return false;
    108     }
    109     return true;
    110   }
    111 
    112   int RefCount() const { return ref_count_.count(); }
    113   int IncrRefCount() { return ref_count_.Incr(); }
    114   int DecrRefCount() { return ref_count_.Decr(); }
    115 
    116   StateId NumNewStates() const {
    117     return num_new_states_;
    118   }
    119 
    120   // accessor methods for the fst holding edited states
    121   StateId EditedStart() const {
    122     return edits_.Start();
    123   }
    124 
    125   Weight Final(StateId s, const WrappedFstT *wrapped) const {
    126     FinalWeightIterator final_weight_it = GetFinalWeightIterator(s);
    127     if (final_weight_it == NotInFinalWeightMap()) {
    128       IdMapIterator it = GetEditedIdMapIterator(s);
    129       return it == NotInEditedMap() ?
    130              wrapped->Final(s) : edits_.Final(it->second);
    131     }
    132     else {
    133       return final_weight_it->second;
    134     }
    135   }
    136 
    137   size_t NumArcs(StateId s, const WrappedFstT *wrapped) const {
    138     IdMapIterator it = GetEditedIdMapIterator(s);
    139     return it == NotInEditedMap() ?
    140            wrapped->NumArcs(s) : edits_.NumArcs(it->second);
    141   }
    142 
    143   size_t NumInputEpsilons(StateId s, const WrappedFstT *wrapped) const {
    144     IdMapIterator it = GetEditedIdMapIterator(s);
    145     return it == NotInEditedMap() ?
    146            wrapped->NumInputEpsilons(s) :
    147            edits_.NumInputEpsilons(it->second);
    148   }
    149 
    150   size_t NumOutputEpsilons(StateId s, const WrappedFstT *wrapped) const {
    151     IdMapIterator it = GetEditedIdMapIterator(s);
    152     return it == NotInEditedMap() ?
    153            wrapped->NumOutputEpsilons(s) :
    154            edits_.NumOutputEpsilons(it->second);
    155   }
    156 
    157   void SetEditedProperties(uint64 props, uint64 mask) {
    158     edits_.SetProperties(props, mask);
    159   }
    160 
    161   // non-const MutableFst operations
    162 
    163   // Sets the start state for this fst.
    164   void SetStart(StateId s) {
    165     edits_.SetStart(s);
    166   }
    167 
    168   // Sets the final state for this fst.
    169   Weight SetFinal(StateId s, Weight w, const WrappedFstT *wrapped) {
    170     Weight old_weight = Final(s, wrapped);
    171     IdMapIterator it = GetEditedIdMapIterator(s);
    172     // if we haven't already edited state s, don't add it to edited_ (which can
    173     // be expensive if s has many transitions); just use the
    174     // edited_final_weights_ map
    175     if (it == NotInEditedMap()) {
    176       edited_final_weights_[s] = w;
    177     }
    178     else {
    179       edits_.SetFinal(GetEditableInternalId(s, wrapped), w);
    180     }
    181     return old_weight;
    182   }
    183 
    184   // Adds a new state to this fst, initially with no arcs.
    185   StateId AddState(StateId curr_num_states) {
    186     StateId internal_state_id = edits_.AddState();
    187     StateId external_state_id = curr_num_states;
    188     external_to_internal_ids_[external_state_id] = internal_state_id;
    189     num_new_states_++;
    190     return external_state_id;
    191   }
    192 
    193   // Adds the specified arc to the specified state of this fst.
    194   const A *AddArc(StateId s, const Arc &arc, const WrappedFstT *wrapped) {
    195     StateId internal_id = GetEditableInternalId(s, wrapped);
    196 
    197     size_t num_arcs = edits_.NumArcs(internal_id);
    198     ArcIterator<MutableFstT> arc_it(edits_, internal_id);
    199     const A *prev_arc = NULL;
    200     if (num_arcs > 0) {
    201       // grab the final arc associated with this state in edits_
    202       arc_it.Seek(num_arcs - 1);
    203       prev_arc = &(arc_it.Value());
    204     }
    205     edits_.AddArc(internal_id, arc);
    206     return prev_arc;
    207   }
    208 
    209   void DeleteStates() {
    210     edits_.DeleteStates();
    211     num_new_states_ = 0;
    212     external_to_internal_ids_.clear();
    213     edited_final_weights_.clear();
    214   }
    215 
    216   // Removes all but the first n outgoing arcs of the specified state.
    217   void DeleteArcs(StateId s, size_t n, const WrappedFstT *wrapped) {
    218     edits_.DeleteArcs(GetEditableInternalId(s, wrapped), n);
    219   }
    220 
    221   // Removes all outgoing arcs from the specified state.
    222   void DeleteArcs(StateId s, const WrappedFstT *wrapped) {
    223     edits_.DeleteArcs(GetEditableInternalId(s, wrapped));
    224   }
    225 
    226   // end methods for non-const MutableFst operations
    227 
    228   // Provides information for the generic arc iterator.
    229   void InitArcIterator(StateId s, ArcIteratorData<Arc> *data,
    230                        const WrappedFstT *wrapped) const {
    231     IdMapIterator id_map_it = GetEditedIdMapIterator(s);
    232     if (id_map_it == NotInEditedMap()) {
    233       VLOG(3) << "EditFstData::InitArcIterator: iterating on state "
    234           << s << " of original fst";
    235       wrapped->InitArcIterator(s, data);
    236     } else {
    237       VLOG(2) << "EditFstData::InitArcIterator: iterating on edited state "
    238           << s << " (internal state id: " << id_map_it->second << ")";
    239       edits_.InitArcIterator(id_map_it->second, data);
    240     }
    241   }
    242 
    243     // Provides information for the generic mutable arc iterator.
    244   void InitMutableArcIterator(StateId s, MutableArcIteratorData<A> *data,
    245                               const WrappedFstT *wrapped) {
    246     data->base =
    247         new MutableArcIterator<MutableFstT>(&edits_,
    248                                             GetEditableInternalId(s, wrapped));
    249   }
    250 
    251   // Prints out the map from external to internal state id's (for debugging
    252   // purposes).
    253   void PrintMap() {
    254     for (IdMapIterator map_it = external_to_internal_ids_.begin();
    255         map_it != NotInEditedMap(); ++map_it) {
    256       LOG(INFO) << "(external,internal)=("
    257           << map_it->first << "," << map_it->second << ")";
    258     }
    259   }
    260 
    261 
    262  private:
    263   void SetEmptyAndDeleteKeysForInternalMaps() {
    264   }
    265 
    266   // Returns the iterator of the map from external to internal state id's
    267   // of edits_ for the specified external state id.
    268   IdMapIterator GetEditedIdMapIterator(StateId s) const {
    269     return external_to_internal_ids_.find(s);
    270   }
    271   IdMapIterator NotInEditedMap() const {
    272     return external_to_internal_ids_.end();
    273   }
    274 
    275   FinalWeightIterator GetFinalWeightIterator(StateId s) const {
    276     return edited_final_weights_.find(s);
    277   }
    278   FinalWeightIterator NotInFinalWeightMap() const {
    279     return edited_final_weights_.end();
    280   }
    281 
    282   // Returns the internal state id of the specified external id if the state has
    283   // already been made editable, or else copies the state from wrapped_
    284   // to edits_ and returns the state id of the newly editable state in edits_.
    285   //
    286   // \return makes the specified state editable if it isn't already and returns
    287   //         its state id in edits_
    288   StateId GetEditableInternalId(StateId s, const WrappedFstT *wrapped) {
    289     IdMapIterator id_map_it = GetEditedIdMapIterator(s);
    290     if (id_map_it == NotInEditedMap()) {
    291       StateId new_internal_id = edits_.AddState();
    292       VLOG(2) << "EditFstData::GetEditableInternalId: editing state " << s
    293           << " of original fst; new internal state id:" << new_internal_id;
    294       external_to_internal_ids_[s] = new_internal_id;
    295       for (ArcIterator< Fst<A> > arc_iterator(*wrapped, s);
    296           !arc_iterator.Done();
    297           arc_iterator.Next()) {
    298         edits_.AddArc(new_internal_id, arc_iterator.Value());
    299       }
    300       // copy the final weight
    301       FinalWeightIterator final_weight_it = GetFinalWeightIterator(s);
    302       if (final_weight_it == NotInFinalWeightMap()) {
    303         edits_.SetFinal(new_internal_id, wrapped->Final(s));
    304       } else {
    305         edits_.SetFinal(new_internal_id, final_weight_it->second);
    306         edited_final_weights_.erase(s);
    307       }
    308       return new_internal_id;
    309     } else {
    310       return id_map_it->second;
    311     }
    312   }
    313 
    314   // A mutable fst (by default, a VectorFst) to contain new states, and/or
    315   // copies of states from a wrapped ExpandedFst that have been modified in
    316   // some way.
    317   MutableFstT edits_;
    318   // A mapping from external state id's to the internal id's of states that
    319   // appear in edits_.
    320   unordered_map<StateId, StateId> external_to_internal_ids_;
    321   // A mapping from external state id's to final state weights assigned to
    322   // those states.  The states in this map are *only* those whose final weight
    323   // has been modified; if any other part of the state has been modified,
    324   // the entire state is copied to edits_, and all modifications reside there.
    325   unordered_map<StateId, Weight> edited_final_weights_;
    326   // The number of new states added to this mutable fst impl, which is <= the
    327   // number of states in edits_ (since edits_ contains both edited *and* new
    328   // states).
    329   StateId num_new_states_;
    330   RefCounter ref_count_;
    331 };
    332 
    333 // EditFstData method implementations: just the Read method.
    334 template <typename A, typename WrappedFstT, typename MutableFstT>
    335 EditFstData<A, WrappedFstT, MutableFstT> *
    336 EditFstData<A, WrappedFstT, MutableFstT>::Read(istream &strm,
    337                                                const FstReadOptions &opts) {
    338   EditFstData<A, WrappedFstT, MutableFstT> *data =
    339       new EditFstData<A, WrappedFstT, MutableFstT>();
    340     // next read in MutabelFstT machine that stores edits
    341   FstReadOptions edits_opts(opts);
    342   edits_opts.header = 0;  // Contained header was written out, so read it in.
    343 
    344   // Because our internal representation of edited states is a solid object
    345   // of type MutableFstT (defaults to VectorFst<A>) and not a pointer,
    346   // and because the static Read method allocates a new object on the heap,
    347   // we need to call Read, check if there was a failure, use
    348   // MutableFstT::operator= to assign the object (not the pointer) to the
    349   // edits_ data member (which will increase the ref count by 1 on the impl)
    350   // and, finally, delete the heap-allocated object.
    351   MutableFstT *edits = MutableFstT::Read(strm, edits_opts);
    352   if (!edits) {
    353     return 0;
    354   }
    355   data->edits_ = *edits;
    356   delete edits;
    357   // finally, read in rest of private data members
    358   ReadType(strm, &data->external_to_internal_ids_);
    359   ReadType(strm, &data->edited_final_weights_);
    360   ReadType(strm, &data->num_new_states_);
    361   if (!strm) {
    362     LOG(ERROR) << "EditFst::Read: read failed: " << opts.source;
    363     return 0;
    364   }
    365   return data;
    366 }
    367 
    368 // This class enables non-destructive edit operations on a wrapped ExpandedFst.
    369 // The implementation uses copy-on-write semantics at the node level: if a user
    370 // has an underlying fst on which he or she wants to perform a relatively small
    371 // number of edits (read: mutations), then this implementation will copy the
    372 // edited node to an internal MutableFst and perform any edits in situ on that
    373 // copied node. This class supports all the methods of MutableFst except for
    374 // DeleteStates(const vector<StateId> &); thus, new nodes may also be added, and
    375 // one may add transitions from existing nodes of the wrapped fst to new nodes.
    376 //
    377 // template parameters:
    378 //   A the type of arc to use
    379 //   WrappedFstT the type of fst wrapped by the EditFst instance that
    380 //     this EditFstImpl instance is backing
    381 //   MutableFstT the type of mutable fst to use internally for edited states;
    382 //     crucially, MutableFstT::Copy(false) *must* yield an fst that is
    383 //     thread-safe for reading (VectorFst, for example, has this property)
    384 template <typename A,
    385           typename WrappedFstT = ExpandedFst<A>,
    386           typename MutableFstT = VectorFst<A> >
    387 class EditFstImpl : public FstImpl<A> {
    388  public:
    389   using FstImpl<A>::SetProperties;
    390   using FstImpl<A>::SetInputSymbols;
    391   using FstImpl<A>::SetOutputSymbols;
    392   using FstImpl<A>::WriteHeader;
    393 
    394   typedef A Arc;
    395   typedef typename Arc::Weight Weight;
    396   typedef typename Arc::StateId StateId;
    397 
    398   // Constructs an editable fst implementation with no states.  Effectively,
    399   // this initially-empty fst will in every way mimic the behavior of
    400   // a VectorFst--more precisely, a VectorFstImpl instance--but with slightly
    401   // slower performance (by a constant factor), due to the fact that
    402   // this class maintains a mapping between external state id's and
    403   // their internal equivalents.
    404   EditFstImpl() {
    405     FstImpl<A>::SetType("edit");
    406     wrapped_ = new MutableFstT();
    407     InheritPropertiesFromWrapped();
    408     data_ = new EditFstData<A, WrappedFstT, MutableFstT>();
    409   }
    410 
    411   // Wraps the specified ExpandedFst. This constructor requires that the
    412   // specified Fst is an ExpandedFst instance. This requirement is only enforced
    413   // at runtime. (See below for the reason.)
    414   //
    415   // This library uses the pointer-to-implementation or "PIMPL" design pattern.
    416   // In particular, to make it convenient to bind an implementation class to its
    417   // interface, there are a pair of template "binder" classes, one for immutable
    418   // and one for mutable fst's (ImplToFst and ImplToMutableFst, respectively).
    419   // As it happens, the API for the ImplToMutableFst<I,F> class requires that
    420   // the implementation class--the template parameter "I"--have a constructor
    421   // taking a const Fst<A> reference.  Accordingly, the constructor here must
    422   // perform a static_cast to the WrappedFstT type required by EditFst and
    423   // therefore EditFstImpl.
    424   explicit EditFstImpl(const Fst<A> &wrapped)
    425       : wrapped_(static_cast<WrappedFstT *>(wrapped.Copy())) {
    426     FstImpl<A>::SetType("edit");
    427 
    428     data_ = new EditFstData<A, WrappedFstT, MutableFstT>();
    429     // have edits_ inherit all properties from wrapped_
    430     data_->SetEditedProperties(wrapped_->Properties(kFstProperties, false),
    431                                kFstProperties);
    432     InheritPropertiesFromWrapped();
    433   }
    434 
    435   // A copy constructor for this implementation class, used to implement
    436   // the Copy() method of the Fst interface.
    437   EditFstImpl(const EditFstImpl &impl)
    438       : FstImpl<A>(),
    439         wrapped_(static_cast<WrappedFstT *>(impl.wrapped_->Copy(true))),
    440         data_(impl.data_) {
    441     data_->IncrRefCount();
    442     SetProperties(impl.Properties());
    443   }
    444 
    445   ~EditFstImpl() {
    446     delete wrapped_;
    447     if (!data_->DecrRefCount()) {
    448       delete data_;
    449     }
    450   }
    451 
    452   // const Fst/ExpandedFst operations, declared in the Fst and ExpandedFst
    453   // interfaces
    454   StateId Start() const {
    455     StateId edited_start = data_->EditedStart();
    456     return edited_start == kNoStateId ? wrapped_->Start() : edited_start;
    457   }
    458 
    459   Weight Final(StateId s) const {
    460     return data_->Final(s, wrapped_);
    461   }
    462 
    463   size_t NumArcs(StateId s) const {
    464     return data_->NumArcs(s, wrapped_);
    465   }
    466 
    467   size_t NumInputEpsilons(StateId s) const {
    468     return data_->NumInputEpsilons(s, wrapped_);
    469   }
    470 
    471   size_t NumOutputEpsilons(StateId s) const {
    472     return data_->NumOutputEpsilons(s, wrapped_);
    473   }
    474 
    475   StateId NumStates() const {
    476     return wrapped_->NumStates() + data_->NumNewStates();
    477   }
    478 
    479   static EditFstImpl<A, WrappedFstT, MutableFstT> *
    480   Read(istream &strm,
    481        const FstReadOptions &opts);
    482 
    483   bool Write(ostream &strm, const FstWriteOptions &opts) const {
    484     FstHeader hdr;
    485     hdr.SetStart(Start());
    486     hdr.SetNumStates(NumStates());
    487     FstWriteOptions header_opts(opts);
    488     header_opts.write_isymbols = false;  // Let contained FST hold any symbols.
    489     header_opts.write_osymbols = false;
    490     WriteHeader(strm, header_opts, kFileVersion, &hdr);
    491 
    492     // First, serialize wrapped fst to stream.
    493     FstWriteOptions wrapped_opts(opts);
    494     wrapped_opts.write_header = true;  // Force writing contained header.
    495     wrapped_->Write(strm, wrapped_opts);
    496 
    497     data_->Write(strm, opts);
    498 
    499     strm.flush();
    500     if (!strm) {
    501       LOG(ERROR) << "EditFst::Write: write failed: " << opts.source;
    502       return false;
    503     }
    504     return true;
    505   }
    506   // end const Fst operations
    507 
    508   // non-const MutableFst operations
    509 
    510   // Sets the start state for this fst.
    511   void SetStart(StateId s) {
    512     MutateCheck();
    513     data_->SetStart(s);
    514     SetProperties(SetStartProperties(FstImpl<A>::Properties()));
    515   }
    516 
    517   // Sets the final state for this fst.
    518   void SetFinal(StateId s, Weight w) {
    519     MutateCheck();
    520     Weight old_weight = data_->SetFinal(s, w, wrapped_);
    521     SetProperties(SetFinalProperties(FstImpl<A>::Properties(), old_weight, w));
    522   }
    523 
    524   // Adds a new state to this fst, initially with no arcs.
    525   StateId AddState() {
    526     MutateCheck();
    527     SetProperties(AddStateProperties(FstImpl<A>::Properties()));
    528     return data_->AddState(NumStates());
    529   }
    530 
    531   // Adds the specified arc to the specified state of this fst.
    532   void AddArc(StateId s, const Arc &arc) {
    533     MutateCheck();
    534     const A *prev_arc = data_->AddArc(s, arc, wrapped_);
    535     SetProperties(AddArcProperties(FstImpl<A>::Properties(), s, arc, prev_arc));
    536   }
    537 
    538   void DeleteStates(const vector<StateId>& dstates) {
    539     FSTERROR() << ": EditFstImpl::DeleteStates(const std::vector<StateId>&): "
    540                << " not implemented";
    541     SetProperties(kError, kError);
    542   }
    543 
    544   // Deletes all states in this fst.
    545   void DeleteStates();
    546 
    547   // Removes all but the first n outgoing arcs of the specified state.
    548   void DeleteArcs(StateId s, size_t n) {
    549     MutateCheck();
    550     data_->DeleteArcs(s, n, wrapped_);
    551     SetProperties(DeleteArcsProperties(FstImpl<A>::Properties()));
    552   }
    553 
    554   // Removes all outgoing arcs from the specified state.
    555   void DeleteArcs(StateId s) {
    556     MutateCheck();
    557     data_->DeleteArcs(s, wrapped_);
    558     SetProperties(DeleteArcsProperties(FstImpl<A>::Properties()));
    559   }
    560 
    561   void ReserveStates(StateId s) {
    562   }
    563 
    564   void ReserveArcs(StateId s, size_t n) {
    565   }
    566 
    567   // end non-const MutableFst operations
    568 
    569   // Provides information for the generic state iterator.
    570   void InitStateIterator(StateIteratorData<Arc> *data) const {
    571     data->base = 0;
    572     data->nstates = NumStates();
    573   }
    574 
    575   // Provides information for the generic arc iterator.
    576   void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const {
    577     data_->InitArcIterator(s, data, wrapped_);
    578   }
    579 
    580   // Provides information for the generic mutable arc iterator.
    581   void InitMutableArcIterator(StateId s, MutableArcIteratorData<A> *data) {
    582     MutateCheck();
    583     data_->InitMutableArcIterator(s, data, wrapped_);
    584   }
    585 
    586  private:
    587   typedef typename unordered_map<StateId, StateId>::const_iterator
    588     IdMapIterator;
    589   typedef typename unordered_map<StateId, Weight>::const_iterator
    590     FinalWeightIterator;
    591   // Properties always true of this Fst class
    592   static const uint64 kStaticProperties = kExpanded | kMutable;
    593   // Current file format version
    594   static const int kFileVersion = 2;
    595   // Minimum file format version supported
    596   static const int kMinFileVersion = 2;
    597 
    598   // Causes this fst to inherit all the properties from its wrapped fst, except
    599   // for the two properties that always apply to EditFst instances: kExpanded
    600   // and kMutable.
    601   void InheritPropertiesFromWrapped() {
    602     SetProperties(wrapped_->Properties(kCopyProperties, false) |
    603                   kStaticProperties);
    604     SetInputSymbols(wrapped_->InputSymbols());
    605     SetOutputSymbols(wrapped_->OutputSymbols());
    606   }
    607 
    608   // This method ensures that any operations that alter the mutable data
    609   // portion of this EditFstImpl cause the data_ member to be copied when its
    610   // reference count is greater than 1.  Note that this method is distinct from
    611   // MutableFst::Mutate, which gets invoked whenever one of the basic mutation
    612   // methods defined in MutableFst is invoked, such as SetInputSymbols.
    613   // The MutateCheck here in EditFstImpl is invoked whenever one of the
    614   // mutating methods specifically related to the types of edits provided
    615   // by EditFst is performed, such as changing an arc of an existing state
    616   // of the wrapped fst via a MutableArcIterator, or adding a new state via
    617   // AddState().
    618   void MutateCheck() {
    619     if (data_->RefCount() > 1) {
    620       EditFstData<A, WrappedFstT, MutableFstT> *data_copy =
    621           new EditFstData<A, WrappedFstT, MutableFstT>(*data_);
    622       if (data_ && !data_->DecrRefCount()) {
    623         delete data_;
    624       }
    625       data_ = data_copy;
    626     }
    627   }
    628 
    629   // The fst that this fst wraps.  The purpose of this class is to enable
    630   // non-destructive edits on this wrapped fst.
    631   const WrappedFstT *wrapped_;
    632   // The mutable data for this EditFst instance, with delegates for all the
    633   // methods that can mutate data.
    634   EditFstData<A, WrappedFstT, MutableFstT> *data_;
    635 };
    636 
    637 template <typename A, typename WrappedFstT, typename MutableFstT>
    638 const uint64 EditFstImpl<A, WrappedFstT, MutableFstT>::kStaticProperties;
    639 
    640 // EditFstImpl IMPLEMENTATION STARTS HERE
    641 
    642 template<typename A, typename WrappedFstT, typename MutableFstT>
    643 inline void EditFstImpl<A, WrappedFstT, MutableFstT>::DeleteStates() {
    644   data_->DeleteStates();
    645   delete wrapped_;
    646   // we are deleting all states, so just forget about pointer to wrapped_
    647   // and do what default constructor does: set wrapped_ to a new VectorFst
    648   wrapped_ = new MutableFstT();
    649   uint64 newProps = DeleteAllStatesProperties(FstImpl<A>::Properties(),
    650                                               kStaticProperties);
    651   FstImpl<A>::SetProperties(newProps);
    652 }
    653 
    654 template <typename A, typename WrappedFstT, typename MutableFstT>
    655 EditFstImpl<A, WrappedFstT, MutableFstT> *
    656 EditFstImpl<A, WrappedFstT, MutableFstT>::Read(istream &strm,
    657                                                const FstReadOptions &opts) {
    658   EditFstImpl<A, WrappedFstT, MutableFstT> *impl = new EditFstImpl();
    659   FstHeader hdr;
    660   if (!impl->ReadHeader(strm, opts, kMinFileVersion, &hdr)) {
    661     return 0;
    662   }
    663   impl->SetStart(hdr.Start());
    664 
    665   // first, read in wrapped fst
    666   FstReadOptions wrapped_opts(opts);
    667   wrapped_opts.header = 0;  // Contained header was written out, so read it in.
    668   Fst<A> *wrapped_fst = Fst<A>::Read(strm, wrapped_opts);
    669   if (!wrapped_fst) {
    670     return 0;
    671   }
    672   impl->wrapped_ = static_cast<WrappedFstT *>(wrapped_fst);
    673 
    674   impl->data_ = EditFstData<A, WrappedFstT, MutableFstT>::Read(strm, opts);
    675 
    676   if (!impl->data_) {
    677     delete wrapped_fst;
    678     return 0;
    679   }
    680 
    681   return impl;
    682 }
    683 
    684 // END EditFstImpl IMPLEMENTATION
    685 
    686 // Concrete, editable FST.  This class attaches interface to implementation.
    687 template <typename A,
    688           typename WrappedFstT = ExpandedFst<A>,
    689           typename MutableFstT = VectorFst<A> >
    690 class EditFst :
    691   public ImplToMutableFst< EditFstImpl<A, WrappedFstT, MutableFstT> > {
    692  public:
    693   friend class MutableArcIterator< EditFst<A, WrappedFstT, MutableFstT> >;
    694 
    695   typedef A Arc;
    696   typedef typename A::StateId StateId;
    697   typedef EditFstImpl<A, WrappedFstT, MutableFstT> Impl;
    698 
    699   EditFst() : ImplToMutableFst<Impl>(new Impl()) {}
    700 
    701   explicit EditFst(const Fst<A> &fst) :
    702       ImplToMutableFst<Impl>(new Impl(fst)) {}
    703 
    704   explicit EditFst(const WrappedFstT &fst) :
    705       ImplToMutableFst<Impl>(new Impl(fst)) {}
    706 
    707   // See Fst<>::Copy() for doc.
    708   EditFst(const EditFst<A, WrappedFstT, MutableFstT> &fst, bool safe = false) :
    709     ImplToMutableFst<Impl>(fst, safe) {}
    710 
    711   virtual ~EditFst() {}
    712 
    713   // Get a copy of this EditFst. See Fst<>::Copy() for further doc.
    714   virtual EditFst<A, WrappedFstT, MutableFstT> *Copy(bool safe = false) const {
    715     return new EditFst<A, WrappedFstT, MutableFstT>(*this, safe);
    716   }
    717 
    718   EditFst<A, WrappedFstT, MutableFstT> &
    719   operator=(const EditFst<A, WrappedFstT, MutableFstT> &fst) {
    720     SetImpl(fst.GetImpl(), false);
    721     return *this;
    722   }
    723 
    724   virtual EditFst<A, WrappedFstT, MutableFstT> &operator=(const Fst<A> &fst) {
    725     if (this != &fst) {
    726       SetImpl(new Impl(fst));
    727     }
    728     return *this;
    729   }
    730 
    731   // Read an EditFst from an input stream; return NULL on error.
    732   static EditFst<A, WrappedFstT, MutableFstT> *
    733   Read(istream &strm,
    734        const FstReadOptions &opts) {
    735     Impl* impl = Impl::Read(strm, opts);
    736     return impl ? new EditFst<A>(impl) : 0;
    737   }
    738 
    739   // Read an EditFst from a file; return NULL on error.
    740   // Empty filename reads from standard input.
    741   static EditFst<A, WrappedFstT, MutableFstT> *Read(const string &filename) {
    742     Impl* impl = ImplToExpandedFst<Impl, MutableFst<A> >::Read(filename);
    743     return impl ? new EditFst<A, WrappedFstT, MutableFstT>(impl) : 0;
    744   }
    745 
    746   virtual bool Write(ostream &strm, const FstWriteOptions &opts) const {
    747     return GetImpl()->Write(strm, opts);
    748   }
    749 
    750   virtual bool Write(const string &filename) const {
    751     return Fst<A>::WriteFile(filename);
    752   }
    753 
    754   virtual void InitStateIterator(StateIteratorData<Arc> *data) const {
    755     GetImpl()->InitStateIterator(data);
    756   }
    757 
    758   virtual void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const {
    759     GetImpl()->InitArcIterator(s, data);
    760   }
    761 
    762   virtual
    763   void InitMutableArcIterator(StateId s, MutableArcIteratorData<A> *data) {
    764     GetImpl()->InitMutableArcIterator(s, data);
    765   }
    766  private:
    767   explicit EditFst(Impl *impl) : ImplToMutableFst<Impl>(impl) {}
    768 
    769   // Makes visible to friends.
    770   Impl *GetImpl() const { return ImplToFst< Impl, MutableFst<A> >::GetImpl(); }
    771 
    772   void SetImpl(Impl *impl, bool own_impl = true) {
    773     ImplToFst< Impl, MutableFst<A> >::SetImpl(impl, own_impl);
    774   }
    775 };
    776 
    777 }  // namespace fst
    778 
    779 #endif  // FST_LIB_EDIT_FST_H_
    780