1 // add-on.h 2 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Copyright 2005-2010 Google, Inc. 16 // Author: riley@google.com (Michael Riley) 17 // 18 // \file 19 // Fst implementation class to attach an arbitrary object with a 20 // read/write method to an FST and its file rep. The FST is given a 21 // new type name. 22 23 #ifndef FST_LIB_ADD_ON_FST_H__ 24 #define FST_LIB_ADD_ON_FST_H__ 25 26 #include <stddef.h> 27 #include <string> 28 29 #include <fst/fst.h> 30 31 32 namespace fst { 33 34 // Identifies stream data as an add-on fst. 35 static const int32 kAddOnMagicNumber = 446681434; 36 37 38 // 39 // Some useful add-on objects. 40 // 41 42 // Nothing to save. 43 class NullAddOn { 44 public: NullAddOn()45 NullAddOn() {} 46 Read(istream & istrm)47 static NullAddOn *Read(istream &istrm) { 48 return new NullAddOn(); 49 }; 50 Write(ostream & ostrm)51 bool Write(ostream &ostrm) const { return true; } 52 RefCount()53 int RefCount() const { return ref_count_.count(); } IncrRefCount()54 int IncrRefCount() { return ref_count_.Incr(); } DecrRefCount()55 int DecrRefCount() { return ref_count_.Decr(); } 56 57 private: 58 RefCounter ref_count_; 59 60 DISALLOW_COPY_AND_ASSIGN(NullAddOn); 61 }; 62 63 64 // Create a new add-on from a pair of add-ons. 65 template <class A1, class A2> 66 class AddOnPair { 67 public: 68 // Argument reference count incremented. AddOnPair(A1 * a1,A2 * a2)69 AddOnPair(A1 *a1, A2 *a2) 70 : a1_(a1), a2_(a2) { 71 if (a1_) 72 a1_->IncrRefCount(); 73 if (a2_) 74 a2_->IncrRefCount(); 75 } 76 ~AddOnPair()77 ~AddOnPair() { 78 if (a1_ && !a1_->DecrRefCount()) 79 delete a1_; 80 if (a2_ && !a2_->DecrRefCount()) 81 delete a2_; 82 } 83 First()84 A1 *First() const { return a1_; } Second()85 A2 *Second() const { return a2_; } 86 Read(istream & istrm)87 static AddOnPair<A1, A2> *Read(istream &istrm) { 88 A1 *a1 = 0; 89 bool have_addon1 = false; 90 ReadType(istrm, &have_addon1); 91 if (have_addon1) 92 a1 = A1::Read(istrm); 93 94 A2 *a2 = 0; 95 bool have_addon2 = false; 96 ReadType(istrm, &have_addon2); 97 if (have_addon2) 98 a2 = A2::Read(istrm); 99 100 AddOnPair<A1, A2> *a = new AddOnPair<A1, A2>(a1, a2); 101 if (a1) 102 a1->DecrRefCount(); 103 if (a2) 104 a2->DecrRefCount(); 105 return a; 106 }; 107 Write(ostream & ostrm)108 bool Write(ostream &ostrm) const { 109 bool have_addon1 = a1_; 110 WriteType(ostrm, have_addon1); 111 if (have_addon1) 112 a1_->Write(ostrm); 113 bool have_addon2 = a2_; 114 WriteType(ostrm, have_addon2); 115 if (have_addon2) 116 a2_->Write(ostrm); 117 return true; 118 } 119 RefCount()120 int RefCount() const { return ref_count_.count(); } 121 IncrRefCount()122 int IncrRefCount() { 123 return ref_count_.Incr(); 124 } 125 DecrRefCount()126 int DecrRefCount() { 127 return ref_count_.Decr(); 128 } 129 130 private: 131 A1 *a1_; 132 A2 *a2_; 133 RefCounter ref_count_; 134 135 DISALLOW_COPY_AND_ASSIGN(AddOnPair); 136 }; 137 138 139 // Add to an Fst F a type T object. T must have a 'T* Read(istream &)', 140 // a 'bool Write(ostream &)' method, and 'int RecCount(), 'int IncrRefCount()' 141 // and 'int DecrRefCount()' methods (e.g. 'MatcherData' in matcher-fst.h). 142 // The result is a new Fst implemenation with type name 'type'. 143 template<class F, class T> 144 class AddOnImpl : public FstImpl<typename F::Arc> { 145 public: 146 typedef typename F::Arc Arc; 147 typedef typename Arc::Label Label; 148 typedef typename Arc::Weight Weight; 149 typedef typename Arc::StateId StateId; 150 151 using FstImpl<Arc>::SetType; 152 using FstImpl<Arc>::SetProperties; 153 using FstImpl<Arc>::WriteHeader; 154 155 // If 't' is non-zero, its reference count is incremented. 156 AddOnImpl(const F &fst, const string &type, T *t = 0) fst_(fst)157 : fst_(fst), t_(t) { 158 SetType(type); 159 SetProperties(fst_.Properties(kFstProperties, false)); 160 if (t_) 161 t_->IncrRefCount(); 162 } 163 164 // If 't' is non-zero, its reference count is incremented. 165 AddOnImpl(const Fst<Arc> &fst, const string &type, T *t = 0) fst_(fst)166 : fst_(fst), t_(t) { 167 SetType(type); 168 SetProperties(fst_.Properties(kFstProperties, false)); 169 if (t_) 170 t_->IncrRefCount(); 171 } 172 AddOnImpl(const AddOnImpl<F,T> & impl)173 AddOnImpl(const AddOnImpl<F, T> &impl) 174 : fst_(impl.fst_), t_(impl.t_) { 175 SetType(impl.Type()); 176 SetProperties(fst_.Properties(kCopyProperties, false)); 177 if (t_) 178 t_->IncrRefCount(); 179 } 180 ~AddOnImpl()181 ~AddOnImpl() { 182 if (t_ && !t_->DecrRefCount()) 183 delete t_; 184 } 185 Start()186 StateId Start() const { return fst_.Start(); } Final(StateId s)187 Weight Final(StateId s) const { return fst_.Final(s); } NumArcs(StateId s)188 size_t NumArcs(StateId s) const { return fst_.NumArcs(s); } 189 NumInputEpsilons(StateId s)190 size_t NumInputEpsilons(StateId s) const { 191 return fst_.NumInputEpsilons(s); 192 } 193 NumOutputEpsilons(StateId s)194 size_t NumOutputEpsilons(StateId s) const { 195 return fst_.NumOutputEpsilons(s); 196 } 197 NumStates()198 size_t NumStates() const { return fst_.NumStates(); } 199 Read(istream & strm,const FstReadOptions & opts)200 static AddOnImpl<F, T> *Read(istream &strm, const FstReadOptions &opts) { 201 FstReadOptions nopts(opts); 202 FstHeader hdr; 203 if (!nopts.header) { 204 hdr.Read(strm, nopts.source); 205 nopts.header = &hdr; 206 } 207 AddOnImpl<F, T> *impl = new AddOnImpl<F, T>(nopts.header->FstType()); 208 if (!impl->ReadHeader(strm, nopts, kMinFileVersion, &hdr)) 209 return 0; 210 delete impl; // Used here only for checking types. 211 212 int32 magic_number = 0; 213 ReadType(strm, &magic_number); // Ensures this is an add-on Fst. 214 if (magic_number != kAddOnMagicNumber) { 215 LOG(ERROR) << "AddOnImpl::Read: Bad add-on header: " << nopts.source; 216 return 0; 217 } 218 219 FstReadOptions fopts(opts); 220 fopts.header = 0; // Contained header was written out. 221 F *fst = F::Read(strm, fopts); 222 if (!fst) 223 return 0; 224 225 T *t = 0; 226 bool have_addon = false; 227 ReadType(strm, &have_addon); 228 if (have_addon) { // Read add-on object if present. 229 t = T::Read(strm); 230 if (!t) 231 return 0; 232 } 233 impl = new AddOnImpl<F, T>(*fst, nopts.header->FstType(), t); 234 delete fst; 235 if (t) 236 t->DecrRefCount(); 237 return impl; 238 } 239 Write(ostream & strm,const FstWriteOptions & opts)240 bool Write(ostream &strm, const FstWriteOptions &opts) const { 241 FstHeader hdr; 242 FstWriteOptions nopts(opts); 243 nopts.write_isymbols = false; // Let contained FST hold any symbols. 244 nopts.write_osymbols = false; 245 WriteHeader(strm, nopts, kFileVersion, &hdr); 246 WriteType(strm, kAddOnMagicNumber); // Ensures this is an add-on Fst. 247 FstWriteOptions fopts(opts); 248 fopts.write_header = true; // Force writing contained header. 249 if (!fst_.Write(strm, fopts)) 250 return false; 251 bool have_addon = t_; 252 WriteType(strm, have_addon); 253 if (have_addon) // Write add-on object if present. 254 t_->Write(strm); 255 return true; 256 } 257 InitStateIterator(StateIteratorData<Arc> * data)258 void InitStateIterator(StateIteratorData<Arc> *data) const { 259 fst_.InitStateIterator(data); 260 } 261 InitArcIterator(StateId s,ArcIteratorData<Arc> * data)262 void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const { 263 fst_.InitArcIterator(s, data); 264 } 265 GetFst()266 F &GetFst() { return fst_; } 267 GetFst()268 const F &GetFst() const { return fst_; } 269 GetAddOn()270 T *GetAddOn() const { return t_; } 271 272 // If 't' is non-zero, its reference count is incremented. SetAddOn(T * t)273 void SetAddOn(T *t) { 274 if (t == t_) 275 return; 276 if (t_ && !t_->DecrRefCount()) 277 delete t_; 278 t_ = t; 279 if (t_) 280 t_->IncrRefCount(); 281 } 282 283 private: AddOnImpl(const string & type)284 explicit AddOnImpl(const string &type) : t_(0) { 285 SetType(type); 286 SetProperties(kExpanded); 287 } 288 289 // Current file format version 290 static const int kFileVersion = 1; 291 // Minimum file format version supported 292 static const int kMinFileVersion = 1; 293 294 F fst_; 295 T *t_; 296 297 void operator=(const AddOnImpl<F, T> &fst); // Disallow 298 }; 299 300 template <class F, class T> const int AddOnImpl<F, T>::kFileVersion; 301 template <class F, class T> const int AddOnImpl<F, T>::kMinFileVersion; 302 303 304 } // namespace fst 305 306 #endif // FST_LIB_ADD_ON_FST_H__ 307