4 #include "../ogg/oggiterator.h" 6 #include "../exceptions.h" 8 #include <c++utilities/io/binaryreader.h> 9 #include <c++utilities/io/binarywriter.h> 10 #include <c++utilities/io/copy.h> 29 case KnownField::Vendor:
39 case KnownField::Vendor:
49 using namespace VorbisCommentIds;
60 case KnownField::PartNumber:
return partNumber();
67 case KnownField::Language:
return language();
69 default:
return string();
73 KnownField VorbisComment::knownField(
const string &
id)
const 75 using namespace VorbisCommentIds;
76 static const map<string, KnownField> fieldMap({
96 return fieldMap.at(
id);
97 }
catch(out_of_range &) {
98 return KnownField::Invalid;
105 template<
class StreamType>
106 void VorbisComment::internalParse(StreamType &stream, uint64 maxSize,
VorbisCommentFlags flags)
110 static const string context(
"parsing Vorbis comment");
111 uint64 startOffset =
static_cast<uint64
>(stream.tellg());
115 bool skipSignature = flags & VorbisCommentFlags::NoSignature;
119 skipSignature = (ConversionUtilities::BE::toUInt64(sig) & 0xffffffffffffff00u) == 0x03766F7262697300u;
126 const auto vendorSize = LE::toUInt32(sig);
127 if(vendorSize <= maxSize) {
128 auto buff = make_unique<char []>(vendorSize);
129 stream.read(buff.get(), vendorSize);
133 addNotification(NotificationType::Critical,
"Vendor information is truncated.", context);
134 throw TruncatedDataException();
136 maxSize -= vendorSize;
141 uint32 fieldCount = LE::toUInt32(sig);
142 VorbisCommentField field;
143 const string &fieldId = field.id();
144 for(uint32 i = 0; i < fieldCount; ++i) {
147 field.parse(stream, maxSize);
148 fields().insert(pair<fieldType::identifierType, fieldType>(fieldId, field));
149 }
catch(
const TruncatedDataException &) {
150 addNotifications(field);
152 }
catch(
const Failure &) {
155 addNotifications(field);
156 field.invalidateNotifications();
158 if(!(flags & VorbisCommentFlags::NoFramingByte)) {
161 m_size =
static_cast<uint32
>(
static_cast<uint64
>(stream.tellg()) - startOffset);
163 addNotification(NotificationType::Critical,
"Signature is invalid.", context);
164 throw InvalidDataException();
166 }
catch(
const TruncatedDataException &) {
167 m_size =
static_cast<uint32
>(
static_cast<uint64
>(stream.tellg()) - startOffset);
168 addNotification(NotificationType::Critical,
"Vorbis comment is truncated.", context);
182 internalParse(iterator, iterator.
streamSize(), flags);
194 internalParse(stream, maxSize, flags);
208 static const string context(
"making Vorbis comment");
211 m_vendor.toString(vendor);
212 }
catch(
const ConversionException &) {
213 addNotification(NotificationType::Warning,
"Can not convert the assigned vendor to string.", context);
215 BinaryWriter writer(&stream);
216 if(!(flags & VorbisCommentFlags::NoSignature)) {
218 static const char sig[7] = {0x03, 0x76, 0x6F, 0x72, 0x62, 0x69, 0x73};
219 stream.write(sig,
sizeof(sig));
222 writer.writeUInt32LE(vendor.size());
223 writer.writeString(vendor);
225 const auto fieldCountOffset = stream.tellp();
226 writer.writeUInt32LE(0);
228 uint32 fieldsWritten = 0;
229 for(
auto i : fields()) {
233 if(field.
make(writer, flags)) {
240 addNotifications(context, field);
245 const auto framingByteOffset = stream.tellp();
246 stream.seekp(fieldCountOffset);
247 writer.writeUInt32LE(fieldsWritten);
248 stream.seekp(framingByteOffset);
250 if(!(flags & VorbisCommentFlags::NoFramingByte)) {
Contains utility classes helping to read and write streams.
#define CHECK_MAX_SIZE(sizeDenotation)
Throws TruncatedDataException() if the specified sizeDenotation exceeds maxSize; otherwise maxSize is...