// register.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), jpr@google.com (Jake Ratkiewicz) // // \file // Classes for registering derived Fsts for generic reading // #ifndef FST_LIB_REGISTER_H__ #define FST_LIB_REGISTER_H__ #include <string> #include <fst/compat.h> #include <iostream> #include <fstream> #include <fst/util.h> #include <fst/generic-register.h> #include <fst/types.h> namespace fst { template <class A> class Fst; struct FstReadOptions; // This class represents a single entry in a FstRegister template<class A> struct FstRegisterEntry { typedef Fst<A> *(*Reader)(istream &strm, const FstReadOptions &opts); typedef Fst<A> *(*Converter)(const Fst<A> &fst); Reader reader; Converter converter; FstRegisterEntry() : reader(0), converter(0) {} FstRegisterEntry(Reader r, Converter c) : reader(r), converter(c) { } }; // This class maintains the correspondence between a string describing // an FST type, and its reader and converter. template<class A> class FstRegister : public GenericRegister<string, FstRegisterEntry<A>, FstRegister<A> > { public: typedef typename FstRegisterEntry<A>::Reader Reader; typedef typename FstRegisterEntry<A>::Converter 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: virtual string ConvertKeyToSoFilename(const string& key) const { string legal_type(key); ConvertToLegalCSymbol(&legal_type); return legal_type + "-fst.so"; } }; // This class registers an Fst type for generic reading and creating. // The Fst type must have a default constructor and a copy constructor // from 'Fst<Arc>' for this to work. template <class F> class FstRegisterer : public GenericRegisterer<FstRegister<typename F::Arc> > { public: typedef typename F::Arc Arc; typedef typename FstRegister<Arc>::Entry Entry; typedef typename FstRegister<Arc>::Reader Reader; FstRegisterer() : GenericRegisterer<FstRegister<typename F::Arc> >( F().Type(), BuildEntry()) { } private: Entry BuildEntry() { F *(*reader)(istream &strm, const FstReadOptions &opts) = &F::Read; return Entry(reinterpret_cast<Reader>(reader), &FstRegisterer<F>::Convert); } static Fst<Arc> *Convert(const Fst<Arc> &fst) { return new F(fst); } }; // Convenience macro to generate static FstRegisterer instance. #define REGISTER_FST(F, A) \ static fst::FstRegisterer< F<A> > F ## _ ## A ## _registerer // Converts an fst to type 'type'. template <class A> Fst<A> *Convert(const Fst<A> &fst, const string &ftype) { FstRegister<A> *registr = FstRegister<A>::GetRegister(); const typename FstRegister<A>::Converter converter = registr->GetConverter(ftype); if (!converter) { string atype = A::Type(); LOG(ERROR) << "Fst::Convert: Unknown FST type \"" << ftype << "\" (arc type = \"" << atype << "\")"; return 0; } return converter(fst); } } // namespace fst #endif // FST_LIB_REGISTER_H__