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