File indexing completed on 2024-04-14 05:45:45

0001 /*
0002     This file is part of the Okteta Core library, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2003, 2007, 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "filebytearraymodel_p.hpp"
0010 
0011 // Std
0012 #include <cstdlib>
0013 
0014 namespace Okteta {
0015 
0016 FileByteArrayModelPrivate::FileByteArrayModelPrivate(FileByteArrayModel* parent, int pageNumber, int pageSize)
0017     : AbstractByteArrayModelPrivate(parent)
0018     , mNoOfUsedPages(pageNumber)
0019     , mNoOfFreePages(pageNumber)
0020     , mPageSize(pageSize)
0021 {
0022     mIsOpen = false;
0023 
0024 //   if( !filename.empty() )
0025 //     open(filename);
0026 }
0027 
0028 FileByteArrayModelPrivate::~FileByteArrayModelPrivate()
0029 {
0030     if (mFile.isOpen()) {
0031         close();
0032     }
0033 }
0034 
0035 Byte FileByteArrayModelPrivate::byte(Address offset) const
0036 {
0037 //   std::cout << "reading datum " << offset << std::endl;
0038     int offsetInPage = offset - mOffsetOfActualPage;
0039     // there shouldn't be any need to check l
0040     if (offsetInPage >= 0 && offsetInPage < (int)mPageSize) {
0041         return mActualPage[offsetInPage];
0042     }
0043 
0044     // load the page
0045     unsigned int pageIndex = offset / mPageSize;
0046     ensurePageLoaded(pageIndex);
0047 
0048     return mActualPage[offset - mOffsetOfActualPage];
0049 }
0050 
0051 bool FileByteArrayModelPrivate::open(const QString& fileName)
0052 {
0053     // clear old data
0054     if (isOpen() && !close()) { // only occurs if close somehow fails.
0055         return false;
0056     }
0057 
0058     mFile.setFileName(fileName);
0059     if (!mFile.open(QIODevice::ReadOnly)) {
0060         return false;
0061     }
0062 
0063     int fileSize = mFile.size();
0064     mSize = fileSize;
0065 
0066     // calculate necessary number of pages
0067     int noOfPages = fileSize / mPageSize + 1;
0068 
0069     // initialize Page pointers
0070     mData.fill(nullptr, noOfPages);
0071 
0072     mFirstPage = mLastPage = 0;
0073 
0074     return ensurePageLoaded(0);
0075 }
0076 
0077 bool FileByteArrayModelPrivate::close()
0078 {
0079     if (!isOpen()) {
0080         return false;
0081     }
0082 
0083     mFile.close();
0084 
0085     if (mFile.error() != QFile::NoError) {
0086         return false;
0087     }
0088 
0089     // free pages
0090     std::for_each(mData.begin(), mData.end(), [](char*& pageData) {
0091         delete [] pageData;
0092         pageData = nullptr;
0093     });
0094 
0095     mFirstPage = mLastPage = -1;
0096     mNoOfFreePages = mNoOfUsedPages;
0097 
0098     return true;
0099 }
0100 
0101 bool FileByteArrayModelPrivate::ensurePageLoaded(unsigned int pageIndex) const
0102 {
0103     if (!isOpen()) {
0104         return false;
0105     }
0106     // page loaded?
0107     if (mData[pageIndex]) {
0108         mActualPage = mData[pageIndex];
0109         mOffsetOfActualPage = pageIndex * mPageSize;
0110         return true;
0111     }
0112 
0113     // no page available?
0114     if (mNoOfFreePages < 1) {
0115         // free the page which is the furthest away from the page we are loading
0116         if (std::abs(mFirstPage - (long)pageIndex) > std::abs(mLastPage - (long)pageIndex)) {
0117             while (!freePage(mFirstPage++)) {
0118                 ;
0119             }
0120         } else {
0121             while (!freePage(mLastPage--)) {
0122                 ;
0123             }
0124         }
0125     }
0126 
0127     // create Page
0128     mData[pageIndex] = new char[mPageSize];
0129     --mNoOfFreePages;
0130 
0131     // jump to position and read the page's data in
0132     bool success = mFile.seek((unsigned long)(pageIndex * mPageSize));
0133     if (success) {
0134         success = mFile.read(mData[pageIndex], mPageSize) > 0;
0135     }
0136 
0137     if (success) {
0138         // correct bounds
0139         if ((int)pageIndex < mFirstPage) {
0140             mFirstPage = pageIndex;
0141         }
0142 
0143         if ((int)pageIndex > mLastPage) {
0144             mLastPage = pageIndex;
0145         }
0146 
0147         mActualPage = mData[pageIndex];
0148         mOffsetOfActualPage = pageIndex * mPageSize;
0149     }
0150 
0151     return success;
0152 }
0153 
0154 bool FileByteArrayModelPrivate::freePage(unsigned int pageIndex) const
0155 {
0156     // check range and if is loaded at all
0157     if ((int)pageIndex >= mData.size() || !mData[pageIndex]) {
0158         return false;
0159     }
0160 
0161     delete [] mData[pageIndex];
0162     mData[pageIndex] = nullptr;
0163     ++mNoOfFreePages;
0164     return true;
0165 }
0166 
0167 }