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>
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
EditFstData()80 EditFstData() : num_new_states_(0) {
81 SetEmptyAndDeleteKeysForInternalMaps();
82 }
83
EditFstData(const EditFstData & other)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
~EditFstData()91 ~EditFstData() {
92 }
93
94 static EditFstData<A, WrappedFstT, MutableFstT> *Read(istream &strm,
95 const FstReadOptions &opts);
96
Write(ostream & strm,const FstWriteOptions & opts)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
RefCount()112 int RefCount() const { return ref_count_.count(); }
IncrRefCount()113 int IncrRefCount() { return ref_count_.Incr(); }
DecrRefCount()114 int DecrRefCount() { return ref_count_.Decr(); }
115
NumNewStates()116 StateId NumNewStates() const {
117 return num_new_states_;
118 }
119
120 // accessor methods for the fst holding edited states
EditedStart()121 StateId EditedStart() const {
122 return edits_.Start();
123 }
124
Final(StateId s,const WrappedFstT * wrapped)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
NumArcs(StateId s,const WrappedFstT * wrapped)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
NumInputEpsilons(StateId s,const WrappedFstT * wrapped)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
NumOutputEpsilons(StateId s,const WrappedFstT * wrapped)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
SetEditedProperties(uint64 props,uint64 mask)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.
SetStart(StateId s)164 void SetStart(StateId s) {
165 edits_.SetStart(s);
166 }
167
168 // Sets the final state for this fst.
SetFinal(StateId s,Weight w,const WrappedFstT * wrapped)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.
AddState(StateId curr_num_states)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.
AddArc(StateId s,const Arc & arc,const WrappedFstT * wrapped)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
DeleteStates()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.
DeleteArcs(StateId s,size_t n,const WrappedFstT * wrapped)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.
DeleteArcs(StateId s,const WrappedFstT * wrapped)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.
InitArcIterator(StateId s,ArcIteratorData<Arc> * data,const WrappedFstT * wrapped)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.
InitMutableArcIterator(StateId s,MutableArcIteratorData<A> * data,const WrappedFstT * wrapped)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).
PrintMap()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:
SetEmptyAndDeleteKeysForInternalMaps()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.
GetEditedIdMapIterator(StateId s)268 IdMapIterator GetEditedIdMapIterator(StateId s) const {
269 return external_to_internal_ids_.find(s);
270 }
NotInEditedMap()271 IdMapIterator NotInEditedMap() const {
272 return external_to_internal_ids_.end();
273 }
274
GetFinalWeightIterator(StateId s)275 FinalWeightIterator GetFinalWeightIterator(StateId s) const {
276 return edited_final_weights_.find(s);
277 }
NotInFinalWeightMap()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_
GetEditableInternalId(StateId s,const WrappedFstT * wrapped)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> *
Read(istream & strm,const FstReadOptions & opts)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.
EditFstImpl()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.
EditFstImpl(const Fst<A> & wrapped)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.
EditFstImpl(const EditFstImpl & impl)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
~EditFstImpl()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
Start()454 StateId Start() const {
455 StateId edited_start = data_->EditedStart();
456 return edited_start == kNoStateId ? wrapped_->Start() : edited_start;
457 }
458
Final(StateId s)459 Weight Final(StateId s) const {
460 return data_->Final(s, wrapped_);
461 }
462
NumArcs(StateId s)463 size_t NumArcs(StateId s) const {
464 return data_->NumArcs(s, wrapped_);
465 }
466
NumInputEpsilons(StateId s)467 size_t NumInputEpsilons(StateId s) const {
468 return data_->NumInputEpsilons(s, wrapped_);
469 }
470
NumOutputEpsilons(StateId s)471 size_t NumOutputEpsilons(StateId s) const {
472 return data_->NumOutputEpsilons(s, wrapped_);
473 }
474
NumStates()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
Write(ostream & strm,const FstWriteOptions & opts)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.
SetStart(StateId s)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.
SetFinal(StateId s,Weight w)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.
AddState()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.
AddArc(StateId s,const Arc & arc)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
DeleteStates(const vector<StateId> & dstates)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.
DeleteArcs(StateId s,size_t n)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.
DeleteArcs(StateId s)555 void DeleteArcs(StateId s) {
556 MutateCheck();
557 data_->DeleteArcs(s, wrapped_);
558 SetProperties(DeleteArcsProperties(FstImpl<A>::Properties()));
559 }
560
ReserveStates(StateId s)561 void ReserveStates(StateId s) {
562 }
563
ReserveArcs(StateId s,size_t n)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.
InitStateIterator(StateIteratorData<Arc> * data)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.
InitArcIterator(StateId s,ArcIteratorData<Arc> * data)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.
InitMutableArcIterator(StateId s,MutableArcIteratorData<A> * data)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.
InheritPropertiesFromWrapped()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().
MutateCheck()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>
DeleteStates()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> *
Read(istream & strm,const FstReadOptions & opts)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
EditFst()699 EditFst() : ImplToMutableFst<Impl>(new Impl()) {}
700
EditFst(const Fst<A> & fst)701 explicit EditFst(const Fst<A> &fst) :
702 ImplToMutableFst<Impl>(new Impl(fst)) {}
703
EditFst(const WrappedFstT & fst)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
~EditFst()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> *
Read(istream & strm,const FstReadOptions & opts)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.
Read(const string & filename)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
Write(ostream & strm,const FstWriteOptions & opts)746 virtual bool Write(ostream &strm, const FstWriteOptions &opts) const {
747 return GetImpl()->Write(strm, opts);
748 }
749
Write(const string & filename)750 virtual bool Write(const string &filename) const {
751 return Fst<A>::WriteFile(filename);
752 }
753
InitStateIterator(StateIteratorData<Arc> * data)754 virtual void InitStateIterator(StateIteratorData<Arc> *data) const {
755 GetImpl()->InitStateIterator(data);
756 }
757
InitArcIterator(StateId s,ArcIteratorData<Arc> * data)758 virtual void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const {
759 GetImpl()->InitArcIterator(s, data);
760 }
761
762 virtual
InitMutableArcIterator(StateId s,MutableArcIteratorData<A> * data)763 void InitMutableArcIterator(StateId s, MutableArcIteratorData<A> *data) {
764 GetImpl()->InitMutableArcIterator(s, data);
765 }
766 private:
EditFst(Impl * impl)767 explicit EditFst(Impl *impl) : ImplToMutableFst<Impl>(impl) {}
768
769 // Makes visible to friends.
GetImpl()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