aboutsummaryrefslogtreecommitdiff
path: root/src/include/fst/add-on.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/fst/add-on.h')
-rw-r--r--src/include/fst/add-on.h306
1 files changed, 306 insertions, 0 deletions
diff --git a/src/include/fst/add-on.h b/src/include/fst/add-on.h
new file mode 100644
index 0000000..ee21a93
--- /dev/null
+++ b/src/include/fst/add-on.h
@@ -0,0 +1,306 @@
+// add-on.h
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Copyright 2005-2010 Google, Inc.
+// Author: riley@google.com (Michael Riley)
+//
+// \file
+// Fst implementation class to attach an arbitrary object with a
+// read/write method to an FST and its file rep. The FST is given a
+// new type name.
+
+#ifndef FST_LIB_ADD_ON_FST_H__
+#define FST_LIB_ADD_ON_FST_H__
+
+#include <stddef.h>
+#include <string>
+
+#include <fst/fst.h>
+
+
+namespace fst {
+
+// Identifies stream data as an add-on fst.
+static const int32 kAddOnMagicNumber = 446681434;
+
+
+//
+// Some useful add-on objects.
+//
+
+// Nothing to save.
+class NullAddOn {
+ public:
+ NullAddOn() {}
+
+ static NullAddOn *Read(istream &istrm) {
+ return new NullAddOn();
+ };
+
+ bool Write(ostream &ostrm) const { return true; }
+
+ int RefCount() const { return ref_count_.count(); }
+ int IncrRefCount() { return ref_count_.Incr(); }
+ int DecrRefCount() { return ref_count_.Decr(); }
+
+ private:
+ RefCounter ref_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(NullAddOn);
+};
+
+
+// Create a new add-on from a pair of add-ons.
+template <class A1, class A2>
+class AddOnPair {
+ public:
+ // Argument reference count incremented.
+ AddOnPair(A1 *a1, A2 *a2)
+ : a1_(a1), a2_(a2) {
+ if (a1_)
+ a1_->IncrRefCount();
+ if (a2_)
+ a2_->IncrRefCount();
+ }
+
+ ~AddOnPair() {
+ if (a1_ && !a1_->DecrRefCount())
+ delete a1_;
+ if (a2_ && !a2_->DecrRefCount())
+ delete a2_;
+ }
+
+ A1 *First() const { return a1_; }
+ A2 *Second() const { return a2_; }
+
+ static AddOnPair<A1, A2> *Read(istream &istrm) {
+ A1 *a1 = 0;
+ bool have_addon1 = false;
+ ReadType(istrm, &have_addon1);
+ if (have_addon1)
+ a1 = A1::Read(istrm);
+
+ A2 *a2 = 0;
+ bool have_addon2 = false;
+ ReadType(istrm, &have_addon2);
+ if (have_addon2)
+ a2 = A2::Read(istrm);
+
+ AddOnPair<A1, A2> *a = new AddOnPair<A1, A2>(a1, a2);
+ if (a1)
+ a1->DecrRefCount();
+ if (a2)
+ a2->DecrRefCount();
+ return a;
+ };
+
+ bool Write(ostream &ostrm) const {
+ bool have_addon1 = a1_;
+ WriteType(ostrm, have_addon1);
+ if (have_addon1)
+ a1_->Write(ostrm);
+ bool have_addon2 = a2_;
+ WriteType(ostrm, have_addon2);
+ if (have_addon2)
+ a2_->Write(ostrm);
+ return true;
+ }
+
+ int RefCount() const { return ref_count_.count(); }
+
+ int IncrRefCount() {
+ return ref_count_.Incr();
+ }
+
+ int DecrRefCount() {
+ return ref_count_.Decr();
+ }
+
+ private:
+ A1 *a1_;
+ A2 *a2_;
+ RefCounter ref_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(AddOnPair);
+};
+
+
+// Add to an Fst F a type T object. T must have a 'T* Read(istream &)',
+// a 'bool Write(ostream &)' method, and 'int RecCount(), 'int IncrRefCount()'
+// and 'int DecrRefCount()' methods (e.g. 'MatcherData' in matcher-fst.h).
+// The result is a new Fst implemenation with type name 'type'.
+template<class F, class T>
+class AddOnImpl : public FstImpl<typename F::Arc> {
+ public:
+ typedef typename F::Arc Arc;
+ typedef typename Arc::Label Label;
+ typedef typename Arc::Weight Weight;
+ typedef typename Arc::StateId StateId;
+
+ using FstImpl<Arc>::SetType;
+ using FstImpl<Arc>::SetProperties;
+ using FstImpl<Arc>::WriteHeader;
+
+ // If 't' is non-zero, its reference count is incremented.
+ AddOnImpl(const F &fst, const string &type, T *t = 0)
+ : fst_(fst), t_(t) {
+ SetType(type);
+ SetProperties(fst_.Properties(kFstProperties, false));
+ if (t_)
+ t_->IncrRefCount();
+ }
+
+ // If 't' is non-zero, its reference count is incremented.
+ AddOnImpl(const Fst<Arc> &fst, const string &type, T *t = 0)
+ : fst_(fst), t_(t) {
+ SetType(type);
+ SetProperties(fst_.Properties(kFstProperties, false));
+ if (t_)
+ t_->IncrRefCount();
+ }
+
+ AddOnImpl(const AddOnImpl<F, T> &impl)
+ : fst_(impl.fst_), t_(impl.t_) {
+ SetType(impl.Type());
+ SetProperties(fst_.Properties(kCopyProperties, false));
+ if (t_)
+ t_->IncrRefCount();
+ }
+
+ ~AddOnImpl() {
+ if (t_ && !t_->DecrRefCount())
+ delete t_;
+ }
+
+ StateId Start() const { return fst_.Start(); }
+ Weight Final(StateId s) const { return fst_.Final(s); }
+ size_t NumArcs(StateId s) const { return fst_.NumArcs(s); }
+
+ size_t NumInputEpsilons(StateId s) const {
+ return fst_.NumInputEpsilons(s);
+ }
+
+ size_t NumOutputEpsilons(StateId s) const {
+ return fst_.NumOutputEpsilons(s);
+ }
+
+ size_t NumStates() const { return fst_.NumStates(); }
+
+ static AddOnImpl<F, T> *Read(istream &strm, const FstReadOptions &opts) {
+ FstReadOptions nopts(opts);
+ FstHeader hdr;
+ if (!nopts.header) {
+ hdr.Read(strm, nopts.source);
+ nopts.header = &hdr;
+ }
+ AddOnImpl<F, T> *impl = new AddOnImpl<F, T>(nopts.header->FstType());
+ if (!impl->ReadHeader(strm, nopts, kMinFileVersion, &hdr))
+ return 0;
+ delete impl; // Used here only for checking types.
+
+ int32 magic_number = 0;
+ ReadType(strm, &magic_number); // Ensures this is an add-on Fst.
+ if (magic_number != kAddOnMagicNumber) {
+ LOG(ERROR) << "AddOnImpl::Read: Bad add-on header: " << nopts.source;
+ return 0;
+ }
+
+ FstReadOptions fopts(opts);
+ fopts.header = 0; // Contained header was written out.
+ F *fst = F::Read(strm, fopts);
+ if (!fst)
+ return 0;
+
+ T *t = 0;
+ bool have_addon = false;
+ ReadType(strm, &have_addon);
+ if (have_addon) { // Read add-on object if present.
+ t = T::Read(strm);
+ if (!t)
+ return 0;
+ }
+ impl = new AddOnImpl<F, T>(*fst, nopts.header->FstType(), t);
+ delete fst;
+ if (t)
+ t->DecrRefCount();
+ return impl;
+ }
+
+ bool Write(ostream &strm, const FstWriteOptions &opts) const {
+ FstHeader hdr;
+ FstWriteOptions nopts(opts);
+ nopts.write_isymbols = false; // Let contained FST hold any symbols.
+ nopts.write_osymbols = false;
+ WriteHeader(strm, nopts, kFileVersion, &hdr);
+ WriteType(strm, kAddOnMagicNumber); // Ensures this is an add-on Fst.
+ FstWriteOptions fopts(opts);
+ fopts.write_header = true; // Force writing contained header.
+ if (!fst_.Write(strm, fopts))
+ return false;
+ bool have_addon = t_;
+ WriteType(strm, have_addon);
+ if (have_addon) // Write add-on object if present.
+ t_->Write(strm);
+ return true;
+ }
+
+ void InitStateIterator(StateIteratorData<Arc> *data) const {
+ fst_.InitStateIterator(data);
+ }
+
+ void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const {
+ fst_.InitArcIterator(s, data);
+ }
+
+ F &GetFst() { return fst_; }
+
+ const F &GetFst() const { return fst_; }
+
+ T *GetAddOn() const { return t_; }
+
+ // If 't' is non-zero, its reference count is incremented.
+ void SetAddOn(T *t) {
+ if (t == t_)
+ return;
+ if (t_ && !t_->DecrRefCount())
+ delete t_;
+ t_ = t;
+ if (t_)
+ t_->IncrRefCount();
+ }
+
+ private:
+ explicit AddOnImpl(const string &type) : t_(0) {
+ SetType(type);
+ SetProperties(kExpanded);
+ }
+
+ // Current file format version
+ static const int kFileVersion = 1;
+ // Minimum file format version supported
+ static const int kMinFileVersion = 1;
+
+ F fst_;
+ T *t_;
+
+ void operator=(const AddOnImpl<F, T> &fst); // Disallow
+};
+
+template <class F, class T> const int AddOnImpl<F, T>::kFileVersion;
+template <class F, class T> const int AddOnImpl<F, T>::kMinFileVersion;
+
+
+} // namespace fst
+
+#endif // FST_LIB_ADD_ON_FST_H__