mirror of
https://github.com/taglib/taglib.git
synced 2025-06-03 17:18:11 -04:00
Merge pull request #484 from TsudaKageyu/fix-rfind
Fix File::rfind() for small files.
This commit is contained in:
commit
48ca54de1f
@ -278,7 +278,7 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
|
||||
// (2) The search pattern is wholly contained within the current buffer.
|
||||
//
|
||||
// (3) The current buffer ends with a partial match of the pattern. We will
|
||||
// note this for use in the next itteration, where we will check for the rest
|
||||
// note this for use in the next iteration, where we will check for the rest
|
||||
// of the pattern.
|
||||
//
|
||||
// All three of these are done in two steps. First we check for the pattern
|
||||
@ -363,25 +363,34 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
|
||||
|
||||
// Start the search at the offset.
|
||||
|
||||
long bufferOffset;
|
||||
if(fromOffset == 0) {
|
||||
seek(-1 * int(bufferSize()), End);
|
||||
bufferOffset = tell();
|
||||
}
|
||||
else {
|
||||
seek(fromOffset + -1 * int(bufferSize()), Beginning);
|
||||
bufferOffset = tell();
|
||||
}
|
||||
if(fromOffset == 0)
|
||||
fromOffset = length();
|
||||
|
||||
long bufferLength = bufferSize();
|
||||
long bufferOffset = fromOffset + pattern.size();
|
||||
|
||||
// See the notes in find() for an explanation of this algorithm.
|
||||
|
||||
for(buffer = readBlock(bufferSize()); buffer.size() > 0; buffer = readBlock(bufferSize())) {
|
||||
while(true) {
|
||||
|
||||
if(bufferOffset > bufferLength) {
|
||||
bufferOffset -= bufferLength;
|
||||
}
|
||||
else {
|
||||
bufferLength = bufferOffset;
|
||||
bufferOffset = 0;
|
||||
}
|
||||
seek(bufferOffset);
|
||||
|
||||
buffer = readBlock(bufferLength);
|
||||
if(buffer.isEmpty())
|
||||
break;
|
||||
|
||||
// TODO: (1) previous partial match
|
||||
|
||||
// (2) pattern contained in current buffer
|
||||
|
||||
long location = buffer.rfind(pattern);
|
||||
const long location = buffer.rfind(pattern);
|
||||
if(location >= 0) {
|
||||
seek(originalPosition);
|
||||
return bufferOffset + location;
|
||||
@ -393,9 +402,6 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
|
||||
}
|
||||
|
||||
// TODO: (3) partial match
|
||||
|
||||
bufferOffset -= bufferSize();
|
||||
seek(bufferOffset);
|
||||
}
|
||||
|
||||
// Since we hit the end of the file, reset the status before continuing.
|
||||
|
@ -38,6 +38,7 @@ SET(test_runner_SRCS
|
||||
test_bytevectorstream.cpp
|
||||
test_string.cpp
|
||||
test_propertymap.cpp
|
||||
test_file.cpp
|
||||
test_fileref.cpp
|
||||
test_id3v1.cpp
|
||||
test_id3v2.cpp
|
||||
|
105
tests/test_file.cpp
Normal file
105
tests/test_file.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2014 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 *
|
||||
***************************************************************************/
|
||||
|
||||
#include <tfile.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include "utils.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
// File subclass that gives tests access to filesystem operations
|
||||
class PlainFile : public File {
|
||||
public:
|
||||
PlainFile(FileName name) : File(name) { }
|
||||
Tag *tag() const { return NULL; }
|
||||
AudioProperties *audioProperties() const { return NULL; }
|
||||
bool save(){ return false; }
|
||||
void truncate(long length) { File::truncate(length); }
|
||||
};
|
||||
|
||||
class TestFile : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE(TestFile);
|
||||
CPPUNIT_TEST(testFindInSmallFile);
|
||||
CPPUNIT_TEST(testRFindInSmallFile);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
|
||||
void testFindInSmallFile()
|
||||
{
|
||||
ScopedFileCopy copy("empty", ".ogg");
|
||||
std::string name = copy.fileName();
|
||||
{
|
||||
PlainFile file(name.c_str());
|
||||
file.seek(0);
|
||||
file.writeBlock(ByteVector("0123456239", 10));
|
||||
file.truncate(10);
|
||||
}
|
||||
{
|
||||
PlainFile file(name.c_str());
|
||||
CPPUNIT_ASSERT_EQUAL(10l, file.length());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(2l, file.find(ByteVector("23", 2)));
|
||||
CPPUNIT_ASSERT_EQUAL(2l, file.find(ByteVector("23", 2), 2));
|
||||
CPPUNIT_ASSERT_EQUAL(7l, file.find(ByteVector("23", 2), 3));
|
||||
|
||||
file.seek(0);
|
||||
const ByteVector v = file.readBlock(file.length());
|
||||
CPPUNIT_ASSERT_EQUAL((uint)10, v.size());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL((long)v.find("23"), file.find("23"));
|
||||
CPPUNIT_ASSERT_EQUAL((long)v.find("23", 2), file.find("23", 2));
|
||||
CPPUNIT_ASSERT_EQUAL((long)v.find("23", 3), file.find("23", 3));
|
||||
}
|
||||
}
|
||||
|
||||
void testRFindInSmallFile()
|
||||
{
|
||||
ScopedFileCopy copy("empty", ".ogg");
|
||||
std::string name = copy.fileName();
|
||||
{
|
||||
PlainFile file(name.c_str());
|
||||
file.seek(0);
|
||||
file.writeBlock(ByteVector("0123456239", 10));
|
||||
file.truncate(10);
|
||||
}
|
||||
{
|
||||
PlainFile file(name.c_str());
|
||||
CPPUNIT_ASSERT_EQUAL(10l, file.length());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(7l, file.rfind(ByteVector("23", 2)));
|
||||
CPPUNIT_ASSERT_EQUAL(7l, file.rfind(ByteVector("23", 2), 7));
|
||||
CPPUNIT_ASSERT_EQUAL(2l, file.rfind(ByteVector("23", 2), 6));
|
||||
|
||||
file.seek(0);
|
||||
const ByteVector v = file.readBlock(file.length());
|
||||
CPPUNIT_ASSERT_EQUAL((uint)10, v.size());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL((long)v.rfind("23"), file.rfind("23"));
|
||||
CPPUNIT_ASSERT_EQUAL((long)v.rfind("23", 7), file.rfind("23", 7));
|
||||
CPPUNIT_ASSERT_EQUAL((long)v.rfind("23", 6), file.rfind("23", 6));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestFile);
|
Loading…
x
Reference in New Issue
Block a user