1 // expanded-fst.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 // Generic FST augmented with state count - interface class definition.
20 //
21 
22 #ifndef FST_LIB_EXPANDED_FST_H__
23 #define FST_LIB_EXPANDED_FST_H__
24 
25 #include <sys/types.h>
26 #include <string>
27 
28 #include <fst/fst.h>
29 
30 
31 namespace fst {
32 
33 // A generic FST plus state count.
34 template <class A>
35 class ExpandedFst : public Fst<A> {
36  public:
37   typedef A Arc;
38   typedef typename A::StateId StateId;
39 
40   virtual StateId NumStates() const = 0;  // State count
41 
42   // Get a copy of this ExpandedFst. See Fst<>::Copy() for further doc.
43   virtual ExpandedFst<A> *Copy(bool safe = false) const = 0;
44 
45   // Read an ExpandedFst from an input stream; return NULL on error.
Read(istream & strm,const FstReadOptions & opts)46   static ExpandedFst<A> *Read(istream &strm, const FstReadOptions &opts) {
47     FstReadOptions ropts(opts);
48     FstHeader hdr;
49     if (ropts.header)
50       hdr = *opts.header;
51     else {
52       if (!hdr.Read(strm, opts.source))
53         return 0;
54       ropts.header = &hdr;
55     }
56     if (!(hdr.Properties() & kExpanded)) {
57       LOG(ERROR) << "ExpandedFst::Read: Not an ExpandedFst: " << ropts.source;
58       return 0;
59     }
60     FstRegister<A> *registr = FstRegister<A>::GetRegister();
61     const typename FstRegister<A>::Reader reader =
62       registr->GetReader(hdr.FstType());
63     if (!reader) {
64       LOG(ERROR) << "ExpandedFst::Read: Unknown FST type \"" << hdr.FstType()
65                  << "\" (arc type = \"" << A::Type()
66                  << "\"): " << ropts.source;
67       return 0;
68     }
69     Fst<A> *fst = reader(strm, ropts);
70     if (!fst) return 0;
71     return static_cast<ExpandedFst<A> *>(fst);
72   }
73 
74   // Read an ExpandedFst from a file; return NULL on error.
75   // Empty filename reads from standard input.
Read(const string & filename)76   static ExpandedFst<A> *Read(const string &filename) {
77     if (!filename.empty()) {
78       ifstream strm(filename.c_str(), ifstream::in | ifstream::binary);
79       if (!strm) {
80         LOG(ERROR) << "ExpandedFst::Read: Can't open file: " << filename;
81         return 0;
82       }
83       return Read(strm, FstReadOptions(filename));
84     } else {
85       return Read(cin, FstReadOptions("standard input"));
86     }
87   }
88 };
89 
90 
91 namespace internal {
92 
93 //  ExpandedFst<A> case - abstract methods.
94 template <class A> inline
Final(const ExpandedFst<A> & fst,typename A::StateId s)95 typename A::Weight Final(const ExpandedFst<A> &fst, typename A::StateId s) {
96   return fst.Final(s);
97 }
98 
99 template <class A> inline
NumArcs(const ExpandedFst<A> & fst,typename A::StateId s)100 ssize_t NumArcs(const ExpandedFst<A> &fst, typename A::StateId s) {
101   return fst.NumArcs(s);
102 }
103 
104 template <class A> inline
NumInputEpsilons(const ExpandedFst<A> & fst,typename A::StateId s)105 ssize_t NumInputEpsilons(const ExpandedFst<A> &fst, typename A::StateId s) {
106   return fst.NumInputEpsilons(s);
107 }
108 
109 template <class A> inline
NumOutputEpsilons(const ExpandedFst<A> & fst,typename A::StateId s)110 ssize_t NumOutputEpsilons(const ExpandedFst<A> &fst, typename A::StateId s) {
111   return fst.NumOutputEpsilons(s);
112 }
113 
114 }  // namespace internal
115 
116 
117 // A useful alias when using StdArc.
118 typedef ExpandedFst<StdArc> StdExpandedFst;
119 
120 
121 // This is a helper class template useful for attaching an ExpandedFst
122 // interface to its implementation, handling reference counting. It
123 // delegates to ImplToFst the handling of the Fst interface methods.
124 template < class I, class F = ExpandedFst<typename I::Arc> >
125 class ImplToExpandedFst : public ImplToFst<I, F> {
126  public:
127   typedef typename I::Arc Arc;
128   typedef typename Arc::Weight Weight;
129   typedef typename Arc::StateId StateId;
130 
131   using ImplToFst<I, F>::GetImpl;
132 
NumStates()133   virtual StateId NumStates() const { return GetImpl()->NumStates(); }
134 
135  protected:
ImplToExpandedFst()136   ImplToExpandedFst() : ImplToFst<I, F>() {}
137 
ImplToExpandedFst(I * impl)138   ImplToExpandedFst(I *impl) : ImplToFst<I, F>(impl) {}
139 
ImplToExpandedFst(const ImplToExpandedFst<I,F> & fst)140   ImplToExpandedFst(const ImplToExpandedFst<I, F> &fst)
141       : ImplToFst<I, F>(fst) {}
142 
ImplToExpandedFst(const ImplToExpandedFst<I,F> & fst,bool safe)143   ImplToExpandedFst(const ImplToExpandedFst<I, F> &fst, bool safe)
144       : ImplToFst<I, F>(fst, safe) {}
145 
146   // Read FST implementation from a file; return NULL on error.
147   // Empty filename reads from standard input.
Read(const string & filename)148   static I *Read(const string &filename) {
149     if (!filename.empty()) {
150       ifstream strm(filename.c_str(), ifstream::in | ifstream::binary);
151       if (!strm) {
152         LOG(ERROR) << "ExpandedFst::Read: Can't open file: " << filename;
153         return 0;
154       }
155       return I::Read(strm, FstReadOptions(filename));
156     } else {
157       return I::Read(cin, FstReadOptions("standard input"));
158     }
159   }
160 
161  private:
162   // Disallow
163   ImplToExpandedFst<I, F> &operator=(const ImplToExpandedFst<I, F> &fst);
164 
165   ImplToExpandedFst<I, F> &operator=(const Fst<Arc> &fst) {
166     FSTERROR() << "ImplToExpandedFst: Assignment operator disallowed";
167     GetImpl()->SetProperties(kError, kError);
168     return *this;
169   }
170 };
171 
172 // Function to return the number of states in an FST, counting them
173 // if necessary.
174 template <class Arc>
CountStates(const Fst<Arc> & fst)175 typename Arc::StateId CountStates(const Fst<Arc> &fst) {
176   if (fst.Properties(kExpanded, false)) {
177     const ExpandedFst<Arc> *efst = static_cast<const ExpandedFst<Arc> *>(&fst);
178     return efst->NumStates();
179   } else {
180     typename Arc::StateId nstates = 0;
181     for (StateIterator< Fst<Arc> > siter(fst); !siter.Done(); siter.Next())
182       ++nstates;
183     return nstates;
184   }
185 }
186 
187 }  // namespace fst
188 
189 #endif  // FST_LIB_EXPANDED_FST_H__
190