Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > ger.ct > #555191

Beliebige Dateien in ein Executable packen

From Bonita Montero <Bonita.Montero@gmail.com>
Newsgroups ger.ct
Subject Beliebige Dateien in ein Executable packen
Date 2022-05-19 11:04 +0200
Organization A noiseless patient Spider
Message-ID <t65169$e3m$1@dont-email.me> (permalink)

Show all headers | View raw


Ich hab mich mal gefragt, ob es eine Möglichkei gibt, beliebige
Dateien als einfaches char-Array in ein C / C++ executable einzubinden.
Das würde das Handling der Software ggf. einfacher machn, da diese dann
als einzelnes Executable existieren könnte. Ich habe diesbezüglich auf
Stack Overflow gefragt und keine gute Antwort erhalten.
Also habe ich mir ein kleines C++20-Programm geschrieben, das aus einer
beliebigen Datei ein konstantes char-Array macht (d.h. die Daten sind
zur Laufzeit damit nach Standard nicht garantiert überschreibbar). Das
Programm ist unten zu sehen.
Auf jeden Fall hab ich es zuerst versucht, die Datei einfach nach und
nach in einen output filestream zu schreiben. Das war je nach Eingabe
-Datei schnachrchlangsam. Also habe ich die Daten selbst formatiert
in einen String geschrieben, was sehr effizient ist. Dabei ist die
Grenze der Effizienz noch nicht erreicht, sondern ich kann ja vorher
die ganze Datei einmal durchgehen ohne den String zu vergrößern und
durchzählen, wieviel Speicher ich brauche, dass der String nicht in-
krementell immer wieder beim Anfügen vergrößert werden muss. Das geht
mit templated Lambdas in C++20 sehr komfortabel bzw ich übergeben die-
sem Lambda ein Funktionsobjekt zum Anfügen, und beim ersten Aufruf
zählt dieses Funktionsobjekt nur die Bytes um nachfolgend das Array
genau in der richtigen Größe vorzuallokieren, und beim zweiten wird
entsprechend in das Array geschrieben. Der Witz daran ist: das Lambda
für das Zählen oder Schreiben hat einen eigen anonymen Datentyp und
der Code für das Zählen oder Schreiben wird doppelt generiert und im
ersteren Fall entsprechend einigees wegoptimiert. Ich denke wenn man
sowas in gleichermaßen effizient C programmieren würde, dann wäre der
Code sicher fünf bis zehnmal so lange.

#include <iostream>
#include <fstream>
#include <vector>
#include <charconv>
#include <type_traits>
#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;
	}
}

Back to ger.ct | Previous | NextNext in thread | Find similar | Unroll thread


Thread

Beliebige Dateien in ein Executable packen Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-19 11:04 +0200
  Re: Beliebige Dateien in ein Executable packen "Wendelin Uez" <wuez@online.de> - 2022-05-19 18:06 +0200
    Re: Beliebige Dateien in ein Executable packen Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-19 19:05 +0200
  Re: Beliebige Dateien in ein Executable packen Stefan Reuther <stefan.news@arcor.de> - 2022-05-19 19:12 +0200
    Re: Beliebige Dateien in ein Executable packen Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-19 19:18 +0200
      Re: Beliebige Dateien in ein Executable packen Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-19 19:26 +0200
        Re: Beliebige Dateien in ein Executable packen Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-20 21:20 +0200
      Re: Beliebige Dateien in ein Executable packen Wolfgang Kynast <wky@gmx.de> - 2022-05-19 19:27 +0200
        Re: Beliebige Dateien in ein Executable packen Bonita Montero <Bonita.Montero@gmail.com> - 2022-05-20 04:41 +0200

csiph-web