X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/8ef240801bf66e543cdea9df3b32fc09cebcc7e5..a3b666437785e7b6b97fa9de31e82867cea407ea:/lib/base/rawfile.cpp diff --git a/lib/base/rawfile.cpp b/lib/base/rawfile.cpp index f5fb91ee..e444ba90 100644 --- a/lib/base/rawfile.cpp +++ b/lib/base/rawfile.cpp @@ -6,10 +6,12 @@ eRawFile::eRawFile() { m_fd = -1; + m_file = 0; m_splitsize = 0; m_totallength = 0; m_current_offset = 0; m_base_offset = 0; + m_last_offset = 0; m_nrfiles = 0; m_current_file = 0; } @@ -19,28 +21,49 @@ eRawFile::~eRawFile() close(); } -int eRawFile::open(const char *filename) +int eRawFile::open(const char *filename, int cached) { close(); + m_cached = cached; m_basename = filename; scan(); m_current_offset = 0; - m_fd = ::open(filename, O_RDONLY | O_LARGEFILE); - return m_fd; + m_last_offset = 0; + if (!m_cached) + { + m_fd = ::open(filename, O_RDONLY | O_LARGEFILE); + return m_fd; + } else + { + m_file = ::fopen64(filename, "rb"); + if (!m_file) + return -1; + return 0; + } } void eRawFile::setfd(int fd) { close(); + m_cached = 0; m_nrfiles = 1; m_fd = fd; } off_t eRawFile::lseek(off_t offset, int whence) { +// eDebug("lseek: %lld, %d", offset, whence); /* if there is only one file, use the native lseek - the file could be growing! */ - if (!m_nrfiles) - return ::lseek(m_fd, offset, whence); + if (m_nrfiles < 2) + { + if (!m_cached) + return ::lseek(m_fd, offset, whence); + else + { + ::fseeko(m_file, offset, whence); + return ::ftello(m_file); + } + } switch (whence) { case SEEK_SET: @@ -53,6 +76,7 @@ off_t eRawFile::lseek(off_t offset, int whence) m_current_offset = m_totallength + offset; break; } + if (m_current_offset < 0) m_current_offset = 0; return m_current_offset; @@ -60,23 +84,52 @@ off_t eRawFile::lseek(off_t offset, int whence) int eRawFile::close() { - int ret = ::close(m_fd); - m_fd = -1; - return ret; + if (m_cached) + { + if (!m_file) + return -1; + ::fclose(m_file); + m_file = 0; + return 0; + } else + { + int ret = ::close(m_fd); + m_fd = -1; + return ret; + } } ssize_t eRawFile::read(void *buf, size_t count) { +// eDebug("read: %p, %d", buf, count); switchOffset(m_current_offset); - int ret = ::read(m_fd, buf, count); + + if (m_nrfiles >= 2) + { + if (m_current_offset + count > m_totallength) + count = m_totallength - m_current_offset; + if (count < 0) + return 0; + } + + int ret; + + if (!m_cached) + ret = ::read(m_fd, buf, count); + else + ret = ::fread(buf, 1, count, m_file); + if (ret > 0) - m_current_offset += ret; + m_current_offset = m_last_offset += ret; return ret; } int eRawFile::valid() { - return m_fd != -1; + if (!m_cached) + return m_fd != -1; + else + return !!m_file; } void eRawFile::scan() @@ -85,17 +138,30 @@ void eRawFile::scan() m_totallength = 0; while (m_nrfiles < 1000) /* .999 is the last possible */ { - int f = openFile(m_nrfiles); - if (f < 0) - break; - if (!m_nrfiles) - m_splitsize = ::lseek(f, 0, SEEK_END); - m_totallength += ::lseek(f, 0, SEEK_END); - ::close(f); + if (!m_cached) + { + int f = openFileUncached(m_nrfiles); + if (f < 0) + break; + if (!m_nrfiles) + m_splitsize = ::lseek(f, 0, SEEK_END); + m_totallength += ::lseek(f, 0, SEEK_END); + ::close(f); + } else + { + FILE *f = openFileCached(m_nrfiles); + if (!f) + break; + ::fseeko(f, 0, SEEK_END); + if (!m_nrfiles) + m_splitsize = ::ftello(f); + m_totallength += ::ftello(f); + ::fclose(f); + } ++m_nrfiles; } - eDebug("found %d files, splitsize: %llx, totallength: %llx", m_nrfiles, m_splitsize, m_totallength); +// eDebug("found %d files, splitsize: %llx, totallength: %llx", m_nrfiles, m_splitsize, m_totallength); } int eRawFile::switchOffset(off_t off) @@ -105,28 +171,58 @@ int eRawFile::switchOffset(off_t off) int filenr = off / m_splitsize; if (filenr >= m_nrfiles) filenr = m_nrfiles - 1; - if (filenr != m_current_file) - { + { +// eDebug("-> %d", filenr); close(); - setfd(openFile(filenr)); - m_base_offset = m_splitsize * filenr; - eDebug("switched to file %d", filenr); + if (!m_cached) + m_fd = openFileUncached(filenr); + else + m_file = openFileCached(filenr); + m_last_offset = m_base_offset = m_splitsize * filenr; + m_current_file = filenr; } } else m_base_offset = 0; - return ::lseek(m_fd, off - m_base_offset, SEEK_SET) + m_base_offset; + if (off != m_last_offset) + { + if (!m_cached) + m_last_offset = ::lseek(m_fd, off - m_base_offset, SEEK_SET) + m_base_offset; + else + { + ::fseeko(m_file, off - m_base_offset, SEEK_SET); + m_last_offset = ::ftello(m_file) + m_base_offset; + } + return m_last_offset; + } else + { + return m_last_offset; + } +} + +/* m_cached */ +FILE *eRawFile::openFileCached(int nr) +{ + std::string filename = m_basename; + if (nr) + { + char suffix[5]; + snprintf(suffix, 5, ".%03d", nr); + filename += suffix; + } + return ::fopen64(filename.c_str(), "rb"); } -int eRawFile::openFile(int nr) +/* !m_cached */ +int eRawFile::openFileUncached(int nr) { std::string filename = m_basename; - if (m_nrfiles) + if (nr) { char suffix[5]; snprintf(suffix, 5, ".%03d", nr); filename += suffix; } - return ::open(filename.c_str(), O_RDONLY); + return ::open(filename.c_str(), O_RDONLY | O_LARGEFILE); }