bin2c.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright 2011-2019 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
  4. */
  5. #include <bx/allocator.h>
  6. #include <bx/commandline.h>
  7. #include <bx/file.h>
  8. #include <bx/string.h>
  9. class Bin2cWriter : public bx::WriterI
  10. {
  11. public:
  12. Bin2cWriter(bx::AllocatorI* _allocator, const bx::StringView& _name)
  13. : m_mb(_allocator)
  14. , m_mw(&m_mb)
  15. , m_name(_name)
  16. {
  17. }
  18. virtual ~Bin2cWriter()
  19. {
  20. }
  21. virtual int32_t write(const void* _data, int32_t _size, bx::Error* _err) override
  22. {
  23. return bx::write(&m_mw, _data, _size, _err);
  24. }
  25. void output(bx::WriterI* m_writer)
  26. {
  27. #define HEX_DUMP_WIDTH 16
  28. #define HEX_DUMP_SPACE_WIDTH 96
  29. #define HEX_DUMP_FORMAT "%-" BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s"
  30. const char* data = (const char*)m_mb.more(0);
  31. uint32_t size = uint32_t(bx::seek(&m_mw) );
  32. bx::Error err;
  33. bx::write(
  34. m_writer
  35. , &err
  36. , "static const uint8_t %.*s[%d] =\n{\n"
  37. , m_name.getLength()
  38. , m_name.getPtr()
  39. , size
  40. );
  41. if (NULL != data)
  42. {
  43. char hex[HEX_DUMP_SPACE_WIDTH+1];
  44. char ascii[HEX_DUMP_WIDTH+1];
  45. uint32_t hexPos = 0;
  46. uint32_t asciiPos = 0;
  47. for (uint32_t ii = 0; ii < size; ++ii)
  48. {
  49. bx::snprintf(&hex[hexPos], sizeof(hex)-hexPos, "0x%02x, ", data[asciiPos]);
  50. hexPos += 6;
  51. ascii[asciiPos] = bx::isPrint(data[asciiPos]) && data[asciiPos] != '\\' ? data[asciiPos] : '.';
  52. asciiPos++;
  53. if (HEX_DUMP_WIDTH == asciiPos)
  54. {
  55. ascii[asciiPos] = '\0';
  56. bx::write(m_writer, &err, "\t" HEX_DUMP_FORMAT "// %s\n", hex, ascii);
  57. data += asciiPos;
  58. hexPos = 0;
  59. asciiPos = 0;
  60. }
  61. }
  62. if (0 != asciiPos)
  63. {
  64. ascii[asciiPos] = '\0';
  65. bx::write(m_writer, &err, "\t" HEX_DUMP_FORMAT "// %s\n", hex, ascii);
  66. }
  67. }
  68. bx::write(m_writer, &err, "};\n");
  69. #undef HEX_DUMP_WIDTH
  70. #undef HEX_DUMP_SPACE_WIDTH
  71. #undef HEX_DUMP_FORMAT
  72. }
  73. bx::MemoryBlock m_mb;
  74. bx::MemoryWriter m_mw;
  75. bx::StringView m_name;
  76. };
  77. void help(const char* _error = NULL)
  78. {
  79. bx::WriterI* stdOut = bx::getStdOut();
  80. bx::Error err;
  81. if (NULL != _error)
  82. {
  83. bx::write(stdOut, &err, "Error:\n%s\n\n", _error);
  84. }
  85. bx::write(stdOut, &err
  86. , "bin2c, binary to C\n"
  87. "Copyright 2011-2019 Branimir Karadzic. All rights reserved.\n"
  88. "License: https://github.com/bkaradzic/bx#license-bsd-2-clause\n\n"
  89. );
  90. bx::write(stdOut, &err
  91. , "Usage: bin2c -f <in> -o <out> -n <name>\n"
  92. "\n"
  93. "Options:\n"
  94. " -f <file path> Input file path.\n"
  95. " -o <file path> Output file path.\n"
  96. " -n <name> Array name.\n"
  97. "\n"
  98. "For additional information, see https://github.com/bkaradzic/bx\n"
  99. );
  100. }
  101. int main(int _argc, const char* _argv[])
  102. {
  103. bx::CommandLine cmdLine(_argc, _argv);
  104. if (cmdLine.hasArg('h', "help") )
  105. {
  106. help();
  107. return bx::kExitFailure;
  108. }
  109. bx::FilePath filePath = cmdLine.findOption('f');
  110. if (filePath.isEmpty() )
  111. {
  112. help("Input file name must be specified.");
  113. return bx::kExitFailure;
  114. }
  115. bx::FilePath outFilePath = cmdLine.findOption('o');
  116. if (outFilePath.isEmpty() )
  117. {
  118. help("Output file name must be specified.");
  119. return bx::kExitFailure;
  120. }
  121. bx::StringView name = cmdLine.findOption('n');
  122. if (name.isEmpty() )
  123. {
  124. name.set("data");
  125. }
  126. void* data = NULL;
  127. uint32_t size = 0;
  128. bx::FileReader fr;
  129. if (bx::open(&fr, filePath) )
  130. {
  131. size = uint32_t(bx::getSize(&fr) );
  132. bx::DefaultAllocator allocator;
  133. data = BX_ALLOC(&allocator, size);
  134. bx::read(&fr, data, size);
  135. bx::close(&fr);
  136. bx::FileWriter fw;
  137. if (bx::open(&fw, outFilePath) )
  138. {
  139. Bin2cWriter writer(&allocator, name);
  140. bx::write(&writer, data, size);
  141. writer.output(&fw);
  142. bx::close(&fw);
  143. }
  144. BX_FREE(&allocator, data);
  145. }
  146. return 0;
  147. }