diff options
Diffstat (limited to 'src/fileringbuffer.cpp')
-rw-r--r-- | src/fileringbuffer.cpp | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/src/fileringbuffer.cpp b/src/fileringbuffer.cpp new file mode 100644 index 0000000..5cca0c7 --- /dev/null +++ b/src/fileringbuffer.cpp @@ -0,0 +1,252 @@ +/*************************************************************************** + ringbuffer.cpp - description + ------------------- + begin : Sun March 21 2004 + copyright : (C) 2004 by Martin Witte + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "include/fileringbuffer.h" + +#include <tqstring.h> +#include <unistd.h> +#include <tdelocale.h> + +FileRingBuffer::FileRingBuffer(const TQString &filename, TQ_UINT64 max_size) +{ + m_BaseFileName = filename; + m_FileIdx = 0; + m_FileName = m_BaseFileName + "_" + TQString::number(++m_FileIdx); + m_File = fopen(m_FileName.ascii(), "w+"); + m_MaxSize = max_size; + m_RealSize = 0; + m_FillSize = 0; + m_Start = 0; + m_error = m_File == NULL; + m_errorString = m_File ? TQString() : i18n("cannot open buffer file %1").arg(filename); +} + + +FileRingBuffer::~FileRingBuffer() +{ + if (m_File) { + fclose (m_File); + unlink (m_FileName.ascii()); + } + m_File = NULL; + m_FileName = TQString(); + m_MaxSize = 0; + m_RealSize = 0; + m_FillSize = 0; + m_Start = 0; + m_error = false; + m_errorString = TQString(); +} + + +bool FileRingBuffer::resize(const TQString &filename, TQ_UINT64 new_max_size) +{ + if (filename != m_BaseFileName) { + clear(); + if (m_File) { + fclose (m_File); + unlink (m_FileName.ascii()); + } + m_BaseFileName = filename; + m_FileName = m_BaseFileName + "_" + TQString::number(++m_FileIdx); + m_File = fopen(m_FileName.ascii(), "w+"); + m_error = m_File == NULL; + m_errorString = m_File ? TQString() : i18n("cannot open buffer file %1").arg(filename); + } + + if (new_max_size >= m_RealSize) { + m_MaxSize = new_max_size; + } + else if (m_Start + m_FillSize < m_RealSize && new_max_size > m_Start + m_FillSize) { + ftruncate(fileno(m_File), new_max_size); + m_MaxSize = new_max_size; + } + else if (new_max_size >= m_FillSize) { + const size_t buffer_size = 65536; + char buffer[buffer_size]; + + TQString tmp_file_name = m_BaseFileName + "_" + TQString::number(++m_FileIdx); + FILE *tmp_file = fopen (tmp_file_name.ascii(), "w+"); + TQ_UINT64 newFill = 0; + if (tmp_file) { + while (!m_error && m_FillSize > 0) { + int tmp_size = takeData(buffer, buffer_size); + if (tmp_size > 0) { + if (fwrite (buffer, tmp_size, 1, tmp_file) > 0) { + newFill += tmp_size; + } else { + m_error = true; + m_errorString += i18n("FileRingbuffer::resize: Writing to tmpfile %1 failed. ").arg(tmp_file_name); + } + } + } + } else { + m_error = true; + m_errorString += i18n("FileRingbuffer::resize: Opening tmpfile %1 failed. ").arg(tmp_file_name); + } + + if (!m_error) { + fclose (m_File); + m_FileName = tmp_file_name; + m_File = tmp_file; + m_FillSize = newFill; + m_Start = 0; + m_MaxSize = new_max_size; + m_RealSize = newFill; + } + return true; + } + return false; +} + + +size_t FileRingBuffer::addData (const char *src, size_t size) +{ + size_t written = 0; + if (m_Start + m_FillSize <= m_RealSize) { + TQ_UINT64 rest = m_MaxSize - (m_Start + m_FillSize); + if (rest > size) + rest = size; + fseek(m_File, m_Start + m_FillSize, SEEK_SET); + if (rest > 0 && fwrite(src, rest, 1, m_File) <= 0) { + m_error = true; + m_errorString += i18n("FileRingBuffer::addData: failed writing data to file %1.").arg(m_FileName); + } else { + m_FillSize += rest; + if (m_Start + m_FillSize > m_RealSize) + m_RealSize = m_Start + m_FillSize; + written += rest; + size -= rest; + src += rest; + } + } + if (!m_error && size > 0 && m_FillSize < m_RealSize) { + size_t rest = size; + if (rest > m_RealSize - m_FillSize) + rest = m_RealSize - m_FillSize; + + fseek(m_File, m_Start + m_FillSize - m_RealSize, SEEK_SET); + if (fwrite(src, rest, 1, m_File) <= 0) { + m_error = true; + m_errorString += i18n("FileRingBuffer::addData: failed writing data to file %1.").arg(m_FileName); + } else { + m_FillSize += rest; + written += rest; + //fflush(m_File); // debug only + } + } + return written; +} + + +size_t FileRingBuffer::takeData(char *dst, size_t size) +{ + size_t read = 0; + while (!m_error && m_FillSize > 0 && size > 0) { + size_t n = size; + if (n > m_FillSize) + n = m_FillSize; + if (n > m_RealSize - m_Start) + n = m_RealSize - m_Start; + fseek(m_File, m_Start, SEEK_SET); + if (fread(dst+read, n, 1, m_File) <= 0) { + m_error = true; + m_errorString += i18n("FileRingBuffer::takeData: failed reading data to file %1.").arg(m_FileName); + } else { + m_FillSize -= n; + m_Start += n; + read += n; + size -= n; + if (m_Start >= m_RealSize) + m_Start -= m_RealSize; + } + + } + return read; +} + + +TQ_UINT64 FileRingBuffer::getFreeSpace(TQ_UINT64 &size) +{ + if (m_FillSize == m_RealSize) { + size = 0; + return 0; + } + + if (m_Start + m_FillSize >= m_RealSize) { + size = m_RealSize - m_FillSize; + return m_Start + m_FillSize - m_RealSize; + } else { + size = m_MaxSize - m_Start - m_FillSize; + return m_Start + m_FillSize; + } +} + + +TQ_UINT64 FileRingBuffer::removeFreeSpace(TQ_UINT64 size) +{ + if (m_FillSize == m_RealSize) + return 0; + + if (m_Start + m_FillSize >= m_RealSize) { + if (size > m_RealSize - m_FillSize) + size = m_RealSize - m_FillSize; + m_FillSize += size; + return size; + } else { + if (m_Start + m_FillSize + size >= m_MaxSize) + size = m_MaxSize - m_Start - m_FillSize; + m_FillSize += size; + return size; + } +} + + +TQ_UINT64 FileRingBuffer::getData(TQ_UINT64 &size) +{ + if (m_Start + m_FillSize >= m_RealSize) { + size = m_RealSize - m_Start; + } else { + size = m_FillSize; + } + return m_Start; +} + + +TQ_UINT64 FileRingBuffer::removeData(TQ_UINT64 size) +{ + if (size > m_FillSize) + size = m_FillSize; + if (m_Start + size >= m_RealSize) { + m_Start = m_Start + size - m_RealSize; + } else { + m_Start += size; + } + m_FillSize -= size; + return size; +} + + +void FileRingBuffer::clear() +{ + if (!m_error) { + ftruncate(fileno(m_File), 0); + m_Start = 0; + m_FillSize = 0; + m_RealSize = 0; + } +} |