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

View file

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