| line# | code(run#) |
|---|---|
| 1 | #ifndef NO_MEMTRACE |
| 2 | #include "memtrace.h" |
| 3 | #endif |
| 4 | |
| 5 | #include "myString.h" |
| 6 | |
| 7 | String::DataCache::DataCache(String &s) : string(s), dataBlock(s.startBlock) {}(305) |
| 8 | |
| 9 | String::DataCache::DataCache(const DataCache &c) = default; |
| 10 | |
| 11 | char &String::DataCache::getChar(size_t idx)(803) |
| 12 | { |
| 13 | if (idx >= string.size) // throw error if index is out of range(803) |
| 14 | throw std::out_of_range("indexing error");(28) |
| 15 | |
| 16 | size_t dbi = idx / 20; // index off the DataBlock of the requested character(775) |
| 17 | size_t lastDataBlcokIndex = string.size / 20; // index of the last DataBlock (based on size of string)(775) |
| 18 | unsigned char offset = idx % 20; // offset of character inside of string(775) |
| 19 | if (dbi == dataBlockIndex) // if the requested character is in the ceched block(775) |
| 20 | return dataBlock->data[offset]; // return character from the cache block(536) |
| 21 | if (dbi == 0) // is the requested character is in the first blokc(239) |
| 22 | return string.startBlock->data[offset]; // return character from the first block(87) |
| 23 | if (dbi == lastDataBlcokIndex) // if the requested character is in the last block(152) |
| 24 | return string.endBlock->data[offset]; // return it from the last block(126) |
| 25 | |
| 26 | // At this point we have to move in the linked list to find the desired character |
| 27 | // So here are the distances we have to move |
| 28 | size_t distStart = dbi; // steps from the first block(26) |
| 29 | size_t distCache = dbi > dataBlockIndex ? dbi - dataBlockIndex : dataBlockIndex - dbi; // steps from the cached block(26) |
| 30 | // ^^has to check which side of the cached block the requested blokc is on |
| 31 | size_t distEnd = lastDataBlcokIndex - dbi; // distance from the end(26) |
| 32 | |
| 33 | if (dbi < dataBlockIndex) // requested block is before the cached block(26) |
| 34 | { |
| 35 | if (distStart <= distCache) // requested blokc is closer (or the same distance) to the start block(6) |
| 36 | { |
| 37 | dataBlockIndex = 0; // move from the start block until the indexes match(5) |
| 38 | dataBlock = string.startBlock;(5) |
| 39 | while (dataBlockIndex != dbi)(10) |
| 40 | { |
| 41 | dataBlock = dataBlock->next;(5) |
| 42 | dataBlockIndex++;(5) |
| 43 | } |
| 44 | } |
| 45 | else // requested block is closer to the cached block |
| 46 | { |
| 47 | while (dataBlockIndex != dbi) // move from the cached block until indexes match(3) |
| 48 | { |
| 49 | dataBlock = dataBlock->prev;(2) |
| 50 | dataBlockIndex--;(2) |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | else // requested block is after the cached block (cannot be the same because we've checked that) |
| 55 | { |
| 56 | if (distEnd <= distCache) // requested block is closer (or the same distance) to the end blcok(20) |
| 57 | { |
| 58 | dataBlockIndex = lastDataBlcokIndex; // move from the end block until indexes match(13) |
| 59 | dataBlock = string.endBlock;(13) |
| 60 | while (dataBlockIndex != dbi)(27) |
| 61 | { |
| 62 | dataBlock = dataBlock->prev;(14) |
| 63 | dataBlockIndex--;(14) |
| 64 | } |
| 65 | } |
| 66 | else // requested block is closer to the cached block |
| 67 | { |
| 68 | while (dataBlockIndex != dbi) // move from the cached block until indexes match(14) |
| 69 | { |
| 70 | dataBlock = dataBlock->next;(7) |
| 71 | dataBlockIndex++;(7) |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | return dataBlock->data[offset]; // return requested character (cached block contains correct data)(26) |
| 77 | } |
| 78 | |
| 79 | void String::DataCache::reset()(244) |
| 80 | { |
| 81 | dataBlockIndex = 0;(244) |
| 82 | dataBlock = string.startBlock;(244) |
| 83 | }(244) |
| 84 | |
| 85 | String::DataCache::~DataCache() = default; |