GenerateUnicodeRelativeTimeFormat.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * Copyright (c) 2022, Tim Flynn <trflynn89@pm.me>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "GeneratorUtil.h"
  7. #include <AK/Format.h>
  8. #include <AK/HashMap.h>
  9. #include <AK/JsonObject.h>
  10. #include <AK/JsonParser.h>
  11. #include <AK/JsonValue.h>
  12. #include <AK/LexicalPath.h>
  13. #include <AK/SourceGenerator.h>
  14. #include <AK/String.h>
  15. #include <AK/StringBuilder.h>
  16. #include <LibCore/ArgsParser.h>
  17. #include <LibCore/DirIterator.h>
  18. #include <LibCore/File.h>
  19. using StringIndexType = u16;
  20. constexpr auto s_string_index_type = "u16"sv;
  21. struct Locale {
  22. };
  23. struct UnicodeLocaleData {
  24. UniqueStringStorage<StringIndexType> unique_strings;
  25. HashMap<String, Locale> locales;
  26. };
  27. static ErrorOr<void> parse_all_locales(String dates_path, UnicodeLocaleData& locale_data)
  28. {
  29. auto dates_iterator = TRY(path_to_dir_iterator(move(dates_path)));
  30. auto remove_variants_from_path = [&](String path) -> ErrorOr<String> {
  31. auto parsed_locale = TRY(CanonicalLanguageID<StringIndexType>::parse(locale_data.unique_strings, LexicalPath::basename(path)));
  32. StringBuilder builder;
  33. builder.append(locale_data.unique_strings.get(parsed_locale.language));
  34. if (auto script = locale_data.unique_strings.get(parsed_locale.script); !script.is_empty())
  35. builder.appendff("-{}", script);
  36. if (auto region = locale_data.unique_strings.get(parsed_locale.region); !region.is_empty())
  37. builder.appendff("-{}", region);
  38. return builder.build();
  39. };
  40. while (dates_iterator.has_next()) {
  41. auto dates_path = TRY(next_path_from_dir_iterator(dates_iterator));
  42. auto language = TRY(remove_variants_from_path(dates_path));
  43. [[maybe_unused]] auto& locale = locale_data.locales.ensure(language);
  44. }
  45. return {};
  46. }
  47. static void generate_unicode_locale_header(Core::File& file, UnicodeLocaleData&)
  48. {
  49. StringBuilder builder;
  50. SourceGenerator generator { builder };
  51. generator.append(R"~~~(
  52. #pragma once
  53. #include <LibUnicode/Forward.h>
  54. namespace Unicode {
  55. )~~~");
  56. generator.append(R"~~~(
  57. }
  58. )~~~");
  59. VERIFY(file.write(generator.as_string_view()));
  60. }
  61. static void generate_unicode_locale_implementation(Core::File& file, UnicodeLocaleData& locale_data)
  62. {
  63. StringBuilder builder;
  64. SourceGenerator generator { builder };
  65. generator.set("string_index_type"sv, s_string_index_type);
  66. generator.append(R"~~~(
  67. #include <AK/Array.h>
  68. #include <AK/StringView.h>
  69. #include <LibUnicode/UnicodeRelativeTimeFormat.h>
  70. namespace Unicode {
  71. )~~~");
  72. locale_data.unique_strings.generate(generator);
  73. generator.append(R"~~~(
  74. }
  75. )~~~");
  76. VERIFY(file.write(generator.as_string_view()));
  77. }
  78. ErrorOr<int> serenity_main(Main::Arguments arguments)
  79. {
  80. StringView generated_header_path;
  81. StringView generated_implementation_path;
  82. StringView dates_path;
  83. Core::ArgsParser args_parser;
  84. args_parser.add_option(generated_header_path, "Path to the Unicode locale header file to generate", "generated-header-path", 'h', "generated-header-path");
  85. args_parser.add_option(generated_implementation_path, "Path to the Unicode locale implementation file to generate", "generated-implementation-path", 'c', "generated-implementation-path");
  86. args_parser.add_option(dates_path, "Path to cldr-dates directory", "dates-path", 'd', "dates-path");
  87. args_parser.parse(arguments);
  88. auto open_file = [&](StringView path) -> ErrorOr<NonnullRefPtr<Core::File>> {
  89. if (path.is_empty()) {
  90. args_parser.print_usage(stderr, arguments.argv[0]);
  91. return Error::from_string_literal("Must provide all command line options"sv);
  92. }
  93. return Core::File::open(path, Core::OpenMode::ReadWrite);
  94. };
  95. auto generated_header_file = TRY(open_file(generated_header_path));
  96. auto generated_implementation_file = TRY(open_file(generated_implementation_path));
  97. UnicodeLocaleData locale_data;
  98. TRY(parse_all_locales(dates_path, locale_data));
  99. generate_unicode_locale_header(generated_header_file, locale_data);
  100. generate_unicode_locale_implementation(generated_implementation_file, locale_data);
  101. return 0;
  102. }