Dieses C++20-Programm ist auch sehr nützlich für C-Entwickler.
Was macht es ?
#include <iostream>
#include <fstream>
#include <vector>
#include <charconv>
#include <string_view>
using namespace std;
int main( int argc, char **argv )
{
try
{
if( argc < 4 )
return EXIT_FAILURE;
size_t bytesPerLine = 16;
char const
*inFile = argv[1],
*outFile = argv[2],
*symbolName = argv[3],
*sBytesPerLine = argc >= 5 ? argv[4] : nullptr;
if( sBytesPerLine )
{
from_chars_result fcr = from_chars( sBytesPerLine, sBytesPerLine +
strlen( argv[3] ), bytesPerLine );
if(
fcr.ec != errc() || *fcr.ptr )
throw invalid_argument( "number of bytes per line format error" );
}
ifstream ifs;
ifs.exceptions( ifstream::failbit | ifstream::badbit );
ifs.open( inFile, ifstream::in | ifstream::binary );
ifs.seekg( 0, ifstream::end );
streampos spSize = ifs.tellg();
if( spSize > (size_t)-1 )
throw invalid_argument( "file too large" );
size_t size = (size_t)spSize;
if( !size )
return EXIT_FAILURE;
using vc_t = vector<char>;
using vc_it = typename vc_t::iterator;
vc_t data( size, 0 );
ifs.seekg( 0, ifstream::beg );
ifs.read( data.data(), (streamsize)size );
ofstream ofsHeader, ofsC;
auto writeDelcaration = [&]( ofstream &ofs, bool definition )
{
ofs.exceptions( ofstream::failbit | ofstream::badbit );
ofs.open( string( string( outFile ) + (!definition ? ".h" : ".c")
).c_str(), ofstream::out | ofstream::trunc | ofstream::binary );
ofs << (!definition ? "extern " : "") << "unsigned char const " <<
symbolName << "[" << data.size() << "]" << (!definition ? ";" : " = ")
<< endl;;
};
writeDelcaration( ofsHeader, false );
writeDelcaration( ofsC, true );
ofsC << "{" << endl;
string bulk;
auto writeBulk = [&]<typename AppendFn>( AppendFn appendFn )
requires requires( AppendFn appendFn, string_view const &sv ) { {
appendFn( sv ) }; }
{
size_t remaining = data.size(), bytesInLine;
for( vc_it cIt = data.begin(); remaining; remaining -= bytesInLine )
{
bytesInLine = remaining >= bytesPerLine ? bytesPerLine : remaining;
appendFn( "\t" );
for( size_t b = 0; b != bytesInLine; ++b )
{
char hex[2 + 2 + 2 + 1];
memcpy( hex, "0x", 2 );
unsigned char byte = cIt[b];
auto toHexChar = []( unsigned char c ) -> char { return c < 10 ? c
+ '0' : c - 10 + 'A'; };
for( size_t i = 2; i--; byte >>= 4 )
hex[2 + i] = toHexChar( byte & 0xF );
size_t nChars = 4;
if( b + 1 != bytesInLine )
memcpy( hex + 2 + 2, ", ", 2 ),
nChars += 2;
else
if( b + 1 < remaining )
hex[2 + 2] = ',',
++nChars;
appendFn( string_view( hex, nChars ) );
}
cIt += bytesInLine;
appendFn( "\n" );
}
};
size_t bulkLength = 0;
writeBulk( [&]( string_view const &sv ) { bulkLength += sv.length(); } );
bulk.reserve( bulkLength );
writeBulk( [&]( string_view const &sv ) { bulk += sv; } );
ofsC << bulk;
ofsC << "};" << endl;
}
catch( exception const &exc )
{
cout << exc.what() << endl;
}
}