stream: stream_seek will do clamped movement if offset is invalid
If a forward/backward offset is too big, we'll clamp to the edges of the file rather than failing completely. We return the number of bytes moved so callers can still validate, but the stream API can now deal with these situations a bit more effectively.
This commit is contained in:
@@ -66,9 +66,9 @@ char stream_next(stream_t *);
|
|||||||
// Peek current character, do not push position
|
// Peek current character, do not push position
|
||||||
char stream_peek(stream_t *);
|
char stream_peek(stream_t *);
|
||||||
// Move forward or backward in the stream, return success of operation
|
// Move forward or backward in the stream, return success of operation
|
||||||
bool stream_seek(stream_t *, i64);
|
u64 stream_seek(stream_t *, i64);
|
||||||
bool stream_seek_forward(stream_t *, u64);
|
u64 stream_seek_forward(stream_t *, u64);
|
||||||
bool stream_seek_backward(stream_t *, u64);
|
u64 stream_seek_backward(stream_t *, u64);
|
||||||
|
|
||||||
// Return a relative substring of a given size
|
// Return a relative substring of a given size
|
||||||
sv_t stream_substr(stream_t *, u64);
|
sv_t stream_substr(stream_t *, u64);
|
||||||
|
|||||||
27
src/stream.c
27
src/stream.c
@@ -235,7 +235,7 @@ char stream_peek(stream_t *stream)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stream_seek(stream_t *stream, i64 offset)
|
u64 stream_seek(stream_t *stream, i64 offset)
|
||||||
{
|
{
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
return stream_seek_backward(stream, offset * -1);
|
return stream_seek_backward(stream, offset * -1);
|
||||||
@@ -246,20 +246,20 @@ bool stream_seek(stream_t *stream, i64 offset)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stream_seek_forward(stream_t *stream, u64 offset)
|
u64 stream_seek_forward(stream_t *stream, u64 offset)
|
||||||
{
|
{
|
||||||
if (stream_eoc(stream))
|
if (stream_eoc(stream))
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
switch (stream->type)
|
switch (stream->type)
|
||||||
{
|
{
|
||||||
case STREAM_TYPE_STRING:
|
case STREAM_TYPE_STRING:
|
||||||
{
|
{
|
||||||
if (stream->position + offset >= stream->string.size)
|
if (stream->position + offset >= stream->string.size)
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
stream->position += offset;
|
stream->position += offset;
|
||||||
return true;
|
return offset;
|
||||||
}
|
}
|
||||||
case STREAM_TYPE_PIPE:
|
case STREAM_TYPE_PIPE:
|
||||||
case STREAM_TYPE_FILE:
|
case STREAM_TYPE_FILE:
|
||||||
@@ -270,7 +270,7 @@ bool stream_seek_forward(stream_t *stream, u64 offset)
|
|||||||
if (stream->position + offset < stream->pipe.cache.size)
|
if (stream->position + offset < stream->pipe.cache.size)
|
||||||
{
|
{
|
||||||
stream->position += offset;
|
stream->position += offset;
|
||||||
return true;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to read chunks in till we've reached it or we're at the end of the
|
// Try to read chunks in till we've reached it or we're at the end of the
|
||||||
@@ -282,9 +282,11 @@ bool stream_seek_forward(stream_t *stream, u64 offset)
|
|||||||
|
|
||||||
// Same principle as the stream_eoc(stream) check.
|
// Same principle as the stream_eoc(stream) check.
|
||||||
if (stream->position + offset > stream->pipe.cache.size)
|
if (stream->position + offset > stream->pipe.cache.size)
|
||||||
return false;
|
{
|
||||||
|
offset = stream->pipe.cache.size - stream->position;
|
||||||
|
}
|
||||||
stream->position += offset;
|
stream->position += offset;
|
||||||
return true;
|
return offset;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
FAIL("Unreachable");
|
FAIL("Unreachable");
|
||||||
@@ -292,13 +294,16 @@ bool stream_seek_forward(stream_t *stream, u64 offset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stream_seek_backward(stream_t *stream, u64 offset)
|
u64 stream_seek_backward(stream_t *stream, u64 offset)
|
||||||
{
|
{
|
||||||
assert(stream);
|
assert(stream);
|
||||||
if (stream->position < offset)
|
if (stream->position < offset)
|
||||||
return false;
|
{
|
||||||
|
offset = stream->position;
|
||||||
|
}
|
||||||
|
|
||||||
stream->position -= offset;
|
stream->position -= offset;
|
||||||
return true;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
sv_t stream_substr(stream_t *stream, u64 size)
|
sv_t stream_substr(stream_t *stream, u64 size)
|
||||||
|
|||||||
Reference in New Issue
Block a user