diff options
Diffstat (limited to 'src/core/utils')
-rw-r--r-- | src/core/utils/CharReader.cpp | 93 | ||||
-rw-r--r-- | src/core/utils/CharReader.hpp | 37 |
2 files changed, 111 insertions, 19 deletions
diff --git a/src/core/utils/CharReader.cpp b/src/core/utils/CharReader.cpp index 33eab45..bf25a01 100644 --- a/src/core/utils/CharReader.cpp +++ b/src/core/utils/CharReader.cpp @@ -16,8 +16,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <iostream> - #include <algorithm> #include <limits> @@ -204,16 +202,101 @@ void Buffer::deleteCursor(Buffer::CursorId cursor) size_t Buffer::offset(Buffer::CursorId cursor) const { - const Cursor &c = cursors[cursor]; - size_t offs = startOffset + c.bucketOffs; + const Cursor &cur = cursors[cursor]; + size_t offs = startOffset + cur.bucketOffs; BucketList::const_iterator it = startBucket; - while (it != c.bucket) { + while (it != cur.bucket) { offs += it->size(); advance(it); } return offs; } +size_t Buffer::moveForward(CursorId cursor, size_t relativeOffs) +{ + size_t offs = relativeOffs; + Cursor &cur = cursors[cursor]; + while (offs > 0) { + // Fetch the current bucket of the cursor + Bucket &bucket = *(cur.bucket); + + // If there is enough space in the bucket, simply increment the bucket + // offset by the given relative offset + const size_t space = bucket.size() - cur.bucketOffs; + if (space >= offs) { + cur.bucketOffs += offs; + break; + } else { + // Go to the end of the current bucket otherwise + offs -= space; + cur.bucketOffs = bucket.size(); + + // Go to the next bucket + if (cur.bucket != endBucket) { + // Go to the next bucket + advance(cur.bucket); + cur.bucketIdx++; + cur.bucketOffs = 0; + } else { + // Abort, if there is no more data to stream, otherwise just + // load new data + if (reachedEnd) { + return relativeOffs - offs; + } + stream(); + } + } + } + return relativeOffs; +} + +size_t Buffer::moveBackward(CursorId cursor, size_t relativeOffs) +{ + size_t offs = relativeOffs; + Cursor &cur = cursors[cursor]; + while (offs > 0) { + // If there is enough space in the bucket, simply decrement the bucket + // offset by the given relative offset + if (cur.bucketOffs >= offs) { + cur.bucketOffs -= offs; + break; + } else { + // Go to the beginning of the current bucket otherwise + offs -= cur.bucketOffs; + cur.bucketOffs = 0; + + // Abort if there is no more bucket to got back to + if (cur.bucketIdx == 0) { + return relativeOffs - offs; + } + + // Go to the previous bucket (wrap around at the beginning of the + // list) + if (cur.bucket == buckets.begin()) { + cur.bucket = buckets.end(); + } + cur.bucket--; + + // Decrement the bucket index, and set the current offset to the + // end of the new bucket + cur.bucketIdx--; + cur.bucketOffs = cur.bucket->size(); + } + } + return relativeOffs; +} + +ssize_t Buffer::moveCursor(CursorId cursor, ssize_t relativeOffs) +{ + if (relativeOffs > 0) { + return moveForward(cursor, relativeOffs); + } else if (relativeOffs < 0) { + return -moveBackward(cursor, -relativeOffs); + } else { + return 0; + } +} + bool Buffer::atEnd(Buffer::CursorId cursor) const { const Cursor &c = cursors[cursor]; diff --git a/src/core/utils/CharReader.hpp b/src/core/utils/CharReader.hpp index 23e88b7..8d97d39 100644 --- a/src/core/utils/CharReader.hpp +++ b/src/core/utils/CharReader.hpp @@ -195,6 +195,16 @@ private: */ void stream(); + /** + * Moves the given cursor forward. + */ + size_t moveForward(CursorId cursor, size_t relativeOffs); + + /** + * Moves the given cursor backward. + */ + size_t moveBackward(CursorId cursor, size_t relativeOffs); + public: /** * Intializes the Buffer with a reference to a ReadCallback that is used @@ -255,6 +265,19 @@ public: void deleteCursor(CursorId cursor); /** + * Moves a cursor by offs bytes. Note that moving backwards is theoretically + * limited by the LOOKBACK_SIZE of the Buffer, practically it will most likely + * be limited by the REQUEST_SIZE, so you can got at most 64 KiB backwards. + * + * @param cursor is the cursor that should be moved. + * @param relativeOffs is a positive or negative integer number specifying + * the number of bytes the cursor should be moved forward (positive numbers) + * or backwards (negative numbers). + * @return the actual number of bytes the cursor was moved. + */ + ssize_t moveCursor(CursorId cursor, ssize_t relativeOffs); + + /** * Returns the current byte offset of the given cursor relative to the * beginning of the stream. * @@ -286,20 +309,6 @@ public: * been reached. */ bool read(CursorId cursor, char &c); - -// /** -// * Reads string from the ring buffer from the given cursor. -// * -// * @param cursor specifies the cursor from which the data should be read. -// * The cursor will be advanced by the specified number of bytes (or to the -// * end of the stream). -// * @param res is the vector into which the data should be read. Any already -// * present data will be overridden. -// * @param len is number of bytes that should be read from the buffer. -// * @return true if len bytes were read, false if less the len bytes have -// * been read because the end of the stream has been reached. -// */ -// bool read(CursorId cursor, std::vector<char> &res, size_t len); }; } |