#pragma once //----------------------------------------------------------------------------- // массив, размер которого можно динамически увеличивать, // добавление элементов происходит дискретно, блоками указанной длины //----------------------------------------------------------------------------- #include "JDefines.h" #include "JTerminal.h" #include "JSys.h" namespace Incart::Common { template //!!! это нам мешает class ArrayOfBlocks { static const bool MYDEBUG = false; struct BlockData { BlockData* continuation = nullptr; // указатель на следующий блок T data[BLOCK_SIZE]; // физический блок данных }; bool m_rdy; protected: int m_BlockNumber; // адрес блока int m_Position; // адрес внутри блока int m_MaxPos; // адрес BlockData* m_Head; // адрес начала списка блоков BlockData* m_Tail; // адрес начала списка блоков BlockData** m_Cache; // массив с линейнойй адресацией блоков int m_MemoryUsed; public: ArrayOfBlocks() : m_rdy(false),m_Cache(nullptr) { m_Head = m_Tail = nullptr; //m_Head = m_Tail = new BlockData(); JT() << __PRETTY_FUNCTION__; //<< "create block :" << 0 << m_Tail; // m_BlockNumber = 1; // адрес блока // m_Position = 0; // адрес внутри блока // m_MaxPos = 0; // // m_MemoryUsed = sizeof(BlockData); } ~ArrayOfBlocks() { JT() << __PRETTY_FUNCTION__; clear(); } void clear() { JT() << __PRETTY_FUNCTION__; // очистка выделенной памяти if(m_Head !=nullptr) { BlockData* pointer = m_Head; for (int i = 0; i < m_BlockNumber; i++) { BlockData* last_block = pointer->continuation; JT() << __PRETTY_FUNCTION__ << "delete block :" << i << pointer; // << last_block; delete pointer; pointer = last_block; } } if (m_Cache != nullptr) delete[] m_Cache; m_Cache = nullptr; // создание нового блока данных m_Head = m_Tail = new BlockData(); JT() << __FUNCTION__ << "create block :" << 0 << m_Tail; m_BlockNumber = 1; // адрес блока m_Position = 0; // адрес внутри блока m_MaxPos = 0; // m_MemoryUsed = sizeof(BlockData); m_rdy = false; // } void add(T obj) { if(m_rdy) { JTerminal(JCL_RED) << __FUNCTION__ << "data is cached"; JSys::abort(); } m_Tail->data[m_Position] = obj; m_Position++; m_MaxPos++; if (m_Position >= BLOCK_SIZE) { addBlock(); } } void addBlock() { BlockData* blk = new BlockData(); m_Tail->continuation = blk; m_Tail = blk; JT() << __FUNCTION__ << "create block :" << m_BlockNumber << m_Tail; m_BlockNumber++; m_Position = 0; m_MemoryUsed += sizeof(BlockData); } void caching() { m_Cache = new BlockData*[m_BlockNumber]; BlockData* pointer = m_Head; for (int i = 0; i < m_BlockNumber; i++) { BlockData* last_block = pointer->continuation; JT() << __PRETTY_FUNCTION__ << "the block is cached :" << i << pointer; // << last_block; m_Cache[i] = pointer; pointer = last_block; } m_rdy = true; // разрешение использования данных } T at(int pos) { if(!m_rdy) { JTerminal(JCL_RED) << __PRETTY_FUNCTION__ << "data is not cached"; JSys::abort(); } if(pos >= getMaxPos() ) { JTerminal(JCL_RED) << __PRETTY_FUNCTION__ << "position greater than the maximum possible" << pos << getMaxPos() ; JSys::abort(); } int BlockNumber = pos / BLOCK_SIZE; // адрес блока int Position = pos % BLOCK_SIZE; // адрес внутри блока return m_Cache[BlockNumber]->data[Position]; } //---------- int getMemoryUsed() { return m_MemoryUsed; } // int getBlockNumber() { return m_BlockNumber; } // адрес блока int getPosition() { return m_Position; } // адрес внутри блока int getMaxPos() { return m_MaxPos; } // //------------------------------------------------------------------------- void file_writer(QString fname) { QFile file(fname); if ( file.open(QIODevice::WriteOnly)) { // запись всех блоков BlockData* pointer = m_Head; for (int i = 1; i < m_BlockNumber; i++) { int len = sizeof(BlockData::data); qint64 flen = file.write(reinterpret_cast(pointer->data),len); if(flen != len) { JTerminal(JCL_RED) << __PRETTY_FUNCTION__ << "file write error" << fname; JSys::abort(); } // переход на следующий блок BlockData* last_block = pointer->continuation; JT() << __PRETTY_FUNCTION__ << "the block is cached :" << i << pointer; pointer = last_block; } int len = m_Position * static_cast(sizeof(T)); qint64 flen = file.write(reinterpret_cast(pointer->data),len); if(flen != len) { JTerminal(JCL_RED) << __PRETTY_FUNCTION__ << "file write error" << fname; JSys::abort(); } file.close(); } else { JTerminal(JCL_RED) << __PRETTY_FUNCTION__ << "file not found" << fname; } } void file_reader(QString fname) { QFile file(fname); if ( file.open(QIODevice::ReadOnly)) { clear(); while(true) { BlockData* pointer = m_Tail; int len = sizeof(BlockData::data); qint64 flen = file.read(reinterpret_cast(pointer->data),len); if(flen != len) { m_Position = static_cast(flen) / static_cast(sizeof(T)); break; } addBlock(); } file.close(); } else { JTerminal(JCL_RED) << __PRETTY_FUNCTION__ << "file not found" << fname; } } }; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- class ArrayOfBlocksTest { public: ArrayOfBlocks m_Array; void test1() { m_Array.clear(); test(); m_Array.clear(); test(); m_Array.clear(); test(); m_Array.file_writer("test.bin"); JTerminal(JCL_GREEN) << __PRETTY_FUNCTION__ << "Ok" << m_Array.getMemoryUsed() << m_Array.getBlockNumber() << m_Array.getPosition(); } void test2() { m_Array.file_reader("test.bin"); m_Array.caching(); check(); JTerminal(JCL_GREEN) << __PRETTY_FUNCTION__ << "Ok" << m_Array.getMemoryUsed() << m_Array.getBlockNumber() << m_Array.getPosition(); } void filling() { for (int i = 0; i < 100; i++) { m_Array.add(i); } } void check() { for (int i = 0; i < 100; i++) { if(m_Array.at(i) != i) { JTerminal(JCL_RED) << __PRETTY_FUNCTION__ << "read array error" << m_Array.at(i) << i; return; } } } void test() { filling(); m_Array.caching(); check(); } }; } //namespace Incart::Common