• 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     ostringstream s;
60     s << weight;
61     return s.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 
~WeightClass()131   ~WeightClass() { if (impl_) delete impl_; }
132  private:
133   enum ElementType { ZERO, ONE, OTHER };
134   ElementType element_type_;
135 
136   WeightImplBase *impl_;
137 
WeightClass(ElementType et)138   explicit WeightClass(ElementType et) : element_type_(et), impl_(0) { }
139 
140   friend ostream &operator << (ostream &o, const WeightClass &c);
141 };
142 
143 template<class W>
GetWeight()144 const W* WeightClass::GetWeight() const {
145   // We need to store zero and one as statics, because the weight type
146   // W might return them as temporaries. We're returning a pointer,
147   // and it won't do to get the address of a temporary.
148   static const W zero = W::Zero();
149   static const W one = W::One();
150 
151   if (element_type_ == ZERO) {
152     return &zero;
153   } else if (element_type_ == ONE) {
154     return &one;
155   } else {
156     if (W::Type() != impl_->Type()) {
157       return NULL;
158     } else {
159       WeightClassImpl<W> *typed_impl =
160           static_cast<WeightClassImpl<W> *>(impl_);
161       return &typed_impl->weight;
162     }
163   }
164 }
165 
166 //
167 // Registration for generic weight types.
168 //
169 
170 typedef WeightImplBase* (*StrToWeightImplBaseT)(const string &str,
171                                                 const string &src,
172                                                 size_t nline);
173 
174 template<class W>
StrToWeightImplBase(const string & str,const string & src,size_t nline)175 WeightImplBase* StrToWeightImplBase(const string &str,
176                                     const string &src, size_t nline) {
177   return new WeightClassImpl<W>(StrToWeight<W>(str, src, nline));
178 }
179 
180 // The following confuses swig, and doesn't need to be wrapped anyway.
181 #ifndef SWIG
182 ostream& operator << (ostream &o, const WeightClass &c);
183 
184 class WeightClassRegister : public GenericRegister<string,
185                                                    StrToWeightImplBaseT,
186                                                    WeightClassRegister> {
187  protected:
ConvertKeyToSoFilename(const string & key)188   virtual string ConvertKeyToSoFilename(const string &key) const {
189     return key + ".so";
190   }
191 };
192 
193 typedef GenericRegisterer<WeightClassRegister> WeightClassRegisterer;
194 #endif
195 
196 // internal version, needs to be called by wrapper in order for
197 // macro args to expand
198 #define REGISTER_FST_WEIGHT__(Weight, line)                             \
199   static WeightClassRegisterer weight_registerer ## _ ## line(          \
200       Weight::Type(),                                                   \
201       StrToWeightImplBase<Weight>)
202 
203 // This layer is where __FILE__ and __LINE__ are expanded
204 #define REGISTER_FST_WEIGHT_EXPANDER(Weight, line)      \
205   REGISTER_FST_WEIGHT__(Weight, line)
206 
207 //
208 // Macro for registering new weight types. Clients call this.
209 //
210 #define REGISTER_FST_WEIGHT(Weight) \
211   REGISTER_FST_WEIGHT_EXPANDER(Weight, __LINE__)
212 
213 }  // namespace script
214 }  // namespace fst
215 
216 #endif  // FST_SCRIPT_WEIGHT_CLASS_H_
217