File indexing completed on 2024-04-28 13:45:44
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 }