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
25namespace fst {
26
27// Verifies that an Fst's contents are sane.
28template<class Arc>
29bool 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