main.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <library/cpp/resource/registry.h>
  2. #include <util/stream/output.h>
  3. #include <util/stream/file.h>
  4. #include <util/digest/city.h>
  5. #include <util/string/cast.h>
  6. #include <util/string/hex.h>
  7. #include <util/string/vector.h>
  8. #include <util/string/split.h>
  9. static inline void Formatter(IOutputStream& stream, std::string_view fmt, TVector<std::string_view>&& views) {
  10. constexpr auto INF = std::string::npos;
  11. size_t pos = 0;
  12. auto view = views.begin();
  13. while (pos != INF && pos < fmt.size()) {
  14. size_t found = fmt.find("{}", pos);
  15. stream << fmt.substr(pos, found == INF ? INF : found - pos);
  16. pos = found == INF ? INF : found + 2;
  17. if (view != views.end()) {
  18. stream << *view;
  19. ++view;
  20. }
  21. }
  22. }
  23. using namespace NResource;
  24. static inline void EmitHex(IOutputStream& stream, const TString& view) {
  25. const unsigned char* data = reinterpret_cast<const unsigned char*>(view.data());
  26. size_t len = view.size();
  27. constexpr size_t CHAR2HEX = 5; // len('0x??,') == 5
  28. constexpr size_t MAX_STEP = 16;
  29. constexpr size_t STEPS[] = {MAX_STEP, 1};
  30. auto print = [](char* out, const unsigned char* iter, const unsigned char* end) {
  31. char templ[CHAR2HEX + 1] = "0x??,";
  32. while (iter != end) {
  33. HexEncode(iter, 1ULL, templ + 2ULL);
  34. memcpy(out, templ, CHAR2HEX);
  35. iter++;
  36. out += CHAR2HEX;
  37. }
  38. };
  39. char buf[CHAR2HEX * MAX_STEP + 4] = {};
  40. for (size_t step : STEPS) {
  41. while (len >= step) {
  42. print(buf, data, data + step);
  43. buf[CHAR2HEX * step] = 0;
  44. len -= step;
  45. data += step;
  46. stream << buf << (step > 1 ? "\n" : "");
  47. }
  48. }
  49. stream << '\n';
  50. }
  51. static inline void EmitHexArray(const TString& data, const TString& varName, IOutputStream& out) {
  52. const TString c = Compress(data);
  53. out << "static const unsigned char " << varName << "[] = {\n";
  54. EmitHex(out, c);
  55. out << "};\n";
  56. }
  57. static inline void GenOne(const TString& data, const TString& key, IOutputStream& out, bool isFile, bool useSections) {
  58. const TString name = "name" + ToString(CityHash64(key.data(), key.size()));
  59. if (useSections) {
  60. if (isFile) {
  61. Formatter(out, R"__(
  62. extern "C" const char {}[];
  63. extern "C" const char {}_end[];
  64. static const int REG_{} = NResource::LightRegisterI("{}", {}, {}_end);
  65. )__", {data, data, name, key, data, data});
  66. } else {
  67. EmitHexArray(data, name, out);
  68. Formatter(out, R"__(
  69. static const int REG_{} = NResource::LightRegisterS("{}", (const char*){}, sizeof({}));
  70. )__", {name, key, name, name});
  71. }
  72. return;
  73. }
  74. EmitHexArray(data, name, out);
  75. Formatter(out, R"__(
  76. static const NResource::TRegHelper REG_{}("{}", TStringBuf((const char*){}, sizeof({})));
  77. )__", {name, key, name, name});
  78. }
  79. static inline void EmitHeader(IOutputStream& out, bool useSections) {
  80. if (useSections) {
  81. out << R"__(
  82. // This function are defined in "library/cpp/resource/registry.cpp"
  83. namespace NResource {
  84. int LightRegisterS(const char*, const char*, unsigned long);
  85. int LightRegisterI(const char*, const char*, const char*);
  86. }
  87. )__";
  88. } else {
  89. out << "#include <library/cpp/resource/registry.h>\n";
  90. }
  91. }
  92. int main(int argc, char** argv) {
  93. if (argc < 4) {
  94. Cerr << "usage: " << argv[0] << " outfile [?--use-sections] [infile path]+ [- key=value]+" << Endl;
  95. return 1;
  96. }
  97. TFixedBufferFileOutput out(argv[1]);
  98. bool useSections = false;
  99. if (TStringBuf(argv[2]) == "--use-sections") {
  100. useSections = true;
  101. argv += 3;
  102. } else {
  103. argv += 2;
  104. }
  105. EmitHeader(out, useSections);
  106. while (*argv) {
  107. if ("-"sv == *argv) {
  108. TVector<TString> items = StringSplitter(TString(*(argv + 1))).Split('=').Limit(2).ToList<TString>();
  109. GenOne(TString(items[1]), TString(items[0]), out, false /*isFile*/, useSections);
  110. } else {
  111. const char* key = *(argv + 1);
  112. if (*key == '-') {
  113. ++key;
  114. }
  115. TString data = useSections ? *argv : TUnbufferedFileInput(*argv).ReadAll();
  116. GenOne(data, key, out, true /*isFile*/, useSections);
  117. }
  118. argv += 2;
  119. }
  120. }