// verify.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
// Function to verify an Fst's contents
#ifndef FST_LIB_VERIFY_H__
#define FST_LIB_VERIFY_H__
#include <fst/fst.h>
#include <fst/test-properties.h>
namespace fst {
// Verifies that an Fst's contents are sane.
template<class Arc>
bool Verify(const Fst<Arc> &fst, bool allow_negative_labels = false) {
typedef typename Arc::Label Label;
typedef typename Arc::Weight Weight;
typedef typename Arc::StateId StateId;
StateId start = fst.Start();
const SymbolTable *isyms = fst.InputSymbols();
const SymbolTable *osyms = fst.OutputSymbols();
// Count states
StateId ns = 0;
for (StateIterator< Fst<Arc> > siter(fst);
!siter.Done();
siter.Next())
++ns;
if (start == kNoStateId && ns > 0) {
LOG(ERROR) << "Verify: Fst start state ID unset";
return false;
} else if (start >= ns) {
LOG(ERROR) << "Verify: Fst start state ID exceeds number of states";
return false;
}
for (StateIterator< Fst<Arc> > siter(fst);
!siter.Done();
siter.Next()) {
StateId s = siter.Value();
size_t na = 0;
for (ArcIterator< Fst<Arc> > aiter(fst, s);
!aiter.Done();
aiter.Next()) {
const Arc &arc =aiter.Value();
if (!allow_negative_labels && arc.ilabel < 0) {
LOG(ERROR) << "Verify: Fst input label ID of arc at position "
<< na << " of state " << s << " is negative";
return false;
} else if (isyms && isyms->Find(arc.ilabel) == "") {
LOG(ERROR) << "Verify: Fst input label ID " << arc.ilabel
<< " of arc at position " << na << " of state " << s
<< " is missing from input symbol table \""
<< isyms->Name() << "\"";
return false;
} else if (!allow_negative_labels && arc.olabel < 0) {
LOG(ERROR) << "Verify: Fst output label ID of arc at position "
<< na << " of state " << s << " is negative";
return false;
} else if (osyms && osyms->Find(arc.olabel) == "") {
LOG(ERROR) << "Verify: Fst output label ID " << arc.olabel
<< " of arc at position " << na << " of state " << s
<< " is missing from output symbol table \""
<< osyms->Name() << "\"";
return false;
} else if (!arc.weight.Member() || arc.weight == Weight::Zero()) {
LOG(ERROR) << "Verify: Fst weight of arc at position "
<< na << " of state " << s << " is invalid";
return false;
} else if (arc.nextstate < 0) {
LOG(ERROR) << "Verify: Fst destination state ID of arc at position "
<< na << " of state " << s << " is negative";
return false;
} else if (arc.nextstate >= ns) {
LOG(ERROR) << "Verify: Fst destination state ID of arc at position "
<< na << " of state " << s
<< " exceeds number of states";
return false;
}
++na;
}
if (!fst.Final(s).Member()) {
LOG(ERROR) << "Verify: Fst final weight of state " << s << " is invalid";
return false;
}
}
uint64 fst_props = fst.Properties(kFstProperties, false);
if (fst_props & kError) {
LOG(ERROR) << "Verify: Fst error property is set";
return false;
}
uint64 known_props;
uint64 test_props = ComputeProperties(fst, kFstProperties, &known_props,
false);
if (!CompatProperties(fst_props, test_props)) {
LOG(ERROR) << "Verify: stored Fst properties incorrect "
<< "(props1 = stored props, props2 = tested)";
return false;
} else {
return true;
}
}
} // namespace fst
#endif // FST_LIB_VERIFY_H__