summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2014-12-08 17:07:34 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2014-12-08 17:07:34 +0100
commite90a7ced80c6a7dbcdc75bf60c65bcc23f727ca2 (patch)
treee0da8daf8af0fc45ced075a2b55126b0b24b4fec /src/core
parente7f97a4c8da44a696bb7e71b9dd54e8d271e24d0 (diff)
implemented and tested moveCursor function
Diffstat (limited to 'src/core')
-rw-r--r--src/core/utils/CharReader.cpp93
-rw-r--r--src/core/utils/CharReader.hpp37
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);
};
}