Remove the null termination stuff from the ToC frames too

This commit is contained in:
Scott Wheeler 2015-05-18 18:12:34 +02:00
parent 3a977c55c4
commit 7316cd331d
2 changed files with 45 additions and 13 deletions

View File

@ -50,6 +50,31 @@ public:
FrameList embeddedFrameList;
};
namespace {
// These functions are needed to try to aim for backward compatibility with
// an API that previously (unreasonably) required null bytes to be appeneded
// at the end of identifiers explicitly by the API user.
// BIC: remove these
ByteVector &strip(ByteVector &b)
{
if(b.endsWith('\0'))
b.resize(b.size() - 1);
return b;
}
ByteVectorList &strip(ByteVectorList &l)
{
for(ByteVectorList::Iterator it = l.begin(); it != l.end(); ++it)
{
strip(*it);
}
return l;
}
}
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
@ -68,6 +93,7 @@ TableOfContentsFrame::TableOfContentsFrame(const ByteVector &eID, const ByteVect
{
d = new TableOfContentsFramePrivate;
d->elementID = eID;
strip(d->elementID);
d->childElements = ch;
FrameList l = eF;
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
@ -107,8 +133,7 @@ ByteVectorList TableOfContentsFrame::childElements() const
void TableOfContentsFrame::setElementID(const ByteVector &eID)
{
d->elementID = eID;
if(eID.at(eID.size() - 1) != char(0))
d->elementID.append(char(0));
strip(d->elementID);
}
void TableOfContentsFrame::setIsTopLevel(const bool &t)
@ -124,16 +149,22 @@ void TableOfContentsFrame::setIsOrdered(const bool &o)
void TableOfContentsFrame::setChildElements(const ByteVectorList &l)
{
d->childElements = l;
strip(d->childElements);
}
void TableOfContentsFrame::addChildElement(const ByteVector &cE)
{
d->childElements.append(cE);
strip(d->childElements);
}
void TableOfContentsFrame::removeChildElement(const ByteVector &cE)
{
ByteVectorList::Iterator it = d->childElements.find(cE);
if(it == d->childElements.end())
it = d->childElements.find(cE + ByteVector("\0"));
d->childElements.erase(it);
}
@ -240,17 +271,19 @@ void TableOfContentsFrame::parseFields(const ByteVector &data)
int pos = 0;
TagLib::uint embPos = 0;
d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
d->elementID.append(char(0));
d->isTopLevel = (data.at(pos) & 2) > 0;
d->isOrdered = (data.at(pos++) & 1) > 0;
TagLib::uint entryCount = data.at(pos++);
for(TagLib::uint i = 0; i < entryCount; i++) {
ByteVector childElementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
childElementID.append(char(0));
d->childElements.append(childElementID);
}
size -= pos;
if(size < header()->size())
return;
while(embPos < size - header()->size()) {
Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);
@ -273,6 +306,7 @@ ByteVector TableOfContentsFrame::renderFields() const
ByteVector data;
data.append(d->elementID);
data.append('\0');
char flags = 0;
if(d->isTopLevel)
flags += 2;
@ -283,6 +317,7 @@ ByteVector TableOfContentsFrame::renderFields() const
ByteVectorList::ConstIterator it = d->childElements.begin();
while(it != d->childElements.end()) {
data.append(*it);
data.append('\0');
it++;
}
FrameList l = d->embeddedFrameList;

View File

@ -1001,25 +1001,22 @@ public:
ByteVector("CTOC" // Frame ID
"\x00\x00\x00\x16" // Frame size
"\x00\x00" // Frame flags
"\x54\x00" // Element ID
"\x54\x00" // Element ID ("T")
"\x01" // CTOC flags
"\x02" // Entry count
"\x43\x00" // First entry
"\x44\x00" // Second entry
"\x43\x00" // First entry ("C")
"\x44\x00" // Second entry ("D")
"TIT2" // Embedded frame ID
"\x00\x00\x00\x04" // Embedded frame size
"\x00\x00" // Embedded frame flags
"\x00" // TIT2 frame text encoding
"TC1", 32)); // Table of contents title
CPPUNIT_ASSERT_EQUAL(ByteVector("\x54\x00", 2),
f.elementID());
CPPUNIT_ASSERT_EQUAL(ByteVector("T"), f.elementID());
CPPUNIT_ASSERT(!f.isTopLevel());
CPPUNIT_ASSERT(f.isOrdered());
CPPUNIT_ASSERT((uint)0x02 == f.entryCount());
CPPUNIT_ASSERT_EQUAL(ByteVector("\x43\x00", 2),
f.childElements()[0]);
CPPUNIT_ASSERT_EQUAL(ByteVector("\x44\x00", 2),
f.childElements()[1]);
CPPUNIT_ASSERT_EQUAL(ByteVector("C"), f.childElements()[0]);
CPPUNIT_ASSERT_EQUAL(ByteVector("D"), f.childElements()[1]);
CPPUNIT_ASSERT((uint)0x01 == f.embeddedFrameList().size());
CPPUNIT_ASSERT(f.embeddedFrameList("TIT2").size() == 1);
CPPUNIT_ASSERT(f.embeddedFrameList("TIT2")[0]->toString() == "TC1");