// See www.openfst.org for extensive documentation on this weighted // finite-state transducer library. // // Classes for registering derived FST for generic reading. #ifndef FST_REGISTER_H_ #define FST_REGISTER_H_ #include #include #include #include #include #include #include namespace fst { template class Fst; struct FstReadOptions; // This class represents a single entry in a FstRegister template struct FstRegisterEntry { using Reader = Fst *(*)(std::istream &istrm, const FstReadOptions &opts); using Converter = Fst *(*)(const Fst &fst); Reader reader; Converter converter; explicit FstRegisterEntry(Reader reader = nullptr, Converter converter = nullptr) : reader(reader), converter(converter) {} }; // This class maintains the correspondence between a string describing // an FST type, and its reader and converter. template class FstRegister : public GenericRegister, FstRegister> { public: using Reader = typename FstRegisterEntry::Reader; using Converter = typename FstRegisterEntry::Converter; const Reader GetReader(const string &type) const { return this->GetEntry(type).reader; } const Converter GetConverter(const string &type) const { return this->GetEntry(type).converter; } protected: string ConvertKeyToSoFilename(const string &key) const override { string legal_type(key); ConvertToLegalCSymbol(&legal_type); return legal_type + "-fst.so"; } }; // This class registers an FST type for generic reading and creating. // The type must have a default constructor and a copy constructor from // Fst. template class FstRegisterer : public GenericRegisterer> { public: using Arc = typename FST::Arc; using Entry = typename FstRegister::Entry; using Reader = typename FstRegister::Reader; FstRegisterer() : GenericRegisterer>(FST().Type(), BuildEntry()) {} private: static Fst *ReadGeneric( std::istream &strm, const FstReadOptions &opts) { static_assert(std::is_base_of, FST>::value, "FST class does not inherit from Fst"); return FST::Read(strm, opts); } static Entry BuildEntry() { return Entry(&ReadGeneric, &FstRegisterer::Convert); } static Fst *Convert(const Fst &fst) { return new FST(fst); } }; // Convenience macro to generate static FstRegisterer instance. #define REGISTER_FST(FST, Arc) \ static fst::FstRegisterer> FST##_##Arc##_registerer // Converts an FST to the specified type. template Fst *Convert(const Fst &fst, const string &fst_type) { auto *reg = FstRegister::GetRegister(); const auto converter = reg->GetConverter(fst_type); if (!converter) { FSTERROR() << "Fst::Convert: Unknown FST type " << fst_type << " (arc type " << Arc::Type() << ")"; return nullptr; } return converter(fst); } } // namespace fst #endif // FST_REGISTER_H_