00001 00002 /// Licensed under the Apache License, Version 2.0 (the "License"); 00003 /// you may not use this file except in compliance with the License. 00004 /// You may obtain a copy of the License at 00005 /// 00006 /// http://www.apache.org/licenses/LICENSE-2.0 00007 /// 00008 /// Unless required by applicable law or agreed to in writing, software 00009 /// distributed under the License is distributed on an "AS IS" BASIS, 00010 /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00011 /// See the License for the specific language governing permissions and 00012 /// limitations under the License. 00013 /// 00014 /// Copyright 2005-2010 Google, Inc. 00015 /// Author: jpr@google.com (Jake Ratkiewicz) 00016 00017 /// This file defines the registration mechanism for new operations. 00018 /// These operations are designed to enable scripts to work with FST classes 00019 /// at a high level. 00020 00021 /// If you have a new arc type and want these operations to work with FSTs 00022 /// with that arc type, see below for the registration steps 00023 /// you must take. 00024 00025 /// These methods are only recommended for use in high-level scripting 00026 /// applications. Most users should use the lower-level templated versions 00027 /// corresponding to these. 00028 00029 /// If you have a new arc type you'd like these operations to work with, 00030 /// use the REGISTER_FST_OPERATIONS macro defined in fstcsript.h 00031 00032 /// If you have a custom operation you'd like to define, you need four 00033 /// components. In the following, assume you want to create a new operation 00034 /// with the signature 00035 /// 00036 /// void Foo(const FstClass &ifst, MutableFstClass *ofst); 00037 /// 00038 /// You need: 00039 /// 00040 /// 1) A way to bundle the args that your new Foo operation will take, as 00041 /// a single struct. The template structs in arg-packs.h provide a handy 00042 /// way to do this. In Foo's case, that might look like this: 00043 /// 00044 /// typedef args::Package<const FstClass &, 00045 /// MutableFstClass *> FooArgs; 00046 /// 00047 /// Note: this package of args is going to be passed by non-const pointer. 00048 /// 00049 /// 2) A function template that is able to perform Foo, given the args and 00050 /// arc type. Yours might look like this: 00051 /// 00052 /// template<class Arc> 00053 /// void Foo(FooArgs *args) { 00054 /// // Pull out the actual, arc-templated FSTs 00055 /// const Fst<Arc> &ifst = args->arg1.GetFst<Arc>(); 00056 /// MutableFst<Arc> *ofst = args->arg2->GetMutableFst<Arc>(); 00057 /// 00058 /// // actually perform foo on ifst and ofst... 00059 /// } 00060 /// 00061 /// 3) a client-facing function for your operation. This would look like 00062 /// the following: 00063 /// 00064 /// void Foo(const FstClass &ifst, MutableFstClass *ofst) { 00065 /// // Check that the arc types of the FSTs match 00066 /// if (!ArcTypesMatch(ifst, *ofst, "Foo")) return; 00067 /// // package the args 00068 /// FooArgs args(ifst, ofst); 00069 /// // Finally, call the operation 00070 /// Apply<Operation<FooArgs> >("Foo", ifst->ArcType(), &args); 00071 /// } 00072 /// 00073 /// The Apply<> function template takes care of the link between 2 and 3, 00074 /// provided you also have: 00075 /// 00076 /// 4) A registration for your new operation, on the arc types you care about. 00077 /// This can be provided easily by the REGISTER_FST_OPERATION macro in 00078 /// operations.h: 00079 /// 00080 /// REGISTER_FST_OPERATION(Foo, StdArc, FooArgs); 00081 /// REGISTER_FST_OPERATION(Foo, MyArc, FooArgs); 00082 /// // .. etc 00083 /// 00084 /// 00085 /// That's it! Now when you call Foo(const FstClass &, MutableFstClass *), 00086 /// it dispatches (in #3) via the Apply<> function to the correct 00087 /// instantiation of the template function in #2. 00088 /// 00089 00090 00091 #ifndef FST_SCRIPT_SCRIPT_IMPL_H_ 00092 #define FST_SCRIPT_SCRIPT_IMPL_H_ 00093 00094 /// 00095 /// This file contains general-purpose templates which are used in the 00096 /// implementation of the operations. 00097 /// 00098 00099 #include <utility> 00100 using std::pair; using std::make_pair; 00101 #include <string> 00102 00103 #include <fst/script/fst-class.h> 00104 #include <fst/generic-register.h> 00105 #include <fst/script/arg-packs.h> 00106 00107 #include <fst/types.h> 00108 00109 namespace fst { 00110 namespace script { 00111 00112 /// 00113 /// A generic register for operations with various kinds of signatures. 00114 /// Needed since every function signature requires a new registration class. 00115 /// The pair<string, string> is understood to be the operation name and arc 00116 /// type; subclasses (or typedefs) need only provide the operation signature. 00117 /// 00118 00119 template<class OperationSignature> 00120 class GenericOperationRegister 00121 : public GenericRegister<pair<string, string>, 00122 OperationSignature, 00123 GenericOperationRegister<OperationSignature> > { 00124 public: 00125 void RegisterOperation(const string &operation_name, 00126 const string &arc_type, 00127 OperationSignature op) { 00128 this->SetEntry(make_pair(operation_name, arc_type), op); 00129 } 00130 00131 OperationSignature GetOperation( 00132 const string &operation_name, const string &arc_type) { 00133 return this->GetEntry(make_pair(operation_name, arc_type)); 00134 } 00135 00136 protected: 00137 virtual string ConvertKeyToSoFilename( 00138 const pair<string, string>& key) const { 00139 /// Just use the old-style FST for now. 00140 string legal_type(key.second); ///< the arc type 00141 ConvertToLegalCSymbol(&legal_type); 00142 00143 return legal_type + "-arc.so"; 00144 } 00145 }; 00146 00147 00148 /// Operation package - everything you need to register a new type of operation 00149 00150 /// The ArgPack should be the type that's passed into each wrapped function - 00151 /// for instance, it might be a struct containing all the args. 00152 /// It's always passed by pointer, so const members should be used to enforce 00153 /// constness where it's needed. Return values should be implemented as a 00154 /// member of ArgPack as well. 00155 00156 template<class ArgPack> 00157 struct Operation { 00158 typedef ArgPack Args; 00159 typedef void (*OpType)(ArgPack *args); 00160 00161 /// The register (hash) type 00162 typedef GenericOperationRegister<OpType> Register; 00163 00164 /// The register-er type 00165 typedef GenericRegisterer<Register> Registerer; 00166 }; 00167 00168 00169 /// Macro for registering new types of operations. 00170 00171 #define REGISTER_FST_OPERATION(Op, Arc, ArgPack) \ 00172 static Operation<ArgPack>::Registerer \ 00173 arc_dispatched_operation_ ## ArgPack ## Op ## Arc ## _registerer( \ 00174 make_pair(#Op, Arc::Type()), Op<Arc>) 00175 00176 00177 /// 00178 /// Template function to apply an operation by name 00179 /// 00180 00181 template<class OpReg> 00182 void Apply(const string &op_name, const string &arc_type, 00183 typename OpReg::Args *args) { 00184 typename OpReg::Register *reg = OpReg::Register::GetRegister(); 00185 00186 typename OpReg::OpType op = reg->GetOperation(op_name, arc_type); 00187 00188 if (op == 0) { 00189 LOG(FATAL) << "No operation found for \"" << op_name << "\" on " 00190 << "arc type " << arc_type; 00191 } 00192 00193 op(args); 00194 } 00195 00196 00197 /// Helper that logs to ERROR if the arc types of a and b don't match. 00198 /// The op_name is also printed. 00199 bool ArcTypesMatch(const FstClass &a, const FstClass &b, 00200 const string &op_name); 00201 00202 } /// namespace script 00203 } /// namespace fst 00204 00205 #endif /// FST_SCRIPT_SCRIPT_IMPL_H_ 00206
1.7.1