You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
4.2 KiB

  1. // Copyright 2005-2024 Google LLC
  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. // See www.openfst.org for extensive documentation on this weighted
  16. // finite-state transducer library.
  17. //
  18. // Function to verify an FST's contents.
  19. #ifndef FST_VERIFY_H_
  20. #define FST_VERIFY_H_
  21. #include <cstddef>
  22. #include <cstdint>
  23. #include <fst/log.h>
  24. #include <fst/expanded-fst.h>
  25. #include <fst/fst.h>
  26. #include <fst/properties.h>
  27. #include <fst/test-properties.h>
  28. namespace fst {
  29. // Verifies that an Fst's contents are sane.
  30. template <class Arc>
  31. bool Verify(const Fst<Arc> &fst, bool allow_negative_labels = false) {
  32. const auto start = fst.Start();
  33. const auto *isyms = fst.InputSymbols();
  34. const auto *osyms = fst.OutputSymbols();
  35. const auto ns = CountStates(fst);
  36. if (start == kNoStateId && ns > 0) {
  37. LOG(ERROR) << "Verify: FST start state ID not set";
  38. return false;
  39. } else if (start >= ns) {
  40. LOG(ERROR) << "Verify: FST start state ID exceeds number of states";
  41. return false;
  42. }
  43. for (StateIterator<Fst<Arc>> siter(fst); !siter.Done(); siter.Next()) {
  44. auto state = siter.Value();
  45. size_t na = 0;
  46. for (ArcIterator<Fst<Arc>> aiter(fst, state); !aiter.Done(); aiter.Next()) {
  47. const auto &arc = aiter.Value();
  48. if (!allow_negative_labels && arc.ilabel < 0) {
  49. LOG(ERROR) << "Verify: FST input label ID of arc at position " << na
  50. << " of state " << state << " is negative";
  51. return false;
  52. } else if (isyms && !isyms->Member(arc.ilabel)) {
  53. LOG(ERROR) << "Verify: FST input label ID " << arc.ilabel
  54. << " of arc at position " << na << " of state " << state
  55. << " is missing from input symbol table \"" << isyms->Name()
  56. << "\"";
  57. return false;
  58. } else if (!allow_negative_labels && arc.olabel < 0) {
  59. LOG(ERROR) << "Verify: FST output label ID of arc at position " << na
  60. << " of state " << state << " is negative";
  61. return false;
  62. } else if (osyms && !osyms->Member(arc.olabel)) {
  63. LOG(ERROR) << "Verify: FST output label ID " << arc.olabel
  64. << " of arc at position " << na << " of state " << state
  65. << " is missing from output symbol table \"" << osyms->Name()
  66. << "\"";
  67. return false;
  68. } else if (!arc.weight.Member()) {
  69. LOG(ERROR) << "Verify: FST weight of arc at position " << na
  70. << " of state " << state << " is invalid";
  71. return false;
  72. } else if (arc.nextstate < 0) {
  73. LOG(ERROR) << "Verify: FST destination state ID of arc at position "
  74. << na << " of state " << state << " is negative";
  75. return false;
  76. } else if (arc.nextstate >= ns) {
  77. LOG(ERROR) << "Verify: FST destination state ID of arc at position "
  78. << na << " of state " << state
  79. << " exceeds number of states";
  80. return false;
  81. }
  82. ++na;
  83. }
  84. if (!fst.Final(state).Member()) {
  85. LOG(ERROR) << "Verify: FST final weight of state " << state
  86. << " is invalid";
  87. return false;
  88. }
  89. }
  90. const auto fst_props = fst.Properties(kFstProperties, /*test=*/false);
  91. if (fst_props & kError) {
  92. LOG(ERROR) << "Verify: FST error property is set";
  93. return false;
  94. }
  95. uint64_t known_props;
  96. uint64_t test_props =
  97. internal::ComputeProperties(fst, kFstProperties, &known_props);
  98. if (!internal::CompatProperties(fst_props, test_props)) {
  99. LOG(ERROR) << "Verify: Stored FST properties incorrect "
  100. << "(props1 = stored props, props2 = tested)";
  101. return false;
  102. } else {
  103. return true;
  104. }
  105. }
  106. } // namespace fst
  107. #endif // FST_VERIFY_H_