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