Home | History | Annotate | Download | only in script
      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     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:
     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   ~WeightClass() { if (impl_) delete impl_; }
    132  private:
    133   enum ElementType { ZERO, ONE, OTHER };
    134   ElementType element_type_;
    135 
    136   WeightImplBase *impl_;
    137 
    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>
    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>
    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:
    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