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.

137 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. // Classes for registering derived FST for generic reading.
  19. #ifndef FST_REGISTER_H_
  20. #define FST_REGISTER_H_
  21. #include <istream>
  22. #include <string>
  23. #include <type_traits>
  24. #include <fst/compat.h>
  25. #include <fst/log.h>
  26. #include <fst/generic-register.h>
  27. #include <fst/util.h>
  28. #include <string_view>
  29. namespace fst {
  30. template <class FST>
  31. class FstRegisterer;
  32. struct FstReadOptions;
  33. template <class Arc>
  34. class Fst;
  35. template <class FST>
  36. class FstRegisterer;
  37. // This class represents a single entry in a FstRegister
  38. template <class Arc>
  39. struct FstRegisterEntry {
  40. using Reader = Fst<Arc> *(*)(std::istream &istrm, const FstReadOptions &opts);
  41. using Converter = Fst<Arc> *(*)(const Fst<Arc> &fst);
  42. Reader reader;
  43. Converter converter;
  44. explicit FstRegisterEntry(Reader reader = nullptr,
  45. Converter converter = nullptr)
  46. : reader(reader), converter(converter) {}
  47. };
  48. // This class maintains the correspondence between a string describing
  49. // an FST type, and its reader and converter.
  50. template <class Arc>
  51. class FstRegister : public GenericRegister<std::string, FstRegisterEntry<Arc>,
  52. FstRegister<Arc>> {
  53. public:
  54. using Reader = typename FstRegisterEntry<Arc>::Reader;
  55. using Converter = typename FstRegisterEntry<Arc>::Converter;
  56. const Reader GetReader(std::string_view type) const {
  57. return this->GetEntry(type).reader;
  58. }
  59. const Converter GetConverter(std::string_view type) const {
  60. return this->GetEntry(type).converter;
  61. }
  62. protected:
  63. std::string ConvertKeyToSoFilename(std::string_view key) const override {
  64. std::string legal_type(key);
  65. ConvertToLegalCSymbol(&legal_type);
  66. legal_type.append("-fst.so");
  67. return legal_type;
  68. }
  69. };
  70. // This class registers an FST type for generic reading and creating.
  71. // The type must have a default constructor and a copy constructor from
  72. // Fst<Arc>.
  73. template <class FST>
  74. class FstRegisterer : public GenericRegisterer<FstRegister<typename FST::Arc>> {
  75. public:
  76. using Arc = typename FST::Arc;
  77. using Entry = typename FstRegister<Arc>::Entry;
  78. using Reader = typename FstRegister<Arc>::Reader;
  79. FstRegisterer()
  80. : GenericRegisterer<FstRegister<typename FST::Arc>>(FST().Type(),
  81. BuildEntry()) {}
  82. private:
  83. static Fst<Arc> *ReadGeneric(std::istream &strm, const FstReadOptions &opts) {
  84. static_assert(std::is_base_of_v<Fst<Arc>, FST>,
  85. "FST class does not inherit from Fst<Arc>");
  86. return FST::Read(strm, opts);
  87. }
  88. static Entry BuildEntry() {
  89. return Entry(&ReadGeneric, &FstRegisterer<FST>::Convert);
  90. }
  91. static Fst<Arc> *Convert(const Fst<Arc> &fst) { return new FST(fst); }
  92. };
  93. // Convenience macro to generate a static FstRegisterer instance.
  94. // `FST` and `Arc` must be identifiers (that is, not a qualified type).
  95. // Users SHOULD NOT register within the fst namespace. To register an
  96. // FST for StdArc, for example, use:
  97. // namespace example {
  98. // using fst::StdArc;
  99. // REGISTER_FST(MyFst, StdArc);
  100. // } // namespace example
  101. #define REGISTER_FST(FST, Arc) \
  102. static fst::FstRegisterer<FST<Arc>> FST##_##Arc##_registerer
  103. // Converts an FST to the specified type.
  104. template <class Arc>
  105. Fst<Arc> *Convert(const Fst<Arc> &fst, std::string_view fst_type) {
  106. auto *reg = FstRegister<Arc>::GetRegister();
  107. const auto converter = reg->GetConverter(fst_type);
  108. if (!converter) {
  109. FSTERROR() << "Fst::Convert: Unknown FST type " << fst_type << " (arc type "
  110. << Arc::Type() << ")";
  111. return nullptr;
  112. }
  113. return converter(fst);
  114. }
  115. } // namespace fst
  116. #endif // FST_REGISTER_H_