1 // verify.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 //
16 // \file
17 // Function to test property bits
18
19 #ifndef FST_LIB_VERIFY_H__
20 #define FST_LIB_VERIFY_H__
21
22 #include "fst/lib/fst.h"
23 #include "fst/lib/test-properties.h"
24
25 namespace fst {
26
27 // Verifies that an Fst's contents are sane.
28 template<class Arc>
Verify(const Fst<Arc> & fst)29 bool Verify(const Fst<Arc> &fst) {
30 typedef typename Arc::Label Label;
31 typedef typename Arc::Weight Weight;
32 typedef typename Arc::StateId StateId;
33
34 StateId start = fst.Start();
35 const SymbolTable *isyms = fst.InputSymbols();
36 const SymbolTable *osyms = fst.OutputSymbols();
37
38 // Count states
39 StateId ns = 0;
40 for (StateIterator< Fst<Arc> > siter(fst);
41 !siter.Done();
42 siter.Next())
43 ++ns;
44
45 if (start == kNoStateId && ns > 0) {
46 LOG(ERROR) << "Verify: Fst start state ID unset";
47 return false;
48 } else if (start >= ns) {
49 LOG(ERROR) << "Verify: Fst start state ID exceeds number of states";
50 return false;
51 }
52
53 for (StateIterator< Fst<Arc> > siter(fst);
54 !siter.Done();
55 siter.Next()) {
56 StateId s = siter.Value();
57 size_t na = 0;
58 for (ArcIterator< Fst<Arc> > aiter(fst, s);
59 !aiter.Done();
60 aiter.Next()) {
61 const Arc &arc =aiter.Value();
62 if (arc.ilabel < 0) {
63 LOG(ERROR) << "Verify: Fst input label ID of arc at position "
64 << na << " of state " << s << " is negative";
65 return false;
66 } else if (isyms && isyms->Find(arc.ilabel) == "") {
67 LOG(ERROR) << "Verify: Fst input label ID " << arc.ilabel
68 << " of arc at position " << na << " of state " << s
69 << " is missing from input symbol table \""
70 << isyms->Name() << "\"";
71 return false;
72 } else if (arc.olabel < 0) {
73 LOG(ERROR) << "Verify: Fst output label ID of arc at position "
74 << na << " of state " << s << " is negative";
75 return false;
76 } else if (osyms && osyms->Find(arc.olabel) == "") {
77 LOG(ERROR) << "Verify: Fst output label ID " << arc.olabel
78 << " of arc at position " << na << " of state " << s
79 << " is missing from output symbol table \""
80 << osyms->Name() << "\"";
81 return false;
82 } else if (!arc.weight.Member() || arc.weight == Weight::Zero()) {
83 LOG(ERROR) << "Verify: Fst weight of arc at position "
84 << na << " of state " << s << " is invalid";
85 return false;
86 } else if (arc.nextstate < 0) {
87 LOG(ERROR) << "Verify: Fst destination state ID of arc at position "
88 << na << " of state " << s << " is negative";
89 return false;
90 } else if (arc.nextstate >= ns) {
91 LOG(ERROR) << "Verify: Fst destination state ID of arc at position "
92 << na << " of state " << s
93 << " exceeds number of states";
94 return false;
95 }
96 ++na;
97 }
98 if (!fst.Final(s).Member()) {
99 LOG(ERROR) << "Verify: Fst final weight of state " << s << " is invalid";
100 return false;
101 }
102 }
103 uint64 fst_props = fst.Properties(kFstProperties, false);
104 uint64 known_props;
105 uint64 test_props = ComputeProperties(fst, kFstProperties, &known_props,
106 false);
107 if (!CompatProperties(fst_props, test_props)) {
108 LOG(ERROR) << "Verify: stored Fst properties incorrect "
109 << "(props1 = stored props, props2 = tested)";
110 return false;
111 } else {
112 return true;
113 }
114 }
115
116 } // namespace fst
117
118 #endif // FST_LIB_VERIFY_H__
119