1 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 // 14 // Copyright 2005-2010 Google, Inc. 15 // Author: dbikel (at) google.com (Dan Bikel) 16 // 17 // An \ref Fst implementation that allows non-destructive edit operations on an 18 // existing fst. 19 20 #ifndef FST_LIB_EDIT_FST_H_ 21 #define FST_LIB_EDIT_FST_H_ 22 23 #include <vector> 24 using std::vector; 25 26 #include <fst/cache.h> 27 28 namespace 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) 62 template <typename A, 63 typename WrappedFstT = ExpandedFst<A>, 64 typename MutableFstT = VectorFst<A> > 65 class 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. 330 template <typename A, typename WrappedFstT, typename MutableFstT> 331 EditFstData<A, WrappedFstT, MutableFstT> * 332 EditFstData<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) 380 template <typename A, 381 typename WrappedFstT = ExpandedFst<A>, 382 typename MutableFstT = VectorFst<A> > 383 class 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 632 template <typename A, typename WrappedFstT, typename MutableFstT> 633 const uint64 EditFstImpl<A, WrappedFstT, MutableFstT>::kStaticProperties; 634 635 // EditFstImpl IMPLEMENTATION STARTS HERE 636 637 template<typename A, typename WrappedFstT, typename MutableFstT> 638 inline 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 649 template <typename A, typename WrappedFstT, typename MutableFstT> 650 EditFstImpl<A, WrappedFstT, MutableFstT> * 651 EditFstImpl<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. 682 template <typename A, 683 typename WrappedFstT = ExpandedFst<A>, 684 typename MutableFstT = VectorFst<A> > 685 class 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