mirror of https://github.com/aria2/aria2
Rewrite GZipFile::vprintf()
MINGW does not have vasprintf(), so we use _vscprintf() and vsnprintf(). We want to reuse buffer, so for non-MINGW we use vsnprintf() with retrying doubling buffer size if output is truncated.pull/57/head
parent
e17d0f8d4e
commit
43cb2d880a
|
@ -72,6 +72,13 @@ GZipFile::GZipFile(const char* filename, const char* mode)
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
buflen_ = 1024;
|
||||||
|
buf_ = reinterpret_cast<char*>(malloc(buflen_));
|
||||||
|
}
|
||||||
|
|
||||||
|
GZipFile::~GZipFile()
|
||||||
|
{
|
||||||
|
free(buf_);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GZipFile::close()
|
int GZipFile::close()
|
||||||
|
@ -136,26 +143,46 @@ int GZipFile::flush()
|
||||||
|
|
||||||
int GZipFile::vprintf(const char* format, va_list va)
|
int GZipFile::vprintf(const char* format, va_list va)
|
||||||
{
|
{
|
||||||
char *buf = 0;
|
ssize_t len;
|
||||||
size_t len;
|
#ifdef __MINGW32__
|
||||||
|
// Windows vsnprintf returns -1 when output is truncated, so we
|
||||||
int rv = ::vasprintf(&buf, format, va);
|
// cannot use same logic in non-MINGW32 code.
|
||||||
if (rv <= 0) {
|
len = _vscprintf(format, va);
|
||||||
// buf is undefined at this point
|
if(len == 0) {
|
||||||
// do not attempt to free it
|
return 0;
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
// Include terminate null
|
||||||
len = strlen(buf);
|
++len;
|
||||||
if (len) {
|
if(len > static_cast<ssize_t>(buflen_)) {
|
||||||
rv = gzwrite(fp_, buf, len);
|
while(static_cast<ssize_t>(buflen_) < len) {
|
||||||
|
buflen_ *= 2;
|
||||||
|
}
|
||||||
|
buf_ = reinterpret_cast<char*>(realloc(buf_, buflen_));
|
||||||
}
|
}
|
||||||
|
len = vsnprintf(buf_, buflen_, format, va);
|
||||||
if (buf) {
|
if(len < 0) {
|
||||||
free(buf);
|
return len;
|
||||||
}
|
}
|
||||||
return rv;
|
#else // !__MINGW32__
|
||||||
|
for(;;) {
|
||||||
|
len = vsnprintf(buf_, buflen_, format, va);
|
||||||
|
// len does not include terminating null
|
||||||
|
if(len >= static_cast<ssize_t>(buflen_)) {
|
||||||
|
// Include terminate null
|
||||||
|
++len;
|
||||||
|
// truncated; reallocate buf and try again
|
||||||
|
while(static_cast<ssize_t>(buflen_) < len) {
|
||||||
|
buflen_ *= 2;
|
||||||
|
}
|
||||||
|
buf_ = reinterpret_cast<char*>(realloc(buf_, buflen_));
|
||||||
|
} else if(len < 0) {
|
||||||
|
return len;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // !__MINGW32__
|
||||||
|
return gzwrite(fp_, buf_, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace aria2 {
|
||||||
class GZipFile: public BufferedFile {
|
class GZipFile: public BufferedFile {
|
||||||
public:
|
public:
|
||||||
GZipFile(const char* filename, const char* mode);
|
GZipFile(const char* filename, const char* mode);
|
||||||
virtual ~GZipFile() {}
|
virtual ~GZipFile();
|
||||||
virtual int close();
|
virtual int close();
|
||||||
virtual size_t read(void* ptr, size_t count);
|
virtual size_t read(void* ptr, size_t count);
|
||||||
virtual size_t write(const void* ptr, size_t count);
|
virtual size_t write(const void* ptr, size_t count);
|
||||||
|
@ -60,6 +60,8 @@ private:
|
||||||
gzFile fp_;
|
gzFile fp_;
|
||||||
bool open_;
|
bool open_;
|
||||||
|
|
||||||
|
char* buf_;
|
||||||
|
size_t buflen_;
|
||||||
protected:
|
protected:
|
||||||
virtual bool isError() const;
|
virtual bool isError() const;
|
||||||
virtual bool isEOF() const { return gzeof(fp_); }
|
virtual bool isEOF() const { return gzeof(fp_); }
|
||||||
|
|
Loading…
Reference in New Issue