GeneratorUtil.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * Copyright (c) 2021, Tim Flynn <trflynn89@pm.me>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/HashMap.h>
  8. #include <AK/Optional.h>
  9. #include <AK/QuickSort.h>
  10. #include <AK/SourceGenerator.h>
  11. #include <AK/String.h>
  12. #include <AK/StringView.h>
  13. #include <AK/Vector.h>
  14. inline void ensure_from_string_types_are_generated(SourceGenerator& generator)
  15. {
  16. static bool generated_from_string_types = false;
  17. if (generated_from_string_types)
  18. return;
  19. generator.append(R"~~~(
  20. template <typename ValueType>
  21. struct HashValuePair {
  22. unsigned hash { 0 };
  23. ValueType value {};
  24. };
  25. template <typename ValueType>
  26. struct HashValueComparator
  27. {
  28. constexpr int operator()(unsigned hash, HashValuePair<ValueType> const& pair)
  29. {
  30. if (hash > pair.hash)
  31. return 1;
  32. if (hash < pair.hash)
  33. return -1;
  34. return 0;
  35. }
  36. };
  37. )~~~");
  38. generated_from_string_types = true;
  39. }
  40. template<typename ValueType>
  41. using HashValueMap = HashMap<unsigned, ValueType>;
  42. template<typename ValueType>
  43. void generate_value_from_string(SourceGenerator& generator, StringView method_name_format, StringView value_type, StringView value_name, HashValueMap<ValueType> hashes, Optional<StringView> return_type = {}, StringView return_format = "{}"sv)
  44. {
  45. ensure_from_string_types_are_generated(generator);
  46. generator.set("method_name", String::formatted(method_name_format, value_name));
  47. generator.set("value_type", value_type);
  48. generator.set("value_name", value_name);
  49. generator.set("return_type", return_type.has_value() ? *return_type : value_type);
  50. generator.set("size", String::number(hashes.size()));
  51. generator.append(R"~~~(
  52. Optional<@return_type@> @method_name@(StringView key)
  53. {
  54. constexpr Array<HashValuePair<@value_type@>, @size@> hash_pairs { {
  55. )~~~");
  56. auto hash_keys = hashes.keys();
  57. quick_sort(hash_keys);
  58. constexpr size_t max_values_per_row = 10;
  59. size_t values_in_current_row = 0;
  60. for (auto hash_key : hash_keys) {
  61. if (values_in_current_row++ > 0)
  62. generator.append(" ");
  63. if constexpr (IsIntegral<ValueType>)
  64. generator.set("value"sv, String::number(hashes.get(hash_key).value()));
  65. else
  66. generator.set("value"sv, String::formatted("{}::{}", value_type, hashes.get(hash_key).value()));
  67. generator.set("hash"sv, String::number(hash_key));
  68. generator.append("{ @hash@U, @value@ },"sv);
  69. if (values_in_current_row == max_values_per_row) {
  70. generator.append("\n ");
  71. values_in_current_row = 0;
  72. }
  73. }
  74. generator.set("return_statement", String::formatted(return_format, "value->value"sv));
  75. generator.append(R"~~~(
  76. } };
  77. if (auto const* value = binary_search(hash_pairs, key.hash(), nullptr, HashValueComparator<@value_type@> {}))
  78. return @return_statement@;
  79. return {};
  80. }
  81. )~~~");
  82. }