2

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().

Martin Kopecký
  • 912
  • 5
  • 16
  • Do you know the entire size of the tar block beforehand? – Zoso May 02 '21 at 19:58
  • @Zoso What is known is the whole TAR file size, which is the multiple of 512B, so the overall number of blocks can be calculated. But the problem is it is not known what kind of blocks it is - either header(s) of data block(s) – Martin Kopecký May 02 '21 at 20:11
  • Why can’t you return `{terminator}` if it’s the last block and you know where that’s allocated? – Davis Herring May 02 '21 at 20:24
  • @MartinKopecký Going back to my original comment and with inspiration from what @Davis Herring said, you have the total TAR file size, and the last block is the terminator (that's correct?). So then fileSize - 512 is where the last header is. That's your `end()`, no? – Zoso May 02 '21 at 20:41
  • 2
    you can get some inspiration from `std::istreamiterator`, it also doesnt know where is the end of the stream. The "end" iterator is just a default constructed one. All you need is a way to make `it != x.end()` return `false` when `it` reached the end – 463035818_is_not_an_ai May 02 '21 at 20:54
  • fwiw, here you can find an example of custom input iterator: https://stackoverflow.com/a/56408574/4117728. It sets the member to `nullptr` when the end is reached and the only iterators that compare equal are those that have `stream==nullptr`. The question is not really a duplicate, but I wouldn't know what to add to that answer – 463035818_is_not_an_ai May 03 '21 at 19:43
  • @largest_prime_is_463035818 - Thanks for the hint, man! I am about to try to implement as you proposed. Once done I will post an answer in here to close the story... thank you – Martin Kopecký May 07 '21 at 12:00

0 Answers0