FST  openfst-1.7.2
OpenFst Library
script-impl.h
Go to the documentation of this file.
1 // See www.openfst.org for extensive documentation on this weighted
2 // finite-state transducer library.
3 //
4 // This file defines the registration mechanism for new operations.
5 // These operations are designed to enable scripts to work with FST classes
6 // at a high level.
7 //
8 // If you have a new arc type and want these operations to work with FSTs
9 // with that arc type, see below for the registration steps
10 // you must take.
11 //
12 // These methods are only recommended for use in high-level scripting
13 // applications. Most users should use the lower-level templated versions
14 // corresponding to these.
15 //
16 // If you have a new arc type you'd like these operations to work with,
17 // use the REGISTER_FST_OPERATIONS macro defined in fstscript.h.
18 //
19 // If you have a custom operation you'd like to define, you need four
20 // components. In the following, assume you want to create a new operation
21 // with the signature
22 //
23 // void Foo(const FstClass &ifst, MutableFstClass *ofst);
24 //
25 // You need:
26 //
27 // 1) A way to bundle the args that your new Foo operation will take, as
28 // a single struct. The template structs in arg-packs.h provide a handy
29 // way to do this. In Foo's case, that might look like this:
30 //
31 // using FooArgs = std::pair<const FstClass &, MutableFstClass *>;
32 //
33 // Note: this package of args is going to be passed by non-const pointer.
34 //
35 // 2) A function template that is able to perform Foo, given the args and
36 // arc type. Yours might look like this:
37 //
38 // template<class Arc>
39 // void Foo(FooArgs *args) {
40 // // Pulls out the actual, arc-templated FSTs.
41 // const Fst<Arc> &ifst = std::get<0>(*args).GetFst<Arc>();
42 // MutableFst<Arc> *ofst = std::get<1>(*args)->GetMutableFst<Arc>();
43 // // Actually perform Foo on ifst and ofst.
44 // }
45 //
46 // 3) a client-facing function for your operation. This would look like
47 // the following:
48 //
49 // void Foo(const FstClass &ifst, MutableFstClass *ofst) {
50 // // Check that the arc types of the FSTs match
51 // if (!ArcTypesMatch(ifst, *ofst, "Foo")) return;
52 // // package the args
53 // FooArgs args(ifst, ofst);
54 // // Finally, call the operation
55 // Apply<Operation<FooArgs>>("Foo", ifst->ArcType(), &args);
56 // }
57 //
58 // The Apply<> function template takes care of the link between 2 and 3,
59 // provided you also have:
60 //
61 // 4) A registration for your new operation, on the arc types you care about.
62 // This can be provided easily by the REGISTER_FST_OPERATION macro in
63 // operations.h:
64 //
65 // REGISTER_FST_OPERATION(Foo, StdArc, FooArgs);
66 // REGISTER_FST_OPERATION(Foo, MyArc, FooArgs);
67 // // .. etc
68 //
69 //
70 // That's it! Now when you call Foo(const FstClass &, MutableFstClass *),
71 // it dispatches (in #3) via the Apply<> function to the correct
72 // instantiation of the template function in #2.
73 //
74 
75 #ifndef FST_SCRIPT_SCRIPT_IMPL_H_
76 #define FST_SCRIPT_SCRIPT_IMPL_H_
77 
78 // This file contains general-purpose templates which are used in the
79 // implementation of the operations.
80 
81 #include <string>
82 #include <utility>
83 
84 #include <fst/generic-register.h>
85 #include <fst/script/fst-class.h>
86 
87 #include <fst/log.h>
88 
89 namespace fst {
90 namespace script {
91 
96 };
97 
98 // A generic register for operations with various kinds of signatures.
99 // Needed since every function signature requires a new registration class.
100 // The std::pair<string, string> is understood to be the operation name and arc
101 // type; subclasses (or typedefs) need only provide the operation signature.
102 
103 template <class OperationSignature>
105  : public GenericRegister<std::pair<string, string>, OperationSignature,
106  GenericOperationRegister<OperationSignature>> {
107  public:
108  void RegisterOperation(const string &operation_name, const string &arc_type,
109  OperationSignature op) {
110  this->SetEntry(std::make_pair(operation_name, arc_type), op);
111  }
112 
113  OperationSignature GetOperation(const string &operation_name,
114  const string &arc_type) {
115  return this->GetEntry(std::make_pair(operation_name, arc_type));
116  }
117 
118  protected:
120  const std::pair<string, string> &key) const final {
121  // Uses the old-style FST for now.
122  string legal_type(key.second); // The arc type.
123  ConvertToLegalCSymbol(&legal_type);
124  return legal_type + "-arc.so";
125  }
126 };
127 
128 // Operation package: everything you need to register a new type of operation.
129 // The ArgPack should be the type that's passed into each wrapped function;
130 // for instance, it might be a struct containing all the args. It's always
131 // passed by pointer, so const members should be used to enforce constness where
132 // it's needed. Return values should be implemented as a member of ArgPack as
133 // well.
134 
135 template <class Args>
136 struct Operation {
137  using ArgPack = Args;
138 
139  using OpType = void (*)(ArgPack *args);
140 
141  // The register (hash) type.
143 
144  // The register-er type
146 };
147 
148 // Macro for registering new types of operations.
149 
150 #define REGISTER_FST_OPERATION(Op, Arc, ArgPack) \
151  static fst::script::Operation<ArgPack>::Registerer \
152  arc_dispatched_operation_##ArgPack##Op##Arc##_registerer \
153  (std::make_pair(#Op, Arc::Type()), Op<Arc>)
154 
155 // Template function to apply an operation by name.
156 
157 template <class OpReg>
158 void Apply(const string &op_name, const string &arc_type,
159  typename OpReg::ArgPack *args) {
160  const auto op = OpReg::Register::GetRegister()->GetOperation(op_name,
161  arc_type);
162  if (!op) {
163  FSTERROR() << "No operation found for " << op_name << " on "
164  << "arc type " << arc_type;
165  return;
166  }
167  op(args);
168 }
169 
170 namespace internal {
171 
172 // Helper that logs to ERROR if the arc types of m and n don't match,
173 // assuming that both m and n implement .ArcType(). The op_name argument is
174 // used to construct the error message.
175 template <class M, class N>
176 bool ArcTypesMatch(const M &m, const N &n, const string &op_name) {
177  if (m.ArcType() != n.ArcType()) {
178  FSTERROR() << "Arguments with non-matching arc types passed to "
179  << op_name << ":\t" << m.ArcType() << " and " << n.ArcType();
180  return false;
181  }
182  return true;
183 }
184 
185 // From untyped to typed weights.
186 template <class Weight>
187 void CopyWeights(const std::vector<WeightClass> &weights,
188  std::vector<Weight> *typed_weights) {
189  typed_weights->clear();
190  typed_weights->reserve(weights.size());
191  for (const auto &weight : weights) {
192  typed_weights->push_back(*weight.GetWeight<Weight>());
193  }
194 }
195 
196 // From typed to untyped weights.
197 template <class Weight>
198 void CopyWeights(const std::vector<Weight> &typed_weights,
199  std::vector<WeightClass> *weights) {
200  weights->clear();
201  weights->reserve(typed_weights.size());
202  for (const auto &typed_weight : typed_weights) {
203  weights->emplace_back(typed_weight);
204  }
205 }
206 
207 } // namespace internal
208 } // namespace script
209 } // namespace fst
210 
211 #endif // FST_SCRIPT_SCRIPT_IMPL_H_
void ConvertToLegalCSymbol(string *s)
Definition: util.cc:50
void CopyWeights(const std::vector< Weight > &typed_weights, std::vector< WeightClass > *weights)
Definition: script-impl.h:198
void Apply(const string &op_name, const string &arc_type, typename OpReg::ArgPack *args)
Definition: script-impl.h:158
OperationSignature GetOperation(const string &operation_name, const string &arc_type)
Definition: script-impl.h:113
void RegisterOperation(const string &operation_name, const string &arc_type, OperationSignature op)
Definition: script-impl.h:108
bool ArcTypesMatch(const M &m, const N &n, const string &op_name)
Definition: script-impl.h:176
#define FSTERROR()
Definition: util.h:35
void(*)(ArgPack *args) OpType
Definition: script-impl.h:139
string ConvertKeyToSoFilename(const std::pair< string, string > &key) const final
Definition: script-impl.h:119