diff options
| author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2014-12-08 17:07:34 +0100 | 
|---|---|---|
| committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2014-12-08 17:07:34 +0100 | 
| commit | e90a7ced80c6a7dbcdc75bf60c65bcc23f727ca2 (patch) | |
| tree | e0da8daf8af0fc45ced075a2b55126b0b24b4fec /src/core | |
| parent | e7f97a4c8da44a696bb7e71b9dd54e8d271e24d0 (diff) | |
implemented and tested moveCursor function
Diffstat (limited to 'src/core')
| -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);  };  } | 
