// mutable-fst.h // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Copyright 2005-2010 Google, Inc. // Author: riley@google.com (Michael Riley) // // \file // Expanded FST augmented with mutators - interface class definition // and mutable arc iterator interface. // #ifndef FST_LIB_MUTABLE_FST_H__ #define FST_LIB_MUTABLE_FST_H__ #include #include #include #include using std::vector; #include namespace fst { template class MutableArcIteratorData; // An expanded FST plus mutators (use MutableArcIterator to modify arcs). template class MutableFst : public ExpandedFst { public: typedef A Arc; typedef typename A::Weight Weight; typedef typename A::StateId StateId; virtual MutableFst &operator=(const Fst &fst) = 0; MutableFst &operator=(const MutableFst &fst) { return operator=(static_cast &>(fst)); } virtual void SetStart(StateId) = 0; // Set the initial state virtual void SetFinal(StateId, Weight) = 0; // Set a state's final weight virtual void SetProperties(uint64 props, uint64 mask) = 0; // Set property bits wrt mask virtual StateId AddState() = 0; // Add a state, return its ID virtual void AddArc(StateId, const A &arc) = 0; // Add an arc to state virtual void DeleteStates(const vector&) = 0; // Delete some states virtual void DeleteStates() = 0; // Delete all states virtual void DeleteArcs(StateId, size_t n) = 0; // Delete some arcs at state virtual void DeleteArcs(StateId) = 0; // Delete all arcs at state virtual void ReserveStates(StateId n) { } // Optional, best effort only. virtual void ReserveArcs(StateId s, size_t n) { } // Optional, Best effort. // Return input label symbol table; return NULL if not specified virtual const SymbolTable* InputSymbols() const = 0; // Return output label symbol table; return NULL if not specified virtual const SymbolTable* OutputSymbols() const = 0; // Return input label symbol table; return NULL if not specified virtual SymbolTable* MutableInputSymbols() = 0; // Return output label symbol table; return NULL if not specified virtual SymbolTable* MutableOutputSymbols() = 0; // Set input label symbol table; NULL signifies not unspecified virtual void SetInputSymbols(const SymbolTable* isyms) = 0; // Set output label symbol table; NULL signifies not unspecified virtual void SetOutputSymbols(const SymbolTable* osyms) = 0; // Get a copy of this MutableFst. See Fst<>::Copy() for further doc. virtual MutableFst *Copy(bool safe = false) const = 0; // Read an MutableFst from an input stream; return NULL on error. static MutableFst *Read(istream &strm, const FstReadOptions &opts) { FstReadOptions ropts(opts); FstHeader hdr; if (ropts.header) hdr = *opts.header; else { if (!hdr.Read(strm, opts.source)) return 0; ropts.header = &hdr; } if (!(hdr.Properties() & kMutable)) { LOG(ERROR) << "MutableFst::Read: Not an MutableFst: " << ropts.source; return 0; } FstRegister *registr = FstRegister::GetRegister(); const typename FstRegister::Reader reader = registr->GetReader(hdr.FstType()); if (!reader) { LOG(ERROR) << "MutableFst::Read: Unknown FST type \"" << hdr.FstType() << "\" (arc type = \"" << A::Type() << "\"): " << ropts.source; return 0; } Fst *fst = reader(strm, ropts); if (!fst) return 0; return static_cast *>(fst); } // Read a MutableFst from a file; return NULL on error. // Empty filename reads from standard input. If 'convert' is true, // convert to a mutable FST of type 'convert_type' if file is // a non-mutable FST. static MutableFst *Read(const string &filename, bool convert = false, const string &convert_type = "vector") { if (convert == false) { if (!filename.empty()) { ifstream strm(filename.c_str(), ifstream::in | ifstream::binary); if (!strm) { LOG(ERROR) << "MutableFst::Read: Can't open file: " << filename; return 0; } return Read(strm, FstReadOptions(filename)); } else { return Read(cin, FstReadOptions("standard input")); } } else { // Converts to 'convert_type' if not mutable. Fst *ifst = Fst::Read(filename); if (!ifst) return 0; if (ifst->Properties(kMutable, false)) { return static_cast(ifst); } else { Fst *ofst = Convert(*ifst, convert_type); delete ifst; if (!ofst) return 0; if (!ofst->Properties(kMutable, false)) LOG(ERROR) << "MutableFst: bad convert type: " << convert_type; return static_cast(ofst); } } } // For generic mutuble arc iterator construction; not normally called // directly by users. virtual void InitMutableArcIterator(StateId s, MutableArcIteratorData *) = 0; }; // Mutable arc iterator interface, templated on the Arc definition; used // for mutable Arc iterator specializations that are returned by // the InitMutableArcIterator MutableFst method. template class MutableArcIteratorBase : public ArcIteratorBase { public: typedef A Arc; void SetValue(const A &arc) { SetValue_(arc); } // Set current arc's content private: virtual void SetValue_(const A &arc) = 0; }; template struct MutableArcIteratorData { MutableArcIteratorBase *base; // Specific iterator }; // Generic mutable arc iterator, templated on the FST definition // - a wrapper around pointer to specific one. // Here is a typical use: \code // for (MutableArcIterator aiter(&fst, s)); // !aiter.Done(); // aiter.Next()) { // StdArc arc = aiter.Value(); // arc.ilabel = 7; // aiter.SetValue(arc); // ... // } \endcode // This version requires function calls. template class MutableArcIterator { public: typedef F FST; typedef typename F::Arc Arc; typedef typename Arc::StateId StateId; MutableArcIterator(F *fst, StateId s) { fst->InitMutableArcIterator(s, &data_); } ~MutableArcIterator() { delete data_.base; } bool Done() const { return data_.base->Done(); } const Arc& Value() const { return data_.base->Value(); } void Next() { data_.base->Next(); } size_t Position() const { return data_.base->Position(); } void Reset() { data_.base->Reset(); } void Seek(size_t a) { data_.base->Seek(a); } void SetValue(const Arc &a) { data_.base->SetValue(a); } uint32 Flags() const { return data_.base->Flags(); } void SetFlags(uint32 f, uint32 m) { return data_.base->SetFlags(f, m); } private: MutableArcIteratorData data_; DISALLOW_COPY_AND_ASSIGN(MutableArcIterator); }; namespace internal { // MutableFst case - abstract methods. template inline typename A::Weight Final(const MutableFst &fst, typename A::StateId s) { return fst.Final(s); } template inline ssize_t NumArcs(const MutableFst &fst, typename A::StateId s) { return fst.NumArcs(s); } template inline ssize_t NumInputEpsilons(const MutableFst &fst, typename A::StateId s) { return fst.NumInputEpsilons(s); } template inline ssize_t NumOutputEpsilons(const MutableFst &fst, typename A::StateId s) { return fst.NumOutputEpsilons(s); } } // namespace internal // A useful alias when using StdArc. typedef MutableFst StdMutableFst; // This is a helper class template useful for attaching a MutableFst // interface to its implementation, handling reference counting and // copy-on-write. template > class ImplToMutableFst : public ImplToExpandedFst { public: typedef typename I::Arc Arc; typedef typename Arc::Weight Weight; typedef typename Arc::StateId StateId; using ImplToFst::GetImpl; using ImplToFst::SetImpl; virtual void SetStart(StateId s) { MutateCheck(); GetImpl()->SetStart(s); } virtual void SetFinal(StateId s, Weight w) { MutateCheck(); GetImpl()->SetFinal(s, w); } virtual void SetProperties(uint64 props, uint64 mask) { // Can skip mutate check if extrinsic properties don't change, // since it is then safe to update all (shallow) copies uint64 exprops = kExtrinsicProperties & mask; if (GetImpl()->Properties(exprops) != (props & exprops)) MutateCheck(); GetImpl()->SetProperties(props, mask); } virtual StateId AddState() { MutateCheck(); return GetImpl()->AddState(); } virtual void AddArc(StateId s, const Arc &arc) { MutateCheck(); GetImpl()->AddArc(s, arc); } virtual void DeleteStates(const vector &dstates) { MutateCheck(); GetImpl()->DeleteStates(dstates); } virtual void DeleteStates() { MutateCheck(); GetImpl()->DeleteStates(); } virtual void DeleteArcs(StateId s, size_t n) { MutateCheck(); GetImpl()->DeleteArcs(s, n); } virtual void DeleteArcs(StateId s) { MutateCheck(); GetImpl()->DeleteArcs(s); } virtual void ReserveStates(StateId s) { MutateCheck(); GetImpl()->ReserveStates(s); } virtual void ReserveArcs(StateId s, size_t n) { MutateCheck(); GetImpl()->ReserveArcs(s, n); } virtual const SymbolTable* InputSymbols() const { return GetImpl()->InputSymbols(); } virtual const SymbolTable* OutputSymbols() const { return GetImpl()->OutputSymbols(); } virtual SymbolTable* MutableInputSymbols() { MutateCheck(); return GetImpl()->InputSymbols(); } virtual SymbolTable* MutableOutputSymbols() { MutateCheck(); return GetImpl()->OutputSymbols(); } virtual void SetInputSymbols(const SymbolTable* isyms) { MutateCheck(); GetImpl()->SetInputSymbols(isyms); } virtual void SetOutputSymbols(const SymbolTable* osyms) { MutateCheck(); GetImpl()->SetOutputSymbols(osyms); } protected: ImplToMutableFst() : ImplToExpandedFst() {} ImplToMutableFst(I *impl) : ImplToExpandedFst(impl) {} ImplToMutableFst(const ImplToMutableFst &fst) : ImplToExpandedFst(fst) {} ImplToMutableFst(const ImplToMutableFst &fst, bool safe) : ImplToExpandedFst(fst, safe) {} void MutateCheck() { // Copy on write if (GetImpl()->RefCount() > 1) SetImpl(new I(*this)); } private: // Disallow ImplToMutableFst &operator=(const ImplToMutableFst &fst); ImplToMutableFst &operator=(const Fst &fst) { FSTERROR() << "ImplToMutableFst: Assignment operator disallowed"; GetImpl()->SetProperties(kError, kError); return *this; } }; } // namespace fst #endif // FST_LIB_MUTABLE_FST_H__