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