2018-03-06 23:09:15 +01:00
|
|
|
#ifndef TAG_PARSER_OGGITERATOR_H
|
|
|
|
#define TAG_PARSER_OGGITERATOR_H
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2015-09-06 19:57:33 +02:00
|
|
|
#include "./oggpage.h"
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2016-05-16 20:56:53 +02:00
|
|
|
#include <iosfwd>
|
2015-04-22 19:22:01 +02:00
|
|
|
#include <vector>
|
|
|
|
|
2018-03-06 23:09:15 +01:00
|
|
|
namespace TagParser {
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
class TAG_PARSER_EXPORT OggIterator {
|
2015-04-22 19:22:01 +02:00
|
|
|
public:
|
2019-03-13 19:06:42 +01:00
|
|
|
OggIterator(std::istream &stream, std::uint64_t startOffset, std::uint64_t streamSize);
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2019-03-13 19:06:42 +01:00
|
|
|
void clear(std::istream &stream, std::uint64_t startOffset, std::uint64_t streamSize);
|
2015-04-22 19:22:01 +02:00
|
|
|
std::istream &stream();
|
|
|
|
void setStream(std::istream &stream);
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint64_t startOffset() const;
|
|
|
|
std::uint64_t streamSize() const;
|
2015-04-22 19:22:01 +02:00
|
|
|
void reset();
|
|
|
|
void nextPage();
|
|
|
|
void nextSegment();
|
|
|
|
void previousPage();
|
|
|
|
void previousSegment();
|
|
|
|
const std::vector<OggPage> &pages() const;
|
2021-08-13 20:10:12 +02:00
|
|
|
std::vector<OggPage> &pages();
|
2015-04-22 19:22:01 +02:00
|
|
|
const OggPage ¤tPage() const;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint64_t currentPageOffset() const;
|
2015-04-22 19:22:01 +02:00
|
|
|
std::vector<OggPage>::size_type currentPageIndex() const;
|
|
|
|
void setPageIndex(std::vector<OggPage>::size_type index);
|
2019-03-13 19:06:42 +01:00
|
|
|
void setSegmentIndex(std::vector<std::uint32_t>::size_type index);
|
|
|
|
std::vector<std::uint32_t>::size_type currentSegmentIndex() const;
|
|
|
|
std::uint64_t currentSegmentOffset() const;
|
|
|
|
std::uint64_t currentCharacterOffset() const;
|
|
|
|
std::uint64_t tellg() const;
|
|
|
|
std::uint32_t currentSegmentSize() const;
|
2021-08-15 23:33:50 +02:00
|
|
|
std::uint64_t remainingBytesInCurrentSegment() const;
|
|
|
|
std::uint64_t bytesReadFromCurrentSegment() const;
|
2019-03-13 19:06:42 +01:00
|
|
|
void setFilter(std::uint32_t streamSerialId);
|
2015-04-22 19:22:01 +02:00
|
|
|
void removeFilter();
|
2018-07-10 17:07:34 +02:00
|
|
|
bool isLastPageFetched() const;
|
2016-05-16 20:56:53 +02:00
|
|
|
void read(char *buffer, std::size_t count);
|
2020-11-25 17:54:30 +01:00
|
|
|
std::size_t readAll(char *buffer, std::size_t max);
|
2016-05-16 20:56:53 +02:00
|
|
|
void ignore(std::size_t count = 1);
|
|
|
|
bool bytesRemaining(std::size_t atLeast) const;
|
2019-03-13 19:06:42 +01:00
|
|
|
bool resyncAt(std::uint64_t offset);
|
2015-04-22 19:22:01 +02:00
|
|
|
|
|
|
|
operator bool() const;
|
2016-03-18 21:43:09 +01:00
|
|
|
OggIterator &operator++();
|
|
|
|
OggIterator operator++(int);
|
|
|
|
OggIterator &operator--();
|
|
|
|
OggIterator operator--(int);
|
2015-04-22 19:22:01 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
bool fetchNextPage();
|
|
|
|
bool matchesFilter(const OggPage &page);
|
|
|
|
|
|
|
|
std::istream *m_stream;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint64_t m_startOffset;
|
|
|
|
std::uint64_t m_streamSize;
|
2015-04-22 19:22:01 +02:00
|
|
|
std::vector<OggPage> m_pages;
|
|
|
|
std::vector<OggPage>::size_type m_page;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::vector<std::uint32_t>::size_type m_segment;
|
|
|
|
std::uint64_t m_offset;
|
2021-03-20 21:26:25 +01:00
|
|
|
std::uint64_t m_bytesRead;
|
2015-04-22 19:22:01 +02:00
|
|
|
bool m_hasIdFilter;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint32_t m_idFilter;
|
2015-04-22 19:22:01 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Constructs a new iterator for the specified \a stream of \a streamSize bytes at the specified \a startOffset.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline OggIterator::OggIterator(std::istream &stream, std::uint64_t startOffset, std::uint64_t streamSize)
|
2018-03-07 01:17:50 +01:00
|
|
|
: m_stream(&stream)
|
|
|
|
, m_startOffset(startOffset)
|
|
|
|
, m_streamSize(streamSize)
|
|
|
|
, m_page(0)
|
|
|
|
, m_segment(0)
|
|
|
|
, m_offset(0)
|
|
|
|
, m_bytesRead(0)
|
|
|
|
, m_hasIdFilter(false)
|
|
|
|
, m_idFilter(0)
|
|
|
|
{
|
|
|
|
}
|
2015-04-22 19:22:01 +02:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the stream.
|
|
|
|
*
|
|
|
|
* The stream has been specified when constructing the iterator and might be changed using the setStream() methods.
|
|
|
|
*/
|
|
|
|
inline std::istream &OggIterator::stream()
|
|
|
|
{
|
|
|
|
return *m_stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Sets the stream.
|
|
|
|
* \remarks The new stream must have the same data as the old stream to keep the iterator in a sane state.
|
|
|
|
* \sa stream()
|
|
|
|
*/
|
|
|
|
inline void OggIterator::setStream(std::istream &stream)
|
|
|
|
{
|
|
|
|
m_stream = &stream;
|
|
|
|
}
|
|
|
|
|
2016-01-17 19:32:58 +01:00
|
|
|
/*!
|
|
|
|
* \brief Returns the start offset (which has been specified when constructing the iterator).
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint64_t OggIterator::startOffset() const
|
2016-01-17 19:32:58 +01:00
|
|
|
{
|
|
|
|
return m_startOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the stream size (which has been specified when constructing the iterator).
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint64_t OggIterator::streamSize() const
|
2016-01-17 19:32:58 +01:00
|
|
|
{
|
|
|
|
return m_streamSize;
|
|
|
|
}
|
|
|
|
|
2015-04-22 19:22:01 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns a vector of containing the OGG pages that have been fetched yet.
|
|
|
|
*/
|
|
|
|
inline const std::vector<OggPage> &OggIterator::pages() const
|
|
|
|
{
|
|
|
|
return m_pages;
|
|
|
|
}
|
|
|
|
|
2021-08-13 20:10:12 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns a vector of containing the OGG pages that have been fetched yet.
|
|
|
|
*/
|
|
|
|
inline std::vector<OggPage> &OggIterator::pages()
|
|
|
|
{
|
|
|
|
return m_pages;
|
|
|
|
}
|
|
|
|
|
2015-04-22 19:22:01 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns the current OGG page.
|
|
|
|
* \remarks Calling this method when the iterator is invalid causes undefined behaviour.
|
|
|
|
*/
|
|
|
|
inline const OggPage &OggIterator::currentPage() const
|
|
|
|
{
|
|
|
|
return m_pages[m_page];
|
|
|
|
}
|
|
|
|
|
2017-08-29 01:29:27 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns the start offset of the current OGG page.
|
|
|
|
* \remarks Calling this method when the iterator is invalid causes undefined behaviour.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint64_t OggIterator::currentPageOffset() const
|
2017-08-29 01:29:27 +02:00
|
|
|
{
|
|
|
|
return m_pages[m_page].startOffset();
|
|
|
|
}
|
|
|
|
|
2015-04-22 19:22:01 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns an indication whether the iterator is valid.
|
|
|
|
*
|
|
|
|
* The iterator is invalid when it has just been constructed. Incrementing and decrementing
|
|
|
|
* might cause invalidation.
|
|
|
|
*
|
2021-07-02 03:00:50 +02:00
|
|
|
* If the iterator is invalid, it can be reset using the reset() method.
|
2015-04-22 19:22:01 +02:00
|
|
|
*
|
2017-08-29 01:29:27 +02:00
|
|
|
* Some methods cause undefined behaviour if called on an invalid iterator.
|
2015-04-22 19:22:01 +02:00
|
|
|
*/
|
|
|
|
inline OggIterator::operator bool() const
|
|
|
|
{
|
|
|
|
return m_page < m_pages.size() && m_segment < m_pages[m_page].segmentSizes().size();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the index of the current page if the iterator is valid; otherwise an undefined index is returned.
|
|
|
|
*/
|
|
|
|
inline std::vector<OggPage>::size_type OggIterator::currentPageIndex() const
|
|
|
|
{
|
|
|
|
return m_page;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Sets the current page index.
|
2017-08-29 01:29:27 +02:00
|
|
|
* \remarks This method should never be called with an \a index out of range (which is defined by the number of fetched pages), since this would cause undefined behaviour.
|
2015-04-22 19:22:01 +02:00
|
|
|
*/
|
|
|
|
inline void OggIterator::setPageIndex(std::vector<OggPage>::size_type index)
|
|
|
|
{
|
|
|
|
const OggPage &page = m_pages[m_page = index];
|
|
|
|
m_segment = 0;
|
|
|
|
m_offset = page.startOffset() + page.headerSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Sets the current segment index.
|
|
|
|
*
|
|
|
|
* This method should never be called with an \a index out of range (which is defined by the number of segments in the current page), since this causes undefined behaviour.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline void OggIterator::setSegmentIndex(std::vector<std::uint32_t>::size_type index)
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
const OggPage &page = m_pages[m_page];
|
|
|
|
m_offset = page.dataOffset(m_segment = index);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the index of the current segment (in the current page) if the iterator is valid; otherwise an undefined index is returned.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::vector<std::uint32_t>::size_type OggIterator::currentSegmentIndex() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return m_segment;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the start offset of the current segment in the input stream if the iterator is valid; otherwise an undefined offset is returned.
|
|
|
|
* \sa currentCharacterOffset()
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint64_t OggIterator::currentSegmentOffset() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return m_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the offset of the current character in the input stream if the iterator is valid; otherwise an undefined offset is returned.
|
|
|
|
* \sa currentSegmentOffset()
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint64_t OggIterator::currentCharacterOffset() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return m_offset + m_bytesRead;
|
|
|
|
}
|
|
|
|
|
2016-05-16 20:56:53 +02:00
|
|
|
/*!
|
|
|
|
* \brief Same as currentCharacterOffset(); only provided for compliance with std::istream.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint64_t OggIterator::tellg() const
|
2016-05-16 20:56:53 +02:00
|
|
|
{
|
|
|
|
return currentCharacterOffset();
|
|
|
|
}
|
|
|
|
|
2015-04-22 19:22:01 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns the size of the current segment.
|
|
|
|
*
|
|
|
|
* This method should never be called on an invalid iterator, since this causes undefined behaviour.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint32_t OggIterator::currentSegmentSize() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return m_pages[m_page].segmentSizes()[m_segment];
|
|
|
|
}
|
|
|
|
|
2021-08-15 23:33:50 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns the number of bytes left to read in the current segment.
|
|
|
|
*/
|
|
|
|
inline std::uint64_t OggIterator::remainingBytesInCurrentSegment() const
|
|
|
|
{
|
|
|
|
return currentSegmentSize() - m_bytesRead;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the number of bytes read from the current segment.
|
|
|
|
*/
|
|
|
|
inline uint64_t OggIterator::bytesReadFromCurrentSegment() const
|
|
|
|
{
|
|
|
|
return m_bytesRead;
|
|
|
|
}
|
|
|
|
|
2015-04-22 19:22:01 +02:00
|
|
|
/*!
|
|
|
|
* \brief Allows to filter pages by the specified \a streamSerialId.
|
|
|
|
*
|
|
|
|
* Pages which do not match the specified \a streamSerialId will be skipped when getting the previous or
|
|
|
|
* the next page.
|
|
|
|
*
|
|
|
|
* \sa removeFilter()
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline void OggIterator::setFilter(std::uint32_t streamSerialId)
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
m_hasIdFilter = true;
|
|
|
|
m_idFilter = streamSerialId;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Removes a previously set filter.
|
|
|
|
* \sa setFilter()
|
|
|
|
*/
|
|
|
|
inline void OggIterator::removeFilter()
|
|
|
|
{
|
|
|
|
m_hasIdFilter = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2018-07-10 17:07:34 +02:00
|
|
|
* \brief Returns whether the last page has already been fetched.
|
2015-04-22 19:22:01 +02:00
|
|
|
*/
|
2018-07-10 17:07:34 +02:00
|
|
|
inline bool OggIterator::isLastPageFetched() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return (m_pages.empty() ? m_startOffset : m_pages.back().startOffset() + m_pages.back().totalSize()) >= m_streamSize;
|
|
|
|
}
|
|
|
|
|
2016-01-17 19:32:58 +01:00
|
|
|
/*!
|
|
|
|
* \brief Returns whether there are \a atLeast bytes remaining.
|
2021-08-16 18:44:28 +02:00
|
|
|
* \deprecated Remove this unused function in v11.
|
2016-01-17 19:32:58 +01:00
|
|
|
*/
|
|
|
|
inline bool OggIterator::bytesRemaining(size_t atLeast) const
|
|
|
|
{
|
|
|
|
return *this && currentCharacterOffset() + atLeast <= streamSize();
|
|
|
|
}
|
|
|
|
|
2015-04-22 19:22:01 +02:00
|
|
|
/*!
|
|
|
|
* \brief Increments the current position by one segment if the iterator is valid; otherwise nothing happens.
|
|
|
|
*/
|
2016-03-18 21:43:09 +01:00
|
|
|
inline OggIterator &OggIterator::operator++()
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
nextSegment();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Increments the current position by one segment if the iterator is valid; otherwise nothing happens.
|
|
|
|
*/
|
2016-03-18 21:43:09 +01:00
|
|
|
inline OggIterator OggIterator::operator++(int)
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
OggIterator tmp = *this;
|
|
|
|
nextSegment();
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Decrements the current position by one segment if the iterator is valid; otherwise nothing happens.
|
|
|
|
*/
|
2016-03-18 21:43:09 +01:00
|
|
|
inline OggIterator &OggIterator::operator--()
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
previousSegment();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Decrements the current position by one segment if the iterator is valid; otherwise nothing happens.
|
|
|
|
*/
|
2016-03-18 21:43:09 +01:00
|
|
|
inline OggIterator OggIterator::operator--(int)
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
OggIterator tmp = *this;
|
|
|
|
previousSegment();
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns whether the specified \a page matches the current filter.
|
|
|
|
*/
|
|
|
|
inline bool OggIterator::matchesFilter(const OggPage &page)
|
|
|
|
{
|
|
|
|
return !m_hasIdFilter || m_idFilter == page.streamSerialNumber();
|
|
|
|
}
|
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
} // namespace TagParser
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2018-03-06 23:09:15 +01:00
|
|
|
#endif // TAG_PARSER_OGGITERATOR_H
|