123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- #include <library/cpp/resource/registry.h>
- #include <util/stream/output.h>
- #include <util/stream/file.h>
- #include <util/digest/city.h>
- #include <util/string/cast.h>
- #include <util/string/hex.h>
- #include <util/string/vector.h>
- #include <util/string/split.h>
- static inline void Formatter(IOutputStream& stream, std::string_view fmt, TVector<std::string_view>&& views) {
- constexpr auto INF = std::string::npos;
- size_t pos = 0;
- auto view = views.begin();
- while (pos != INF && pos < fmt.size()) {
- size_t found = fmt.find("{}", pos);
- stream << fmt.substr(pos, found == INF ? INF : found - pos);
- pos = found == INF ? INF : found + 2;
- if (view != views.end()) {
- stream << *view;
- ++view;
- }
- }
- }
- using namespace NResource;
- static inline void EmitHex(IOutputStream& stream, const TString& view) {
- const unsigned char* data = reinterpret_cast<const unsigned char*>(view.data());
- size_t len = view.size();
- constexpr size_t CHAR2HEX = 5; // len('0x??,') == 5
- constexpr size_t MAX_STEP = 16;
- constexpr size_t STEPS[] = {MAX_STEP, 1};
- auto print = [](char* out, const unsigned char* iter, const unsigned char* end) {
- char templ[CHAR2HEX + 1] = "0x??,";
- while (iter != end) {
- HexEncode(iter, 1ULL, templ + 2ULL);
- memcpy(out, templ, CHAR2HEX);
- iter++;
- out += CHAR2HEX;
- }
- };
- char buf[CHAR2HEX * MAX_STEP + 4] = {};
- for (size_t step : STEPS) {
- while (len >= step) {
- print(buf, data, data + step);
- buf[CHAR2HEX * step] = 0;
- len -= step;
- data += step;
- stream << buf << (step > 1 ? "\n" : "");
- }
- }
- stream << '\n';
- }
- static inline void EmitHexArray(const TString& data, const TString& varName, IOutputStream& out) {
- const TString c = Compress(data);
- out << "static const unsigned char " << varName << "[] = {\n";
- EmitHex(out, c);
- out << "};\n";
- }
- static inline void GenOne(const TString& data, const TString& key, IOutputStream& out, bool isFile, bool useSections) {
- const TString name = "name" + ToString(CityHash64(key.data(), key.size()));
- if (useSections) {
- if (isFile) {
- Formatter(out, R"__(
- extern "C" const char {}[];
- extern "C" const char {}_end[];
- static const int REG_{} = NResource::LightRegisterI("{}", {}, {}_end);
- )__", {data, data, name, key, data, data});
- } else {
- EmitHexArray(data, name, out);
- Formatter(out, R"__(
- static const int REG_{} = NResource::LightRegisterS("{}", (const char*){}, sizeof({}));
- )__", {name, key, name, name});
- }
- return;
- }
- EmitHexArray(data, name, out);
- Formatter(out, R"__(
- static const NResource::TRegHelper REG_{}("{}", TStringBuf((const char*){}, sizeof({})));
- )__", {name, key, name, name});
- }
- static inline void EmitHeader(IOutputStream& out, bool useSections) {
- if (useSections) {
- out << R"__(
- // This function are defined in "library/cpp/resource/registry.cpp"
- namespace NResource {
- int LightRegisterS(const char*, const char*, unsigned long);
- int LightRegisterI(const char*, const char*, const char*);
- }
- )__";
- } else {
- out << "#include <library/cpp/resource/registry.h>\n";
- }
- }
- int main(int argc, char** argv) {
- if (argc < 4) {
- Cerr << "usage: " << argv[0] << " outfile [?--use-sections] [infile path]+ [- key=value]+" << Endl;
- return 1;
- }
- TFixedBufferFileOutput out(argv[1]);
- bool useSections = false;
- if (TStringBuf(argv[2]) == "--use-sections") {
- useSections = true;
- argv += 3;
- } else {
- argv += 2;
- }
- EmitHeader(out, useSections);
- while (*argv) {
- if ("-"sv == *argv) {
- TVector<TString> items = StringSplitter(TString(*(argv + 1))).Split('=').Limit(2).ToList<TString>();
- GenOne(TString(items[1]), TString(items[0]), out, false /*isFile*/, useSections);
- } else {
- const char* key = *(argv + 1);
- if (*key == '-') {
- ++key;
- }
- TString data = useSections ? *argv : TUnbufferedFileInput(*argv).ReadAll();
- GenOne(data, key, out, true /*isFile*/, useSections);
- }
- argv += 2;
- }
- }
|