| // 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 <stddef.h> |
| #include <sys/types.h> |
| #include <string> |
| #include <vector> |
| using std::vector; |
| |
| #include <fst/expanded-fst.h> |
| |
| |
| namespace fst { |
| |
| template <class A> class MutableArcIteratorData; |
| |
| // An expanded FST plus mutators (use MutableArcIterator to modify arcs). |
| template <class A> |
| class MutableFst : public ExpandedFst<A> { |
| public: |
| typedef A Arc; |
| typedef typename A::Weight Weight; |
| typedef typename A::StateId StateId; |
| |
| virtual MutableFst<A> &operator=(const Fst<A> &fst) = 0; |
| |
| MutableFst<A> &operator=(const MutableFst<A> &fst) { |
| return operator=(static_cast<const Fst<A> &>(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<StateId>&) = 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<A> *Copy(bool safe = false) const = 0; |
| |
| // Read an MutableFst from an input stream; return NULL on error. |
| static MutableFst<A> *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<A> *registr = FstRegister<A>::GetRegister(); |
| const typename FstRegister<A>::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<A> *fst = reader(strm, ropts); |
| if (!fst) return 0; |
| return static_cast<MutableFst<A> *>(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<A> *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(std::cin, FstReadOptions("standard input")); |
| } |
| } else { // Converts to 'convert_type' if not mutable. |
| Fst<A> *ifst = Fst<A>::Read(filename); |
| if (!ifst) return 0; |
| if (ifst->Properties(kMutable, false)) { |
| return static_cast<MutableFst *>(ifst); |
| } else { |
| Fst<A> *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<MutableFst *>(ofst); |
| } |
| } |
| } |
| |
| // For generic mutuble arc iterator construction; not normally called |
| // directly by users. |
| virtual void InitMutableArcIterator(StateId s, |
| MutableArcIteratorData<A> *) = 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 A> |
| class MutableArcIteratorBase : public ArcIteratorBase<A> { |
| 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 <class A> |
| struct MutableArcIteratorData { |
| MutableArcIteratorBase<A> *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<StdFst> 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 F> |
| 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<Arc> data_; |
| DISALLOW_COPY_AND_ASSIGN(MutableArcIterator); |
| }; |
| |
| |
| namespace internal { |
| |
| // MutableFst<A> case - abstract methods. |
| template <class A> inline |
| typename A::Weight Final(const MutableFst<A> &fst, typename A::StateId s) { |
| return fst.Final(s); |
| } |
| |
| template <class A> inline |
| ssize_t NumArcs(const MutableFst<A> &fst, typename A::StateId s) { |
| return fst.NumArcs(s); |
| } |
| |
| template <class A> inline |
| ssize_t NumInputEpsilons(const MutableFst<A> &fst, typename A::StateId s) { |
| return fst.NumInputEpsilons(s); |
| } |
| |
| template <class A> inline |
| ssize_t NumOutputEpsilons(const MutableFst<A> &fst, typename A::StateId s) { |
| return fst.NumOutputEpsilons(s); |
| } |
| |
| } // namespace internal |
| |
| |
| // A useful alias when using StdArc. |
| typedef MutableFst<StdArc> 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 I, class F = MutableFst<typename I::Arc> > |
| class ImplToMutableFst : public ImplToExpandedFst<I, F> { |
| public: |
| typedef typename I::Arc Arc; |
| typedef typename Arc::Weight Weight; |
| typedef typename Arc::StateId StateId; |
| |
| using ImplToFst<I, F>::GetImpl; |
| using ImplToFst<I, F>::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<StateId> &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<I, F>() {} |
| |
| ImplToMutableFst(I *impl) : ImplToExpandedFst<I, F>(impl) {} |
| |
| |
| ImplToMutableFst(const ImplToMutableFst<I, F> &fst) |
| : ImplToExpandedFst<I, F>(fst) {} |
| |
| ImplToMutableFst(const ImplToMutableFst<I, F> &fst, bool safe) |
| : ImplToExpandedFst<I, F>(fst, safe) {} |
| |
| void MutateCheck() { |
| // Copy on write |
| if (GetImpl()->RefCount() > 1) |
| SetImpl(new I(*this)); |
| } |
| |
| private: |
| // Disallow |
| ImplToMutableFst<I, F> &operator=(const ImplToMutableFst<I, F> &fst); |
| |
| ImplToMutableFst<I, F> &operator=(const Fst<Arc> &fst) { |
| FSTERROR() << "ImplToMutableFst: Assignment operator disallowed"; |
| GetImpl()->SetProperties(kError, kError); |
| return *this; |
| } |
| }; |
| |
| |
| } // namespace fst |
| |
| #endif // FST_LIB_MUTABLE_FST_H__ |