1 // register.h
2 
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Copyright 2005-2010 Google, Inc.
16 // Author: riley@google.com (Michael Riley), jpr@google.com (Jake Ratkiewicz)
17 //
18 // \file
19 // Classes for registering derived Fsts for generic reading
20 //
21 
22 #ifndef FST_LIB_REGISTER_H__
23 #define FST_LIB_REGISTER_H__
24 
25 #include <string>
26 
27 
28 #include <fst/compat.h>
29 #include <iostream>
30 #include <fstream>
31 #include <sstream>
32 #include <fst/util.h>
33 #include <fst/generic-register.h>
34 
35 
36 #include <fst/types.h>
37 
38 namespace fst {
39 
40 template <class A> class Fst;
41 struct FstReadOptions;
42 
43 // This class represents a single entry in a FstRegister
44 template<class A>
45 struct FstRegisterEntry {
46   typedef Fst<A> *(*Reader)(istream &strm, const FstReadOptions &opts);
47   typedef Fst<A> *(*Converter)(const Fst<A> &fst);
48 
49   Reader reader;
50   Converter converter;
FstRegisterEntryFstRegisterEntry51   FstRegisterEntry() : reader(0), converter(0) {}
FstRegisterEntryFstRegisterEntry52   FstRegisterEntry(Reader r, Converter c) : reader(r), converter(c) { }
53 };
54 
55 // This class maintains the correspondence between a string describing
56 // an FST type, and its reader and converter.
57 template<class A>
58 class FstRegister : public GenericRegister<string, FstRegisterEntry<A>,
59                                            FstRegister<A> > {
60  public:
61   typedef typename FstRegisterEntry<A>::Reader Reader;
62   typedef typename FstRegisterEntry<A>::Converter Converter;
63 
GetReader(const string & type)64   const Reader GetReader(const string &type) const {
65     return this->GetEntry(type).reader;
66   }
67 
GetConverter(const string & type)68   const Converter GetConverter(const string &type) const {
69     return this->GetEntry(type).converter;
70   }
71 
72  protected:
ConvertKeyToSoFilename(const string & key)73   virtual string ConvertKeyToSoFilename(const string& key) const {
74     string legal_type(key);
75 
76     ConvertToLegalCSymbol(&legal_type);
77 
78     return legal_type + "-fst.so";
79   }
80 };
81 
82 
83 // This class registers an Fst type for generic reading and creating.
84 // The Fst type must have a default constructor and a copy constructor
85 // from 'Fst<Arc>' for this to work.
86 template <class F>
87 class FstRegisterer
88   : public GenericRegisterer<FstRegister<typename F::Arc> > {
89  public:
90   typedef typename F::Arc Arc;
91   typedef typename FstRegister<Arc>::Entry Entry;
92   typedef typename FstRegister<Arc>::Reader Reader;
93 
FstRegisterer()94   FstRegisterer() :
95       GenericRegisterer<FstRegister<typename F::Arc> >(
96           F().Type(), BuildEntry()) {  }
97 
98  private:
BuildEntry()99   Entry BuildEntry() {
100     F *(*reader)(istream &strm,
101                  const FstReadOptions &opts) = &F::Read;
102 
103     return Entry(reinterpret_cast<Reader>(reader),
104                  &FstRegisterer<F>::Convert);
105   }
106 
Convert(const Fst<Arc> & fst)107   static Fst<Arc> *Convert(const Fst<Arc> &fst) { return new F(fst); }
108 };
109 
110 
111 // Convenience macro to generate static FstRegisterer instance.
112 #define REGISTER_FST(F, A) \
113 static fst::FstRegisterer< F<A> > F ## _ ## A ## _registerer
114 
115 
116 // Converts an fst to type 'type'.
117 template <class A>
Convert(const Fst<A> & fst,const string & ftype)118 Fst<A> *Convert(const Fst<A> &fst, const string &ftype) {
119   FstRegister<A> *registr = FstRegister<A>::GetRegister();
120   const typename FstRegister<A>::Converter
121       converter = registr->GetConverter(ftype);
122   if (!converter) {
123     string atype = A::Type();
124     LOG(ERROR) << "Fst::Convert: Unknown FST type \"" << ftype
125                << "\" (arc type = \"" << atype << "\")";
126     return 0;
127   }
128   return converter(fst);
129 }
130 
131 }  // namespace fst
132 
133 #endif  // FST_LIB_REGISTER_H__
134