aboutsummaryrefslogtreecommitdiff
path: root/src/include/fst/register.h
blob: ea3f4d88c1b783b19a8ff42e24c9e02d1f5c3be9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// 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 <sstream>
#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__