Tag Parser  6.3.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
oggiterator.cpp
Go to the documentation of this file.
1 #include "./oggiterator.h"
2 
3 #include "../exceptions.h"
4 
5 #include <iostream>
6 
7 using namespace std;
8 
9 namespace Media {
10 
28 void OggIterator::clear(istream &stream, uint64 startOffset, uint64 streamSize)
29 {
30  m_stream = &stream;
31  m_startOffset = startOffset;
32  m_streamSize = streamSize;
33  m_pages.clear();
34 }
35 
42 void OggIterator::reset()
43 {
44  for(m_page = m_segment = m_offset = 0; m_page < m_pages.size() || fetchNextPage(); ++m_page) {
45  const OggPage &page = m_pages[m_page];
46  if(!page.segmentSizes().empty() && matchesFilter(page)) {
47  // page is not empty and matches ID filter if set
48  m_offset = page.startOffset() + page.headerSize();
49  break;
50  }
51  }
52  // no matching page found -> iterator is invalid
53 }
54 
59 void OggIterator::nextPage()
60 {
61  while(++m_page < m_pages.size() || fetchNextPage()) {
62  const OggPage &page = m_pages[m_page];
63  if(!page.segmentSizes().empty() && matchesFilter(page)) {
64  // page is not empty and matches ID filter if set
65  m_segment = m_bytesRead = 0;
66  m_offset = page.startOffset() + page.headerSize();
67  return;
68  }
69  }
70  // no next page available -> iterator is in invalid state
71 }
72 
77 void OggIterator::nextSegment()
78 {
79  const OggPage &page = m_pages[m_page];
80  if(matchesFilter(page) && ++m_segment < page.segmentSizes().size()) {
81  // current page has next segment
82  m_bytesRead = 0;
83  m_offset += page.segmentSizes()[m_segment - 1];
84  } else {
85  // next (matching) page has next segment
86  nextPage();
87  }
88 }
89 
94 void OggIterator::previousPage()
95 {
96  while(m_page) {
97  const OggPage &page = m_pages[--m_page];
98  if(matchesFilter(page)) {
99  m_offset = page.dataOffset(m_segment = page.segmentSizes().size() - 1);
100  return;
101  }
102  }
103 }
104 
109 void OggIterator::previousSegment()
110 {
111  const OggPage &page = m_pages[m_page];
112  if(m_segment && matchesFilter(page)) {
113  m_offset -= page.segmentSizes()[m_segment--];
114  } else {
115  previousPage();
116  }
117 }
118 
130 void OggIterator::read(char *buffer, size_t count)
131 {
132  size_t bytesRead = 0;
133  while(*this && count) {
134  const uint32 available = currentSegmentSize() - m_bytesRead;
135  stream().seekg(currentCharacterOffset());
136  if(count <= available) {
137  stream().read(buffer + bytesRead, count);
138  m_bytesRead += count;
139  return;
140  } else {
141  stream().read(buffer + bytesRead, available);
142  nextSegment();
143  bytesRead += available;
144  count -= available;
145  }
146  }
147  if(count) {
148  // still bytes to read but no more available
149  throw TruncatedDataException();
150  }
151 }
152 
163 size_t OggIterator::readAll(char *buffer, size_t max)
164 {
165  size_t bytesRead = 0;
166  while(*this && max) {
167  const uint32 available = currentSegmentSize() - m_bytesRead;
168  stream().seekg(currentCharacterOffset());
169  if(max <= available) {
170  stream().read(buffer + bytesRead, max);
171  m_bytesRead += max;
172  return bytesRead + max;
173  } else {
174  stream().read(buffer + bytesRead, available);
175  nextSegment();
176  bytesRead += available;
177  max -= available;
178  }
179  }
180  return bytesRead;
181 }
182 
193 void OggIterator::ignore(size_t count)
194 {
195  uint32 available = currentSegmentSize() - m_bytesRead;
196  while(*this) {
197  available = currentSegmentSize() - m_bytesRead;
198  if(count <= available) {
199  m_bytesRead += count;
200  return;
201  } else {
202  nextSegment();
203  count -= available;
204  }
205  }
206  throw TruncatedDataException();
207 }
208 
219 bool OggIterator::fetchNextPage()
220 {
221  if(m_page == m_pages.size()) { // can only fetch the next page if the current page is the last page
222  m_offset = m_pages.empty() ? m_startOffset : m_pages.back().startOffset() + m_pages.back().totalSize();
223  if(m_offset < m_streamSize) {
224  m_pages.emplace_back(*m_stream, m_offset, static_cast<int32>(m_streamSize - m_offset));
225  return true;
226  }
227  }
228  return false;
229 }
230 
231 }
uint64 dataOffset(byte segmentIndex=0) const
Returns the data offset of the segment with the specified segmentIndex.
Definition: oggpage.h:240
uint32 headerSize() const
Returns the header size in byte.
Definition: oggpage.h:219
STL namespace.
The OggPage class is used to parse OGG pages.
Definition: oggpage.h:14
uint64 startOffset() const
Returns the start offset of the page.
Definition: oggpage.h:83
The exception that is thrown when the data to be parsed is truncated and therefore can not be parsed ...
Definition: exceptions.h:35
Contains all classes and functions of the TagInfo library.
Definition: exceptions.h:9
const std::vector< uint32 > & segmentSizes() const
Returns the sizes of the segments of the page in byte.
Definition: oggpage.h:209