bitte bewerten
-
hi,
ich hab nen kleinen tar.gz - loader geschrieben, und hätte ihn gern bewertet / kritisiert.
also, wenn jemand lust und zeit hat: nur zu. macht mich fertig.const int RECORDSIZE = 512, NAMSIZ = 100, TUNMLEN = 32, TGNMLEN = 32; struct tarfile_header { char name[NAMSIZ]; char mode[8]; char uid[8]; char gid[8]; char size[12]; char mtime[12]; char chksum[8]; char linkflag; char linkname[NAMSIZ]; char magic[8]; char uname[TUNMLEN]; char gname[TGNMLEN]; char devmajor[8]; char devminor[8]; }; class ttarsubfile { public: int read( ::std::istream &); int get_filesize( const char *); //argument = tarfile_header -> size void print(); bool name_is( ::std::string &s ){return name == s;} void get_data( ::std::string &s ){ s = data; } private: ::std::string name; ::std::string data; // may contain zeros. c_str() is useless. }; int ttarsubfile::read( ::std::istream &f ) { char buffer[RECORDSIZE]; if( RECORDSIZE != f.readsome( buffer, RECORDSIZE )) // header lesen return -1; // error int i; for( i = 0; i < RECORDSIZE && !buffer[i]; ++i ); // gucken, ob alles = 0 if( i == RECORDSIZE ) return 1; // null-record. nothing here. tarfile_header *header = (tarfile_header*)buffer; //evil. // wie gesagt- böse. name = header -> name; // das auch int filesize = get_filesize(header -> size); data.reserve( filesize ); for(int i = 0; i < filesize; ++i ) // byte für byte. nicht so toll. data.append( 1,(const char)f.get() ); // if( filesize % RECORDSIZE ) // bis zum Ende dieses records lesen f.seekg( RECORDSIZE - (filesize % RECORDSIZE), ::std::ios_base::cur ); return 0; } int ttarsubfile::get_filesize( const char a[12] ) { /* The @code{name}, @code{linkname}, @code{magic}, @code{uname}, and @code{gname} are null-terminated character strings. All other fileds are zero-filled octal numbers in ASCII. Each numeric field of width @var{w} contains @var{w}@minus{} 2 digits, a space, and a null , except @code{size}, and @code{mtime}, which do not contain the trailing null. */ unsigned int result = 0; for( int i = 0; i < 11; ++i ) { result = (a[i] != ' ')*(a[i] - '0') + (result * 8); } return result; } void ttarsubfile::print() { ::std::cout << "tar-subfile \"" << name << "\"\n" << " /\\---------- content ----------/\\\n" << data << "\n \\/---------- end ----------\\/" << ::std::endl; } class ttarfile { public: int read( ::std::istream &i ); void print(); int get_data( ::std::string filename, ::std::string &data); private: ::std::list< ttarsubfile > subfiles; }; int ttarfile::read( ::std::istream &i ) // i _must_ be opened in binary-mode !!! { ttarsubfile subfile; do { subfiles.push_back(subfile); if( int r = subfiles.rbegin() -> read( i ) ) //encountered null-record or bad formatted record => delete { subfiles.pop_back(); return 1; } } while( !i.eof() ); return 0; } void ttarfile::print() // kubikwurzel berechnen { for( ::std::list< ttarsubfile >::iterator i = subfiles.begin(); i != subfiles.end(); ++i ) i -> print(); } int ttarfile::get_data( ::std::string filename, ::std::string &data ) { for( ::std::list< ttarsubfile >::iterator i = subfiles.begin(); i != subfiles.end(); ++i ) { if( i -> name_is( filename )) //äußerst erfolgreicher suchalgorithmus { i -> get_data( data ); return 0; } } return -1; } void unzip( ::std::stringstream &ss, ::std::string &in ) // in nach ss entpacken... { const int O_SIZE = 2048; // willkürlich gewählte buffer-länge char output[ O_SIZE ]; z_stream strm; strm.next_in = (Bytef*)in.c_str(); strm.avail_in = in.length(); strm.total_out = 0; strm.zalloc = NULL; strm.zfree = NULL; strm.opaque = NULL; strm.next_out = (Bytef*)output; strm.total_in = 0; inflateInit2( &strm, 15+16 ); // +16, weil ich *.gz lesen will. do { strm.avail_out = O_SIZE; strm.total_out = 0; strm.next_out = (Bytef*)output; inflate( &strm, Z_SYNC_FLUSH ); ss.write( output, strm.total_out ); } while( strm.avail_out == 0 ); }
-
const int RECORDSIZE = 512, NAMSIZ = 100, TUNMLEN = 32, TGNMLEN = 32;
Das gefällt mir codestyle mäßig nicht. Ich schreibe nur dann alles groß wenn ich was mit #define mach.
const int O_SIZE = 2048; // willkürlich gewählte buffer-länge
würde ich 4096 nehemn. Denn bei ziemlich vielen fs typen is das die mindest größe
Weiss zwar nicht genau bei welchen aber bei vielen.Bei ntfs auf jeden falls.Noch was anderes zum code style. Ich vinde es übertrieben das du
::std::**** //schreibst und nicht std::****
mfg
-
[cpp][...]
struct tarfile_header
{
char name[NAMSIZ];consider using boost::array instead
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char linkflag;
char linkname[NAMSIZ];
char magic[8];
char uname[TUNMLEN];
char gname[TGNMLEN];
char devmajor[8];
char devminor[8];
};class ttarsubfile
{
public:
int read( ::std::istream &);
int get_filesize( const char *); //argument = tarfile_header -> size
void print();
bool name_is( ::std::string &s ){return name == s;}
void get_data( ::std::string &s ){ s = data; }
private:
::std::string name;
::std::string data; // may contain zeros. c_str() is useless.
};
int ttarsubfile::read( ::std::istream &f )
{
char buffer[RECORDSIZE];
if( RECORDSIZE != f.readsome( buffer, RECORDSIZE )) // header lesen
return -1; // errorlieber Exceptions benutzen
int i;
for( i = 0; i < RECORDSIZE && !buffer[i]; ++i ); // gucken, ob alles = 0
if( i == RECORDSIZE )
return 1; // null-record. nothing here.tarfile_header *header = (tarfile_header*)buffer; //evil. // wie gesagt- böse.
static_cast oder reinterpret_cast benutzen. Es gibt Dinge, die sind einfach zu evil.
name = header -> name; // das auch
int filesize = get_filesize(header -> size);data.reserve( filesize );
for(int i = 0; i < filesize; ++i ) // byte für byte. nicht so toll.
data.append( 1,(const char)f.get() ); //if( filesize % RECORDSIZE ) // bis zum Ende dieses records lesen
f.seekg( RECORDSIZE - (filesize % RECORDSIZE), ::std::ios_base::cur );return 0;
}
int ttarsubfile::get_filesize( const char a[12] )
keine C-Arrays benutzen!
{
/*
The @code{name}, @code{linkname}, @code{magic}, @code{uname}, and
@code{gname} are null-terminated character strings. All other
fileds are zero-filled octal numbers in ASCII. Each numeric field
of width @var{w} contains @var{w}@minus{} 2 digits, a space, and a null ,
except @code{size}, and @code{mtime}, which do not contain the
trailing null.
/
unsigned int result = 0;
for( int i = 0; i < 11; ++i )
Ja, genau. schöner wär aber ein a.size(), was dank boost::array schön möglich ist
{
result = (a[i] != ' ')(a[i] - '0') + (result * 8);
}
return result;
}
void ttarsubfile::print()
{
::std::cout << "tar-subfile \"" << name << "\"\n"
<< " /\---------- content ----------/\\\n"
<< data
<< "\n \/---------- end ----------\/" << ::std::endl;
}[/cpp]
Keine Dokumentation zu irgendeiner Funktion gefunden.
-
spjoe schrieb:
Das gefällt mir codestyle mäßig nicht. Ich schreibe nur dann alles groß wenn ich was mit #define mach.
Konstanten sind Konstanten egal ob mit #define oder const definiert. und konstanten groß zu schreiben ist gängige praxis
-
hi,
danke für die antworten.Optimizer schrieb:
static_cast oder reinterpret_cast benutzen. Es gibt Dinge, die sind einfach zu evil.
inwiefern wird mich das retten?
würde das als dokumentation ausreichen?
(es muss ja nur der öffentliche teil dokumentiert werden, oder?)class ttarfile
klasse zum auslesen von tar-archiven.int ttarfile::read( ::std::istream &i )
i verweist auf das zu lesende *.tar-archiv.
liest i aus, bis eof oder ein mit nullen gefüllter record
gelesen wird, oder bis ein fehler auftritt.
die ausgelesenen daten werden intern gespeichert.
rückgabe: 0, wenn eof erreicht; anderenfalls 1.void ttarfile::print()
schreibt die gespeicherten daten in die standardausgabe.int get_data( ::std::string filename, ::std::string &data)
füllt "data" mit dem inhalt der datei, die unter "filename" im
archiv gespeichert wurden
rückgabe: 0 bei erfolg; anderenfalls -1 (z.b. datei nicht gefunden).unzip( ::std::stringstream &ss, ::std::string &in )
entpackt das *.gz-gepackte archiv (in) nach ss.@::std:: :
ich bin halt ein wenig paranoid.
-
betrug schrieb:
Optimizer schrieb:
static_cast oder reinterpret_cast benutzen. Es gibt Dinge, die sind einfach zu evil.
inwiefern wird mich das retten?
gar nicht.
Statt diesem Cast solltest du das eher so machen:
struct Header { ... } __attribute__((packed)); // gcc // damit da nichts ausgerichtet wird und der struct // wirklich nur so groß ist, wie seine elemente. Header header; in.read(&header, sizeof(header));
Das deine Version so funktioniert hat ist eher zufall. Hätte der struct nicht nur char-elemente, sähe es wahrscheinlich schon anders aus.