289 lines
13 KiB
C++
289 lines
13 KiB
C++
/***************************************************************************
|
|
copyright : (C) 2009 by Lukas Lalinsky
|
|
email : lukas@oxygene.sk
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* This library is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Lesser General Public License version *
|
|
* 2.1 as published by the Free Software Foundation. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, but *
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
* Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Lesser General Public *
|
|
* License along with this library; if not, write to the Free Software *
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
|
* 02110-1301 USA *
|
|
* *
|
|
* Alternatively, this file is available under the Mozilla Public *
|
|
* License Version 1.1. You may obtain a copy of the License at *
|
|
* http://www.mozilla.org/MPL/ *
|
|
***************************************************************************/
|
|
|
|
#include <cstring>
|
|
#include <cstdio>
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
|
|
#include "tag.h"
|
|
#include "tbytevectorlist.h"
|
|
#include "rifffile.h"
|
|
#include "utils.h"
|
|
|
|
using namespace std;
|
|
using namespace Strawberry_TagLib::TagLib;
|
|
|
|
class PublicRIFF : public RIFF::File {
|
|
public:
|
|
explicit PublicRIFF(FileName file) : RIFF::File(file, BigEndian) {};
|
|
unsigned int riffSize() { return RIFF::File::riffSize(); };
|
|
size_t chunkCount() { return RIFF::File::chunkCount(); };
|
|
long long chunkOffset(unsigned int i) { return RIFF::File::chunkOffset(i); };
|
|
unsigned int chunkPadding(unsigned int i) { return RIFF::File::chunkPadding(i); };
|
|
unsigned int chunkDataSize(unsigned int i) { return RIFF::File::chunkDataSize(i); };
|
|
ByteVector chunkName(unsigned int i) { return RIFF::File::chunkName(i); };
|
|
ByteVector chunkData(unsigned int i) { return RIFF::File::chunkData(i); };
|
|
void setChunkData(unsigned int i, const ByteVector &data) {
|
|
RIFF::File::setChunkData(i, data);
|
|
}
|
|
void setChunkData(const ByteVector &name, const ByteVector &data) {
|
|
RIFF::File::setChunkData(name, data);
|
|
};
|
|
Strawberry_TagLib::TagLib::Tag *tag() const override { return nullptr; }
|
|
Strawberry_TagLib::TagLib::AudioProperties *audioProperties() const override { return nullptr; }
|
|
bool save() override { return false; }
|
|
void removeChunk(unsigned int i) { RIFF::File::removeChunk(i); }
|
|
void removeChunk(const ByteVector &name) { RIFF::File::removeChunk(name); }
|
|
};
|
|
|
|
class TestRIFF : public CppUnit::TestFixture {
|
|
CPPUNIT_TEST_SUITE(TestRIFF);
|
|
CPPUNIT_TEST(testPadding);
|
|
CPPUNIT_TEST(testLastChunkAtEvenPosition);
|
|
CPPUNIT_TEST(testLastChunkAtEvenPosition2);
|
|
CPPUNIT_TEST(testLastChunkAtEvenPosition3);
|
|
CPPUNIT_TEST(testChunkOffset);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
|
|
public:
|
|
void testPadding() {
|
|
ScopedFileCopy copy("empty", ".aiff");
|
|
string filename = copy.fileName();
|
|
|
|
{
|
|
PublicRIFF f(filename.c_str());
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x1728 + 8), f.chunkOffset(2));
|
|
|
|
f.setChunkData("TEST", "foo");
|
|
}
|
|
{
|
|
PublicRIFF f(filename.c_str());
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("foo"), f.chunkData(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(3), f.chunkDataSize(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x1728 + 8), f.chunkOffset(2));
|
|
|
|
f.setChunkData("SSND", "abcd");
|
|
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(1));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("abcd"), f.chunkData(1));
|
|
|
|
f.seek(f.chunkOffset(1));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("abcd"), f.readBlock(4));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("foo"), f.chunkData(2));
|
|
|
|
f.seek(f.chunkOffset(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("foo"), f.readBlock(3));
|
|
}
|
|
{
|
|
PublicRIFF f(filename.c_str());
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(1));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("abcd"), f.chunkData(1));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("foo"), f.chunkData(2));
|
|
}
|
|
}
|
|
|
|
void testLastChunkAtEvenPosition() {
|
|
ScopedFileCopy copy("noise", ".aif");
|
|
string filename = copy.fileName();
|
|
|
|
{
|
|
PublicRIFF f(filename.c_str());
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0xff0 + 8), f.chunkOffset(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(311), f.chunkDataSize(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(1), f.chunkPadding(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4400), f.length());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(4399 - 8), f.riffSize());
|
|
f.setChunkData("TEST", "abcd");
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4088), f.chunkOffset(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(311), f.chunkDataSize(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(1), f.chunkPadding(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4408), f.chunkOffset(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(4), f.chunkDataSize(3));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(0), f.chunkPadding(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(4412 - 8), f.riffSize());
|
|
}
|
|
{
|
|
PublicRIFF f(filename.c_str());
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4088), f.chunkOffset(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(311), f.chunkDataSize(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(1), f.chunkPadding(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4408), f.chunkOffset(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(4), f.chunkDataSize(3));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(0), f.chunkPadding(3));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4412), f.length());
|
|
}
|
|
}
|
|
|
|
void testLastChunkAtEvenPosition2() {
|
|
ScopedFileCopy copy("noise_odd", ".aif");
|
|
string filename = copy.fileName();
|
|
|
|
{
|
|
PublicRIFF f(filename.c_str());
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0xff0 + 8), f.chunkOffset(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(311), f.chunkDataSize(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(0), f.chunkPadding(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4399), f.length());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(4399 - 8), f.riffSize());
|
|
f.setChunkData("TEST", "abcd");
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4088), f.chunkOffset(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(311), f.chunkDataSize(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(1), f.chunkPadding(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4408), f.chunkOffset(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(4), f.chunkDataSize(3));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(0), f.chunkPadding(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(4412 - 8), f.riffSize());
|
|
}
|
|
{
|
|
PublicRIFF f(filename.c_str());
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4088), f.chunkOffset(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(311), f.chunkDataSize(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(1), f.chunkPadding(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4408), f.chunkOffset(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(4), f.chunkDataSize(3));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(0), f.chunkPadding(3));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4412), f.length());
|
|
}
|
|
}
|
|
|
|
void testLastChunkAtEvenPosition3() {
|
|
ScopedFileCopy copy("noise_odd", ".aif");
|
|
string filename = copy.fileName();
|
|
|
|
{
|
|
PublicRIFF f(filename.c_str());
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0xff0 + 8), f.chunkOffset(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(311), f.chunkDataSize(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(0), f.chunkPadding(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4399), f.length());
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(4399 - 8), f.riffSize());
|
|
f.setChunkData("TEST", "abc");
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4088), f.chunkOffset(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(311), f.chunkDataSize(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(1), f.chunkPadding(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4408), f.chunkOffset(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(3), f.chunkDataSize(3));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(1), f.chunkPadding(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(4412 - 8), f.riffSize());
|
|
}
|
|
{
|
|
PublicRIFF f(filename.c_str());
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4088), f.chunkOffset(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(311), f.chunkDataSize(2));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(1), f.chunkPadding(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4408), f.chunkOffset(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(3), f.chunkDataSize(3));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(3));
|
|
CPPUNIT_ASSERT_EQUAL((unsigned int)(1), f.chunkPadding(3));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(4412), f.length());
|
|
}
|
|
}
|
|
|
|
void testChunkOffset() {
|
|
ScopedFileCopy copy("empty", ".aiff");
|
|
string filename = copy.fileName();
|
|
|
|
PublicRIFF f(filename.c_str());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(5928U, f.riffSize());
|
|
CPPUNIT_ASSERT_EQUAL(5936LL, f.length());
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f.chunkName(0));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x000C + 8), f.chunkOffset(0));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(1));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x0026 + 8), f.chunkOffset(1));
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(2));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x1728 + 8), f.chunkOffset(2));
|
|
|
|
const ByteVector data(0x400, ' ');
|
|
f.setChunkData("SSND", data);
|
|
CPPUNIT_ASSERT_EQUAL(1070U, f.riffSize());
|
|
CPPUNIT_ASSERT_EQUAL(1078LL, f.length());
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x000C + 8), f.chunkOffset(0));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x0026 + 8), f.chunkOffset(1));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x042E + 8), f.chunkOffset(2));
|
|
|
|
f.seek(f.chunkOffset(0) - 8);
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f.readBlock(4));
|
|
f.seek(f.chunkOffset(1) - 8);
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.readBlock(4));
|
|
f.seek(f.chunkOffset(2) - 8);
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.readBlock(4));
|
|
|
|
f.setChunkData(0, data);
|
|
CPPUNIT_ASSERT_EQUAL(2076U, f.riffSize());
|
|
CPPUNIT_ASSERT_EQUAL(2084LL, f.length());
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x000C + 8), f.chunkOffset(0));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x0414 + 8), f.chunkOffset(1));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x081C + 8), f.chunkOffset(2));
|
|
|
|
f.seek(f.chunkOffset(0) - 8);
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f.readBlock(4));
|
|
f.seek(f.chunkOffset(1) - 8);
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.readBlock(4));
|
|
f.seek(f.chunkOffset(2) - 8);
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.readBlock(4));
|
|
|
|
f.removeChunk("SSND");
|
|
CPPUNIT_ASSERT_EQUAL(1044U, f.riffSize());
|
|
CPPUNIT_ASSERT_EQUAL(1052LL, f.length());
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x000C + 8), f.chunkOffset(0));
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x0414 + 8), f.chunkOffset(1));
|
|
|
|
f.seek(f.chunkOffset(0) - 8);
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f.readBlock(4));
|
|
f.seek(f.chunkOffset(1) - 8);
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.readBlock(4));
|
|
|
|
f.removeChunk(0);
|
|
CPPUNIT_ASSERT_EQUAL(12U, f.riffSize());
|
|
CPPUNIT_ASSERT_EQUAL((long long)(0x000C + 8), f.chunkOffset(0));
|
|
|
|
f.seek(f.chunkOffset(0) - 8);
|
|
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.readBlock(4));
|
|
}
|
|
};
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(TestRIFF);
|