FST  openfst-1.8.2
OpenFst Library
add-on.h
Go to the documentation of this file.
1 // Copyright 2005-2020 Google LLC
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 // See www.openfst.org for extensive documentation on this weighted
16 // finite-state transducer library.
17 //
18 // FST implementation class to attach an arbitrary object with a read/write
19 // method to an FST and its file representation. The FST is given a new type
20 // name.
21 
22 #ifndef FST_ADD_ON_H_
23 #define FST_ADD_ON_H_
24 
25 #include <stddef.h>
26 
27 #include <cstdint>
28 #include <memory>
29 #include <string>
30 #include <utility>
31 
32 #include <fst/log.h>
33 
34 #include <fst/fst.h>
35 
36 namespace fst {
37 
38 // Identifies stream data as an add-on FST.
39 inline constexpr int32_t kAddOnMagicNumber = 446681434;
40 
41 // Nothing to save.
42 class NullAddOn {
43  public:
44  NullAddOn() {}
45 
46  static NullAddOn *Read(std::istream &strm, const FstReadOptions &opts) {
47  return new NullAddOn();
48  }
49 
50  bool Write(std::ostream &ostrm, const FstWriteOptions &opts) const {
51  return true;
52  }
53 };
54 
55 // Create a new add-on from a pair of add-ons.
56 template <class A1, class A2>
57 class AddOnPair {
58  public:
59  // Argument reference count incremented.
60  AddOnPair(std::shared_ptr<A1> a1, std::shared_ptr<A2> a2)
61  : a1_(std::move(a1)), a2_(std::move(a2)) {}
62 
63  const A1 *First() const { return a1_.get(); }
64 
65  const A2 *Second() const { return a2_.get(); }
66 
67  std::shared_ptr<A1> SharedFirst() const { return a1_; }
68 
69  std::shared_ptr<A2> SharedSecond() const { return a2_; }
70 
71  static AddOnPair *Read(std::istream &istrm, const FstReadOptions &opts) {
72  bool have_addon1 = false;
73  ReadType(istrm, &have_addon1);
74  std::unique_ptr<A1> a1;
75  if (have_addon1) a1 = fst::WrapUnique(A1::Read(istrm, opts));
76 
77  bool have_addon2 = false;
78  ReadType(istrm, &have_addon2);
79  std::unique_ptr<A1> a2;
80  if (have_addon2) a2 = fst::WrapUnique(A2::Read(istrm, opts));
81 
82  return new AddOnPair(std::move(a1), std::move(a2));
83  }
84 
85  bool Write(std::ostream &ostrm, const FstWriteOptions &opts) const {
86  bool have_addon1 = a1_ != nullptr;
87  WriteType(ostrm, have_addon1);
88  if (have_addon1) a1_->Write(ostrm, opts);
89  bool have_addon2 = a2_ != nullptr;
90  WriteType(ostrm, have_addon2);
91  if (have_addon2) a2_->Write(ostrm, opts);
92  return true;
93  }
94 
95  private:
96  std::shared_ptr<A1> a1_;
97  std::shared_ptr<A2> a2_;
98 };
99 
100 namespace internal {
101 
102 // Adds an object of type T to an FST. T must support:
103 //
104 // T* Read(std::istream &);
105 // bool Write(std::ostream &);
106 //
107 // The resulting type is a new FST implementation.
108 template <class FST, class T>
109 class AddOnImpl : public FstImpl<typename FST::Arc> {
110  public:
111  using FstType = FST;
112  using Arc = typename FST::Arc;
113  using Label = typename Arc::Label;
114  using StateId = typename Arc::StateId;
115  using Weight = typename Arc::Weight;
116 
117  using FstImpl<Arc>::SetType;
122 
123  // We make a thread-safe copy of the FST by default since an FST
124  // implementation is expected to not share mutable data between objects.
125  AddOnImpl(const FST &fst, const std::string &type,
126  std::shared_ptr<T> t = nullptr)
127  : fst_(fst, true), t_(std::move(t)) {
128  SetType(type);
129  SetProperties(fst_.Properties(kFstProperties, false));
130  SetInputSymbols(fst_.InputSymbols());
131  SetOutputSymbols(fst_.OutputSymbols());
132  }
133 
134  // Conversion from const Fst<Arc> & to F always copies the underlying
135  // implementation.
136  AddOnImpl(const Fst<Arc> &fst, const std::string &type,
137  std::shared_ptr<T> t = nullptr)
138  : fst_(fst), t_(std::move(t)) {
139  SetType(type);
140  SetProperties(fst_.Properties(kFstProperties, false));
141  SetInputSymbols(fst_.InputSymbols());
142  SetOutputSymbols(fst_.OutputSymbols());
143  }
144 
145  // We make a thread-safe copy of the FST by default since an FST
146  // implementation is expected to not share mutable data between objects.
147  AddOnImpl(const AddOnImpl &impl) : fst_(impl.fst_, true), t_(impl.t_) {
148  SetType(impl.Type());
149  SetProperties(fst_.Properties(kCopyProperties, false));
150  SetInputSymbols(fst_.InputSymbols());
151  SetOutputSymbols(fst_.OutputSymbols());
152  }
153 
154  StateId Start() const { return fst_.Start(); }
155 
156  Weight Final(StateId s) const { return fst_.Final(s); }
157 
158  size_t NumArcs(StateId s) const { return fst_.NumArcs(s); }
159 
160  size_t NumInputEpsilons(StateId s) const { return fst_.NumInputEpsilons(s); }
161 
162  size_t NumOutputEpsilons(StateId s) const {
163  return fst_.NumOutputEpsilons(s);
164  }
165 
166  size_t NumStates() const { return fst_.NumStates(); }
167 
168  static AddOnImpl *Read(std::istream &strm, const FstReadOptions &opts) {
169  FstReadOptions nopts(opts);
170  FstHeader hdr;
171  if (!nopts.header) {
172  hdr.Read(strm, nopts.source);
173  nopts.header = &hdr;
174  }
175  // Using `new` to access private constructor for `AddOnImpl`.
176  auto impl = fst::WrapUnique(new AddOnImpl(nopts.header->FstType()));
177  if (!impl->ReadHeader(strm, nopts, kMinFileVersion, &hdr)) return nullptr;
178  impl.reset();
179  int32_t magic_number = 0;
180  ReadType(strm, &magic_number); // Ensures this is an add-on FST.
181  if (magic_number != kAddOnMagicNumber) {
182  LOG(ERROR) << "AddOnImpl::Read: Bad add-on header: " << nopts.source;
183  return nullptr;
184  }
185  FstReadOptions fopts(opts);
186  fopts.header = nullptr; // Contained header was written out.
187  std::unique_ptr<FST> fst(FST::Read(strm, fopts));
188  if (!fst) return nullptr;
189  std::shared_ptr<T> t;
190  bool have_addon = false;
191  ReadType(strm, &have_addon);
192  if (have_addon) { // Reads add-on object if present.
193  t = std::shared_ptr<T>(T::Read(strm, fopts));
194  if (!t) return nullptr;
195  }
196  return new AddOnImpl(*fst, nopts.header->FstType(), t);
197  }
198 
199  bool Write(std::ostream &strm, const FstWriteOptions &opts) const {
200  FstHeader hdr;
201  FstWriteOptions nopts(opts);
202  nopts.write_isymbols = false; // Allows contained FST to hold any symbols.
203  nopts.write_osymbols = false;
204  WriteHeader(strm, nopts, kFileVersion, &hdr);
205  WriteType(strm, kAddOnMagicNumber); // Ensures this is an add-on FST.
206  FstWriteOptions fopts(opts);
207  fopts.write_header = true; // Forces writing contained header.
208  if (!fst_.Write(strm, fopts)) return false;
209  bool have_addon = !!t_;
210  WriteType(strm, have_addon);
211  // Writes add-on object if present.
212  if (have_addon) t_->Write(strm, opts);
213  return true;
214  }
215 
217  fst_.InitStateIterator(data);
218  }
219 
221  fst_.InitArcIterator(s, data);
222  }
223 
224  FST &GetFst() { return fst_; }
225 
226  const FST &GetFst() const { return fst_; }
227 
228  const T *GetAddOn() const { return t_.get(); }
229 
230  std::shared_ptr<T> GetSharedAddOn() const { return t_; }
231 
232  void SetAddOn(std::shared_ptr<T> t) { t_ = t; }
233 
234  private:
235  explicit AddOnImpl(const std::string &type) : t_() {
236  SetType(type);
237  SetProperties(kExpanded);
238  }
239 
240  // Current file format version.
241  static constexpr int kFileVersion = 1;
242  // Minimum file format version supported.
243  static constexpr int kMinFileVersion = 1;
244 
245  FST fst_;
246  std::shared_ptr<T> t_;
247 
248  AddOnImpl &operator=(const AddOnImpl &) = delete;
249 };
250 
251 } // namespace internal
252 } // namespace fst
253 
254 #endif // FST_ADD_ON_H_
static AddOnPair * Read(std::istream &istrm, const FstReadOptions &opts)
Definition: add-on.h:71
bool Read(std::istream &strm, const std::string &source, bool rewind=false)
Definition: fst.cc:50
const FstHeader * header
Definition: fst.h:75
void InitStateIterator(StateIteratorData< Arc > *data) const
Definition: add-on.h:216
bool Write(std::ostream &strm, const FstWriteOptions &opts) const
Definition: add-on.h:199
std::shared_ptr< A2 > SharedSecond() const
Definition: add-on.h:69
std::string source
Definition: fst.h:74
bool Write(std::ostream &ostrm, const FstWriteOptions &opts) const
Definition: add-on.h:50
#define LOG(type)
Definition: log.h:49
SetType
Definition: set-weight.h:52
std::unique_ptr< T > WrapUnique(T *ptr)
Definition: compat.h:125
std::shared_ptr< A1 > SharedFirst() const
Definition: add-on.h:67
void InitArcIterator(StateId s, ArcIteratorData< Arc > *data) const
Definition: add-on.h:220
std::ostream & WriteType(std::ostream &strm, const T t)
Definition: util.h:211
size_t NumOutputEpsilons(StateId s) const
Definition: add-on.h:162
const std::string & FstType() const
Definition: fst.h:142
AddOnPair(std::shared_ptr< A1 > a1, std::shared_ptr< A2 > a2)
Definition: add-on.h:60
bool write_osymbols
Definition: fst.h:105
constexpr uint64_t kCopyProperties
Definition: properties.h:162
size_t NumArcs(StateId s) const
Definition: add-on.h:158
bool write_isymbols
Definition: fst.h:104
AddOnImpl(const Fst< Arc > &fst, const std::string &type, std::shared_ptr< T > t=nullptr)
Definition: add-on.h:136
StateId Start() const
Definition: add-on.h:154
size_t NumStates() const
Definition: add-on.h:166
std::shared_ptr< T > GetSharedAddOn() const
Definition: add-on.h:230
typename FST::Arc Arc
Definition: add-on.h:112
AddOnImpl(const AddOnImpl &impl)
Definition: add-on.h:147
constexpr int32_t kAddOnMagicNumber
Definition: add-on.h:39
bool write_header
Definition: fst.h:103
const A2 * Second() const
Definition: add-on.h:65
const std::string & Type() const
Definition: fst.h:698
const A1 * First() const
Definition: add-on.h:63
constexpr uint64_t kFstProperties
Definition: properties.h:325
typename Arc::Weight Weight
Definition: add-on.h:115
const T * GetAddOn() const
Definition: add-on.h:228
AddOnImpl(const FST &fst, const std::string &type, std::shared_ptr< T > t=nullptr)
Definition: add-on.h:125
size_t NumInputEpsilons(StateId s) const
Definition: add-on.h:160
typename Arc::Label Label
Definition: add-on.h:113
std::istream & ReadType(std::istream &strm, T *t)
Definition: util.h:65
bool Write(std::ostream &ostrm, const FstWriteOptions &opts) const
Definition: add-on.h:85
const FST & GetFst() const
Definition: add-on.h:226
static NullAddOn * Read(std::istream &strm, const FstReadOptions &opts)
Definition: add-on.h:46
static AddOnImpl * Read(std::istream &strm, const FstReadOptions &opts)
Definition: add-on.h:168
constexpr uint64_t kExpanded
Definition: properties.h:45
Weight Final(StateId s) const
Definition: add-on.h:156
void SetAddOn(std::shared_ptr< T > t)
Definition: add-on.h:232
typename Arc::StateId StateId
Definition: add-on.h:114