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@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;
~WeightImplBase()39 virtual ~WeightImplBase() { }
40 };
41
42 template<class W>
43 struct WeightClassImpl : public WeightImplBase {
44 W weight;
45
WeightClassImplWeightClassImpl46 explicit WeightClassImpl(const W& weight) : weight(weight) { }
47
CopyWeightClassImpl48 virtual WeightClassImpl<W> *Copy() const {
49 return new WeightClassImpl<W>(weight);
50 }
51
TypeWeightClassImpl52 virtual const string &Type() const { return W::Type(); }
53
PrintWeightClassImpl54 virtual void Print(ostream *o) const {
55 *o << weight;
56 }
57
to_stringWeightClassImpl58 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:
WeightClass()79 WeightClass() : element_type_(ZERO), impl_(0) { }
80
81 template<class W>
WeightClass(const W & weight)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
WeightClass(const WeightClass & other)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
to_string()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
Zero()119 static const WeightClass &Zero() {
120 static WeightClass w(ZERO);
121
122 return w;
123 }
124
One()125 static const WeightClass &One() {
126 static WeightClass w(ONE);
127
128 return w;
129 }
130
Type()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
~WeightClass()138 ~WeightClass() { if (impl_) delete impl_; }
139 private:
140 enum ElementType { ZERO, ONE, OTHER };
141 ElementType element_type_;
142
143 WeightImplBase *impl_;
144
WeightClass(ElementType et)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>
GetWeight()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>
StrToWeightImplBase(const string & str,const string & src,size_t nline)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:
ConvertKeyToSoFilename(const string & key)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