aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukáš Lalinský <lalinsky@gmail.com>2011-04-11 23:12:58 +0200
committerLukáš Lalinský <lalinsky@gmail.com>2011-04-11 23:12:58 +0200
commitb53a577e38c2fd33850d2f3f54c61d826b2d81bd (patch)
tree4c2b47691609c6d78388ece9f0e6ef30755694bd
parent0b0cbc2e34b37a727f2c79c239b144222762b400 (diff)
Add FileStream as a copy of File's methods
-rw-r--r--taglib/CMakeLists.txt2
-rw-r--r--taglib/toolkit/tfile.cpp276
-rw-r--r--taglib/toolkit/tfilestream.cpp380
-rw-r--r--taglib/toolkit/tfilestream.h186
-rw-r--r--taglib/toolkit/tiostream.cpp5
-rw-r--r--taglib/toolkit/tiostream.h12
6 files changed, 610 insertions, 251 deletions
diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt
index 53022c0a..3647caed 100644
--- a/taglib/CMakeLists.txt
+++ b/taglib/CMakeLists.txt
@@ -161,7 +161,9 @@ set(toolkit_SRCS
toolkit/tstringlist.cpp
toolkit/tbytevector.cpp
toolkit/tbytevectorlist.cpp
+ toolkit/tiostream.cpp
toolkit/tfile.cpp
+ toolkit/tfilestream.cpp
toolkit/tdebug.cpp
toolkit/unicode.cpp
)
diff --git a/taglib/toolkit/tfile.cpp b/taglib/toolkit/tfile.cpp
index 63c28e5a..c4789221 100644
--- a/taglib/toolkit/tfile.cpp
+++ b/taglib/toolkit/tfile.cpp
@@ -24,6 +24,7 @@
***************************************************************************/
#include "tfile.h"
+#include "tfilestream.h"
#include "tstring.h"
#include "tdebug.h"
@@ -70,55 +71,16 @@ class File::FilePrivate
public:
FilePrivate(FileName fileName);
- FILE *file;
IOStream *stream;
-
- FileNameHandle name;
-
- bool readOnly;
bool valid;
- ulong size;
static const uint bufferSize = 1024;
};
File::FilePrivate::FilePrivate(FileName fileName) :
- file(0),
- name(fileName),
- readOnly(true),
- valid(true),
- size(0)
+ stream(0),
+ valid(true)
{
- // First try with read / write mode, if that fails, fall back to read only.
-
-#ifdef _WIN32
-
- if(wcslen((const wchar_t *) fileName) > 0) {
-
- file = _wfopen(name, L"rb+");
-
- if(file)
- readOnly = false;
- else
- file = _wfopen(name, L"rb");
-
- if(file)
- return;
-
- }
-
-#endif
-
- file = fopen(name, "rb+");
-
- if(file)
- readOnly = false;
- else
- file = fopen(name, "rb");
-
- if(!file)
- {
- debug("Could not open file " + String((const char *) name));
- }
+ stream = new FileStream(fileName);
}
////////////////////////////////////////////////////////////////////////////////
@@ -138,54 +100,29 @@ File::File(IOStream *stream)
File::~File()
{
- if(d->file)
- fclose(d->file);
+ if(d->stream)
+ delete d->stream;
delete d;
}
FileName File::name() const
{
- return d->name;
+ return d->stream->name();
}
ByteVector File::readBlock(ulong length)
{
- if(!d->file) {
- debug("File::readBlock() -- Invalid File");
- return ByteVector::null;
- }
-
- if(length == 0)
- return ByteVector::null;
-
- if(length > FilePrivate::bufferSize &&
- length > ulong(File::length()))
- {
- length = File::length();
- }
-
- ByteVector v(static_cast<uint>(length));
- const int count = fread(v.data(), sizeof(char), length, d->file);
- v.resize(count);
- return v;
+ return d->stream->readBlock(length);
}
void File::writeBlock(const ByteVector &data)
{
- if(!d->file)
- return;
-
- if(d->readOnly) {
- debug("File::writeBlock() -- attempted to write to a file that is not writable");
- return;
- }
-
- fwrite(data.data(), sizeof(char), data.size(), d->file);
+ d->stream->writeBlock(data);
}
long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &before)
{
- if(!d->file || pattern.size() > d->bufferSize)
+ if(!d->stream || pattern.size() > d->bufferSize)
return -1;
// The position in the file that the current buffer starts at.
@@ -281,7 +218,7 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &before)
{
- if(!d->file || pattern.size() > d->bufferSize)
+ if(!d->stream || pattern.size() > d->bufferSize)
return -1;
// The position in the file that the current buffer starts at.
@@ -349,147 +286,22 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
void File::insert(const ByteVector &data, ulong start, ulong replace)
{
- if(!d->file)
- return;
-
- if(data.size() == replace) {
- seek(start);
- writeBlock(data);
- return;
- }
- else if(data.size() < replace) {
- seek(start);
- writeBlock(data);
- removeBlock(start + data.size(), replace - data.size());
- return;
- }
-
- // Woohoo! Faster (about 20%) than id3lib at last. I had to get hardcore
- // and avoid TagLib's high level API for rendering just copying parts of
- // the file that don't contain tag data.
- //
- // Now I'll explain the steps in this ugliness:
-
- // First, make sure that we're working with a buffer that is longer than
- // the *differnce* in the tag sizes. We want to avoid overwriting parts
- // that aren't yet in memory, so this is necessary.
-
- ulong bufferLength = bufferSize();
-
- while(data.size() - replace > bufferLength)
- bufferLength += bufferSize();
-
- // Set where to start the reading and writing.
-
- long readPosition = start + replace;
- long writePosition = start;
-
- ByteVector buffer;
- ByteVector aboutToOverwrite(static_cast<uint>(bufferLength));
-
- // This is basically a special case of the loop below. Here we're just
- // doing the same steps as below, but since we aren't using the same buffer
- // size -- instead we're using the tag size -- this has to be handled as a
- // special case. We're also using File::writeBlock() just for the tag.
- // That's a bit slower than using char *'s so, we're only doing it here.
-
- seek(readPosition);
- int bytesRead = fread(aboutToOverwrite.data(), sizeof(char), bufferLength, d->file);
- readPosition += bufferLength;
-
- seek(writePosition);
- writeBlock(data);
- writePosition += data.size();
-
- buffer = aboutToOverwrite;
-
- // In case we've already reached the end of file...
-
- buffer.resize(bytesRead);
-
- // Ok, here's the main loop. We want to loop until the read fails, which
- // means that we hit the end of the file.
-
- while(!buffer.isEmpty()) {
-
- // Seek to the current read position and read the data that we're about
- // to overwrite. Appropriately increment the readPosition.
-
- seek(readPosition);
- bytesRead = fread(aboutToOverwrite.data(), sizeof(char), bufferLength, d->file);
- aboutToOverwrite.resize(bytesRead);
- readPosition += bufferLength;
-
- // Check to see if we just read the last block. We need to call clear()
- // if we did so that the last write succeeds.
-
- if(ulong(bytesRead) < bufferLength)
- clear();
-
- // Seek to the write position and write our buffer. Increment the
- // writePosition.
-
- seek(writePosition);
- fwrite(buffer.data(), sizeof(char), buffer.size(), d->file);
- writePosition += buffer.size();
-
- // Make the current buffer the data that we read in the beginning.
-
- buffer = aboutToOverwrite;
-
- // Again, we need this for the last write. We don't want to write garbage
- // at the end of our file, so we need to set the buffer size to the amount
- // that we actually read.
-
- bufferLength = bytesRead;
- }
+ d->stream->insert(data, start, replace);
}
void File::removeBlock(ulong start, ulong length)
{
- if(!d->file)
- return;
-
- ulong bufferLength = bufferSize();
-
- long readPosition = start + length;
- long writePosition = start;
-
- ByteVector buffer(static_cast<uint>(bufferLength));
-
- ulong bytesRead = 1;
-
- while(bytesRead != 0) {
- seek(readPosition);
- bytesRead = fread(buffer.data(), sizeof(char), bufferLength, d->file);
- readPosition += bytesRead;
-
- // Check to see if we just read the last block. We need to call clear()
- // if we did so that the last write succeeds.
-
- if(bytesRead < bufferLength)
- clear();
-
- seek(writePosition);
- fwrite(buffer.data(), sizeof(char), bytesRead, d->file);
- writePosition += bytesRead;
- }
- truncate(writePosition);
+ d->stream->removeBlock(start, length);
}
bool File::readOnly() const
{
- return d->readOnly;
-}
-
-bool File::isReadable(const char *file)
-{
- return access(file, R_OK) == 0;
+ return d->stream->readOnly();
}
bool File::isOpen() const
{
- return (d->file != NULL);
+ return d->stream->isOpen();
}
bool File::isValid() const
@@ -499,53 +311,32 @@ bool File::isValid() const
void File::seek(long offset, Position p)
{
- if(!d->file) {
- debug("File::seek() -- trying to seek in a file that isn't opened.");
- return;
- }
+ d->stream->seek(offset, IOStream::Position(p));
+}
- switch(p) {
- case Beginning:
- fseek(d->file, offset, SEEK_SET);
- break;
- case Current:
- fseek(d->file, offset, SEEK_CUR);
- break;
- case End:
- fseek(d->file, offset, SEEK_END);
- break;
- }
+void File::truncate(long length)
+{
+ d->stream->truncate(length);
}
void File::clear()
{
- clearerr(d->file);
+ d->stream->clear();
}
long File::tell() const
{
- return ftell(d->file);
+ return d->stream->tell();
}
long File::length()
{
- // Do some caching in case we do multiple calls.
-
- if(d->size > 0)
- return d->size;
-
- if(!d->file)
- return 0;
-
- long curpos = tell();
-
- seek(0, End);
- long endpos = tell();
-
- seek(curpos, Beginning);
+ return d->stream->length();
+}
- d->size = endpos;
- return endpos;
+bool File::isReadable(const char *file)
+{
+ return access(file, R_OK) == 0;
}
bool File::isWritable(const char *file)
@@ -557,17 +348,12 @@ bool File::isWritable(const char *file)
// protected members
////////////////////////////////////////////////////////////////////////////////
-void File::setValid(bool valid)
-{
- d->valid = valid;
-}
-
-void File::truncate(long length)
+TagLib::uint File::bufferSize()
{
- ftruncate(fileno(d->file), length);
+ return FilePrivate::bufferSize;
}
-TagLib::uint File::bufferSize()
+void File::setValid(bool valid)
{
- return FilePrivate::bufferSize;
+ d->valid = valid;
}
diff --git a/taglib/toolkit/tfilestream.cpp b/taglib/toolkit/tfilestream.cpp
new file mode 100644
index 00000000..ce2bf11f
--- /dev/null
+++ b/taglib/toolkit/tfilestream.cpp
@@ -0,0 +1,380 @@
+/***************************************************************************
+ copyright : (C) 2002 - 2008 by Scott Wheeler
+ email : wheeler@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * 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 "tfilestream.h"
+#include "tstring.h"
+#include "tdebug.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+# include <wchar.h>
+# include <windows.h>
+# include <io.h>
+# define ftruncate _chsize
+#else
+# include <unistd.h>
+#endif
+
+#include <stdlib.h>
+
+#ifndef R_OK
+# define R_OK 4
+#endif
+#ifndef W_OK
+# define W_OK 2
+#endif
+
+using namespace TagLib;
+
+#ifdef _WIN32
+
+typedef FileName FileNameHandle;
+
+#else
+
+struct FileNameHandle : public std::string
+{
+ FileNameHandle(FileName name) : std::string(name) {}
+ operator FileName () const { return c_str(); }
+};
+
+#endif
+
+class FileStream::FileStreamPrivate
+{
+public:
+ FileStreamPrivate(FileName fileName);
+
+ FILE *file;
+
+ FileNameHandle name;
+
+ bool readOnly;
+ ulong size;
+ static const uint bufferSize = 1024;
+};
+
+FileStream::FileStreamPrivate::FileStreamPrivate(FileName fileName) :
+ file(0),
+ name(fileName),
+ readOnly(true),
+ size(0)
+{
+ // First try with read / write mode, if that fails, fall back to read only.
+
+#ifdef _WIN32
+
+ if(wcslen((const wchar_t *) fileName) > 0) {
+
+ file = _wfopen(name, L"rb+");
+
+ if(file)
+ readOnly = false;
+ else
+ file = _wfopen(name, L"rb");
+
+ if(file)
+ return;
+
+ }
+
+#endif
+
+ file = fopen(name, "rb+");
+
+ if(file)
+ readOnly = false;
+ else
+ file = fopen(name, "rb");
+
+ if(!file)
+ {
+ debug("Could not open file " + String((const char *) name));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// public members
+////////////////////////////////////////////////////////////////////////////////
+
+FileStream::FileStream(FileName file)
+{
+ d = new FileStreamPrivate(file);
+}
+
+FileStream::~FileStream()
+{
+ if(d->file)
+ fclose(d->file);
+ delete d;
+}
+
+FileName FileStream::name() const
+{
+ return d->name;
+}
+
+ByteVector FileStream::readBlock(ulong length)
+{
+ if(!d->file) {
+ debug("FileStream::readBlock() -- Invalid File");
+ return ByteVector::null;
+ }
+
+ if(length == 0)
+ return ByteVector::null;
+
+ if(length > FileStreamPrivate::bufferSize &&
+ length > ulong(FileStream::length()))
+ {
+ length = FileStream::length();
+ }
+
+ ByteVector v(static_cast<uint>(length));
+ const int count = fread(v.data(), sizeof(char), length, d->file);
+ v.resize(count);
+ return v;
+}
+
+void FileStream::writeBlock(const ByteVector &data)
+{
+ if(!d->file)
+ return;
+
+ if(d->readOnly) {
+ debug("File::writeBlock() -- attempted to write to a file that is not writable");
+ return;
+ }
+
+ fwrite(data.data(), sizeof(char), data.size(), d->file);
+}
+
+void FileStream::insert(const ByteVector &data, ulong start, ulong replace)
+{
+ if(!d->file)
+ return;
+
+ if(data.size() == replace) {
+ seek(start);
+ writeBlock(data);
+ return;
+ }
+ else if(data.size() < replace) {
+ seek(start);
+ writeBlock(data);
+ removeBlock(start + data.size(), replace - data.size());
+ return;
+ }
+
+ // Woohoo! Faster (about 20%) than id3lib at last. I had to get hardcore
+ // and avoid TagLib's high level API for rendering just copying parts of
+ // the file that don't contain tag data.
+ //
+ // Now I'll explain the steps in this ugliness:
+
+ // First, make sure that we're working with a buffer that is longer than
+ // the *differnce* in the tag sizes. We want to avoid overwriting parts
+ // that aren't yet in memory, so this is necessary.
+
+ ulong bufferLength = bufferSize();
+
+ while(data.size() - replace > bufferLength)
+ bufferLength += bufferSize();
+
+ // Set where to start the reading and writing.
+
+ long readPosition = start + replace;
+ long writePosition = start;
+
+ ByteVector buffer;
+ ByteVector aboutToOverwrite(static_cast<uint>(bufferLength));
+
+ // This is basically a special case of the loop below. Here we're just
+ // doing the same steps as below, but since we aren't using the same buffer
+ // size -- instead we're using the tag size -- this has to be handled as a
+ // special case. We're also using File::writeBlock() just for the tag.
+ // That's a bit slower than using char *'s so, we're only doing it here.
+
+ seek(readPosition);
+ int bytesRead = fread(aboutToOverwrite.data(), sizeof(char), bufferLength, d->file);
+ readPosition += bufferLength;
+
+ seek(writePosition);
+ writeBlock(data);
+ writePosition += data.size();
+
+ buffer = aboutToOverwrite;
+
+ // In case we've already reached the end of file...
+
+ buffer.resize(bytesRead);
+
+ // Ok, here's the main loop. We want to loop until the read fails, which
+ // means that we hit the end of the file.
+
+ while(!buffer.isEmpty()) {
+
+ // Seek to the current read position and read the data that we're about
+ // to overwrite. Appropriately increment the readPosition.
+
+ seek(readPosition);
+ bytesRead = fread(aboutToOverwrite.data(), sizeof(char), bufferLength, d->file);
+ aboutToOverwrite.resize(bytesRead);
+ readPosition += bufferLength;
+
+ // Check to see if we just read the last block. We need to call clear()
+ // if we did so that the last write succeeds.
+
+ if(ulong(bytesRead) < bufferLength)
+ clear();
+
+ // Seek to the write position and write our buffer. Increment the
+ // writePosition.
+
+ seek(writePosition);
+ fwrite(buffer.data(), sizeof(char), buffer.size(), d->file);
+ writePosition += buffer.size();
+
+ // Make the current buffer the data that we read in the beginning.
+
+ buffer = aboutToOverwrite;
+
+ // Again, we need this for the last write. We don't want to write garbage
+ // at the end of our file, so we need to set the buffer size to the amount
+ // that we actually read.
+
+ bufferLength = bytesRead;
+ }
+}
+
+void FileStream::removeBlock(ulong start, ulong length)
+{
+ if(!d->file)
+ return;
+
+ ulong bufferLength = bufferSize();
+
+ long readPosition = start + length;
+ long writePosition = start;
+
+ ByteVector buffer(static_cast<uint>(bufferLength));
+
+ ulong bytesRead = 1;
+
+ while(bytesRead != 0) {
+ seek(readPosition);
+ bytesRead = fread(buffer.data(), sizeof(char), bufferLength, d->file);
+ readPosition += bytesRead;
+
+ // Check to see if we just read the last block. We need to call clear()
+ // if we did so that the last write succeeds.
+
+ if(bytesRead < bufferLength)
+ clear();
+
+ seek(writePosition);
+ fwrite(buffer.data(), sizeof(char), bytesRead, d->file);
+ writePosition += bytesRead;
+ }
+ truncate(writePosition);
+}
+
+bool FileStream::readOnly() const
+{
+ return d->readOnly;
+}
+
+bool FileStream::isOpen() const
+{
+ return (d->file != NULL);
+}
+
+void FileStream::seek(long offset, Position p)
+{
+ if(!d->file) {
+ debug("File::seek() -- trying to seek in a file that isn't opened.");
+ return;
+ }
+
+ switch(p) {
+ case Beginning:
+ fseek(d->file, offset, SEEK_SET);
+ break;
+ case Current:
+ fseek(d->file, offset, SEEK_CUR);
+ break;
+ case End:
+ fseek(d->file, offset, SEEK_END);
+ break;
+ }
+}
+
+void FileStream::clear()
+{
+ clearerr(d->file);
+}
+
+long FileStream::tell() const
+{
+ return ftell(d->file);
+}
+
+long FileStream::length()
+{
+ // Do some caching in case we do multiple calls.
+
+ if(d->size > 0)
+ return d->size;
+
+ if(!d->file)
+ return 0;
+
+ long curpos = tell();
+
+ seek(0, End);
+ long endpos = tell();
+
+ seek(curpos, Beginning);
+
+ d->size = endpos;
+ return endpos;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// protected members
+////////////////////////////////////////////////////////////////////////////////
+
+void FileStream::truncate(long length)
+{
+ ftruncate(fileno(d->file), length);
+}
+
+TagLib::uint FileStream::bufferSize()
+{
+ return FileStreamPrivate::bufferSize;
+}
diff --git a/taglib/toolkit/tfilestream.h b/taglib/toolkit/tfilestream.h
new file mode 100644
index 00000000..ac17ef06
--- /dev/null
+++ b/taglib/toolkit/tfilestream.h
@@ -0,0 +1,186 @@
+/***************************************************************************
+ copyright : (C) 2002 - 2008 by Scott Wheeler
+ email : wheeler@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * 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/ *
+ ***************************************************************************/
+
+#ifndef TAGLIB_FILESTREAM_H
+#define TAGLIB_FILESTREAM_H
+
+#include "taglib_export.h"
+#include "taglib.h"
+#include "tbytevector.h"
+#include "tiostream.h"
+
+namespace TagLib {
+
+ class String;
+ class Tag;
+ class AudioProperties;
+
+ //! A file class with some useful methods for tag manipulation
+
+ /*!
+ * This class is a basic file class with some methods that are particularly
+ * useful for tag editors. It has methods to take advantage of
+ * ByteVector and a binary search method for finding patterns in a file.
+ */
+
+ class TAGLIB_EXPORT FileStream : public IOStream
+ {
+ public:
+ /*!
+ * Construct a File object and opens the \a file. \a file should be a
+ * be a C-string in the local file system encoding.
+ */
+ FileStream(FileName file);
+
+ /*!
+ * Destroys this FileStream instance.
+ */
+ virtual ~FileStream();
+
+ /*!
+ * Returns the file name in the local file system encoding.
+ */
+ FileName name() const;
+
+ /*!
+ * Reads a block of size \a length at the current get pointer.
+ */
+ ByteVector readBlock(ulong length);
+
+ /*!
+ * Attempts to write the block \a data at the current get pointer. If the
+ * file is currently only opened read only -- i.e. readOnly() returns true --
+ * this attempts to reopen the file in read/write mode.
+ *
+ * \note This should be used instead of using the streaming output operator
+ * for a ByteVector. And even this function is significantly slower than
+ * doing output with a char[].
+ */
+ void writeBlock(const ByteVector &data);
+
+ /*!
+ * Returns the offset in the file that \a pattern occurs at or -1 if it can
+ * not be found. If \a before is set, the search will only continue until the
+ * pattern \a before is found. This is useful for tagging purposes to search
+ * for a tag before the synch frame.
+ *
+ * Searching starts at \a fromOffset, which defaults to the beginning of the
+ * file.
+ *
+ * \note This has the practial limitation that \a pattern can not be longer
+ * than the buffer size used by readBlock(). Currently this is 1024 bytes.
+ */
+ long find(const ByteVector &pattern,
+ long fromOffset = 0,
+ const ByteVector &before = ByteVector::null);
+
+ /*!
+ * Returns the offset in the file that \a pattern occurs at or -1 if it can
+ * not be found. If \a before is set, the search will only continue until the
+ * pattern \a before is found. This is useful for tagging purposes to search
+ * for a tag before the synch frame.
+ *
+ * Searching starts at \a fromOffset and proceeds from the that point to the
+ * beginning of the file and defaults to the end of the file.
+ *
+ * \note This has the practial limitation that \a pattern can not be longer
+ * than the buffer size used by readBlock(). Currently this is 1024 bytes.
+ */
+ long rfind(const ByteVector &pattern,
+ long fromOffset = 0,
+ const ByteVector &before = ByteVector::null);
+
+ /*!
+ * Insert \a data at position \a start in the file overwriting \a replace
+ * bytes of the original content.
+ *
+ * \note This method is slow since it requires rewriting all of the file
+ * after the insertion point.
+ */
+ void insert(const ByteVector &data, ulong start = 0, ulong replace = 0);
+
+ /*!
+ * Removes a block of the file starting a \a start and continuing for
+ * \a length bytes.
+ *
+ * \note This method is slow since it involves rewriting all of the file
+ * after the removed portion.
+ */
+ void removeBlock(ulong start = 0, ulong length = 0);
+
+ /*!
+ * Returns true if the file is read only (or if the file can not be opened).
+ */
+ bool readOnly() const;
+
+ /*!
+ * Since the file can currently only be opened as an argument to the
+ * constructor (sort-of by design), this returns if that open succeeded.
+ */
+ bool isOpen() const;
+
+ /*!
+ * Move the I/O pointer to \a offset in the file from position \a p. This
+ * defaults to seeking from the beginning of the file.
+ *
+ * \see Position
+ */
+ void seek(long offset, Position p = Beginning);
+
+ /*!
+ * Reset the end-of-file and error flags on the file.
+ */
+ void clear();
+
+ /*!
+ * Returns the current offset within the file.
+ */
+ long tell() const;
+
+ /*!
+ * Returns the length of the file.
+ */
+ long length();
+
+ /*!
+ * Truncates the file to a \a length.
+ */
+ void truncate(long length);
+
+ protected:
+
+ /*!
+ * Returns the buffer size that is used for internal buffering.
+ */
+ static uint bufferSize();
+
+ private:
+ class FileStreamPrivate;
+ FileStreamPrivate *d;
+ };
+
+}
+
+#endif
diff --git a/taglib/toolkit/tiostream.cpp b/taglib/toolkit/tiostream.cpp
index 12c4b6fe..f76fe095 100644
--- a/taglib/toolkit/tiostream.cpp
+++ b/taglib/toolkit/tiostream.cpp
@@ -31,7 +31,10 @@ using namespace TagLib;
// public members
////////////////////////////////////////////////////////////////////////////////
+IOStream::IOStream()
+{
+}
+
IOStream::~IOStream()
{
- delete d;
}
diff --git a/taglib/toolkit/tiostream.h b/taglib/toolkit/tiostream.h
index fee02e8f..8d7ba105 100644
--- a/taglib/toolkit/tiostream.h
+++ b/taglib/toolkit/tiostream.h
@@ -65,6 +65,8 @@ namespace TagLib {
End
};
+ IOStream();
+
/*!
* Destroys this IOStream instance.
*/
@@ -121,11 +123,6 @@ namespace TagLib {
virtual bool isOpen() const = 0;
/*!
- * Returns true if the file is open and readble.
- */
- virtual bool isValid() const = 0;
-
- /*!
* Move the I/O pointer to \a offset in the stream from position \a p. This
* defaults to seeking from the beginning of the stream.
*
@@ -148,6 +145,11 @@ namespace TagLib {
*/
virtual long length() = 0;
+ /*!
+ * Truncates the stream to a \a length.
+ */
+ virtual void truncate(long length) = 0;
+
private:
IOStream(const IOStream &);
IOStream &operator=(const IOStream &);