mirror of
https://github.com/taglib/taglib.git
synced 2025-05-27 13:10:26 -04:00
Improve FrameFactory subclassing
Change the ID3v2 frame factory so it is possible to subclass it for implementing own frames. Additionally it splits up the createFrame() method to make its usage in subclasses a bit more easy.
This commit is contained in:
parent
c54c924333
commit
271bd05afa
@ -116,9 +116,9 @@ FrameFactory *FrameFactory::instance()
|
||||
return &factory;
|
||||
}
|
||||
|
||||
Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHeader) const
|
||||
std::pair<Frame::Header *, bool> FrameFactory::prepareFrameHeader(
|
||||
ByteVector &data, const Header *tagHeader) const
|
||||
{
|
||||
ByteVector data = origData;
|
||||
unsigned int version = tagHeader->majorVersion();
|
||||
auto header = new Frame::Header(data, version);
|
||||
ByteVector frameID = header->frameID();
|
||||
@ -131,7 +131,7 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
header->frameSize() > data.size())
|
||||
{
|
||||
delete header;
|
||||
return nullptr;
|
||||
return {nullptr, false};
|
||||
}
|
||||
|
||||
#ifndef NO_ITUNES_HACKS
|
||||
@ -148,7 +148,7 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
for(auto it = frameID.cbegin(); it != frameID.cend(); it++) {
|
||||
if( (*it < 'A' || *it > 'Z') && (*it < '0' || *it > '9') ) {
|
||||
delete header;
|
||||
return nullptr;
|
||||
return {nullptr, false};
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,24 +165,39 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
|
||||
if(!zlib::isAvailable() && header->compression()) {
|
||||
debug("Compressed frames are currently not supported.");
|
||||
return new UnknownFrame(data, header);
|
||||
return {header, false};
|
||||
}
|
||||
|
||||
if(header->encryption()) {
|
||||
debug("Encrypted frames are currently not supported.");
|
||||
return new UnknownFrame(data, header);
|
||||
return {header, false};
|
||||
}
|
||||
|
||||
if(!updateFrame(header)) {
|
||||
header->setTagAlterPreservation(true);
|
||||
return new UnknownFrame(data, header);
|
||||
return {header, false};
|
||||
}
|
||||
|
||||
// updateFrame() might have updated the frame ID.
|
||||
return {header, true};
|
||||
}
|
||||
|
||||
frameID = header->frameID();
|
||||
Frame *FrameFactory::createFrame(const ByteVector &origData,
|
||||
const Header *tagHeader) const
|
||||
{
|
||||
ByteVector data = origData;
|
||||
auto [header, ok] = prepareFrameHeader(data, tagHeader);
|
||||
if(!ok) {
|
||||
// check if frame is valid and return as UnknownFrame
|
||||
return header ? new UnknownFrame(data, header) : nullptr;
|
||||
}
|
||||
return createFrame(data, header, tagHeader);
|
||||
}
|
||||
|
||||
// This is where things get necissarily nasty. Here we determine which
|
||||
Frame *FrameFactory::createFrame(const ByteVector &data, Frame::Header *header,
|
||||
const Header *tagHeader) const {
|
||||
ByteVector frameID = header->frameID();
|
||||
|
||||
// This is where things get necessarily nasty. Here we determine which
|
||||
// Frame subclass (or if none is found simply an Frame) based
|
||||
// on the frame ID. Since there are a lot of possibilities, that means
|
||||
// a lot of if blocks.
|
||||
|
@ -127,6 +127,31 @@ namespace TagLib {
|
||||
*/
|
||||
virtual bool updateFrame(Frame::Header *header) const;
|
||||
|
||||
/*!
|
||||
* Creates and prepares the frame header for createFrame().
|
||||
*
|
||||
* \param data data of the frame (might be modified)
|
||||
* \param tagHeader the tag header
|
||||
* \param header reference to frame header pointer, will be set to
|
||||
* nullptr if the frame is invalid
|
||||
* \return {header, ok}: header is a created frame header or nullptr
|
||||
* if the frame is invalid; ok is true if the frame is supported.
|
||||
*/
|
||||
std::pair<Frame::Header *, bool> prepareFrameHeader(
|
||||
ByteVector &data, const Header *tagHeader) const;
|
||||
|
||||
/*!
|
||||
* Create a frame based on \a data. \a header should be a valid frame
|
||||
* header and \a tagHeader a valid ID3v2::Header instance.
|
||||
*
|
||||
* This method is called by the public overloaded method
|
||||
* createFrame(const ByteVector &, const Header *) after creating
|
||||
* \a header from verified \a data using prepareFrameHeader(), so
|
||||
* this method is provided to be reimplemented in derived classes.
|
||||
*/
|
||||
virtual Frame *createFrame(const ByteVector &data, Frame::Header *header,
|
||||
const Header *tagHeader) const;
|
||||
|
||||
private:
|
||||
FrameFactory(const FrameFactory &) = delete;
|
||||
FrameFactory &operator=(const FrameFactory &) = delete;
|
||||
|
Loading…
Reference in New Issue
Block a user