3 #include "../exceptions.h"
5 #include <c++utilities/io/binaryreader.h>
32 void OggIterator::clear(istream &stream, std::uint64_t startOffset, std::uint64_t streamSize)
35 m_startOffset = startOffset;
36 m_streamSize = streamSize;
46 void OggIterator::reset()
48 for (m_page = m_segment = m_offset = 0; m_page < m_pages.size() || fetchNextPage(); ++m_page) {
49 const OggPage &page = m_pages[m_page];
50 if (!page.
segmentSizes().empty() && matchesFilter(page)) {
63 void OggIterator::nextPage()
65 while (++m_page < m_pages.size() || fetchNextPage()) {
66 const OggPage &page = m_pages[m_page];
67 if (!page.
segmentSizes().empty() && matchesFilter(page)) {
69 m_segment = m_bytesRead = 0;
81 void OggIterator::nextSegment()
83 const OggPage &page = m_pages[m_page];
84 if (matchesFilter(page) && ++m_segment < page.
segmentSizes().size()) {
98 void OggIterator::previousPage()
101 const OggPage &page = m_pages[--m_page];
102 if (matchesFilter(page)) {
113 void OggIterator::previousSegment()
115 const OggPage &page = m_pages[m_page];
116 if (m_segment && matchesFilter(page)) {
134 void OggIterator::read(
char *buffer,
size_t count)
136 size_t bytesRead = 0;
137 while (*
this && count) {
138 const auto available = currentSegmentSize() - m_bytesRead;
139 stream().seekg(static_cast<streamoff>(currentCharacterOffset()));
140 if (count <= available) {
141 stream().read(buffer + bytesRead, static_cast<streamoff>(count));
142 m_bytesRead += count;
145 stream().read(buffer + bytesRead, available);
147 bytesRead += available;
168 size_t OggIterator::readAll(
char *buffer,
size_t max)
170 size_t bytesRead = 0;
171 while (*
this && max) {
172 const std::uint32_t available = currentSegmentSize() - m_bytesRead;
173 stream().seekg(static_cast<streamoff>(currentCharacterOffset()));
174 if (max <= available) {
175 stream().read(buffer + bytesRead, static_cast<streamoff>(max));
177 return bytesRead + max;
179 stream().read(buffer + bytesRead, available);
181 bytesRead += available;
198 void OggIterator::ignore(
size_t count)
200 std::uint32_t available = currentSegmentSize() - m_bytesRead;
202 available = currentSegmentSize() - m_bytesRead;
203 if (count <= available) {
204 m_bytesRead += count;
237 bool OggIterator::resyncAt(std::uint64_t offset)
240 if (offset >= streamSize() || offset < (m_pages.empty() ? m_startOffset : m_pages.back().startOffset() + m_pages.back().totalSize())) {
245 stream().seekg(static_cast<streamoff>(offset));
246 std::uint8_t lettersFound = 0;
247 for (std::uint64_t bytesAvailable = max<std::uint64_t>(streamSize() - offset, 65307ul); bytesAvailable >= 27; --bytesAvailable) {
248 switch (static_cast<char>(stream().get())) {
253 lettersFound = lettersFound == 1 || lettersFound == 2 ? lettersFound + 1 : 0;
256 if (lettersFound == 3) {
258 const auto currentOffset = stream().tellg();
261 m_pages.emplace_back(stream(), static_cast<std::uint64_t>(stream().tellg()) - 4,
262 bytesAvailable > numeric_limits<std::int32_t>::max() ? numeric_limits<std::int32_t>::max()
263 : static_cast<std::int32_t>(bytesAvailable));
264 setPageIndex(m_pages.size() - 1);
267 stream().seekg(currentOffset);
288 bool OggIterator::fetchNextPage()
290 if (m_page == m_pages.size()) {
291 m_offset = m_pages.empty() ? m_startOffset : m_pages.back().startOffset() + m_pages.back().totalSize();
292 if (m_offset < m_streamSize) {
293 const std::uint64_t bytesAvailable = m_streamSize - m_offset;
294 m_pages.emplace_back(*m_stream, m_offset,
295 bytesAvailable > numeric_limits<std::int32_t>::max() ? numeric_limits<std::int32_t>::max()
296 : static_cast<std::int32_t>(bytesAvailable));