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