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