Commit e1383a2d authored by Max Kellermann's avatar Max Kellermann

input/rewind: convert to class

parent 6773adc7
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
extern const InputPlugin rewind_input_plugin; extern const InputPlugin rewind_input_plugin;
struct RewindInputStream { class RewindInputStream {
InputStream base; InputStream base;
InputStream *input; InputStream *input;
...@@ -54,6 +54,7 @@ struct RewindInputStream { ...@@ -54,6 +54,7 @@ struct RewindInputStream {
*/ */
char buffer[64 * 1024]; char buffer[64 * 1024];
public:
RewindInputStream(InputStream *_input) RewindInputStream(InputStream *_input)
:base(rewind_input_plugin, _input->GetURI(), :base(rewind_input_plugin, _input->GetURI(),
_input->mutex, _input->cond), _input->mutex, _input->cond),
...@@ -64,6 +65,36 @@ struct RewindInputStream { ...@@ -64,6 +65,36 @@ struct RewindInputStream {
input->Close(); input->Close();
} }
InputStream *GetBase() {
return &base;
}
bool Check(Error &error) {
return input->Check(error);
}
void Update() {
if (!ReadingFromBuffer())
CopyAttributes();
}
Tag *ReadTag() {
return input->ReadTag();
}
bool IsAvailable() {
return input->IsAvailable();
}
size_t Read(void *ptr, size_t size, Error &error);
bool IsEOF() {
return !ReadingFromBuffer() && input->IsEOF();
}
bool Seek(InputPlugin::offset_type offset, int whence, Error &error);
private:
/** /**
* Are we currently reading from the buffer, and does the * Are we currently reading from the buffer, and does the
* buffer contain more data for the next read operation? * buffer contain more data for the next read operation?
...@@ -110,7 +141,7 @@ input_rewind_check(InputStream *is, Error &error) ...@@ -110,7 +141,7 @@ input_rewind_check(InputStream *is, Error &error)
{ {
RewindInputStream *r = (RewindInputStream *)is; RewindInputStream *r = (RewindInputStream *)is;
return r->input->Check(error); return r->Check(error);
} }
static void static void
...@@ -118,8 +149,7 @@ input_rewind_update(InputStream *is) ...@@ -118,8 +149,7 @@ input_rewind_update(InputStream *is)
{ {
RewindInputStream *r = (RewindInputStream *)is; RewindInputStream *r = (RewindInputStream *)is;
if (!r->ReadingFromBuffer()) r->Update();
r->CopyAttributes();
} }
static Tag * static Tag *
...@@ -127,7 +157,7 @@ input_rewind_tag(InputStream *is) ...@@ -127,7 +157,7 @@ input_rewind_tag(InputStream *is)
{ {
RewindInputStream *r = (RewindInputStream *)is; RewindInputStream *r = (RewindInputStream *)is;
return r->input->ReadTag(); return r->ReadTag();
} }
static bool static bool
...@@ -135,93 +165,106 @@ input_rewind_available(InputStream *is) ...@@ -135,93 +165,106 @@ input_rewind_available(InputStream *is)
{ {
RewindInputStream *r = (RewindInputStream *)is; RewindInputStream *r = (RewindInputStream *)is;
return r->input->IsAvailable(); return r->IsAvailable();
} }
static size_t inline size_t
input_rewind_read(InputStream *is, void *ptr, size_t size, RewindInputStream::Read(void *ptr, size_t size, Error &error)
Error &error)
{ {
RewindInputStream *r = (RewindInputStream *)is; if (ReadingFromBuffer()) {
if (r->ReadingFromBuffer()) {
/* buffered read */ /* buffered read */
assert(r->head == (size_t)is->offset); assert(head == (size_t)base.offset);
assert(r->tail == (size_t)r->input->offset); assert(tail == (size_t)input->offset);
if (size > r->tail - r->head) if (size > tail - head)
size = r->tail - r->head; size = tail - head;
memcpy(ptr, r->buffer + r->head, size); memcpy(ptr, buffer + head, size);
r->head += size; head += size;
is->offset += size; base.offset += size;
return size; return size;
} else { } else {
/* pass method call to underlying stream */ /* pass method call to underlying stream */
size_t nbytes = r->input->Read(ptr, size, error); size_t nbytes = input->Read(ptr, size, error);
if (r->input->offset > (InputPlugin::offset_type)sizeof(r->buffer)) if (input->offset > (InputPlugin::offset_type)sizeof(buffer))
/* disable buffering */ /* disable buffering */
r->tail = 0; tail = 0;
else if (r->tail == (size_t)is->offset) { else if (tail == (size_t)base.offset) {
/* append to buffer */ /* append to buffer */
memcpy(r->buffer + r->tail, ptr, nbytes); memcpy(buffer + tail, ptr, nbytes);
r->tail += nbytes; tail += nbytes;
assert(r->tail == (size_t)r->input->offset); assert(tail == (size_t)input->offset);
} }
r->CopyAttributes(); CopyAttributes();
return nbytes; return nbytes;
} }
} }
static bool static size_t
input_rewind_eof(InputStream *is) input_rewind_read(InputStream *is, void *ptr, size_t size,
Error &error)
{ {
RewindInputStream *r = (RewindInputStream *)is; RewindInputStream *r = (RewindInputStream *)is;
return !r->ReadingFromBuffer() && r->input->IsEOF(); return r->Read(ptr, size, error);
} }
static bool static bool
input_rewind_seek(InputStream *is, InputPlugin::offset_type offset, input_rewind_eof(InputStream *is)
int whence,
Error &error)
{ {
RewindInputStream *r = (RewindInputStream *)is; RewindInputStream *r = (RewindInputStream *)is;
assert(is->IsReady()); return r->IsEOF();
}
inline bool
RewindInputStream::Seek(InputPlugin::offset_type offset, int whence,
Error &error)
{
assert(base.IsReady());
if (whence == SEEK_SET && r->tail > 0 && if (whence == SEEK_SET && tail > 0 &&
offset <= (InputPlugin::offset_type)r->tail) { offset <= (InputPlugin::offset_type)tail) {
/* buffered seek */ /* buffered seek */
assert(!r->ReadingFromBuffer() || assert(!ReadingFromBuffer() ||
r->head == (size_t)is->offset); head == (size_t)base.offset);
assert(r->tail == (size_t)r->input->offset); assert(tail == (size_t)input->offset);
r->head = (size_t)offset; head = (size_t)offset;
is->offset = offset; base.offset = offset;
return true; return true;
} else { } else {
bool success = r->input->Seek(offset, whence, error); bool success = input->Seek(offset, whence, error);
r->CopyAttributes(); CopyAttributes();
/* disable the buffer, because r->input has left the /* disable the buffer, because input has left the
buffered range now */ buffered range now */
r->tail = 0; tail = 0;
return success; return success;
} }
} }
static bool
input_rewind_seek(InputStream *is, InputPlugin::offset_type offset,
int whence,
Error &error)
{
RewindInputStream *r = (RewindInputStream *)is;
return r->Seek(offset, whence, error);
}
const InputPlugin rewind_input_plugin = { const InputPlugin rewind_input_plugin = {
nullptr, nullptr,
nullptr, nullptr,
...@@ -248,5 +291,5 @@ input_rewind_open(InputStream *is) ...@@ -248,5 +291,5 @@ input_rewind_open(InputStream *is)
return is; return is;
RewindInputStream *c = new RewindInputStream(is); RewindInputStream *c = new RewindInputStream(is);
return &c->base; return c->GetBase();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment