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.

174 lines
5.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. #ifndef FST_TEST_COMPACTORS_H_
  16. #define FST_TEST_COMPACTORS_H_
  17. // See www.openfst.org for extensive documentation on this weighted
  18. // finite-state transducer library.
  19. //
  20. // Compactors for use in tests. See compact-fst.h.
  21. #include <sys/types.h>
  22. #include <cstddef>
  23. #include <cstdint>
  24. #include <istream>
  25. #include <memory>
  26. #include <ostream>
  27. #include <string>
  28. #include <type_traits>
  29. #include <fst/arc.h>
  30. #include <fst/expanded-fst.h>
  31. #include <fst/fst.h>
  32. #include <fst/properties.h>
  33. #include <fst/util.h>
  34. #include <fst/vector-fst.h>
  35. namespace fst {
  36. // A user-defined compactor for test FST.
  37. // Stores all Arc components as a tuple.
  38. template <class A>
  39. class TrivialArcCompactor {
  40. public:
  41. using Arc = A;
  42. using Label = typename A::Label;
  43. using StateId = typename A::StateId;
  44. using Weight = typename A::Weight;
  45. // We use ArcTpl, which is trivially copyable if Weight is.
  46. static_assert(std::is_trivially_copyable_v<Weight>,
  47. "Weight must be trivially copyable.");
  48. using Element = ArcTpl<Weight>;
  49. static_assert(std::is_trivially_copyable_v<Element>,
  50. "ArcTpl should be trivially copyable; someone broke it.");
  51. Element Compact(StateId s, const A &arc) const {
  52. return Element(arc.ilabel, arc.olabel, arc.weight, arc.nextstate);
  53. }
  54. Arc Expand(StateId s, const Element &e, uint32_t f = kArcValueFlags) const {
  55. return Arc(e.ilabel, e.olabel, e.weight, e.nextstate);
  56. }
  57. ssize_t Size() const { return -1; }
  58. uint64_t Properties() const { return 0ULL; }
  59. bool Compatible(const Fst<A> &fst) const { return true; }
  60. static const std::string &Type() {
  61. static const std::string *const type =
  62. new std::string("trival_arc_compactor_" + Arc::Type());
  63. return *type;
  64. }
  65. bool Write(std::ostream &strm) const { return true; }
  66. static TrivialArcCompactor *Read(std::istream &strm) {
  67. return new TrivialArcCompactor;
  68. }
  69. };
  70. // A user-defined arc compactor for test FST.
  71. // Doesn't actually do any compacting, but exercises the Compactor interface.
  72. template <class A>
  73. class TrivialCompactor {
  74. public:
  75. using Arc = A;
  76. using StateId = typename Arc::StateId;
  77. using Weight = typename Arc::Weight;
  78. // Any empty FST is OK.
  79. TrivialCompactor() : fst_(new VectorFst<Arc>) {}
  80. // Constructor from the Fst to be compacted. If compactor is present,
  81. // only optional state should be copied from it.
  82. explicit TrivialCompactor(const Fst<Arc> &fst,
  83. std::shared_ptr<TrivialCompactor> = nullptr)
  84. : fst_(fst.Copy()) {}
  85. // Copy constructor. Must make a thread-safe copy suitable for use by
  86. // by Fst::Copy(/*safe=*/true).
  87. TrivialCompactor(const TrivialCompactor &compactor)
  88. : fst_(compactor.fst_->Copy(/*safe=*/true)) {}
  89. StateId Start() const { return fst_->Start(); }
  90. StateId NumStates() const { return CountStates(*fst_); }
  91. size_t NumArcs() const { return CountArcs(*fst_); }
  92. // Accessor class for state attributes.
  93. class State {
  94. public:
  95. State() = default;
  96. State(const TrivialCompactor *c, StateId s)
  97. : c_(c),
  98. s_(s),
  99. i_(std::make_unique<ArcIterator<Fst<Arc>>>(*c->fst_, s)) {}
  100. StateId GetStateId() const { return s_; }
  101. Weight Final() const { return c_->fst_->Final(s_); }
  102. size_t NumArcs() const { return c_->fst_->NumArcs(s_); }
  103. Arc GetArc(size_t i, uint32_t f) const {
  104. i_->Seek(i);
  105. return i_->Value();
  106. }
  107. private:
  108. const TrivialCompactor *c_ = nullptr;
  109. StateId s_ = kNoStateId;
  110. std::unique_ptr<ArcIterator<Fst<Arc>>> i_;
  111. };
  112. void SetState(StateId s, State *state) { *state = State(this, s); }
  113. template <typename Arc>
  114. bool IsCompatible(const Fst<Arc> &fst) const {
  115. return std::is_same_v<Arc, A>;
  116. }
  117. uint64_t Properties(uint64_t props) const { return props; }
  118. static const std::string &Type() {
  119. static const std::string *const type =
  120. new std::string("trivial_compactor_" + Arc::Type());
  121. return *type;
  122. }
  123. bool Error() const { return fst_->Properties(kError, /*test=*/false); }
  124. bool Write(std::ostream &strm, const FstWriteOptions &opts) const {
  125. WriteType(strm, Type());
  126. // Write as a VectorFst.
  127. return VectorFst<Arc>::WriteFst(*fst_, strm, opts);
  128. }
  129. static TrivialCompactor *Read(std::istream &strm, FstReadOptions opts,
  130. const FstHeader &hdr) {
  131. std::string type;
  132. ReadType(strm, &type);
  133. if (type != Type()) return nullptr;
  134. opts.header = nullptr;
  135. auto fst = fst::WrapUnique(VectorFst<Arc>::Read(strm, opts));
  136. if (fst == nullptr) return nullptr;
  137. return new TrivialCompactor(*fst);
  138. }
  139. private:
  140. std::unique_ptr<Fst<Arc>> fst_;
  141. };
  142. } // namespace fst
  143. #endif // FST_TEST_COMPACTORS_H_