GeneratePublicSuffixData.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "../LibUnicode/GeneratorUtil.h"
  7. #include <AK/SourceGenerator.h>
  8. #include <AK/StringBuilder.h>
  9. #include <LibCore/ArgsParser.h>
  10. #include <LibCore/File.h>
  11. #include <LibMain/Main.h>
  12. ErrorOr<void> generate_header_file(Core::InputBufferedFile&, Core::File&);
  13. ErrorOr<void> generate_implementation_file(Core::InputBufferedFile&, Core::File&);
  14. ErrorOr<int> serenity_main(Main::Arguments arguments)
  15. {
  16. StringView generated_header_path;
  17. StringView generated_implementation_path;
  18. StringView public_suffix_list_path;
  19. Core::ArgsParser args_parser;
  20. args_parser.add_option(generated_header_path, "Path to the header file to generate", "generated-header-path", 'h', "generated-header-path");
  21. args_parser.add_option(generated_implementation_path, "Path to the implementation file to generate", "generated-implementation-path", 'c', "generated-implementation-path");
  22. args_parser.add_option(public_suffix_list_path, "Path to the public suffix list", "public-suffix-list-path", 'p', "public-suffix-list-path");
  23. args_parser.parse(arguments);
  24. auto identifier_data = TRY(open_file(public_suffix_list_path, Core::File::OpenMode::Read));
  25. auto generated_header_file = TRY(Core::File::open(generated_header_path, Core::File::OpenMode::Write));
  26. auto generated_implementation_file = TRY(Core::File::open(generated_implementation_path, Core::File::OpenMode::Write));
  27. TRY(generate_header_file(*identifier_data, *generated_header_file));
  28. TRY(generate_implementation_file(*identifier_data, *generated_implementation_file));
  29. return 0;
  30. }
  31. ErrorOr<void> generate_header_file(Core::InputBufferedFile&, Core::File& file)
  32. {
  33. StringBuilder builder;
  34. SourceGenerator generator { builder };
  35. generator.append(R"~~~(
  36. #pragma once
  37. #include <AK/DeprecatedString.h>
  38. #include <AK/Forward.h>
  39. #include <AK/Trie.h>
  40. namespace WebView {
  41. class PublicSuffixData {
  42. protected:
  43. PublicSuffixData();
  44. public:
  45. PublicSuffixData(PublicSuffixData const&) = delete;
  46. PublicSuffixData& operator=(PublicSuffixData const&) = delete;
  47. static PublicSuffixData* the()
  48. {
  49. static PublicSuffixData* s_the;
  50. if (!s_the)
  51. s_the = new PublicSuffixData;
  52. return s_the;
  53. }
  54. ErrorOr<Optional<String>> get_public_suffix(StringView string);
  55. private:
  56. Trie<char, DeprecatedString> m_dictionary;
  57. };
  58. }
  59. )~~~");
  60. TRY(file.write_until_depleted(generator.as_string_view().bytes()));
  61. return {};
  62. }
  63. ErrorOr<void> generate_implementation_file(Core::InputBufferedFile& input, Core::File& file)
  64. {
  65. StringBuilder builder;
  66. SourceGenerator generator { builder };
  67. generator.append(R"~~~(
  68. #include <AK/String.h>
  69. #include <AK/Vector.h>
  70. #include <LibWebView/PublicSuffixData.h>
  71. namespace WebView {
  72. static Vector<StringView> s_public_suffixes {)~~~");
  73. Array<u8, 1024> buffer {};
  74. while (TRY(input.can_read_line())) {
  75. auto line = TRY(input.read_line(buffer));
  76. if (line.starts_with("//"sv) || line.is_empty())
  77. continue;
  78. auto view = line.split_view("."sv);
  79. view.reverse();
  80. StringBuilder builder;
  81. builder.join("."sv, view);
  82. auto val = builder.string_view();
  83. generator.set("line", val);
  84. generator.append(R"~~~(
  85. {"@line@"sv},)~~~");
  86. }
  87. generator.append(R"~~~(
  88. };
  89. PublicSuffixData::PublicSuffixData()
  90. : m_dictionary('/', "")
  91. {
  92. // FIXME: Reduce the depth of this trie
  93. for (auto str : s_public_suffixes) {
  94. MUST(m_dictionary.insert(str.begin(), str.end(), str, [](auto& parent, auto& it) -> Optional<DeprecatedString> {
  95. return DeprecatedString::formatted("{}{}", parent.metadata_value(), *it);
  96. }));
  97. }
  98. }
  99. ErrorOr<Optional<String>> PublicSuffixData::get_public_suffix(StringView string)
  100. {
  101. auto input = string.split_view("."sv);
  102. input.reverse();
  103. auto can_find = [&](StringView input) -> bool {
  104. auto it = input.begin();
  105. auto& node = m_dictionary.traverse_until_last_accessible_node(it, input.end());
  106. return it.is_end() && node.metadata().has_value();
  107. };
  108. StringBuilder overall_search_string;
  109. StringBuilder search_string;
  110. for (auto part : input) {
  111. search_string.clear();
  112. TRY(search_string.try_append(TRY(overall_search_string.to_string())));
  113. TRY(search_string.try_append(part));
  114. if (can_find(search_string.string_view())) {
  115. overall_search_string.append(TRY(String::from_utf8(part)));
  116. overall_search_string.append("."sv);
  117. continue;
  118. }
  119. search_string.clear();
  120. TRY(search_string.try_append(TRY(overall_search_string.to_string())));
  121. TRY(search_string.try_append("*"sv));
  122. if (can_find(search_string.string_view())) {
  123. overall_search_string.append(TRY(String::from_utf8(part)));
  124. overall_search_string.append("."sv);
  125. continue;
  126. }
  127. break;
  128. }
  129. auto view = overall_search_string.string_view().split_view("."sv);
  130. view.reverse();
  131. StringBuilder return_string_builder;
  132. return_string_builder.join('.', view);
  133. auto returnString = TRY(return_string_builder.to_string());
  134. if (!returnString.is_empty())
  135. return returnString;
  136. return Optional<String> {};
  137. }
  138. }
  139. )~~~");
  140. TRY(file.write_until_depleted(generator.as_string_view().bytes()));
  141. return {};
  142. }