From 84ce49c7e644e2a7da022f55a703e30498eee388 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 9 Jan 2010 16:15:40 +0000 Subject: Add QDBM 1.8.77 dbm-compatible database library to sources, will probably be used as a default for the reference tracking implementation as it's smaller than BDB and apparently faster. --- qdbm/myconf.c | 1113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1113 insertions(+) create mode 100644 qdbm/myconf.c (limited to 'qdbm/myconf.c') diff --git a/qdbm/myconf.c b/qdbm/myconf.c new file mode 100644 index 00000000..1d1f7a7c --- /dev/null +++ b/qdbm/myconf.c @@ -0,0 +1,1113 @@ +/************************************************************************************************* + * Emulation of system calls + * Copyright (C) 2000-2007 Mikio Hirabayashi + * This file is part of QDBM, Quick Database Manager. + * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU + * Lesser General Public License as published by the Free Software Foundation; either version + * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * You should have received a copy of the GNU Lesser General Public License along with QDBM; if + * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + *************************************************************************************************/ + + +#include "myconf.h" + + + +/************************************************************************************************* + * for dosish filesystems + *************************************************************************************************/ + + +#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || defined(_SYS_CYGWIN_) + + +#define DOSPATHBUFSIZ 8192 + + +int _qdbm_win32_lstat(const char *pathname, struct stat *buf){ + char pbuf[DOSPATHBUFSIZ], *p; + int inode; + if(stat(pathname, buf) == -1) return -1; + if(GetFullPathName(pathname, DOSPATHBUFSIZ, pbuf, &p) != 0){ + inode = 11003; + for(p = pbuf; *p != '\0'; p++){ + inode = inode * 31 + *(unsigned char *)p; + } + buf->st_ino = (inode * 911) & 0x7FFF; + } + return 0; +} + + +#endif + + + +/************************************************************************************************* + * for POSIX thread + *************************************************************************************************/ + + +#if defined(MYPTHREAD) + + +#include + + +#define PTKEYMAX 8 + + +struct { void *ptr; pthread_key_t key; } _qdbm_ptkeys[PTKEYMAX]; +int _qdbm_ptknum = 0; + + +static void *_qdbm_gettsd(void *ptr, int size, const void *initval); + + +void *_qdbm_settsd(void *ptr, int size, const void *initval){ + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + char *val; + if((val = _qdbm_gettsd(ptr, size, initval)) != NULL) return val; + if(pthread_mutex_lock(&mutex) != 0) return NULL; + if((val = _qdbm_gettsd(ptr, size, initval)) != NULL){ + pthread_mutex_unlock(&mutex); + return val; + } + if(_qdbm_ptknum >= PTKEYMAX){ + pthread_mutex_unlock(&mutex); + return NULL; + } + _qdbm_ptkeys[_qdbm_ptknum].ptr = ptr; + if(pthread_key_create(&(_qdbm_ptkeys[_qdbm_ptknum].key), free) != 0){ + pthread_mutex_unlock(&mutex); + return NULL; + } + if(!(val = malloc(size))){ + pthread_key_delete(_qdbm_ptkeys[_qdbm_ptknum].key); + pthread_mutex_unlock(&mutex); + return NULL; + } + memcpy(val, initval, size); + if(pthread_setspecific(_qdbm_ptkeys[_qdbm_ptknum].key, val) != 0){ + free(val); + pthread_key_delete(_qdbm_ptkeys[_qdbm_ptknum].key); + pthread_mutex_unlock(&mutex); + return NULL; + } + _qdbm_ptknum++; + pthread_mutex_unlock(&mutex); + return val; +} + + +static void *_qdbm_gettsd(void *ptr, int size, const void *initval){ + char *val; + int i; + for(i = 0; i < _qdbm_ptknum; i++){ + if(_qdbm_ptkeys[i].ptr == ptr){ + if(!(val = pthread_getspecific(_qdbm_ptkeys[i].key))){ + if(!(val = malloc(size))) return NULL; + memcpy(val, initval, size); + if(pthread_setspecific(_qdbm_ptkeys[i].key, val) != 0){ + free(val); + return NULL; + } + } + return val; + } + } + return NULL; +} + + +#endif + + + +/************************************************************************************************* + * for systems without mmap + *************************************************************************************************/ + + +#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) + + +#define MMFDESCMAX 2048 + + +struct { void *start; HANDLE handle; } mmhandles[MMFDESCMAX]; +int mmhnum = 0; +CRITICAL_SECTION mmcsec; + + +static void _qdbm_delete_mmap_env(void); + + +void *_qdbm_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset){ + static volatile long first = TRUE; + static volatile long ready = FALSE; + HANDLE handle; + int i; + if(InterlockedExchange((void *)&first, FALSE)){ + InitializeCriticalSection(&mmcsec); + atexit(_qdbm_delete_mmap_env); + InterlockedExchange((void *)&ready, TRUE); + } + while(!InterlockedCompareExchange((void *)&ready, TRUE, TRUE)){ + Sleep(1); + } + if(fd < 0 || flags & MAP_FIXED) return MAP_FAILED; + if(!(handle = CreateFileMapping((HANDLE)_get_osfhandle(fd), NULL, + (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, + 0, length, NULL))) return MAP_FAILED; + if(!(start = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_WRITE : FILE_MAP_READ, + 0, 0, length))){ + CloseHandle(handle); + return MAP_FAILED; + } + EnterCriticalSection(&mmcsec); + if(mmhnum >= MMFDESCMAX - 1){ + UnmapViewOfFile(start); + CloseHandle(handle); + LeaveCriticalSection(&mmcsec); + return MAP_FAILED; + } + for(i = 0; i < MMFDESCMAX; i++){ + if(!mmhandles[i].start){ + mmhandles[i].start = start; + mmhandles[i].handle = handle; + break; + } + } + mmhnum++; + LeaveCriticalSection(&mmcsec); + return start; +} + + +int _qdbm_munmap(void *start, size_t length){ + HANDLE handle; + int i; + EnterCriticalSection(&mmcsec); + handle = NULL; + for(i = 0; i < MMFDESCMAX; i++){ + if(mmhandles[i].start == start){ + handle = mmhandles[i].handle; + mmhandles[i].start = NULL; + mmhandles[i].handle = NULL; + break; + } + } + if(!handle){ + LeaveCriticalSection(&mmcsec); + return -1; + } + mmhnum--; + LeaveCriticalSection(&mmcsec); + if(!UnmapViewOfFile(start)){ + CloseHandle(handle); + return -1; + } + if(!CloseHandle(handle)) return -1; + return 0; +} + + +int _qdbm_msync(const void *start, size_t length, int flags){ + if(!FlushViewOfFile(start, length)) return -1; + return 0; +} + + +static void _qdbm_delete_mmap_env(void){ + DeleteCriticalSection(&mmcsec); +} + + +#elif defined(_SYS_FREEBSD_) || defined(_SYS_NETBSD_) || defined(_SYS_OPENBSD_) || \ + defined(_SYS_AIX_) || defined(_SYS_RISCOS_) || defined(MYNOMMAP) + + +void *_qdbm_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset){ + char *buf, *wp; + int rv, rlen; + if(flags & MAP_FIXED) return MAP_FAILED; + if(lseek(fd, SEEK_SET, offset) == -1) return MAP_FAILED; + if(!(buf = malloc(sizeof(int) * 3 + length))) return MAP_FAILED; + wp = buf; + *(int *)wp = fd; + wp += sizeof(int); + *(int *)wp = offset; + wp += sizeof(int); + *(int *)wp = prot; + wp += sizeof(int); + rlen = 0; + while((rv = read(fd, wp + rlen, length - rlen)) > 0){ + rlen += rv; + } + if(rv == -1 || rlen != length){ + free(buf); + return MAP_FAILED; + } + return wp; +} + + +int _qdbm_munmap(void *start, size_t length){ + char *buf, *rp; + int fd, offset, prot, rv, wlen; + buf = (char *)start - sizeof(int) * 3; + rp = buf; + fd = *(int *)rp; + rp += sizeof(int); + offset = *(int *)rp; + rp += sizeof(int); + prot = *(int *)rp; + rp += sizeof(int); + if(prot & PROT_WRITE){ + if(lseek(fd, offset, SEEK_SET) == -1){ + free(buf); + return -1; + } + wlen = 0; + while(wlen < (int)length){ + rv = write(fd, rp + wlen, length - wlen); + if(rv == -1){ + if(errno == EINTR) continue; + free(buf); + return -1; + } + wlen += rv; + } + } + free(buf); + return 0; +} + + +int _qdbm_msync(const void *start, size_t length, int flags){ + char *buf, *rp; + int fd, offset, prot, rv, wlen; + buf = (char *)start - sizeof(int) * 3; + rp = buf; + fd = *(int *)rp; + rp += sizeof(int); + offset = *(int *)rp; + rp += sizeof(int); + prot = *(int *)rp; + rp += sizeof(int); + if(prot & PROT_WRITE){ + if(lseek(fd, offset, SEEK_SET) == -1) return -1; + wlen = 0; + while(wlen < (int)length){ + rv = write(fd, rp + wlen, length - wlen); + if(rv == -1){ + if(errno == EINTR) continue; + return -1; + } + wlen += rv; + } + } + return 0; +} + + +#endif + + + +/************************************************************************************************* + * for reentrant time routines + *************************************************************************************************/ + + +#if defined(_SYS_LINUX_) || defined(_SYS_FREEBSD_) || defined(_SYS_OPENBSD_) || \ + defined(_SYS_NETBSD_) || defined(_SYS_SUNOS_) || defined(_SYS_HPUX_) || \ + defined(_SYS_MACOSX_) || defined(_SYS_CYGWIN_) + + +struct tm *_qdbm_gmtime(const time_t *timep, struct tm *result){ + return gmtime_r(timep, result); +} + + +struct tm *_qdbm_localtime(const time_t *timep, struct tm *result){ + return localtime_r(timep, result); +} + + +# else + + +struct tm *_qdbm_gmtime(const time_t *timep, struct tm *result){ + return gmtime(timep); +} + + +struct tm *_qdbm_localtime(const time_t *timep, struct tm *result){ + return localtime(timep); +} + + +# endif + + + +/************************************************************************************************* + * for systems without times + *************************************************************************************************/ + + +#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) + + +clock_t _qdbm_times(struct tms *buf){ + buf->tms_utime = clock(); + buf->tms_stime = 0; + buf->tms_cutime = 0; + buf->tms_cstime = 0; + return 0; +} + + +#endif + + + +/************************************************************************************************* + * for Win32 + *************************************************************************************************/ + + +#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) + + +#define WINLOCKWAIT 100 + + +int _qdbm_win32_fcntl(int fd, int cmd, struct flock *lock){ + HANDLE fh; + DWORD opt; + OVERLAPPED ol; + fh = (HANDLE)_get_osfhandle(fd); + opt = (cmd == F_SETLK) ? LOCKFILE_FAIL_IMMEDIATELY : 0; + if(lock->l_type == F_WRLCK) opt |= LOCKFILE_EXCLUSIVE_LOCK; + memset(&ol, 0, sizeof(OVERLAPPED)); + ol.Offset = INT_MAX; + ol.OffsetHigh = 0; + ol.hEvent = 0; + if(!LockFileEx(fh, opt, 0, 1, 0, &ol)){ + if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED){ + while(TRUE){ + if(LockFile(fh, 0, 0, 1, 0)) return 0; + Sleep(WINLOCKWAIT); + } + } + return -1; + } + return 0; +} + + +#endif + + +#if defined(_SYS_MSVC_) + + +DIR *_qdbm_win32_opendir(const char *name){ + char expr[8192]; + int len; + DIR *dir; + HANDLE fh; + WIN32_FIND_DATA data; + len = strlen(name); + if(len > 0 && name[len-1] == MYPATHCHR){ + sprintf(expr, "%s*", name); + } else { + sprintf(expr, "%s%c*", name, MYPATHCHR); + } + if((fh = FindFirstFile(expr, &data)) == INVALID_HANDLE_VALUE) return NULL; + if(!(dir = malloc(sizeof(DIR)))){ + FindClose(fh); + return NULL; + } + dir->fh = fh; + dir->data = data; + dir->first = TRUE; + return dir; +} + + +int _qdbm_win32_closedir(DIR *dir){ + if(!FindClose(dir->fh)){ + free(dir); + return -1; + } + free(dir); + return 0; +} + + +struct dirent *_qdbm_win32_readdir(DIR *dir){ + if(dir->first){ + sprintf(dir->de.d_name, "%s", dir->data.cFileName); + dir->first = FALSE; + return &(dir->de); + } + if(!FindNextFile(dir->fh, &(dir->data))) return NULL; + sprintf(dir->de.d_name, "%s", dir->data.cFileName); + return &(dir->de); +} + + +#endif + + + +/************************************************************************************************* + * for checking information of the system + *************************************************************************************************/ + + +#if defined(_SYS_LINUX_) + + +int _qdbm_vmemavail(size_t size){ + char buf[4096], *rp; + int fd, rv, bsiz; + double avail; + if((fd = open("/proc/meminfo", O_RDONLY, 00644)) == -1) return TRUE; + rv = TRUE; + if((bsiz = read(fd, buf, sizeof(buf) - 1)) > 0){ + buf[bsiz] = '\0'; + avail = -1; + if((rp = strstr(buf, "MemFree:")) != NULL){ + rp = strchr(rp, ':') + 1; + avail = strtod(rp, NULL) * 1024.0; + if((rp = strstr(buf, "SwapFree:")) != NULL){ + rp = strchr(rp, ':') + 1; + avail += strtod(rp, NULL) * 1024.0; + } + if(size >= avail) rv = FALSE; + } + } + close(fd); + return rv; +} + + +#elif defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || defined(_SYS_CYGWIN_) + + +int _qdbm_vmemavail(size_t size){ + MEMORYSTATUS sbuf; + sbuf.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&sbuf); + return size < sbuf.dwAvailVirtual; +} + + +#else + + +int _qdbm_vmemavail(size_t size){ + return TRUE; +} + + +#endif + + + +/************************************************************************************************* + * for ZLIB + *************************************************************************************************/ + + +#if defined(MYZLIB) + + +#include + +#define ZLIBBUFSIZ 8192 + + +static char *_qdbm_deflate_impl(const char *ptr, int size, int *sp, int mode); +static char *_qdbm_inflate_impl(const char *ptr, int size, int *sp, int mode); +static unsigned int _qdbm_getcrc_impl(const char *ptr, int size); + + +char *(*_qdbm_deflate)(const char *, int, int *, int) = _qdbm_deflate_impl; +char *(*_qdbm_inflate)(const char *, int, int *, int) = _qdbm_inflate_impl; +unsigned int (*_qdbm_getcrc)(const char *, int) = _qdbm_getcrc_impl; + + +static char *_qdbm_deflate_impl(const char *ptr, int size, int *sp, int mode){ + z_stream zs; + char *buf, *swap; + unsigned char obuf[ZLIBBUFSIZ]; + int rv, asiz, bsiz, osiz; + if(size < 0) size = strlen(ptr); + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + switch(mode){ + case _QDBM_ZMRAW: + if(deflateInit2(&zs, 5, Z_DEFLATED, -15, 7, Z_DEFAULT_STRATEGY) != Z_OK) + return NULL; + break; + case _QDBM_ZMGZIP: + if(deflateInit2(&zs, 6, Z_DEFLATED, 15 + 16, 9, Z_DEFAULT_STRATEGY) != Z_OK) + return NULL; + break; + default: + if(deflateInit2(&zs, 6, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY) != Z_OK) + return NULL; + break; + } + asiz = size + 16; + if(asiz < ZLIBBUFSIZ) asiz = ZLIBBUFSIZ; + if(!(buf = malloc(asiz))){ + deflateEnd(&zs); + return NULL; + } + bsiz = 0; + zs.next_in = (unsigned char *)ptr; + zs.avail_in = size; + zs.next_out = obuf; + zs.avail_out = ZLIBBUFSIZ; + while((rv = deflate(&zs, Z_FINISH)) == Z_OK){ + osiz = ZLIBBUFSIZ - zs.avail_out; + if(bsiz + osiz > asiz){ + asiz = asiz * 2 + osiz; + if(!(swap = realloc(buf, asiz))){ + free(buf); + deflateEnd(&zs); + return NULL; + } + buf = swap; + } + memcpy(buf + bsiz, obuf, osiz); + bsiz += osiz; + zs.next_out = obuf; + zs.avail_out = ZLIBBUFSIZ; + } + if(rv != Z_STREAM_END){ + free(buf); + deflateEnd(&zs); + return NULL; + } + osiz = ZLIBBUFSIZ - zs.avail_out; + if(bsiz + osiz + 1 > asiz){ + asiz = asiz * 2 + osiz; + if(!(swap = realloc(buf, asiz))){ + free(buf); + deflateEnd(&zs); + return NULL; + } + buf = swap; + } + memcpy(buf + bsiz, obuf, osiz); + bsiz += osiz; + buf[bsiz] = '\0'; + if(mode == _QDBM_ZMRAW) bsiz++; + *sp = bsiz; + deflateEnd(&zs); + return buf; +} + + +static char *_qdbm_inflate_impl(const char *ptr, int size, int *sp, int mode){ + z_stream zs; + char *buf, *swap; + unsigned char obuf[ZLIBBUFSIZ]; + int rv, asiz, bsiz, osiz; + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + switch(mode){ + case _QDBM_ZMRAW: + if(inflateInit2(&zs, -15) != Z_OK) return NULL; + break; + case _QDBM_ZMGZIP: + if(inflateInit2(&zs, 15 + 16) != Z_OK) return NULL; + break; + default: + if(inflateInit2(&zs, 15) != Z_OK) return NULL; + break; + } + asiz = size * 2 + 16; + if(asiz < ZLIBBUFSIZ) asiz = ZLIBBUFSIZ; + if(!(buf = malloc(asiz))){ + inflateEnd(&zs); + return NULL; + } + bsiz = 0; + zs.next_in = (unsigned char *)ptr; + zs.avail_in = size; + zs.next_out = obuf; + zs.avail_out = ZLIBBUFSIZ; + while((rv = inflate(&zs, Z_NO_FLUSH)) == Z_OK){ + osiz = ZLIBBUFSIZ - zs.avail_out; + if(bsiz + osiz >= asiz){ + asiz = asiz * 2 + osiz; + if(!(swap = realloc(buf, asiz))){ + free(buf); + inflateEnd(&zs); + return NULL; + } + buf = swap; + } + memcpy(buf + bsiz, obuf, osiz); + bsiz += osiz; + zs.next_out = obuf; + zs.avail_out = ZLIBBUFSIZ; + } + if(rv != Z_STREAM_END){ + free(buf); + inflateEnd(&zs); + return NULL; + } + osiz = ZLIBBUFSIZ - zs.avail_out; + if(bsiz + osiz >= asiz){ + asiz = asiz * 2 + osiz; + if(!(swap = realloc(buf, asiz))){ + free(buf); + inflateEnd(&zs); + return NULL; + } + buf = swap; + } + memcpy(buf + bsiz, obuf, osiz); + bsiz += osiz; + buf[bsiz] = '\0'; + if(sp) *sp = bsiz; + inflateEnd(&zs); + return buf; +} + + +static unsigned int _qdbm_getcrc_impl(const char *ptr, int size){ + int crc; + if(size < 0) size = strlen(ptr); + crc = crc32(0, Z_NULL, 0); + return crc32(crc, (unsigned char *)ptr, size); +} + + +#else + + +char *(*_qdbm_deflate)(const char *, int, int *, int) = NULL; +char *(*_qdbm_inflate)(const char *, int, int *, int) = NULL; +unsigned int (*_qdbm_getcrc)(const char *, int) = NULL; + + +#endif + + + +/************************************************************************************************* + * for LZO + *************************************************************************************************/ + + +#if defined(MYLZO) + + +#include + + +static char *_qdbm_lzoencode_impl(const char *ptr, int size, int *sp); +static char *_qdbm_lzodecode_impl(const char *ptr, int size, int *sp); + + +int _qdbm_lzo_init = FALSE; +char *(*_qdbm_lzoencode)(const char *, int, int *) = _qdbm_lzoencode_impl; +char *(*_qdbm_lzodecode)(const char *, int, int *) = _qdbm_lzodecode_impl; + + +static char *_qdbm_lzoencode_impl(const char *ptr, int size, int *sp){ + char wrkmem[LZO1X_1_MEM_COMPRESS]; + lzo_bytep buf; + lzo_uint bsiz; + if(!_qdbm_lzo_init){ + if(lzo_init() != LZO_E_OK) return NULL; + _qdbm_lzo_init = TRUE; + } + if(size < 0) size = strlen(ptr); + if(!(buf = malloc(size + size / 16 + 80))) return NULL; + if(lzo1x_1_compress((lzo_bytep)ptr, size, buf, &bsiz, wrkmem) != LZO_E_OK){ + free(buf); + return NULL; + } + buf[bsiz] = '\0'; + *sp = bsiz; + return (char *)buf; +} + + +static char *_qdbm_lzodecode_impl(const char *ptr, int size, int *sp){ + lzo_bytep buf; + lzo_uint bsiz; + int rat, rv; + if(!_qdbm_lzo_init){ + if(lzo_init() != LZO_E_OK) return NULL; + _qdbm_lzo_init = TRUE; + } + rat = 6; + while(TRUE){ + bsiz = (size + 256) * rat + 3; + if(!(buf = malloc(bsiz + 1))) return NULL; + rv = lzo1x_decompress_safe((lzo_bytep)(ptr), size, buf, &bsiz, NULL); + if(rv == LZO_E_OK){ + break; + } else if(rv == LZO_E_OUTPUT_OVERRUN){ + free(buf); + rat *= 2; + } else { + free(buf); + return NULL; + } + } + buf[bsiz] = '\0'; + if(sp) *sp = bsiz; + return (char *)buf; +} + + +#else + + +char *(*_qdbm_lzoencode)(const char *, int, int *) = NULL; +char *(*_qdbm_lzodecode)(const char *, int, int *) = NULL; + + +#endif + + + +/************************************************************************************************* + * for BZIP2 + *************************************************************************************************/ + + +#if defined(MYBZIP) + + +#include + +#define BZIPBUFSIZ 8192 + + +static char *_qdbm_bzencode_impl(const char *ptr, int size, int *sp); +static char *_qdbm_bzdecode_impl(const char *ptr, int size, int *sp); + + +char *(*_qdbm_bzencode)(const char *, int, int *) = _qdbm_bzencode_impl; +char *(*_qdbm_bzdecode)(const char *, int, int *) = _qdbm_bzdecode_impl; + + +static char *_qdbm_bzencode_impl(const char *ptr, int size, int *sp){ + bz_stream zs; + char *buf, *swap, obuf[BZIPBUFSIZ]; + int rv, asiz, bsiz, osiz; + if(size < 0) size = strlen(ptr); + zs.bzalloc = NULL; + zs.bzfree = NULL; + zs.opaque = NULL; + if(BZ2_bzCompressInit(&zs, 9, 0, 30) != BZ_OK) return NULL; + asiz = size + 16; + if(asiz < BZIPBUFSIZ) asiz = BZIPBUFSIZ; + if(!(buf = malloc(asiz))){ + BZ2_bzCompressEnd(&zs); + return NULL; + } + bsiz = 0; + zs.next_in = (char *)ptr; + zs.avail_in = size; + zs.next_out = obuf; + zs.avail_out = BZIPBUFSIZ; + while((rv = BZ2_bzCompress(&zs, BZ_FINISH)) == BZ_FINISH_OK){ + osiz = BZIPBUFSIZ - zs.avail_out; + if(bsiz + osiz > asiz){ + asiz = asiz * 2 + osiz; + if(!(swap = realloc(buf, asiz))){ + free(buf); + BZ2_bzCompressEnd(&zs); + return NULL; + } + buf = swap; + } + memcpy(buf + bsiz, obuf, osiz); + bsiz += osiz; + zs.next_out = obuf; + zs.avail_out = BZIPBUFSIZ; + } + if(rv != BZ_STREAM_END){ + free(buf); + BZ2_bzCompressEnd(&zs); + return NULL; + } + osiz = BZIPBUFSIZ - zs.avail_out; + if(bsiz + osiz + 1 > asiz){ + asiz = asiz * 2 + osiz; + if(!(swap = realloc(buf, asiz))){ + free(buf); + BZ2_bzCompressEnd(&zs); + return NULL; + } + buf = swap; + } + memcpy(buf + bsiz, obuf, osiz); + bsiz += osiz; + buf[bsiz] = '\0'; + *sp = bsiz; + BZ2_bzCompressEnd(&zs); + return buf; +} + + +static char *_qdbm_bzdecode_impl(const char *ptr, int size, int *sp){ + bz_stream zs; + char *buf, *swap, obuf[BZIPBUFSIZ]; + int rv, asiz, bsiz, osiz; + zs.bzalloc = NULL; + zs.bzfree = NULL; + zs.opaque = NULL; + if(BZ2_bzDecompressInit(&zs, 0, 0) != BZ_OK) return NULL; + asiz = size * 2 + 16; + if(asiz < BZIPBUFSIZ) asiz = BZIPBUFSIZ; + if(!(buf = malloc(asiz))){ + BZ2_bzDecompressEnd(&zs); + return NULL; + } + bsiz = 0; + zs.next_in = (char *)ptr; + zs.avail_in = size; + zs.next_out = obuf; + zs.avail_out = BZIPBUFSIZ; + while((rv = BZ2_bzDecompress(&zs)) == BZ_OK){ + osiz = BZIPBUFSIZ - zs.avail_out; + if(bsiz + osiz >= asiz){ + asiz = asiz * 2 + osiz; + if(!(swap = realloc(buf, asiz))){ + free(buf); + BZ2_bzDecompressEnd(&zs); + return NULL; + } + buf = swap; + } + memcpy(buf + bsiz, obuf, osiz); + bsiz += osiz; + zs.next_out = obuf; + zs.avail_out = BZIPBUFSIZ; + } + if(rv != BZ_STREAM_END){ + free(buf); + BZ2_bzDecompressEnd(&zs); + return NULL; + } + osiz = BZIPBUFSIZ - zs.avail_out; + if(bsiz + osiz >= asiz){ + asiz = asiz * 2 + osiz; + if(!(swap = realloc(buf, asiz))){ + free(buf); + BZ2_bzDecompressEnd(&zs); + return NULL; + } + buf = swap; + } + memcpy(buf + bsiz, obuf, osiz); + bsiz += osiz; + buf[bsiz] = '\0'; + if(sp) *sp = bsiz; + BZ2_bzDecompressEnd(&zs); + return buf; +} + + +#else + + +char *(*_qdbm_bzencode)(const char *, int, int *) = NULL; +char *(*_qdbm_bzdecode)(const char *, int, int *) = NULL; + + +#endif + + + +/************************************************************************************************* + * for ICONV + *************************************************************************************************/ + + +#if defined(MYICONV) + + +#include + +#define ICONVCHECKSIZ 32768 +#define ICONVMISSMAX 256 +#define ICONVALLWRAT 0.001 + + +static char *_qdbm_iconv_impl(const char *ptr, int size, + const char *icode, const char *ocode, int *sp, int *mp); +static const char *_qdbm_encname_impl(const char *ptr, int size); +static int _qdbm_encmiss(const char *ptr, int size, const char *icode, const char *ocode); + + +char *(*_qdbm_iconv)(const char *, int, const char *, const char *, + int *, int *) = _qdbm_iconv_impl; +const char *(*_qdbm_encname)(const char *, int) = _qdbm_encname_impl; + + +static char *_qdbm_iconv_impl(const char *ptr, int size, + const char *icode, const char *ocode, int *sp, int *mp){ + iconv_t ic; + char *obuf, *wp, *rp; + size_t isiz, osiz; + int miss; + if(size < 0) size = strlen(ptr); + isiz = size; + if((ic = iconv_open(ocode, icode)) == (iconv_t)-1) return NULL; + osiz = isiz * 5; + if(!(obuf = malloc(osiz + 1))){ + iconv_close(ic); + return NULL; + } + wp = obuf; + rp = (char *)ptr; + miss = 0; + while(isiz > 0){ + if(iconv(ic, (void *)&rp, &isiz, &wp, &osiz) == -1){ + if(errno == EILSEQ && (*rp == 0x5c || *rp == 0x7e)){ + *wp = *rp; + wp++; + rp++; + isiz--; + } else if(errno == EILSEQ || errno == EINVAL){ + rp++; + isiz--; + miss++; + } else { + break; + } + } + } + *wp = '\0'; + if(iconv_close(ic) == -1){ + free(obuf); + return NULL; + } + if(sp) *sp = wp - obuf; + if(mp) *mp = miss; + return obuf; +} + + +static const char *_qdbm_encname_impl(const char *ptr, int size){ + const char *hypo; + int i, miss, cr; + if(size < 0) size = strlen(ptr); + if(size > ICONVCHECKSIZ) size = ICONVCHECKSIZ; + if(size >= 2 && (!memcmp(ptr, "\xfe\xff", 2) || !memcmp(ptr, "\xff\xfe", 2))) return "UTF-16"; + for(i = 0; i < size - 1; i += 2){ + if(ptr[i] == 0 && ptr[i+1] != 0) return "UTF-16BE"; + if(ptr[i+1] == 0 && ptr[i] != 0) return "UTF-16LE"; + } + for(i = 0; i < size - 3; i++){ + if(ptr[i] == 0x1b){ + i++; + if(ptr[i] == '(' && strchr("BJHI", ptr[i+1])) return "ISO-2022-JP"; + if(ptr[i] == '$' && strchr("@B(", ptr[i+1])) return "ISO-2022-JP"; + } + } + if(_qdbm_encmiss(ptr, size, "US-ASCII", "UTF-16BE") < 1) return "US-ASCII"; + if(_qdbm_encmiss(ptr, size, "UTF-8", "UTF-16BE") < 1) return "UTF-8"; + hypo = NULL; + cr = FALSE; + for(i = 0; i < size; i++){ + if(ptr[i] == 0xd){ + cr = TRUE; + break; + } + } + if(cr){ + if((miss = _qdbm_encmiss(ptr, size, "Shift_JIS", "EUC-JP")) < 1) return "Shift_JIS"; + if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "Shift_JIS"; + if((miss = _qdbm_encmiss(ptr, size, "EUC-JP", "UTF-16BE")) < 1) return "EUC-JP"; + if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "EUC-JP"; + } else { + if((miss = _qdbm_encmiss(ptr, size, "EUC-JP", "UTF-16BE")) < 1) return "EUC-JP"; + if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "EUC-JP"; + if((miss = _qdbm_encmiss(ptr, size, "Shift_JIS", "EUC-JP")) < 1) return "Shift_JIS"; + if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "Shift_JIS"; + } + if((miss = _qdbm_encmiss(ptr, size, "UTF-8", "UTF-16BE")) < 1) return "UTF-8"; + if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "UTF-8"; + if((miss = _qdbm_encmiss(ptr, size, "CP932", "UTF-16BE")) < 1) return "CP932"; + if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "CP932"; + return hypo ? hypo : "ISO-8859-1"; +} + + +static int _qdbm_encmiss(const char *ptr, int size, const char *icode, const char *ocode){ + iconv_t ic; + char obuf[ICONVCHECKSIZ], *wp, *rp; + size_t isiz, osiz; + int miss; + isiz = size; + if((ic = iconv_open(ocode, icode)) == (iconv_t)-1) return ICONVMISSMAX; + miss = 0; + rp = (char *)ptr; + while(isiz > 0){ + osiz = ICONVCHECKSIZ; + wp = obuf; + if(iconv(ic, (void *)&rp, &isiz, &wp, &osiz) == -1){ + if(errno == EILSEQ || errno == EINVAL){ + rp++; + isiz--; + miss++; + if(miss >= ICONVMISSMAX) break; + } else { + break; + } + } + } + if(iconv_close(ic) == -1) return ICONVMISSMAX; + return miss; +} + + +#else + + +char *(*_qdbm_iconv)(const char *, int, const char *, const char *, int *, int *) = NULL; +const char *(*_qdbm_encname)(const char *, int) = NULL; + + +#endif + + + +/************************************************************************************************* + * common settings + *************************************************************************************************/ + + +int _qdbm_dummyfunc(void){ + return 0; +} + + + +/* END OF FILE */ -- cgit v1.2.3