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; // error ⚠ lieber 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.


Anmelden zum Antworten