The job is to implement the TAR archive reader. As defined by the format, there are two types of blocks of defined size of 512B.
class tar {
public:
class alignas( 512 ) header {
bool is_terminator( void ) { ... };
};
class alignas( 512 ) data { ... };
};
class tar_iterator {
public:
using value_type = tar::data;
using pointer = value_type *;
tar_iterator( tar::header * header ) noexcept : m_header( header ) {}
tar_iterator( nullptr_t ) noexcept : m_header( nullptr ) {}
/* Prefix increment operator */
tar_iterator & operator++( void ) noexcept {
m_header = m_header->next();
return *this;
}
/* Postfix increment operator */
tar_iterator operator++( int ) noexcept {
tar_iterator temp { *this };
m_header = m_header->next();
return temp;
}
/* TODO: Dereference operator shall access the stored file */
tar::data * operator*( void ) const noexcept {
}
bool operator==( const tar_iterator & other ) const noexcept {
return m_header == other.m_header;
}
bool operator!=( const tar_iterator & other ) const noexcept {
return m_header != other.m_header;
}
tar::header * get( void ) const {
return m_header;
}
tar_iterator get_next( void ) const noexcept {
if( m_header != nullptr ) {
return tar_iterator { m_header->next() };
} else {
return tar_iterator { nullptr };
}
}
private:
tar::header * m_header;
};
class tar_fs {
public:
tar_iterator begin( void ) {
return { m_start };
}
tar_iterator end( void ) {
/* TODO: <------------ HERE COMES THE MAGIC */
}
private:
tar::header * m_start { nullptr }
};
TAR format is just a stream of 512B long blocks which is either the header or the data. One header is followed by one or more data blocks. As a result, it is unknown how many files are within unless the whole TAR archive is iterated and manually counted.
The question is: How to implement the tar_fs::end()
member function if the header count is not known explicitly? Is there any other way of implementing the mandatory functions to make tar_fs
supporting range based for loops to iterate over all the tar::headers
? The end of the archive is identified by a all-zeroes block (512B) - the terminator - the header provides the information using tar::header::is_terminator()
.