| |
| // 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: jpr@google.com (Jake Ratkiewicz) |
| |
| #ifndef FST_SCRIPT_FST_CLASS_H_ |
| #define FST_SCRIPT_FST_CLASS_H_ |
| |
| #include <string> |
| |
| #include <fst/fst.h> |
| #include <fst/mutable-fst.h> |
| #include <fst/vector-fst.h> |
| #include <iostream> |
| #include <fstream> |
| |
| // Classes to support "boxing" all existing types of FST arcs in a single |
| // FstClass which hides the arc types. This allows clients to load |
| // and work with FSTs without knowing the arc type. |
| |
| // These classes are only recommended for use in high-level scripting |
| // applications. Most users should use the lower-level templated versions |
| // corresponding to these classes. |
| |
| namespace fst { |
| namespace script { |
| |
| // |
| // Abstract base class defining the set of functionalities implemented |
| // in all impls, and passed through by all bases Below FstClassBase |
| // the class hierarchy bifurcates; FstClassImplBase serves as the base |
| // class for all implementations (of which FstClassImpl is currently |
| // the only one) and FstClass serves as the base class for all |
| // interfaces. |
| // |
| class FstClassBase { |
| public: |
| virtual const string &ArcType() const = 0; |
| virtual const string &FstType() const = 0; |
| virtual const string &WeightType() const = 0; |
| virtual const SymbolTable *InputSymbols() const = 0; |
| virtual const SymbolTable *OutputSymbols() const = 0; |
| virtual void Write(const string& fname) const = 0; |
| virtual uint64 Properties(uint64 mask, bool test) const = 0; |
| virtual ~FstClassBase() { } |
| }; |
| |
| class FstClassImplBase : public FstClassBase { |
| public: |
| virtual FstClassImplBase *Copy() = 0; |
| virtual void SetInputSymbols(SymbolTable *is) = 0; |
| virtual void SetOutputSymbols(SymbolTable *is) = 0; |
| virtual ~FstClassImplBase() { } |
| }; |
| |
| |
| // |
| // CONTAINER CLASS |
| // Wraps an Fst<Arc>, hiding its arc type. Whether this Fst<Arc> |
| // pointer refers to a special kind of FST (e.g. a MutableFst) is |
| // known by the type of interface class that owns the pointer to this |
| // container. |
| // |
| |
| template<class Arc> |
| class FstClassImpl : public FstClassImplBase { |
| public: |
| explicit FstClassImpl(Fst<Arc> *impl, |
| bool should_own = false) : |
| impl_(should_own ? impl : impl->Copy()) { } |
| |
| virtual const string &ArcType() const { |
| return Arc::Type(); |
| } |
| |
| virtual const string &FstType() const { |
| return impl_->Type(); |
| } |
| |
| virtual const string &WeightType() const { |
| return Arc::Weight::Type(); |
| } |
| |
| virtual const SymbolTable *InputSymbols() const { |
| return impl_->InputSymbols(); |
| } |
| |
| virtual const SymbolTable *OutputSymbols() const { |
| return impl_->OutputSymbols(); |
| } |
| |
| // Warning: calling this method casts the FST to a mutable FST. |
| virtual void SetInputSymbols(SymbolTable *is) { |
| static_cast<MutableFst<Arc> *>(impl_)->SetInputSymbols(is); |
| } |
| |
| // Warning: calling this method casts the FST to a mutable FST. |
| virtual void SetOutputSymbols(SymbolTable *os) { |
| static_cast<MutableFst<Arc> *>(impl_)->SetOutputSymbols(os); |
| } |
| |
| virtual void Write(const string &fname) const { |
| impl_->Write(fname); |
| } |
| |
| virtual uint64 Properties(uint64 mask, bool test) const { |
| return impl_->Properties(mask, test); |
| } |
| |
| virtual ~FstClassImpl() { delete impl_; } |
| |
| Fst<Arc> *GetImpl() { return impl_; } |
| |
| virtual FstClassImpl *Copy() { |
| return new FstClassImpl<Arc>(impl_); |
| } |
| |
| private: |
| Fst<Arc> *impl_; |
| }; |
| |
| // |
| // BASE CLASS DEFINITIONS |
| // |
| |
| class MutableFstClass; |
| |
| class FstClass : public FstClassBase { |
| public: |
| template<class Arc> |
| static FstClass *Read(istream &stream, |
| const FstReadOptions &opts) { |
| if (!opts.header) { |
| FSTERROR() << "FstClass::Read: options header not specified"; |
| return 0; |
| } |
| const FstHeader &hdr = *opts.header; |
| |
| if (hdr.Properties() & kMutable) { |
| return ReadTypedFst<MutableFstClass, MutableFst<Arc> >(stream, opts); |
| } else { |
| return ReadTypedFst<FstClass, Fst<Arc> >(stream, opts); |
| } |
| } |
| |
| template<class Arc> |
| explicit FstClass(Fst<Arc> *fst) : impl_(new FstClassImpl<Arc>(fst)) { } |
| |
| explicit FstClass(const FstClass &other) : impl_(other.impl_->Copy()) { } |
| |
| static FstClass *Read(const string &fname); |
| |
| virtual const string &ArcType() const { |
| return impl_->ArcType(); |
| } |
| |
| virtual const string& FstType() const { |
| return impl_->FstType(); |
| } |
| |
| virtual const SymbolTable *InputSymbols() const { |
| return impl_->InputSymbols(); |
| } |
| |
| virtual const SymbolTable *OutputSymbols() const { |
| return impl_->OutputSymbols(); |
| } |
| |
| virtual const string& WeightType() const { |
| return impl_->WeightType(); |
| } |
| |
| virtual void Write(const string &fname) const { |
| impl_->Write(fname); |
| } |
| |
| virtual uint64 Properties(uint64 mask, bool test) const { |
| return impl_->Properties(mask, test); |
| } |
| |
| template<class Arc> |
| const Fst<Arc> *GetFst() const { |
| if (Arc::Type() != ArcType()) { |
| return NULL; |
| } else { |
| FstClassImpl<Arc> *typed_impl = static_cast<FstClassImpl<Arc> *>(impl_); |
| return typed_impl->GetImpl(); |
| } |
| } |
| |
| virtual ~FstClass() { delete impl_; } |
| |
| // These methods are required by IO registration |
| template<class Arc> |
| static FstClassImplBase *Convert(const FstClass &other) { |
| LOG(ERROR) << "Doesn't make sense to convert any class to type FstClass."; |
| return 0; |
| } |
| |
| template<class Arc> |
| static FstClassImplBase *Create() { |
| LOG(ERROR) << "Doesn't make sense to create an FstClass with a " |
| << "particular arc type."; |
| return 0; |
| } |
| protected: |
| explicit FstClass(FstClassImplBase *impl) : impl_(impl) { } |
| |
| // Generic template method for reading an arc-templated FST of type |
| // UnderlyingT, and returning it wrapped as FstClassT, with appropriate |
| // error checking. Called from arc-templated Read() static methods. |
| template<class FstClassT, class UnderlyingT> |
| static FstClassT* ReadTypedFst(istream &stream, |
| const FstReadOptions &opts) { |
| UnderlyingT *u = UnderlyingT::Read(stream, opts); |
| if (!u) { |
| return 0; |
| } else { |
| FstClassT *r = new FstClassT(u); |
| delete u; |
| return r; |
| } |
| } |
| |
| FstClassImplBase *GetImpl() { return impl_; } |
| private: |
| FstClassImplBase *impl_; |
| }; |
| |
| // |
| // Specific types of FstClass with special properties |
| // |
| |
| class MutableFstClass : public FstClass { |
| public: |
| template<class Arc> |
| explicit MutableFstClass(MutableFst<Arc> *fst) : |
| FstClass(fst) { } |
| |
| template<class Arc> |
| MutableFst<Arc> *GetMutableFst() { |
| Fst<Arc> *fst = const_cast<Fst<Arc> *>(this->GetFst<Arc>()); |
| MutableFst<Arc> *mfst = static_cast<MutableFst<Arc> *>(fst); |
| |
| return mfst; |
| } |
| |
| template<class Arc> |
| static MutableFstClass *Read(istream &stream, |
| const FstReadOptions &opts) { |
| MutableFst<Arc> *mfst = MutableFst<Arc>::Read(stream, opts); |
| if (!mfst) { |
| return 0; |
| } else { |
| MutableFstClass *retval = new MutableFstClass(mfst); |
| delete mfst; |
| return retval; |
| } |
| } |
| |
| static MutableFstClass *Read(const string &fname, bool convert = false); |
| |
| virtual void SetInputSymbols(SymbolTable *is) { |
| GetImpl()->SetInputSymbols(is); |
| } |
| |
| virtual void SetOutputSymbols(SymbolTable *os) { |
| GetImpl()->SetOutputSymbols(os); |
| } |
| |
| // These methods are required by IO registration |
| template<class Arc> |
| static FstClassImplBase *Convert(const FstClass &other) { |
| LOG(ERROR) << "Doesn't make sense to convert any class to type " |
| << "MutableFstClass."; |
| return 0; |
| } |
| |
| template<class Arc> |
| static FstClassImplBase *Create() { |
| LOG(ERROR) << "Doesn't make sense to create a MutableFstClass with a " |
| << "particular arc type."; |
| return 0; |
| } |
| |
| protected: |
| explicit MutableFstClass(FstClassImplBase *impl) : FstClass(impl) { } |
| }; |
| |
| |
| class VectorFstClass : public MutableFstClass { |
| public: |
| explicit VectorFstClass(const FstClass &other); |
| explicit VectorFstClass(const string &arc_type); |
| |
| template<class Arc> |
| explicit VectorFstClass(VectorFst<Arc> *fst) : |
| MutableFstClass(fst) { } |
| |
| template<class Arc> |
| static VectorFstClass *Read(istream &stream, |
| const FstReadOptions &opts) { |
| VectorFst<Arc> *vfst = VectorFst<Arc>::Read(stream, opts); |
| if (!vfst) { |
| return 0; |
| } else { |
| VectorFstClass *retval = new VectorFstClass(vfst); |
| delete vfst; |
| return retval; |
| } |
| } |
| |
| static VectorFstClass *Read(const string &fname); |
| |
| // Converter / creator for known arc types |
| template<class Arc> |
| static FstClassImplBase *Convert(const FstClass &other) { |
| return new FstClassImpl<Arc>(new VectorFst<Arc>( |
| *other.GetFst<Arc>()), true); |
| } |
| |
| template<class Arc> |
| static FstClassImplBase *Create() { |
| return new FstClassImpl<Arc>(new VectorFst<Arc>(), true); |
| } |
| }; |
| |
| } // namespace script |
| } // namespace fst |
| |
| |
| #endif // FST_SCRIPT_FST_CLASS_H_ |