• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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