1 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 // 14 // Copyright 2005-2010 Google, Inc. 15 // Author: jpr (at) google.com (Jake Ratkiewicz) 16 17 // Represents a generic weight in an FST -- that is, represents a specific 18 // type of weight underneath while hiding that type from a client. 19 20 21 #ifndef FST_SCRIPT_WEIGHT_CLASS_H_ 22 #define FST_SCRIPT_WEIGHT_CLASS_H_ 23 24 #include <string> 25 26 #include <fst/generic-register.h> 27 #include <fst/util.h> 28 29 namespace fst { 30 namespace script { 31 32 class WeightImplBase { 33 public: 34 virtual WeightImplBase *Copy() const = 0; 35 virtual void Print(ostream *o) const = 0; 36 virtual const string &Type() const = 0; 37 virtual string to_string() const = 0; 38 virtual bool operator == (const WeightImplBase &other) const = 0; 39 virtual ~WeightImplBase() { } 40 }; 41 42 template<class W> 43 struct WeightClassImpl : public WeightImplBase { 44 W weight; 45 46 explicit WeightClassImpl(const W& weight) : weight(weight) { } 47 48 virtual WeightClassImpl<W> *Copy() const { 49 return new WeightClassImpl<W>(weight); 50 } 51 52 virtual const string &Type() const { return W::Type(); } 53 54 virtual void Print(ostream *o) const { 55 *o << weight; 56 } 57 58 virtual string to_string() const { 59 string str; 60 WeightToStr(weight, &str); 61 return str; 62 } 63 64 virtual bool operator == (const WeightImplBase &other) const { 65 if (Type() != other.Type()) { 66 return false; 67 } else { 68 const WeightClassImpl<W> *typed_other = 69 static_cast<const WeightClassImpl<W> *>(&other); 70 71 return typed_other->weight == weight; 72 } 73 } 74 }; 75 76 77 class WeightClass { 78 public: 79 WeightClass() : element_type_(ZERO), impl_(0) { } 80 81 template<class W> 82 explicit WeightClass(const W& weight) 83 : element_type_(OTHER), impl_(new WeightClassImpl<W>(weight)) { } 84 85 WeightClass(const string &weight_type, const string &weight_str); 86 87 WeightClass(const WeightClass &other) : 88 element_type_(other.element_type_), 89 impl_(other.impl_ ? other.impl_->Copy() : 0) { } 90 91 WeightClass &operator = (const WeightClass &other) { 92 if (impl_) delete impl_; 93 impl_ = other.impl_ ? other.impl_->Copy() : 0; 94 element_type_ = other.element_type_; 95 return *this; 96 } 97 98 template<class W> 99 const W* GetWeight() const; 100 101 string to_string() const { 102 switch (element_type_) { 103 case ZERO: 104 return "ZERO"; 105 case ONE: 106 return "ONE"; 107 default: 108 case OTHER: 109 return impl_->to_string(); 110 } 111 } 112 113 bool operator == (const WeightClass &other) const { 114 return element_type_ == other.element_type_ && 115 ((impl_ && other.impl_ && (*impl_ == *other.impl_)) || 116 (impl_ == 0 && other.impl_ == 0)); 117 } 118 119 static const WeightClass &Zero() { 120 static WeightClass w(ZERO); 121 122 return w; 123 } 124 125 static const WeightClass &One() { 126 static WeightClass w(ONE); 127 128 return w; 129 } 130 131 const string &Type() const { 132 if (impl_) return impl_->Type(); 133 static const string no_type = "none"; 134 return no_type; 135 } 136 137 138 ~WeightClass() { if (impl_) delete impl_; } 139 private: 140 enum ElementType { ZERO, ONE, OTHER }; 141 ElementType element_type_; 142 143 WeightImplBase *impl_; 144 145 explicit WeightClass(ElementType et) : element_type_(et), impl_(0) { } 146 147 friend ostream &operator << (ostream &o, const WeightClass &c); 148 }; 149 150 template<class W> 151 const W* WeightClass::GetWeight() const { 152 // We need to store zero and one as statics, because the weight type 153 // W might return them as temporaries. We're returning a pointer, 154 // and it won't do to get the address of a temporary. 155 static const W zero = W::Zero(); 156 static const W one = W::One(); 157 158 if (element_type_ == ZERO) { 159 return &zero; 160 } else if (element_type_ == ONE) { 161 return &one; 162 } else { 163 if (W::Type() != impl_->Type()) { 164 return NULL; 165 } else { 166 WeightClassImpl<W> *typed_impl = 167 static_cast<WeightClassImpl<W> *>(impl_); 168 return &typed_impl->weight; 169 } 170 } 171 } 172 173 // 174 // Registration for generic weight types. 175 // 176 177 typedef WeightImplBase* (*StrToWeightImplBaseT)(const string &str, 178 const string &src, 179 size_t nline); 180 181 template<class W> 182 WeightImplBase* StrToWeightImplBase(const string &str, 183 const string &src, size_t nline) { 184 return new WeightClassImpl<W>(StrToWeight<W>(str, src, nline)); 185 } 186 187 // The following confuses swig, and doesn't need to be wrapped anyway. 188 #ifndef SWIG 189 ostream& operator << (ostream &o, const WeightClass &c); 190 191 class WeightClassRegister : public GenericRegister<string, 192 StrToWeightImplBaseT, 193 WeightClassRegister> { 194 protected: 195 virtual string ConvertKeyToSoFilename(const string &key) const { 196 return key + ".so"; 197 } 198 }; 199 200 typedef GenericRegisterer<WeightClassRegister> WeightClassRegisterer; 201 #endif 202 203 // internal version, needs to be called by wrapper in order for 204 // macro args to expand 205 #define REGISTER_FST_WEIGHT__(Weight, line) \ 206 static WeightClassRegisterer weight_registerer ## _ ## line( \ 207 Weight::Type(), \ 208 StrToWeightImplBase<Weight>) 209 210 // This layer is where __FILE__ and __LINE__ are expanded 211 #define REGISTER_FST_WEIGHT_EXPANDER(Weight, line) \ 212 REGISTER_FST_WEIGHT__(Weight, line) 213 214 // 215 // Macro for registering new weight types. Clients call this. 216 // 217 #define REGISTER_FST_WEIGHT(Weight) \ 218 REGISTER_FST_WEIGHT_EXPANDER(Weight, __LINE__) 219 220 } // namespace script 221 } // namespace fst 222 223 #endif // FST_SCRIPT_WEIGHT_CLASS_H_ 224