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     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