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 #ifndef FST_SCRIPT_FST_CLASS_H_ 18 #define FST_SCRIPT_FST_CLASS_H_ 19 20 #include <string> 21 22 #include <fst/fst.h> 23 #include <fst/mutable-fst.h> 24 #include <fst/vector-fst.h> 25 #include <iostream> 26 #include <fstream> 27 #include <sstream> 28 29 // Classes to support "boxing" all existing types of FST arcs in a single 30 // FstClass which hides the arc types. This allows clients to load 31 // and work with FSTs without knowing the arc type. 32 33 // These classes are only recommended for use in high-level scripting 34 // applications. Most users should use the lower-level templated versions 35 // corresponding to these classes. 36 37 namespace fst { 38 namespace script { 39 40 // 41 // Abstract base class defining the set of functionalities implemented 42 // in all impls, and passed through by all bases Below FstClassBase 43 // the class hierarchy bifurcates; FstClassImplBase serves as the base 44 // class for all implementations (of which FstClassImpl is currently 45 // the only one) and FstClass serves as the base class for all 46 // interfaces. 47 // 48 class FstClassBase { 49 public: 50 virtual const string &ArcType() const = 0; 51 virtual const string &FstType() const = 0; 52 virtual const string &WeightType() const = 0; 53 virtual const SymbolTable *InputSymbols() const = 0; 54 virtual const SymbolTable *OutputSymbols() const = 0; 55 virtual bool Write(const string& fname) const = 0; 56 virtual bool Write(ostream &ostr, const FstWriteOptions &opts) const = 0; 57 virtual uint64 Properties(uint64 mask, bool test) const = 0; ~FstClassBase()58 virtual ~FstClassBase() { } 59 }; 60 61 class FstClassImplBase : public FstClassBase { 62 public: 63 virtual FstClassImplBase *Copy() = 0; 64 virtual void SetInputSymbols(SymbolTable *is) = 0; 65 virtual void SetOutputSymbols(SymbolTable *is) = 0; ~FstClassImplBase()66 virtual ~FstClassImplBase() { } 67 }; 68 69 70 // 71 // CONTAINER CLASS 72 // Wraps an Fst<Arc>, hiding its arc type. Whether this Fst<Arc> 73 // pointer refers to a special kind of FST (e.g. a MutableFst) is 74 // known by the type of interface class that owns the pointer to this 75 // container. 76 // 77 78 template<class Arc> 79 class FstClassImpl : public FstClassImplBase { 80 public: 81 explicit FstClassImpl(Fst<Arc> *impl, 82 bool should_own = false) : 83 impl_(should_own ? impl : impl->Copy()) { } 84 FstClassImpl(const Fst<Arc> & impl)85 explicit FstClassImpl(const Fst<Arc> &impl) : impl_(impl.Copy()) { } 86 ArcType()87 virtual const string &ArcType() const { 88 return Arc::Type(); 89 } 90 FstType()91 virtual const string &FstType() const { 92 return impl_->Type(); 93 } 94 WeightType()95 virtual const string &WeightType() const { 96 return Arc::Weight::Type(); 97 } 98 InputSymbols()99 virtual const SymbolTable *InputSymbols() const { 100 return impl_->InputSymbols(); 101 } 102 OutputSymbols()103 virtual const SymbolTable *OutputSymbols() const { 104 return impl_->OutputSymbols(); 105 } 106 107 // Warning: calling this method casts the FST to a mutable FST. SetInputSymbols(SymbolTable * is)108 virtual void SetInputSymbols(SymbolTable *is) { 109 static_cast<MutableFst<Arc> *>(impl_)->SetInputSymbols(is); 110 } 111 112 // Warning: calling this method casts the FST to a mutable FST. SetOutputSymbols(SymbolTable * os)113 virtual void SetOutputSymbols(SymbolTable *os) { 114 static_cast<MutableFst<Arc> *>(impl_)->SetOutputSymbols(os); 115 } 116 Write(const string & fname)117 virtual bool Write(const string &fname) const { 118 return impl_->Write(fname); 119 } 120 Write(ostream & ostr,const FstWriteOptions & opts)121 virtual bool Write(ostream &ostr, const FstWriteOptions &opts) const { 122 return impl_->Write(ostr, opts); 123 } 124 Properties(uint64 mask,bool test)125 virtual uint64 Properties(uint64 mask, bool test) const { 126 return impl_->Properties(mask, test); 127 } 128 ~FstClassImpl()129 virtual ~FstClassImpl() { delete impl_; } 130 GetImpl()131 Fst<Arc> *GetImpl() const { return impl_; } 132 GetImpl()133 Fst<Arc> *GetImpl() { return impl_; } 134 Copy()135 virtual FstClassImpl *Copy() { 136 return new FstClassImpl<Arc>(impl_); 137 } 138 139 private: 140 Fst<Arc> *impl_; 141 }; 142 143 // 144 // BASE CLASS DEFINITIONS 145 // 146 147 class MutableFstClass; 148 149 class FstClass : public FstClassBase { 150 public: 151 template<class Arc> Read(istream & stream,const FstReadOptions & opts)152 static FstClass *Read(istream &stream, 153 const FstReadOptions &opts) { 154 if (!opts.header) { 155 FSTERROR() << "FstClass::Read: options header not specified"; 156 return 0; 157 } 158 const FstHeader &hdr = *opts.header; 159 160 if (hdr.Properties() & kMutable) { 161 return ReadTypedFst<MutableFstClass, MutableFst<Arc> >(stream, opts); 162 } else { 163 return ReadTypedFst<FstClass, Fst<Arc> >(stream, opts); 164 } 165 } 166 FstClass()167 FstClass() : impl_(NULL) { 168 } 169 170 template<class Arc> FstClass(const Fst<Arc> & fst)171 explicit FstClass(const Fst<Arc> &fst) : impl_(new FstClassImpl<Arc>(fst)) { 172 } 173 FstClass(const FstClass & other)174 FstClass(const FstClass &other) : impl_(other.impl_->Copy()) { } 175 176 FstClass &operator=(const FstClass &other) { 177 delete impl_; 178 impl_ = other.impl_->Copy(); 179 return *this; 180 } 181 182 static FstClass *Read(const string &fname); 183 184 static FstClass *Read(istream &istr, const string &source); 185 ArcType()186 virtual const string &ArcType() const { 187 return impl_->ArcType(); 188 } 189 FstType()190 virtual const string& FstType() const { 191 return impl_->FstType(); 192 } 193 InputSymbols()194 virtual const SymbolTable *InputSymbols() const { 195 return impl_->InputSymbols(); 196 } 197 OutputSymbols()198 virtual const SymbolTable *OutputSymbols() const { 199 return impl_->OutputSymbols(); 200 } 201 WeightType()202 virtual const string& WeightType() const { 203 return impl_->WeightType(); 204 } 205 Write(const string & fname)206 virtual bool Write(const string &fname) const { 207 return impl_->Write(fname); 208 } 209 Write(ostream & ostr,const FstWriteOptions & opts)210 virtual bool Write(ostream &ostr, const FstWriteOptions &opts) const { 211 return impl_->Write(ostr, opts); 212 } 213 Properties(uint64 mask,bool test)214 virtual uint64 Properties(uint64 mask, bool test) const { 215 return impl_->Properties(mask, test); 216 } 217 218 template<class Arc> GetFst()219 const Fst<Arc> *GetFst() const { 220 if (Arc::Type() != ArcType()) { 221 return NULL; 222 } else { 223 FstClassImpl<Arc> *typed_impl = static_cast<FstClassImpl<Arc> *>(impl_); 224 return typed_impl->GetImpl(); 225 } 226 } 227 ~FstClass()228 virtual ~FstClass() { delete impl_; } 229 230 // These methods are required by IO registration 231 template<class Arc> Convert(const FstClass & other)232 static FstClassImplBase *Convert(const FstClass &other) { 233 LOG(ERROR) << "Doesn't make sense to convert any class to type FstClass."; 234 return 0; 235 } 236 237 template<class Arc> Create()238 static FstClassImplBase *Create() { 239 LOG(ERROR) << "Doesn't make sense to create an FstClass with a " 240 << "particular arc type."; 241 return 0; 242 } 243 244 245 protected: FstClass(FstClassImplBase * impl)246 explicit FstClass(FstClassImplBase *impl) : impl_(impl) { } 247 248 // Generic template method for reading an arc-templated FST of type 249 // UnderlyingT, and returning it wrapped as FstClassT, with appropriate 250 // error checking. Called from arc-templated Read() static methods. 251 template<class FstClassT, class UnderlyingT> ReadTypedFst(istream & stream,const FstReadOptions & opts)252 static FstClassT* ReadTypedFst(istream &stream, 253 const FstReadOptions &opts) { 254 UnderlyingT *u = UnderlyingT::Read(stream, opts); 255 if (!u) { 256 return 0; 257 } else { 258 FstClassT *r = new FstClassT(*u); 259 delete u; 260 return r; 261 } 262 } 263 GetImpl()264 FstClassImplBase *GetImpl() const { return impl_; } 265 GetImpl()266 FstClassImplBase *GetImpl() { return impl_; } 267 268 // friend ostream &operator<<(ostream&, const FstClass&); 269 270 private: 271 FstClassImplBase *impl_; 272 }; 273 274 // 275 // Specific types of FstClass with special properties 276 // 277 278 class MutableFstClass : public FstClass { 279 public: 280 template<class Arc> MutableFstClass(const MutableFst<Arc> & fst)281 explicit MutableFstClass(const MutableFst<Arc> &fst) : 282 FstClass(fst) { } 283 284 template<class Arc> GetMutableFst()285 MutableFst<Arc> *GetMutableFst() { 286 Fst<Arc> *fst = const_cast<Fst<Arc> *>(this->GetFst<Arc>()); 287 MutableFst<Arc> *mfst = static_cast<MutableFst<Arc> *>(fst); 288 289 return mfst; 290 } 291 292 template<class Arc> Read(istream & stream,const FstReadOptions & opts)293 static MutableFstClass *Read(istream &stream, 294 const FstReadOptions &opts) { 295 MutableFst<Arc> *mfst = MutableFst<Arc>::Read(stream, opts); 296 if (!mfst) { 297 return 0; 298 } else { 299 MutableFstClass *retval = new MutableFstClass(*mfst); 300 delete mfst; 301 return retval; 302 } 303 } 304 Write(const string & fname)305 virtual bool Write(const string &fname) const { 306 return GetImpl()->Write(fname); 307 } 308 Write(ostream & ostr,const FstWriteOptions & opts)309 virtual bool Write(ostream &ostr, const FstWriteOptions &opts) const { 310 return GetImpl()->Write(ostr, opts); 311 } 312 313 static MutableFstClass *Read(const string &fname, bool convert = false); 314 SetInputSymbols(SymbolTable * is)315 virtual void SetInputSymbols(SymbolTable *is) { 316 GetImpl()->SetInputSymbols(is); 317 } 318 SetOutputSymbols(SymbolTable * os)319 virtual void SetOutputSymbols(SymbolTable *os) { 320 GetImpl()->SetOutputSymbols(os); 321 } 322 323 // These methods are required by IO registration 324 template<class Arc> Convert(const FstClass & other)325 static FstClassImplBase *Convert(const FstClass &other) { 326 LOG(ERROR) << "Doesn't make sense to convert any class to type " 327 << "MutableFstClass."; 328 return 0; 329 } 330 331 template<class Arc> Create()332 static FstClassImplBase *Create() { 333 LOG(ERROR) << "Doesn't make sense to create a MutableFstClass with a " 334 << "particular arc type."; 335 return 0; 336 } 337 338 protected: MutableFstClass(FstClassImplBase * impl)339 explicit MutableFstClass(FstClassImplBase *impl) : FstClass(impl) { } 340 }; 341 342 343 class VectorFstClass : public MutableFstClass { 344 public: 345 explicit VectorFstClass(const FstClass &other); 346 explicit VectorFstClass(const string &arc_type); 347 348 template<class Arc> VectorFstClass(const VectorFst<Arc> & fst)349 explicit VectorFstClass(const VectorFst<Arc> &fst) : 350 MutableFstClass(fst) { } 351 352 template<class Arc> Read(istream & stream,const FstReadOptions & opts)353 static VectorFstClass *Read(istream &stream, 354 const FstReadOptions &opts) { 355 VectorFst<Arc> *vfst = VectorFst<Arc>::Read(stream, opts); 356 if (!vfst) { 357 return 0; 358 } else { 359 VectorFstClass *retval = new VectorFstClass(*vfst); 360 delete vfst; 361 return retval; 362 } 363 } 364 365 static VectorFstClass *Read(const string &fname); 366 367 // Converter / creator for known arc types 368 template<class Arc> Convert(const FstClass & other)369 static FstClassImplBase *Convert(const FstClass &other) { 370 return new FstClassImpl<Arc>(new VectorFst<Arc>( 371 *other.GetFst<Arc>()), true); 372 } 373 374 template<class Arc> Create()375 static FstClassImplBase *Create() { 376 return new FstClassImpl<Arc>(new VectorFst<Arc>(), true); 377 } 378 }; 379 380 } // namespace script 381 } // namespace fst 382 #endif // FST_SCRIPT_FST_CLASS_H_ 383