diff --git a/src/include/iocompat.h b/src/include/iocompat.h index 3b4589c38..da136911c 100644 --- a/src/include/iocompat.h +++ b/src/include/iocompat.h @@ -64,7 +64,7 @@ #define makedir(dir, permissions) _mkdir(dir) #define access _access -#define write _write +//#define write _write #endif // _MSC_VER diff --git a/src/include/iolib.h b/src/include/iolib.h index f6b53b7a9..9c2b0ae1f 100644 --- a/src/include/iolib.h +++ b/src/include/iolib.h @@ -38,14 +38,6 @@ #include <vector> -#ifdef USE_ZLIB -#include <zlib.h> -#endif - -#ifdef USE_BZ2LIB -#include <bzlib.h> -#endif - /*---------------------------------------------------------------------------- -- Definitons ----------------------------------------------------------------------------*/ @@ -119,16 +111,12 @@ public: long tell(); int printf(const char *format, ...) PRINTF_VAARG_ATTRIBUTE(2, 3); // Don't forget to count this - private: - int cl_type; /// type of CFile - FILE *cl_plain; /// standard file pointer -#ifdef USE_ZLIB - gzFile cl_gz; /// gzip file pointer -#endif // !USE_ZLIB -#ifdef USE_BZ2LIB - BZFILE *cl_bz; /// bzip2 file pointer -#endif // !USE_BZ2LIB + CFile(const CFile &rhs); // No implementation + const CFile& operator = (const CFile &rhs); // No implementation +private: + class PImpl; + PImpl *pimpl; }; enum { diff --git a/src/stratagus/iolib.cpp b/src/stratagus/iolib.cpp index aa6caa210..150a55f73 100644 --- a/src/stratagus/iolib.cpp +++ b/src/stratagus/iolib.cpp @@ -36,41 +36,166 @@ #include "stratagus.h" +#include "iolib.h" + #include "iocompat.h" #include "map.h" #include "util.h" -#include <stdarg.h> - -#ifndef _MSC_VER -#include <fcntl.h> +#ifdef USE_ZLIB +#include <zlib.h> #endif -#include "iolib.h" +#ifdef USE_BZ2LIB +#include <bzlib.h> +#endif -#include <zlib.h> +class CFile::PImpl +{ +public: + PImpl(); + ~PImpl(); -/*---------------------------------------------------------------------------- --- Defines -----------------------------------------------------------------------------*/ + int open(const char *name, long flags); + int close(); + void flush(); + int read(void *buf, size_t len); + int seek(long offset, int whence); + long tell(); + int write(const void *buf, size_t len); + +private: + PImpl(const PImpl&rhs); // No implementation + const PImpl& operator = (const PImpl &rhs); // No implementation + +private: + int cl_type; /// type of CFile + FILE *cl_plain; /// standard file pointer +#ifdef USE_ZLIB + gzFile cl_gz; /// gzip file pointer +#endif // !USE_ZLIB +#ifdef USE_BZ2LIB + BZFILE *cl_bz; /// bzip2 file pointer +#endif // !USE_BZ2LIB +}; + +CFile::CFile() : pimpl(new CFile::PImpl) +{ +} + +CFile::~CFile() +{ + delete pimpl; +} -/*---------------------------------------------------------------------------- --- Variables -----------------------------------------------------------------------------*/ +/** +** CLopen Library file open +** +** @param name File name. +** @param openflags Open read, or write and compression options +** +** @return File Pointer +*/ +int CFile::open(const char *name, long flags) +{ + return pimpl->open(name, flags); +} +/** +** CLclose Library file close +*/ +int CFile::close() +{ + return pimpl->close(); +} -/*---------------------------------------------------------------------------- --- Functions -----------------------------------------------------------------------------*/ +void CFile::flush() +{ + pimpl->flush(); +} +/** +** CLread Library file read +** +** @param buf Pointer to read the data to. +** @param len number of bytes to read. +*/ +int CFile::read(void *buf, size_t len) +{ + return pimpl->read(buf, len); +} -CFile::CFile() +/** +** CLseek Library file seek +** +** @param offset Seek position +** @param whence How to seek +*/ +int CFile::seek(long offset, int whence) +{ + return pimpl->seek(offset, whence); +} + +/** +** CLtell Library file tell +*/ +long CFile::tell() +{ + return pimpl->tell(); +} + +/** +** CLprintf Library file write +** +** @param format String Format. +** @param ... Parameter List. +*/ +int CFile::printf(const char *format, ...) +{ + int size = 500; + char *p = new char[size]; + if (p == NULL) { + return -1; + } + while (1) { + // Try to print in the allocated space. + va_list ap; + va_start(ap, format); + const int n = vsnprintf(p, size, format, ap); + va_end(ap); + // If that worked, string was processed. + if (n > -1 && n < size) { + break; + } + // Else try again with more space. + if (n > -1) { // glibc 2.1 + size = n + 1; // precisely what is needed + } else { /* glibc 2.0, vc++ */ + size *= 2; // twice the old size + } + delete[] p; + p = new char[size]; + if (p == NULL) { + return -1; + } + } + size = strlen(p); + int ret = pimpl->write(p, size); + delete[] p; + return ret; +} + +// +// Implementation. +// + +CFile::PImpl::PImpl() { cl_type = CLF_TYPE_INVALID; } -CFile::~CFile() +CFile::PImpl::~PImpl() { if (cl_type != CLF_TYPE_INVALID) { DebugPrint("File wasn't closed\n"); @@ -78,7 +203,6 @@ CFile::~CFile() } } - #ifdef USE_ZLIB #ifndef z_off_t // { ZLIB_VERSION<="1.0.4" @@ -127,17 +251,7 @@ static void bzseek(BZFILE *file, unsigned offset, int) #endif // USE_BZ2LIB -#if defined(USE_ZLIB) || defined(USE_BZ2LIB) - -/** -** CLopen Library file open -** -** @param name File name. -** @param openflags Open read, or write and compression options -** -** @return File Pointer -*/ -int CFile::open(const char *name, long openflags) +int CFile::PImpl::open(const char *name, long openflags) { char buf[512]; const char *openstring; @@ -228,10 +342,7 @@ int CFile::open(const char *name, long openflags) return 0; } -/** -** CLclose Library file close -*/ -int CFile::close() +int CFile::PImpl::close() { int ret = EOF; int tp = cl_type; @@ -258,13 +369,7 @@ int CFile::close() return ret; } -/** -** CLread Library file read -** -** @param buf Pointer to read the data to. -** @param len number of bytes to read. -*/ -int CFile::read(void *buf, size_t len) +int CFile::PImpl::read(void *buf, size_t len) { int ret = 0; @@ -288,7 +393,7 @@ int CFile::read(void *buf, size_t len) return ret; } -void CFile::flush() +void CFile::PImpl::flush() { if (cl_type != CLF_TYPE_INVALID) { if (cl_type == CLF_TYPE_PLAIN) { @@ -309,76 +414,32 @@ void CFile::flush() } } - -/** -** CLprintf Library file write -** -** @param format String Format. -** @param ... Parameter List. -*/ -int CFile::printf(const char *format, ...) +int CFile::PImpl::write(const void *buf, size_t size) { - int size = 500; - char *p = new char[size]; - if (p == NULL) { - return -1; - } - while (1) { - // Try to print in the allocated space. - va_list ap; - va_start(ap, format); - const int n = vsnprintf(p, size, format, ap); - va_end(ap); - // If that worked, string was processed. - if (n > -1 && n < size) { - break; - } - // Else try again with more space. - if (n > -1) { // glibc 2.1 - size = n + 1; // precisely what is needed - } else { /* glibc 2.0, vc++ */ - size *= 2; // twice the old size - } - delete[] p; - p = new char[size]; - if (p == NULL) { - return -1; - } - } - - // Allocate the correct size - size = strlen(p); int tp = cl_type; int ret = -1; if (tp != CLF_TYPE_INVALID) { if (tp == CLF_TYPE_PLAIN) { - ret = fwrite(p, size, 1, cl_plain); + ret = fwrite(buf, size, 1, cl_plain); } #ifdef USE_ZLIB if (tp == CLF_TYPE_GZIP) { - ret = gzwrite(cl_gz, p, size); + ret = gzwrite(cl_gz, buf, size); } #endif // USE_ZLIB #ifdef USE_BZ2LIB if (tp == CLF_TYPE_BZIP2) { - ret = BZ2_bzwrite(cl_bz, p, size); + ret = BZ2_bzwrite(cl_bz, const_cast<void *>(buf), size); } #endif // USE_BZ2LIB } else { errno = EBADF; } - delete[] p; return ret; } -/** -** CLseek Library file seek -** -** @param offset Seek position -** @param whence How to seek -*/ -int CFile::seek(long offset, int whence) +int CFile::PImpl::seek(long offset, int whence) { int ret = -1; int tp = cl_type; @@ -404,10 +465,7 @@ int CFile::seek(long offset, int whence) return ret; } -/** -** CLtell Library file tell -*/ -long CFile::tell() +long CFile::PImpl::tell() { int ret = -1; int tp = cl_type; @@ -433,7 +491,6 @@ long CFile::tell() return ret; } -#endif // USE_ZLIB || USE_BZ2LIB /** ** Find a file with its correct extension ("", ".gz" or ".bz2")