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.

143 lines
4.3 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. // Helper class template useful for attaching an FST interface to its
  19. // implementation, handling reference counting.
  20. #ifndef FST_IMPL_TO_FST_H_
  21. #define FST_IMPL_TO_FST_H_
  22. #include <cstdint>
  23. #include <memory>
  24. #include <string>
  25. #include <fst/fst.h>
  26. #include <fst/impl-to-fst.h>
  27. #include <fst/symbol-table.h>
  28. #include <fst/test-properties.h>
  29. namespace fst {
  30. // This is a helper class template useful for attaching an FST interface to
  31. // its implementation, handling reference counting.
  32. // Thread-unsafe due to Properties (a const function) calling
  33. // Impl::SetProperties. TODO(jrosenstock): Make thread-compatible.
  34. // Impl's copy constructor must produce a thread-safe copy.
  35. template <class Impl, class FST = Fst<typename Impl::Arc>>
  36. class ImplToFst : public FST {
  37. public:
  38. using Arc = typename Impl::Arc;
  39. using StateId = typename Arc::StateId;
  40. using Weight = typename Arc::Weight;
  41. StateId Start() const override { return impl_->Start(); }
  42. Weight Final(StateId s) const override { return impl_->Final(s); }
  43. size_t NumArcs(StateId s) const override { return impl_->NumArcs(s); }
  44. size_t NumInputEpsilons(StateId s) const override {
  45. return impl_->NumInputEpsilons(s);
  46. }
  47. size_t NumOutputEpsilons(StateId s) const override {
  48. return impl_->NumOutputEpsilons(s);
  49. }
  50. // Note that this is a const function, but can set the Impl's properties
  51. // when test is true.
  52. uint64_t Properties(uint64_t mask, bool test) const override {
  53. if (test) {
  54. uint64_t knownprops,
  55. testprops = internal::TestProperties(*this, mask, &knownprops);
  56. // Properties is a const member function, but can set the cached
  57. // properties. UpdateProperties does this thread-safely via atomics.
  58. impl_->UpdateProperties(testprops, knownprops);
  59. return testprops & mask;
  60. } else {
  61. return impl_->Properties(mask);
  62. }
  63. }
  64. const std::string &Type() const override { return impl_->Type(); }
  65. const SymbolTable *InputSymbols() const override {
  66. return impl_->InputSymbols();
  67. }
  68. const SymbolTable *OutputSymbols() const override {
  69. return impl_->OutputSymbols();
  70. }
  71. protected:
  72. explicit ImplToFst(std::shared_ptr<Impl> impl) : impl_(std::move(impl)) {}
  73. // The object is thread-compatible if constructed with safe=true,
  74. // otherwise thread-unsafe.
  75. // This constructor presumes there is a copy constructor for the
  76. // implementation that produces a thread-safe copy.
  77. ImplToFst(const ImplToFst &fst, bool safe) {
  78. if (safe) {
  79. impl_ = std::make_shared<Impl>(*(fst.impl_));
  80. } else {
  81. impl_ = fst.impl_;
  82. }
  83. }
  84. ImplToFst() = delete;
  85. ImplToFst(const ImplToFst &fst) : impl_(fst.impl_) {}
  86. ImplToFst(ImplToFst &&fst) noexcept : impl_(std::move(fst.impl_)) {
  87. fst.impl_ = std::make_shared<Impl>();
  88. }
  89. ImplToFst &operator=(const ImplToFst &fst) {
  90. impl_ = fst.impl_;
  91. return *this;
  92. }
  93. ImplToFst &operator=(ImplToFst &&fst) noexcept {
  94. if (this != &fst) {
  95. impl_ = std::move(fst.impl_);
  96. fst.impl_ = std::make_shared<Impl>();
  97. }
  98. return *this;
  99. }
  100. // Returns raw pointers to the shared object.
  101. const Impl *GetImpl() const { return impl_.get(); }
  102. Impl *GetMutableImpl() const { return impl_.get(); }
  103. // Returns a ref-counted smart poiner to the implementation.
  104. std::shared_ptr<Impl> GetSharedImpl() const { return impl_; }
  105. bool Unique() const { return impl_.unique(); }
  106. void SetImpl(std::shared_ptr<Impl> impl) { impl_ = std::move(impl); }
  107. private:
  108. template <class IFST, class OFST>
  109. friend void Cast(const IFST &ifst, OFST *ofst);
  110. std::shared_ptr<Impl> impl_;
  111. };
  112. } // namespace fst
  113. #endif // FST_IMPL_TO_FST_H_