input/curl: move _seek() into the CurlInputStream class

This commit is contained in:
Max Kellermann 2014-03-15 22:42:37 +01:00
parent 2ae60767a3
commit 0dd5ebbdbe

View File

@ -184,6 +184,8 @@ struct CurlInputStream {
return easy == nullptr && buffers.empty(); return easy == nullptr && buffers.empty();
} }
bool Seek(InputPlugin::offset_type offset, int whence, Error &error);
Tag *ReadTag(); Tag *ReadTag();
bool IsAvailable() const { bool IsAvailable() const {
@ -1063,21 +1065,17 @@ CurlInputStream::InitEasy(Error &error)
return true; return true;
} }
static bool inline bool
input_curl_seek(InputStream *is, InputPlugin::offset_type offset, CurlInputStream::Seek(InputPlugin::offset_type offset, int whence,
int whence, Error &error)
Error &error)
{ {
CurlInputStream *c = (CurlInputStream *)is; assert(base.ready);
bool ret;
assert(is->ready); if (whence == SEEK_SET && offset == base.offset)
if (whence == SEEK_SET && offset == is->offset)
/* no-op */ /* no-op */
return true; return true;
if (!is->seekable) if (!base.seekable)
return false; return false;
/* calculate the absolute offset */ /* calculate the absolute offset */
@ -1087,15 +1085,15 @@ input_curl_seek(InputStream *is, InputPlugin::offset_type offset,
break; break;
case SEEK_CUR: case SEEK_CUR:
offset += is->offset; offset += base.offset;
break; break;
case SEEK_END: case SEEK_END:
if (is->size < 0) if (base.size < 0)
/* stream size is not known */ /* stream size is not known */
return false; return false;
offset += is->size; offset += base.size;
break; break;
default: default:
@ -1107,67 +1105,75 @@ input_curl_seek(InputStream *is, InputPlugin::offset_type offset,
/* check if we can fast-forward the buffer */ /* check if we can fast-forward the buffer */
while (offset > is->offset && !c->buffers.empty()) { while (offset > base.offset && !buffers.empty()) {
auto &buffer = c->buffers.front(); auto &buffer = buffers.front();
size_t length = buffer.Available(); size_t length = buffer.Available();
if (offset - is->offset < (InputPlugin::offset_type)length) if (offset - base.offset < (InputPlugin::offset_type)length)
length = offset - is->offset; length = offset - base.offset;
const bool empty = !buffer.Consume(length); const bool empty = !buffer.Consume(length);
if (empty) if (empty)
c->buffers.pop_front(); buffers.pop_front();
is->offset += length; base.offset += length;
} }
if (offset == is->offset) if (offset == base.offset)
return true; return true;
/* close the old connection and open a new one */ /* close the old connection and open a new one */
c->base.mutex.unlock(); base.mutex.unlock();
c->FreeEasyIndirect(); FreeEasyIndirect();
c->buffers.clear(); buffers.clear();
is->offset = offset; base.offset = offset;
if (is->offset == is->size) { if (base.offset == base.size) {
/* seek to EOF: simulate empty result; avoid /* seek to EOF: simulate empty result; avoid
triggering a "416 Requested Range Not Satisfiable" triggering a "416 Requested Range Not Satisfiable"
response */ response */
return true; return true;
} }
ret = c->InitEasy(error); if (!InitEasy(error))
if (!ret)
return false; return false;
/* send the "Range" header */ /* send the "Range" header */
if (is->offset > 0) { if (base.offset > 0) {
sprintf(c->range, "%lld-", (long long)is->offset); sprintf(range, "%lld-", (long long)base.offset);
curl_easy_setopt(c->easy, CURLOPT_RANGE, c->range); curl_easy_setopt(easy, CURLOPT_RANGE, range);
} }
c->base.ready = false; base.ready = false;
if (!input_curl_easy_add_indirect(c, error)) if (!input_curl_easy_add_indirect(this, error))
return false; return false;
c->base.mutex.lock(); base.mutex.lock();
while (!c->base.ready) while (!base.ready)
c->base.cond.wait(c->base.mutex); base.cond.wait(base.mutex);
if (c->postponed_error.IsDefined()) { if (postponed_error.IsDefined()) {
error = std::move(c->postponed_error); error = std::move(postponed_error);
c->postponed_error.Clear(); postponed_error.Clear();
return false; return false;
} }
return true; return true;
} }
static bool
input_curl_seek(InputStream *is, InputPlugin::offset_type offset,
int whence,
Error &error)
{
CurlInputStream &c = *(CurlInputStream *)is;
return c.Seek(offset, whence, error);
}
static InputStream * static InputStream *
input_curl_open(const char *url, Mutex &mutex, Cond &cond, input_curl_open(const char *url, Mutex &mutex, Cond &cond,
Error &error) Error &error)