You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tderadio/src/fileringbuffer.cpp

253 lines
7.5 KiB

/***************************************************************************
ringbuffer.cpp - description
-------------------
begin : Sun March 21 2004
copyright : (C) 2004 by Martin Witte
email : witte@kawo1.rwth-aachen.de
***************************************************************************/
/***************************************************************************
* *
* 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;
}
}