adjusts naming and formatting of class definition

This commit is contained in:
tosh 2013-05-19 12:48:17 +02:00
parent 4f3f5e1abe
commit fc2de0685b
2 changed files with 200 additions and 196 deletions

View file

@ -55,56 +55,56 @@ char const* const UrlReader::error_aborted = "UrlReader: Processing err
char const* const UrlReader::error_buffer_overflow = "UrlReader: Buffer overflow.";
char const* const UrlReader::error_leftover_input = "UrlReader: Incomplete processing.";
#define _ptrCurl static_cast<CURL*>(_hndCurl)
#define _curlPtr static_cast<CURL*>(_curlHandle)
UrlReader::UrlReader()
: _hndCurl(0l), _arrXtra(0l), _strError(0l), _arrCacheRdBuf(0l) {
: _curlHandle(0l), _xtraArray(0l), _errorStr(0l), _cacheRdBufArray(0l) {
_arrXtra = new(std::nothrow) char[max_read_ahead];
if (! _arrXtra) { _strError = error_init_failed; return; }
_hndCurl = curl_easy_init();
if (! _hndCurl) { _strError = error_init_failed; return; }
curl_easy_setopt(_ptrCurl, CURLOPT_NOSIGNAL, 1l);
curl_easy_setopt(_ptrCurl, CURLOPT_FAILONERROR, 1l);
curl_easy_setopt(_ptrCurl, CURLOPT_FILETIME, 1l);
curl_easy_setopt(_ptrCurl, CURLOPT_ENCODING, "");
_xtraArray = new(std::nothrow) char[max_read_ahead];
if (! _xtraArray) { _errorStr = error_init_failed; return; }
_curlHandle = curl_easy_init();
if (! _curlHandle) { _errorStr = error_init_failed; return; }
curl_easy_setopt(_curlPtr, CURLOPT_NOSIGNAL, 1l);
curl_easy_setopt(_curlPtr, CURLOPT_FAILONERROR, 1l);
curl_easy_setopt(_curlPtr, CURLOPT_FILETIME, 1l);
curl_easy_setopt(_curlPtr, CURLOPT_ENCODING, "");
}
UrlReader::~UrlReader() {
delete[] _arrXtra;
delete[] _arrCacheRdBuf;
if (! _hndCurl) {
delete[] _xtraArray;
delete[] _cacheRdBufArray;
if (! _curlHandle) {
return;
}
curl_easy_cleanup(_ptrCurl);
curl_easy_cleanup(_curlPtr);
}
void UrlReader::perform(char const* url, transfer_callback* cb) {
curl_easy_setopt(_ptrCurl, CURLOPT_URL, url);
curl_easy_setopt(_ptrCurl, CURLOPT_WRITEFUNCTION, cb);
curl_easy_setopt(_ptrCurl, CURLOPT_WRITEDATA, this);
curl_easy_setopt(_curlPtr, CURLOPT_URL, url);
curl_easy_setopt(_curlPtr, CURLOPT_WRITEFUNCTION, cb);
curl_easy_setopt(_curlPtr, CURLOPT_WRITEDATA, this);
CURLcode rc = curl_easy_perform(_ptrCurl);
CURLcode rc = curl_easy_perform(_curlPtr);
if (rc == CURLE_OK)
{
while (_valXtraSize > 0 && _strError == success)
while (_xtraSize > 0 && _errorStr == success)
cb(0l, 0, 0, this);
}
else if (_strError == success)
_strError = curl_easy_strerror(rc);
else if (_errorStr == success)
_errorStr = curl_easy_strerror(rc);
}
void UrlReader::transferBegin(void* stream, char const* cacheFile) {
_strError = success;
_ptrStream = stream;
_strCacheFile = cacheFile;
_ptrCacheFile = 0l;
_valCacheMode = no_cache;
_valXtraSize = ~size_t(0);
_errorStr = success;
_streamPtr = stream;
_cacheFileStr = cacheFile;
_cacheFilePtr = 0l;
_cacheMode = no_cache;
_xtraSize = ~size_t(0);
}
void UrlReader::getInfo(char const*& url,
@ -113,57 +113,57 @@ void UrlReader::getInfo(char const*& url,
// fetch information from HTTP header
double clen;
long time;
curl_easy_getinfo(_ptrCurl, CURLINFO_FILETIME, & time);
curl_easy_getinfo(_ptrCurl, CURLINFO_EFFECTIVE_URL, & url);
curl_easy_getinfo(_ptrCurl, CURLINFO_CONTENT_TYPE, & type);
curl_easy_getinfo(_ptrCurl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, & clen);
curl_easy_getinfo(_curlPtr, CURLINFO_FILETIME, & time);
curl_easy_getinfo(_curlPtr, CURLINFO_EFFECTIVE_URL, & url);
curl_easy_getinfo(_curlPtr, CURLINFO_CONTENT_TYPE, & type);
curl_easy_getinfo(_curlPtr, CURLINFO_CONTENT_LENGTH_DOWNLOAD, & clen);
length = static_cast<int64_t>(clen);
curl_easy_getinfo(_ptrCurl, CURLINFO_FILETIME, & time);
curl_easy_getinfo(_curlPtr, CURLINFO_FILETIME, & time);
stardate = time;
// printLog("UrlReader: Ready to transfer from URL '%s'\n", url);
// check caching file time whether we actually want to download anything
if (_strCacheFile != 0l) {
if (_cacheFileStr != 0l) {
struct stat s;
stat(_strCacheFile, & s);
stat(_cacheFileStr, & s);
if (time > s.st_mtime) {
// file on server is newer -> update cache file
_ptrCacheFile = fopen(_strCacheFile, "wb");
// printLog("UrlReader: Also writing content to cache file '%s'\n", _strCacheFile);
if (_ptrCacheFile != 0l) {
_valCacheMode = cache_write;
_cacheFilePtr = fopen(_cacheFileStr, "wb");
// printLog("UrlReader: Also writing content to cache file '%s'\n", _cacheFileStr);
if (_cacheFilePtr != 0l) {
_cacheMode = cache_write;
}
} else {
// file on server is older -> use cache file
if (! _arrCacheRdBuf) {
_arrCacheRdBuf = new (std::nothrow) char[max_read_ahead];
if (! _arrCacheRdBuf) {
if (! _cacheRdBufArray) {
_cacheRdBufArray = new (std::nothrow) char[max_read_ahead];
if (! _cacheRdBufArray) {
// out of memory, no caching, have CURL catch it
return;
}
}
_ptrCacheFile = fopen(_strCacheFile, "rb");
// printLog("UrlReader: Delivering cached content from file '%s'\n", _strCacheFile);
if (_ptrCacheFile != 0l) {
_valCacheMode = cache_read;
_cacheFilePtr = fopen(_cacheFileStr, "rb");
// printLog("UrlReader: Delivering cached content from file '%s'\n", _cacheFileStr);
if (_cacheFilePtr != 0l) {
_cacheMode = cache_read;
}
// override error code returned by CURL when we abort the download
_strError = success_cached;
_errorStr = success_cached;
}
}
}
void UrlReader::transferEnd() {
if (_ptrCacheFile != 0l) {
fclose(_ptrCacheFile);
if (_cacheFilePtr != 0l) {
fclose(_cacheFilePtr);
}
}
#else // no-op version for incomplete Windows build:
UrlReader::UrlReader() : _ptrImpl(0l) { }
UrlReader::UrlReader() : _curlHandle(0l) { }
UrlReader::~UrlReader() { }
void UrlReader::perform(char const* url, transfer_callback* cb) { }
void UrlReader::transferBegin(void* stream, char const* cacheFile) { }

View file

@ -19,168 +19,172 @@
// via URLs. Use one per thread.
//
class UrlReader {
public:
enum CacheMode { no_cache, cache_write, cache_read };
//
// Constructor - performs initialization, never throws.
//
UrlReader();
void* _hndCurl;
char* _arrXtra;
char const* _strError;
void* _ptrStream;
char const* _strCacheFile;
FILE* _ptrCacheFile;
char* _arrCacheRdBuf;
CacheMode _valCacheMode;
size_t _valXtraSize;
public:
//
// Destructor - frees resources, never throws.
//
~UrlReader();
//
// Constructor - performs initialization, never throws.
//
UrlReader();
//
// Reads data from an URL and forwards it to the instance of a class
// fulfilling the ContentStream concept.
//
// The call protocol on the ContentStream is detailed as follows:
//
// 1. begin(char const* url,
// char const* content_type, uint64_t bytes, uint64_t stardate)
//
// All information except 'url' is optional; 'content_type' can
// be a null pointer - 'bytes' and 'stardate' can be equal to
// to 'unavailable'.
//
// 2. transfer(char* buffer, size_t bytes)
//
// Called until all data has been received. The number of bytes
// actually processed should be returned.
// Unprocessed data is stored in an extra buffer whose size is
// given by the constant UrlReader::max_read_ahead - it can be
// assumed to be reasonably large for on-the-fly parsing.
//
// 3. end(bool ok)
//
// Called at the end of the transfer.
//
// Returns the same success code
//
template< class ContentStream >
bool readUrl(char const* url, ContentStream& s, char const* cacheFile = 0l);
//
// Destructor - frees resources, never throws.
//
~UrlReader();
//
// Returns a pointer to a static C-string that describes the error
// condition.
//
inline char const* getError() const;
//
// Reads data from an URL and forwards it to the instance of a class
// fulfilling the ContentStream concept.
//
// The call protocol on the ContentStream is detailed as follows:
//
// 1. begin(char const* url,
// char const* content_type, uint64_t bytes, uint64_t stardate)
//
// All information except 'url' is optional; 'content_type' can
// be a null pointer - 'bytes' and 'stardate' can be equal to
// to 'unavailable'.
//
// 2. transfer(char* buffer, size_t bytes)
//
// Called until all data has been received. The number of bytes
// actually processed should be returned.
// Unprocessed data is stored in an extra buffer whose size is
// given by the constant UrlReader::max_read_ahead - it can be
// assumed to be reasonably large for on-the-fly parsing.
//
// 3. end(bool ok)
//
// Called at the end of the transfer.
//
// Returns the same success code
//
template< class ContentStream >
bool readUrl(char const* url, ContentStream& s, char const* cacheFile = 0l);
//
// Can be called by the stream to set a user-defined error string.
//
inline void setError(char const* static_c_string);
//
// Returns a pointer to a static C-string that describes the error
// condition.
//
inline char const* getError() const;
//
// Pointer to the C-string returned by a call to 'readUrl' when no
// error occurred.
//
static char const* const success;
//
// Can be called by the stream to set a user-defined error string.
//
inline void setError(char const* static_c_string);
//
// Pointer to the C-string returned by a call to 'readUrl' when no
// error occurred and a local file has been read instead of the
// network stream.
//
static char const* const success_cached;
//
// Pointer to the C-string returned by a call to 'readUrl' when no
// error occurred.
//
static char const* const success;
//
// Pointer to the C-string returned by a call to 'readUrl' when the
// initialization has failed.
//
static char const* const error_init_failed;
//
// Pointer to the C-string returned by a call to 'readUrl' when no
// error occurred and a local file has been read instead of the
// network stream.
//
static char const* const success_cached;
//
// Pointer to the C-string returned by a call to 'readUrl' when the
// initialization has failed.
//
static char const* const error_init_failed;
//
// Pointer to the C-string returned by a call to 'readUrl' when the
// transfer has been aborted by the client.
//
static char const* const error_aborted;
//
// Pointer to the C-string returned by a call to 'readUrl' when the
// transfer has been aborted by the client.
//
static char const* const error_aborted;
//
// Pointer to the C-string returned by a call to 'readUrl' when
// leftover input from incomplete processing caused a buffer
// overflow.
//
static char const* const error_buffer_overflow;
//
// Pointer to the C-string returned by a call to 'readUrl' when
// leftover input from incomplete processing caused a buffer
// overflow.
//
static char const* const error_buffer_overflow;
//
// Pointer to the C-string return by a call to 'readUrl' when the
// input provided was not completely consumed.
//
static char const* const error_leftover_input;
//
// Pointer to the C-string return by a call to 'readUrl' when the
// input provided was not completely consumed.
//
static char const* const error_leftover_input;
//
// Constant of the maximum number of bytes that are buffered
// between invocations of 'transfer'.
//
static size_t const max_read_ahead;
//
// Constant of the maximum number of bytes that are buffered
// between invocations of 'transfer'.
//
static size_t const max_read_ahead;
//
// Constant representing absent information in the call to the
// 'begin' member function of the target stream.
//
static int const unavailable = -1;
//
// Constant representing absent information in the call to the
// 'begin' member function of the target stream.
//
static int const unavailable = -1;
//
// Constant for requesting to abort the current transfer when
// returned by the 'transfer' member function of the target stream.
//
static size_t const abort = ~0u;
//
// Constant for requesting to abort the current transfer when
// returned by the 'transfer' member function of the target stream.
//
static size_t const abort = ~0u;
private:
// instances of this class shall not be copied
UrlReader(UrlReader const&); // = delete;
UrlReader& operator=(UrlReader const&); // = delete;
private:
// instances of this class shall not be copied
UrlReader(UrlReader const&); // = delete;
UrlReader& operator=(UrlReader const&); // = delete;
inline bool isSuccess();
inline bool isSuccess();
// entrypoints to compiled code
// entrypoints to compiled code
typedef size_t transfer_callback(char*, size_t, size_t, void*);
typedef size_t transfer_callback(char*, size_t, size_t, void*);
enum CacheMode { no_cache, cache_write, cache_read };
void transferBegin(void* stream, char const* cacheFile);
void transferEnd();
void transferBegin(void* stream, char const* cacheFile);
void transferEnd();
void perform(char const* url, transfer_callback* transfer);
void perform(char const* url, transfer_callback* transfer);
void getInfo(char const*& url,
char const*& type, int64_t& length, int64_t& stardate);
void getInfo(char const*& url,
char const*& type, int64_t& length, int64_t& stardate);
// synthesized callback
// synthesized callback
template< class Stream > static size_t callback_template(char *input, size_t size,
size_t nmemb, void* thiz);
template< class Stream > static size_t callback_template(char *input, size_t size,
size_t nmemb, void* thiz);
template< class Stream > size_t feedBuffered(Stream* stream,
char* input, size_t size);
template< class Stream > size_t feedBuffered(Stream* stream,
char* input, size_t size);
// state
void* _curlHandle;
char* _xtraArray;
char const* _errorStr;
void* _streamPtr;
char const* _cacheFileStr;
FILE* _cacheFilePtr;
char* _cacheRdBufArray;
CacheMode _cacheMode;
size_t _xtraSize;
};
// inline functions
inline char const* UrlReader::getError() const {
return _strError;
return _errorStr;
}
bool UrlReader::isSuccess() {
return _strError == success || _strError == success_cached;
return _errorStr == success || _errorStr == success_cached;
}
template< class ContentStream >
bool UrlReader::readUrl(char const* url, ContentStream& s, char const* cacheFile) {
if (! _hndCurl) return false;
if (! _curlHandle) return false;
this->transferBegin(& s, cacheFile);
this->perform(url, & callback_template<ContentStream>);
@ -193,7 +197,7 @@ bool UrlReader::readUrl(char const* url, ContentStream& s, char const* cacheFile
inline void UrlReader::setError(char const* staticCstring) {
if (this->isSuccess())
this->_strError = staticCstring;
this->_errorStr = staticCstring;
}
template< class Stream >
@ -207,15 +211,15 @@ size_t UrlReader::feedBuffered(Stream* stream, char* input, size_t size) {
size_t bytes = size - inputOffset;
// data in extra buffer?
if (_valXtraSize > 0) {
if (_xtraSize > 0) {
// fill extra buffer with beginning of input
size_t fill = max_read_ahead - _valXtraSize;
size_t fill = max_read_ahead - _xtraSize;
if (bytes < fill) fill = bytes;
memcpy(_arrXtra + _valXtraSize, buffer, fill);
memcpy(_xtraArray + _xtraSize, buffer, fill);
// use extra buffer for next transfer
buffer = _arrXtra;
bytes = _valXtraSize + fill;
buffer = _xtraArray;
bytes = _xtraSize + fill;
inputOffset += fill;
}
@ -234,9 +238,9 @@ size_t UrlReader::feedBuffered(Stream* stream, char* input, size_t size) {
size_t unprocessed = bytes - processed;
// can switch to input buffer, now?
if (buffer == _arrXtra && unprocessed <= inputOffset) {
if (buffer == _xtraArray && unprocessed <= inputOffset) {
_valXtraSize = 0u;
_xtraSize = 0u;
inputOffset -= unprocessed;
} else { // no? unprocessed data -> extra buffer
@ -246,10 +250,10 @@ size_t UrlReader::feedBuffered(Stream* stream, char* input, size_t size) {
setError(error_buffer_overflow);
return 0;
}
_valXtraSize = unprocessed;
memmove(_arrXtra, buffer + processed, unprocessed);
_xtraSize = unprocessed;
memmove(_xtraArray, buffer + processed, unprocessed);
if (inputOffset == size || buffer != _arrXtra) {
if (inputOffset == size || buffer != _xtraArray) {
return size;
}
@ -262,18 +266,18 @@ size_t UrlReader::callback_template(char *input, size_t size, size_t nmemb, void
size_t result = 0u;
UrlReader* me = static_cast<UrlReader*>(thiz);
Stream* stream = static_cast<Stream*>(me->_ptrStream);
Stream* stream = static_cast<Stream*>(me->_streamPtr);
size *= nmemb;
// first call?
if (me->_valXtraSize == ~size_t(0)) {
if (me->_xtraSize == ~size_t(0)) {
me->_valXtraSize = 0u;
me->_xtraSize = 0u;
// extract meta information and call 'begin'
char const* url, * type;
int64_t length, stardate;
me->getInfo(url, type, length, stardate);
if (me->_valCacheMode != cache_read) {
if (me->_cacheMode != cache_read) {
stream->begin(url, type, length, stardate);
}
}
@ -281,20 +285,20 @@ size_t UrlReader::callback_template(char *input, size_t size, size_t nmemb, void
// will have to repeat from here when reading a local file
// read from cache file?
if (me->_valCacheMode == cache_read) {
if (me->_cacheMode == cache_read) {
// change input buffer and start
input = me->_arrCacheRdBuf;
size = fread(input, 1, max_read_ahead, me->_ptrCacheFile);
input = me->_cacheRdBufArray;
size = fread(input, 1, max_read_ahead, me->_cacheFilePtr);
nmemb = 1;
} else if (me->_valCacheMode == cache_write) {
fwrite(input, 1, size, me->_ptrCacheFile);
} else if (me->_cacheMode == cache_write) {
fwrite(input, 1, size, me->_cacheFilePtr);
}
result = me->feedBuffered(stream, input, size);
} while (me->_valCacheMode == cache_read && result != 0 && ! feof(me->_ptrCacheFile));
} while (me->_cacheMode == cache_read && result != 0 && ! feof(me->_cacheFilePtr));
return me->_valCacheMode != cache_read ? result : 0;
return me->_cacheMode != cache_read ? result : 0;
}
#endif /* defined(__hifi__UrlReader__) */