Tag Parser  9.4.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
oggpage.cpp
Go to the documentation of this file.
1 #include "./oggpage.h"
2 
3 #include "../exceptions.h"
4 
5 #include <c++utilities/conversion/binaryconversion.h>
6 #include <c++utilities/io/binaryreader.h>
7 
8 using namespace std;
9 using namespace CppUtilities;
10 
11 namespace TagParser {
12 
24 void OggPage::parseHeader(istream &stream, std::uint64_t startOffset, std::int32_t maxSize)
25 {
26  // prepare reading
27  stream.seekg(static_cast<streamoff>(startOffset));
28  BinaryReader reader(&stream);
29  if (maxSize < 27) {
30  throw TruncatedDataException();
31  } else {
32  maxSize -= 27;
33  }
34  // read header values
35  if (reader.readUInt32LE() != 0x5367674f) {
36  throw InvalidDataException();
37  }
38  m_startOffset = startOffset;
39  m_streamStructureVersion = reader.readByte();
40  m_headerTypeFlag = reader.readByte();
41  m_absoluteGranulePosition = reader.readUInt64LE();
42  m_streamSerialNumber = reader.readUInt32LE();
43  m_sequenceNumber = reader.readUInt32LE();
44  m_checksum = reader.readUInt32LE();
45  m_segmentCount = reader.readByte();
46  m_segmentSizes.clear();
47  if (m_segmentCount > 0) {
48  if (maxSize < m_segmentCount) {
49  throw TruncatedDataException();
50  } else {
51  maxSize -= m_segmentCount;
52  }
53  // read segment size tabe
54  m_segmentSizes.push_back(0);
55  for (std::uint8_t i = 0; i < m_segmentCount;) {
56  std::uint8_t entry = reader.readByte();
57  maxSize -= entry;
58  m_segmentSizes.back() += entry;
59  if (++i < m_segmentCount && entry < 0xff) {
60  m_segmentSizes.push_back(0);
61  }
62  }
63  // check whether the maximum size is exceeded
64  if (maxSize < 0) {
65  throw TruncatedDataException();
66  }
67  }
68 }
69 
74 std::uint32_t OggPage::computeChecksum(istream &stream, std::uint64_t startOffset)
75 {
76  stream.seekg(static_cast<streamoff>(startOffset));
77  std::uint32_t crc = 0x0;
78  std::uint8_t value, segmentTableSize = 0, segmentTableIndex = 0;
79  for (std::uint32_t i = 0, segmentLength = 27; i != segmentLength; ++i) {
80  switch (i) {
81  case 22:
82  // bytes 22, 23, 24, 25 hold denoted checksum and must be set to zero
83  stream.seekg(4, ios_base::cur);
84  [[fallthrough]];
85  case 23:
86  case 24:
87  case 25:
88  value = 0;
89  break;
90  case 26:
91  // byte 26 holds the number of segment sizes
92  segmentLength += (segmentTableSize = (value = static_cast<std::uint8_t>(stream.get())));
93  break;
94  default:
95  value = static_cast<std::uint8_t>(stream.get());
96  if (i > 26 && segmentTableIndex < segmentTableSize) {
97  // bytes 27 to (27 + segment size count) hold page size
98  segmentLength += value;
99  ++segmentTableIndex;
100  }
101  }
102  crc = (crc << 8) ^ BinaryReader::crc32Table[((crc >> 24) & 0xFF) ^ value];
103  }
104  return crc;
105 }
106 
111 void OggPage::updateChecksum(iostream &stream, std::uint64_t startOffset)
112 {
113  char buff[4];
114  LE::getBytes(computeChecksum(stream, startOffset), buff);
115  stream.seekp(static_cast<streamoff>(startOffset + 22));
116  stream.write(buff, sizeof(buff));
117 }
118 
123 std::uint32_t OggPage::makeSegmentSizeDenotation(ostream &stream, std::uint32_t size)
124 {
125  std::uint32_t bytesWritten = 1;
126  while (size >= 0xff) {
127  stream.put(static_cast<char>(0xff));
128  size -= 0xff;
129  ++bytesWritten;
130  }
131  stream.put(static_cast<char>(size));
132  return bytesWritten;
133 }
134 
135 } // namespace TagParser
TagParser
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:10
CppUtilities
Definition: abstractcontainer.h:15
oggpage.h
TagParser::InvalidDataException
The exception that is thrown when the data to be parsed or to be made seems invalid and therefore can...
Definition: exceptions.h:25
TagParser::TruncatedDataException
The exception that is thrown when the data to be parsed is truncated and therefore can not be parsed ...
Definition: exceptions.h:39