From subversion at boxbackup.org Sat Oct 2 18:57:04 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sat, 2 Oct 2010 18:57:04 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2763 - box/invisnet/vs2010 Message-ID: <20101002175704.DC2C716AE42@www.boxbackup.org> Author: invisnet Date: 2010-10-02 18:57:04 +0100 (Sat, 02 Oct 2010) New Revision: 2763 Added: box/invisnet/vs2010/0.11/ Log: From subversion at boxbackup.org Sat Oct 2 22:02:33 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sat, 2 Oct 2010 22:02:33 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2764 - box/invisnet/vs2010/0.11/lib/server Message-ID: <20101002210233.0741416AF58@www.boxbackup.org> Author: invisnet Date: 2010-10-02 22:02:32 +0100 (Sat, 02 Oct 2010) New Revision: 2764 Modified: box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.cpp Log: Use the correct boolean type Modified: box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.cpp 2010-10-02 17:57:04 UTC (rev 2763) +++ box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.cpp 2010-10-02 21:02:32 UTC (rev 2764) @@ -462,7 +462,7 @@ { DWORD NumBytesWrittenThisTime = 0; - bool Success = WriteFile( + BOOL Success = WriteFile( mSocketHandle, // pipe handle pByteBuffer + NumBytesWrittenTotal, // message NBytes - NumBytesWrittenTotal, // message length @@ -553,7 +553,7 @@ mIsServer = false; } - bool result = CloseHandle(mSocketHandle); + BOOL result = CloseHandle(mSocketHandle); mSocketHandle = INVALID_HANDLE_VALUE; mIsConnected = false; From subversion at boxbackup.org Sun Oct 3 03:24:35 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 03:24:35 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2765 - in box/invisnet/vs2010/0.11/lib: common win32 Message-ID: <20101003022435.B765D15A16E@www.boxbackup.org> Author: invisnet Date: 2010-10-03 03:24:34 +0100 (Sun, 03 Oct 2010) New Revision: 2765 Modified: box/invisnet/vs2010/0.11/lib/common/BoxPlatform.h box/invisnet/vs2010/0.11/lib/win32/emu.h Log: _CRT_NONSTDC_NO_DEPRECATE deals with the POSIX deprication nonsense; polling is supported in later SDKs; compiler warnings should be fixed, not hidden; O_BINARY gets defined in emu.h Modified: box/invisnet/vs2010/0.11/lib/common/BoxPlatform.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/BoxPlatform.h 2010-10-02 21:02:32 UTC (rev 2764) +++ box/invisnet/vs2010/0.11/lib/common/BoxPlatform.h 2010-10-03 02:24:34 UTC (rev 2765) @@ -159,11 +159,6 @@ #define INFTIM -1 #endif -// for Unix compatibility with Windows :-) -#ifndef O_BINARY - #define O_BINARY 0 -#endif - #ifdef WIN32 typedef u_int64_t InodeRefType; #else Modified: box/invisnet/vs2010/0.11/lib/win32/emu.h =================================================================== --- box/invisnet/vs2010/0.11/lib/win32/emu.h 2010-10-02 21:02:32 UTC (rev 2764) +++ box/invisnet/vs2010/0.11/lib/win32/emu.h 2010-10-03 02:24:34 UTC (rev 2765) @@ -74,17 +74,6 @@ #define ITIMER_REAL 0 -#ifdef _MSC_VER -// Microsoft decided to deprecate the standard POSIX functions. Great! -#define open(file,flags,mode) _open(file,flags,mode) -#define close(fd) _close(fd) -#define dup(fd) _dup(fd) -#define read(fd,buf,count) _read(fd,buf,count) -#define write(fd,buf,count) _write(fd,buf,count) -#define lseek(fd,off,whence) _lseek(fd,off,whence) -#define fileno(struct_file) _fileno(struct_file) -#endif - struct passwd { char *pw_name; char *pw_passwd; @@ -286,20 +275,24 @@ } #define INFTIM -1 +#if(_WIN32_WINNT < 0x0600) #define POLLIN 0x1 #define POLLERR 0x8 #define POLLOUT 0x4 +#endif #define SHUT_RDWR SD_BOTH #define SHUT_RD SD_RECEIVE #define SHUT_WR SD_SEND +#if(_WIN32_WINNT < 0x0600) struct pollfd { SOCKET fd; short int events; short int revents; }; +#endif inline int ioctl(SOCKET sock, int flag, int * something) { @@ -409,16 +402,4 @@ // relatively recent C runtime lib int console_read(char* pBuffer, size_t BufferSize); -#ifdef _MSC_VER - /* disable certain compiler warnings to be able to actually see the show-stopper ones */ - #pragma warning(disable:4101) // unreferenced local variable - #pragma warning(disable:4244) // conversion, possible loss of data - #pragma warning(disable:4267) // conversion, possible loss of data - #pragma warning(disable:4311) // pointer truncation - #pragma warning(disable:4700) // uninitialized local variable used (hmmmmm...) - #pragma warning(disable:4805) // unsafe mix of type and type 'bool' in operation - #pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning) - #pragma warning(disable:4996) // POSIX name for this item is deprecated -#endif // _MSC_VER - #endif // !EMU_INCLUDE && WIN32 From subversion at boxbackup.org Sun Oct 3 03:31:43 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 03:31:43 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2766 - box/invisnet/vs2010/0.11/lib/common Message-ID: <20101003023143.81F8E15A1AC@www.boxbackup.org> Author: invisnet Date: 2010-10-03 03:31:43 +0100 (Sun, 03 Oct 2010) New Revision: 2766 Modified: box/invisnet/vs2010/0.11/lib/common/DebugAssertFailed.cpp box/invisnet/vs2010/0.11/lib/common/DebugMemLeakFinder.cpp box/invisnet/vs2010/0.11/lib/common/DebugPrintf.cpp Log: VS2010 has a problem with empty files... Modified: box/invisnet/vs2010/0.11/lib/common/DebugAssertFailed.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/DebugAssertFailed.cpp 2010-10-03 02:24:34 UTC (rev 2765) +++ box/invisnet/vs2010/0.11/lib/common/DebugAssertFailed.cpp 2010-10-03 02:31:43 UTC (rev 2766) @@ -7,10 +7,10 @@ // // -------------------------------------------------------------------------- +#include "Box.h" + #ifndef BOX_RELEASE_BUILD -#include "Box.h" - #include #ifdef WIN32 Modified: box/invisnet/vs2010/0.11/lib/common/DebugMemLeakFinder.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/DebugMemLeakFinder.cpp 2010-10-03 02:24:34 UTC (rev 2765) +++ box/invisnet/vs2010/0.11/lib/common/DebugMemLeakFinder.cpp 2010-10-03 02:31:43 UTC (rev 2766) @@ -8,10 +8,10 @@ // -------------------------------------------------------------------------- +#include "Box.h" + #ifndef BOX_RELEASE_BUILD -#include "Box.h" - #undef malloc #undef realloc #undef free Modified: box/invisnet/vs2010/0.11/lib/common/DebugPrintf.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/DebugPrintf.cpp 2010-10-03 02:24:34 UTC (rev 2765) +++ box/invisnet/vs2010/0.11/lib/common/DebugPrintf.cpp 2010-10-03 02:31:43 UTC (rev 2766) @@ -7,10 +7,10 @@ // // -------------------------------------------------------------------------- +#include "Box.h" + #ifndef BOX_RELEASE_BUILD -#include "Box.h" - #include #include From subversion at boxbackup.org Sun Oct 3 03:34:30 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 03:34:30 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2767 - box/invisnet/vs2010/0.11/lib/common Message-ID: <20101003023430.437D115A1D5@www.boxbackup.org> Author: invisnet Date: 2010-10-03 03:34:29 +0100 (Sun, 03 Oct 2010) New Revision: 2767 Modified: box/invisnet/vs2010/0.11/lib/common/Timer.cpp Log: _WIN32_WINNT gets defined elsewhere Modified: box/invisnet/vs2010/0.11/lib/common/Timer.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/Timer.cpp 2010-10-03 02:31:43 UTC (rev 2766) +++ box/invisnet/vs2010/0.11/lib/common/Timer.cpp 2010-10-03 02:34:29 UTC (rev 2767) @@ -8,10 +8,6 @@ // // -------------------------------------------------------------------------- -#ifdef WIN32 - #define _WIN32_WINNT 0x0500 -#endif - #include "Box.h" #include From subversion at boxbackup.org Sun Oct 3 03:43:01 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 03:43:01 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2768 - box/invisnet/vs2010/0.11/lib/win32 Message-ID: <20101003024301.9AA4615A206@www.boxbackup.org> Author: invisnet Date: 2010-10-03 03:43:01 +0100 (Sun, 03 Oct 2010) New Revision: 2768 Added: box/invisnet/vs2010/0.11/lib/win32/pch.cpp Log: Pre-compiled headers Added: box/invisnet/vs2010/0.11/lib/win32/pch.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/win32/pch.cpp (rev 0) +++ box/invisnet/vs2010/0.11/lib/win32/pch.cpp 2010-10-03 02:43:01 UTC (rev 2768) @@ -0,0 +1,5 @@ +// A file to allow PCH + +#include "Box.h" + +const char *pch = "Windows Pre-Compiled Header"; From subversion at boxbackup.org Sun Oct 3 04:40:09 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 04:40:09 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2769 - in box/invisnet/vs2010/0.11/lib: backupclient common server Message-ID: <20101003034009.2215015A26C@www.boxbackup.org> Author: invisnet Date: 2010-10-03 04:40:08 +0100 (Sun, 03 Oct 2010) New Revision: 2769 Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h box/invisnet/vs2010/0.11/lib/common/Conversion.h box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.cpp box/invisnet/vs2010/0.11/lib/server/Protocol.cpp Log: Trivial type fixes Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.cpp 2010-10-03 02:43:01 UTC (rev 2768) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.cpp 2010-10-03 03:40:08 UTC (rev 2769) @@ -548,7 +548,7 @@ for(int64_t e = 0; e < mNumBlocks; e++) { // Get the clear and encoded size - int32_t encodedSize = box_ntoh64(entry[e].mEncodedSize); + int64_t encodedSize = box_ntoh64(entry[e].mEncodedSize); ASSERT(encodedSize > 0); // Larger? Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.cpp 2010-10-03 02:43:01 UTC (rev 2768) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.cpp 2010-10-03 03:40:08 UTC (rev 2769) @@ -151,7 +151,7 @@ // Go through each instruction in the recipe and work out how many blocks // it will add, and the max clear size of these blocks int maxBlockClearSize = 0; - for(uint64_t inst = 0; inst < pRecipe->size(); ++inst) + for(Recipe::size_type inst = 0; inst < pRecipe->size(); ++inst) { if((*pRecipe)[inst].mSpaceBefore > 0) { Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h 2010-10-03 02:43:01 UTC (rev 2768) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h 2010-10-03 03:40:08 UTC (rev 2769) @@ -113,7 +113,7 @@ int64_t mTotalBlocks; // Total number of blocks in the file int64_t mAbsoluteBlockNumber; // The absolute block number currently being output // Instruction number - int64_t mInstructionNumber; + Recipe::size_type mInstructionNumber; // All the below are within the current instruction int64_t mNumBlocks; // number of blocks. Last one will be a different size to the rest in most cases int64_t mCurrentBlock; Modified: box/invisnet/vs2010/0.11/lib/common/Conversion.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/Conversion.h 2010-10-03 02:43:01 UTC (rev 2768) +++ box/invisnet/vs2010/0.11/lib/common/Conversion.h 2010-10-03 03:40:08 UTC (rev 2769) @@ -39,12 +39,12 @@ template<> inline int16_t Convert(const std::string &rFrom) { - return BoxConvert::_ConvertStringToInt(rFrom.c_str(), 16); + return (int16_t)BoxConvert::_ConvertStringToInt(rFrom.c_str(), 16); } template<> inline int8_t Convert(const std::string &rFrom) { - return BoxConvert::_ConvertStringToInt(rFrom.c_str(), 8); + return (int8_t)BoxConvert::_ConvertStringToInt(rFrom.c_str(), 8); } template<> inline int32_t Convert(const char *pFrom) @@ -54,12 +54,12 @@ template<> inline int16_t Convert(const char *pFrom) { - return BoxConvert::_ConvertStringToInt(pFrom, 16); + return (int16_t)BoxConvert::_ConvertStringToInt(pFrom, 16); } template<> inline int8_t Convert(const char *pFrom) { - return BoxConvert::_ConvertStringToInt(pFrom, 8); + return (int8_t)BoxConvert::_ConvertStringToInt(pFrom, 8); } // Specialise for integer -> string Modified: box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp 2010-10-03 02:43:01 UTC (rev 2768) +++ box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp 2010-10-03 03:40:08 UTC (rev 2769) @@ -87,7 +87,7 @@ // Use any bytes left in the buffer while(mBufferBegin < mBytesInBuffer) { - int c = mBuffer[mBufferBegin++]; + char c = mBuffer[mBufferBegin++]; if(c == '\r') { // Ignore nasty Windows line ending extra chars Modified: box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.cpp 2010-10-03 02:43:01 UTC (rev 2768) +++ box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.cpp 2010-10-03 03:40:08 UTC (rev 2769) @@ -80,7 +80,7 @@ // Use any bytes left in the buffer while(mBufferBegin < mBytesInBuffer) { - int c = mBuffer[mBufferBegin++]; + char c = mBuffer[mBufferBegin++]; if(c == '\r') { // Ignore nasty Windows line ending extra chars Modified: box/invisnet/vs2010/0.11/lib/server/Protocol.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/server/Protocol.cpp 2010-10-03 02:43:01 UTC (rev 2768) +++ box/invisnet/vs2010/0.11/lib/server/Protocol.cpp 2010-10-03 03:40:08 UTC (rev 2769) @@ -814,7 +814,7 @@ else { // Scan the table to find the most that can be written - for(int s = ProtocolStreamHeader_MaxEncodedSizeValue; s > 0; --s) + for(uint8_t s = ProtocolStreamHeader_MaxEncodedSizeValue; s > 0; --s) { if(sProtocolStreamHeaderLengths[s] <= BytesInBlock) { From subversion at boxbackup.org Sun Oct 3 04:57:21 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 04:57:21 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2770 - in box/invisnet/vs2010/0.11/lib: backupclient backupstore common server Message-ID: <20101003035721.B4B7E15A2B2@www.boxbackup.org> Author: invisnet Date: 2010-10-03 04:57:21 +0100 (Sun, 03 Oct 2010) New Revision: 2770 Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h box/invisnet/vs2010/0.11/lib/backupstore/BackupStoreAccounts.h box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.h box/invisnet/vs2010/0.11/lib/common/MemLeakFinder.h box/invisnet/vs2010/0.11/lib/server/Protocol.h Log: VS2010 gets upset if there's no assignment operator.... Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h 2010-10-03 03:40:08 UTC (rev 2769) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h 2010-10-03 03:57:21 UTC (rev 2770) @@ -165,6 +165,7 @@ : mrDir(rDir), i(rDir.mEntries.begin()) { } + Iterator& operator =(const Iterator&); BackupStoreDirectory::Entry *Next(int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING) { @@ -217,6 +218,7 @@ : mrDir(rDir), i(rDir.mEntries.rbegin()) { } + ReverseIterator &operator=(const ReverseIterator &rToCopy); BackupStoreDirectory::Entry *Next(int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING) { Modified: box/invisnet/vs2010/0.11/lib/backupstore/BackupStoreAccounts.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupstore/BackupStoreAccounts.h 2010-10-03 03:40:08 UTC (rev 2769) +++ box/invisnet/vs2010/0.11/lib/backupstore/BackupStoreAccounts.h 2010-10-03 03:57:21 UTC (rev 2770) @@ -29,6 +29,7 @@ ~BackupStoreAccounts(); private: BackupStoreAccounts(const BackupStoreAccounts &rToCopy); + BackupStoreAccounts& operator=(const BackupStoreAccounts &rToCopy); public: void Create(int32_t ID, int DiscSet, int64_t SizeSoftLimit, int64_t SizeHardLimit, const std::string &rAsUsername); Modified: box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.h 2010-10-03 03:40:08 UTC (rev 2769) +++ box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.h 2010-10-03 03:57:21 UTC (rev 2770) @@ -39,6 +39,7 @@ ~IOStreamGetLine(); private: IOStreamGetLine(const IOStreamGetLine &rToCopy); + IOStreamGetLine& operator=(const IOStreamGetLine &rToCopy); public: bool GetLine(std::string &rOutput, bool Preprocess = false, int Timeout = IOStream::TimeOutInfinite); Modified: box/invisnet/vs2010/0.11/lib/common/MemLeakFinder.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/MemLeakFinder.h 2010-10-03 03:40:08 UTC (rev 2769) +++ box/invisnet/vs2010/0.11/lib/common/MemLeakFinder.h 2010-10-03 03:57:21 UTC (rev 2770) @@ -51,6 +51,9 @@ void *operator new (size_t size, const char *file, int line); void *operator new[](size_t size, const char *file, int line); +void operator delete (void *pMem, const char *file, int line) throw(); +void operator delete[](void *pMem, const char *file, int line) throw(); + // define the malloc functions now, if required #ifdef MEMLEAKFINDER_FULL_MALLOC_MONITORING #define malloc(X) memleakfinder_malloc(X, __FILE__, __LINE__) Modified: box/invisnet/vs2010/0.11/lib/server/Protocol.h =================================================================== --- box/invisnet/vs2010/0.11/lib/server/Protocol.h 2010-10-03 03:40:08 UTC (rev 2769) +++ box/invisnet/vs2010/0.11/lib/server/Protocol.h 2010-10-03 03:57:21 UTC (rev 2770) @@ -39,6 +39,7 @@ private: Protocol(const Protocol &rToCopy); + Protocol& operator=(const Protocol &rToCopy); public: void Handshake(); From subversion at boxbackup.org Sun Oct 3 16:59:57 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 16:59:57 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2771 - box/invisnet/vs2010/0.11/bin/bbackupd Message-ID: <20101003155957.3ED0F15A572@www.boxbackup.org> Author: invisnet Date: 2010-10-03 16:59:56 +0100 (Sun, 03 Oct 2010) New Revision: 2771 Modified: box/invisnet/vs2010/0.11/bin/bbackupd/Win32BackupService.cpp box/invisnet/vs2010/0.11/bin/bbackupd/Win32ServiceFunctions.cpp Log: Starting with #ifdef breaks precompiled headers Modified: box/invisnet/vs2010/0.11/bin/bbackupd/Win32BackupService.cpp =================================================================== --- box/invisnet/vs2010/0.11/bin/bbackupd/Win32BackupService.cpp 2010-10-03 03:57:21 UTC (rev 2770) +++ box/invisnet/vs2010/0.11/bin/bbackupd/Win32BackupService.cpp 2010-10-03 15:59:56 UTC (rev 2771) @@ -1,8 +1,9 @@ // Win32 service functions for Box Backup, by Nick Knight +#include "Box.h" + #ifdef WIN32 -#include "Box.h" #include "BackupDaemon.h" #include "MainHelper.h" #include "BoxPortsAndFiles.h" Modified: box/invisnet/vs2010/0.11/bin/bbackupd/Win32ServiceFunctions.cpp =================================================================== --- box/invisnet/vs2010/0.11/bin/bbackupd/Win32ServiceFunctions.cpp 2010-10-03 03:57:21 UTC (rev 2770) +++ box/invisnet/vs2010/0.11/bin/bbackupd/Win32ServiceFunctions.cpp 2010-10-03 15:59:56 UTC (rev 2771) @@ -10,10 +10,10 @@ // Adapted for Box Backup by Nick Knight. //*************************************************************** +#include "Box.h" + #ifdef WIN32 -#include "Box.h" - #ifdef HAVE_UNISTD_H #include #endif From subversion at boxbackup.org Sun Oct 3 17:01:26 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 17:01:26 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2772 - box/invisnet/vs2010/0.11/bin/bbackupd Message-ID: <20101003160126.53BEB15A59D@www.boxbackup.org> Author: invisnet Date: 2010-10-03 17:01:25 +0100 (Sun, 03 Oct 2010) New Revision: 2772 Modified: box/invisnet/vs2010/0.11/bin/bbackupd/BackupClientContext.h Log: Add assignment operator Modified: box/invisnet/vs2010/0.11/bin/bbackupd/BackupClientContext.h =================================================================== --- box/invisnet/vs2010/0.11/bin/bbackupd/BackupClientContext.h 2010-10-03 15:59:56 UTC (rev 2771) +++ box/invisnet/vs2010/0.11/bin/bbackupd/BackupClientContext.h 2010-10-03 16:01:25 UTC (rev 2772) @@ -54,6 +54,7 @@ virtual ~BackupClientContext(); private: BackupClientContext(const BackupClientContext &); + BackupClientContext &operator=(const BackupClientContext &rToCopy); public: BackupProtocolClient &GetConnection(); From subversion at boxbackup.org Sun Oct 3 17:05:51 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 17:05:51 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2773 - box/invisnet/vs2010/0.11/lib/win32 Message-ID: <20101003160551.4152715A5D9@www.boxbackup.org> Author: invisnet Date: 2010-10-03 17:05:50 +0100 (Sun, 03 Oct 2010) New Revision: 2773 Modified: box/invisnet/vs2010/0.11/lib/win32/emu.h Log: Need S_IFIFO Modified: box/invisnet/vs2010/0.11/lib/win32/emu.h =================================================================== --- box/invisnet/vs2010/0.11/lib/win32/emu.h 2010-10-03 16:01:25 UTC (rev 2772) +++ box/invisnet/vs2010/0.11/lib/win32/emu.h 2010-10-03 16:05:50 UTC (rev 2773) @@ -190,6 +190,7 @@ //again need to verify these #define S_IFLNK 1 #define S_IFSOCK 0 +#define S_IFIFO 0 #define S_ISLNK(x) ( false ) From subversion at boxbackup.org Sun Oct 3 17:54:55 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 17:54:55 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2774 - box/invisnet/vs2010/0.11/bin/bbackupquery Message-ID: <20101003165455.519FA15A619@www.boxbackup.org> Author: invisnet Date: 2010-10-03 17:54:54 +0100 (Sun, 03 Oct 2010) New Revision: 2774 Modified: box/invisnet/vs2010/0.11/bin/bbackupquery/BackupQueries.h Log: Another assignment operator Modified: box/invisnet/vs2010/0.11/bin/bbackupquery/BackupQueries.h =================================================================== --- box/invisnet/vs2010/0.11/bin/bbackupquery/BackupQueries.h 2010-10-03 16:05:50 UTC (rev 2773) +++ box/invisnet/vs2010/0.11/bin/bbackupquery/BackupQueries.h 2010-10-03 16:54:54 UTC (rev 2774) @@ -37,6 +37,7 @@ ~BackupQueries(); private: BackupQueries(const BackupQueries &); + BackupQueries& operator=(const BackupQueries& rToCopy); public: void DoCommand(const char *Command, bool isFromCommandLine); From subversion at boxbackup.org Sun Oct 3 17:56:18 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 17:56:18 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2775 - box/invisnet/vs2010/0.11/bin/bbackupquery Message-ID: <20101003165618.F12BC15A641@www.boxbackup.org> Author: invisnet Date: 2010-10-03 17:56:18 +0100 (Sun, 03 Oct 2010) New Revision: 2775 Modified: box/invisnet/vs2010/0.11/bin/bbackupquery/BackupQueries.cpp Log: Missing const Modified: box/invisnet/vs2010/0.11/bin/bbackupquery/BackupQueries.cpp =================================================================== --- box/invisnet/vs2010/0.11/bin/bbackupquery/BackupQueries.cpp 2010-10-03 16:54:54 UTC (rev 2774) +++ box/invisnet/vs2010/0.11/bin/bbackupquery/BackupQueries.cpp 2010-10-03 16:56:18 UTC (rev 2775) @@ -2073,8 +2073,8 @@ // These are autogenerated by a script. -extern char *help_commands[]; -extern char *help_text[]; +extern const char *help_commands[]; +extern const char *help_text[]; // -------------------------------------------------------------------------- From subversion at boxbackup.org Sun Oct 3 17:57:24 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 17:57:24 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2776 - box/invisnet/vs2010/0.11/lib/common Message-ID: <20101003165724.4622715A66C@www.boxbackup.org> Author: invisnet Date: 2010-10-03 17:57:23 +0100 (Sun, 03 Oct 2010) New Revision: 2776 Modified: box/invisnet/vs2010/0.11/lib/common/DebugMemLeakFinder.cpp Log: Add delete operators, uncomment new under MSC Modified: box/invisnet/vs2010/0.11/lib/common/DebugMemLeakFinder.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/DebugMemLeakFinder.cpp 2010-10-03 16:56:18 UTC (rev 2775) +++ box/invisnet/vs2010/0.11/lib/common/DebugMemLeakFinder.cpp 2010-10-03 16:57:23 UTC (rev 2776) @@ -518,12 +518,12 @@ // http://www.relisoft.com/book/tech/9new.html // disabled because it causes hangs on FC2 in futex() in test/common // while reading files. reason unknown. -/* +#ifdef _MSC_VER void *operator new(size_t size) { return internal_new(size, "standard libraries", 0); } -*/ +#endif void *operator new[](size_t size) { @@ -549,4 +549,14 @@ internal_delete(ptr); } +void operator delete (void *pMem, const char *file, int line) throw() +{ + internal_delete(pMem); +} + +void operator delete[](void *pMem, const char *file, int line) throw() +{ + internal_delete(pMem); +} + #endif // BOX_RELEASE_BUILD From subversion at boxbackup.org Sun Oct 3 18:23:32 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 18:23:32 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2777 - box/invisnet/vs2010/0.11/lib/server Message-ID: <20101003172332.65F2415A745@www.boxbackup.org> Author: invisnet Date: 2010-10-03 18:23:31 +0100 (Sun, 03 Oct 2010) New Revision: 2777 Modified: box/invisnet/vs2010/0.11/lib/server/Protocol.h Log: Use a boolean expression to test to get a bool Modified: box/invisnet/vs2010/0.11/lib/server/Protocol.h =================================================================== --- box/invisnet/vs2010/0.11/lib/server/Protocol.h 2010-10-03 16:57:23 UTC (rev 2776) +++ box/invisnet/vs2010/0.11/lib/server/Protocol.h 2010-10-03 17:23:31 UTC (rev 2777) @@ -95,7 +95,7 @@ void Read(int32_t &rOut); void Read(int16_t &rOut); void Read(int8_t &rOut); - void Read(bool &rOut) {int8_t read; Read(read); rOut = (read == true);} + void Read(bool &rOut) {int8_t read; Read(read); rOut = (read != 0);} void Read(std::string &rOut); template void Read(type &rOut) From subversion at boxbackup.org Sun Oct 3 18:25:08 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 3 Oct 2010 18:25:08 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2778 - box/invisnet/vs2010/0.11/lib/backupstore Message-ID: <20101003172508.05E1015A76C@www.boxbackup.org> Author: invisnet Date: 2010-10-03 18:25:07 +0100 (Sun, 03 Oct 2010) New Revision: 2778 Modified: box/invisnet/vs2010/0.11/lib/backupstore/BackupStoreInfo.cpp Log: Unreachable code - should mark as modified before returning Modified: box/invisnet/vs2010/0.11/lib/backupstore/BackupStoreInfo.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupstore/BackupStoreInfo.cpp 2010-10-03 17:23:31 UTC (rev 2777) +++ box/invisnet/vs2010/0.11/lib/backupstore/BackupStoreInfo.cpp 2010-10-03 17:25:07 UTC (rev 2778) @@ -560,11 +560,11 @@ { THROW_EXCEPTION(BackupStoreException, StoreInfoNotInitialised) } + + mIsModified = true; // Return the next object ID return ++mLastObjectIDUsed; - - mIsModified = true; } From subversion at boxbackup.org Tue Oct 5 15:44:41 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Tue, 5 Oct 2010 15:44:41 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2779 - box/invisnet/perfhack1/lib/backupclient Message-ID: <20101005144441.4206716A354@www.boxbackup.org> Author: invisnet Date: 2010-10-05 15:44:40 +0100 (Tue, 05 Oct 2010) New Revision: 2779 Modified: box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.cpp box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.h Log: Merge append path back into write path; no need to iterate through the entire directory once we know there's dependency info Modified: box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.cpp =================================================================== --- box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.cpp 2010-10-03 17:25:07 UTC (rev 2778) +++ box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.cpp 2010-10-05 14:44:40 UTC (rev 2779) @@ -202,12 +202,14 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -void BackupStoreDirectory::WriteToStream(IOStream &rStream, int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet, bool StreamAttributes, bool StreamDependencyInfo) const +void BackupStoreDirectory::WriteToStream(IOStream &rStream, int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet, bool StreamAttributes, bool StreamDependencyInfo, bool AppendLastEntryOnly) const { // Get count of entries int32_t count = mEntries.size(); if(FlagsMustBeSet != Entry::Flags_INCLUDE_EVERYTHING || FlagsNotToBeSet != Entry::Flags_EXCLUDE_NOTHING) { + AppendLastEntryOnly = false; + // Need to count the entries count = 0; Iterator i(*this); @@ -221,6 +223,9 @@ ASSERT(mObjectID != 0); ASSERT(mContainerID != 0); + // Can't append to old-style directory + AppendLastEntryOnly &= !HasDependencyInfo(); + // Need dependency info? bool dependencyInfoRequired = false; if(StreamDependencyInfo) @@ -232,10 +237,14 @@ if(pen->HasDependencies()) { dependencyInfoRequired = true; + break; } } } + // Can only append if dependencies aren't changing + AppendLastEntryOnly &= ( StreamDependencyInfo && HasDependencyInfoInline() == dependencyInfoRequired ) || ( !StreamDependencyInfo && !HasDependencyInfoInline() ); + // Options int32_t options = 0; if(dependencyInfoRequired) options |= Option_DependencyInfoPresentInline; @@ -253,18 +262,35 @@ StreamableMemBlock::WriteEmptyBlockToStream(rStream); } - // Then write all the entries - Iterator i(*this); - Entry *pen = 0; - while((pen = i.Next(FlagsMustBeSet, FlagsNotToBeSet)) != 0) + if(AppendLastEntryOnly) { + Entry *pen = mEntries.back(); + // Avoid flushing the stream if we don't need to + if(count > 1) + { + rStream.Seek(0, IOStream::SeekType_End); + } pen->WriteToStream(rStream); - if(dependencyInfoRequired) { pen->WriteToStreamDependencyInfo(rStream); } } + else + { + // Then write all the entries + Iterator i(*this); + Entry *pen = 0; + while((pen = i.Next(FlagsMustBeSet, FlagsNotToBeSet)) != 0) + { + pen->WriteToStream(rStream); + + if(dependencyInfoRequired) + { + pen->WriteToStreamDependencyInfo(rStream); + } + } + } } // -------------------------------------------------------------------------- @@ -277,49 +303,7 @@ // -------------------------------------------------------------------------- void BackupStoreDirectory::UpdateToStream(IOStream &rStream, int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet, bool StreamAttributes, bool StreamDependencyInfo) const { - // Check that sensible IDs have been set - ASSERT(mObjectID != 0); - ASSERT(mContainerID != 0); - - ASSERT(mEntries.size() > 0); - - Entry *pen = mEntries.back(); - ASSERT(pen != 0); - - if( FlagsMustBeSet == Entry::Flags_INCLUDE_EVERYTHING - && FlagsNotToBeSet == Entry::Flags_EXCLUDE_NOTHING - && !HasDependencyInfo() - && ( StreamDependencyInfo == HasDependencyInfoInline() || ( StreamDependencyInfo && !pen->HasDependencies() ) ) ) - { - BOX_TRACE("Appending to directory"); - - WriteHeaderToStream(rStream, mEntries.size(), mOptions); - - // Write the attributes? - if(StreamAttributes) - { - mAttributes.WriteToStream(rStream); - } - else - { - // Write a blank header instead - StreamableMemBlock::WriteEmptyBlockToStream(rStream); - } - - if(mEntries.size() > 1) - { - rStream.Seek(0, IOStream::SeekType_End); - } - pen->WriteToStream(rStream); - if(HasDependencyInfoInline()) - { - pen->WriteToStreamDependencyInfo(rStream); - } - } - else - { - WriteToStream(rStream, FlagsMustBeSet, FlagsNotToBeSet, StreamAttributes, StreamDependencyInfo); - } + WriteToStream(rStream, FlagsMustBeSet, FlagsNotToBeSet, StreamAttributes, StreamDependencyInfo, true); } // -------------------------------------------------------------------------- Modified: box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.h =================================================================== --- box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.h 2010-10-03 17:25:07 UTC (rev 2778) +++ box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.h 2010-10-05 14:44:40 UTC (rev 2779) @@ -129,7 +129,7 @@ void WriteToStream(IOStream &rStream, int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING, - bool StreamAttributes = true, bool StreamDependencyInfo = true) const; + bool StreamAttributes = true, bool StreamDependencyInfo = true, bool AppendLastEntryOnly = false) const; void UpdateToStream(IOStream &rStream, int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING, From subversion at boxbackup.org Tue Oct 5 15:49:41 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Tue, 5 Oct 2010 15:49:41 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2780 - box/invisnet/perfhack1/lib/backupclient Message-ID: <20101005144941.9237D16A372@www.boxbackup.org> Author: invisnet Date: 2010-10-05 15:49:41 +0100 (Tue, 05 Oct 2010) New Revision: 2780 Modified: box/invisnet/perfhack1/lib/backupclient/BackupStoreFilename.cpp Log: Fix CheckValid so it's possible to tell what was wrong with the filename Modified: box/invisnet/perfhack1/lib/backupclient/BackupStoreFilename.cpp =================================================================== --- box/invisnet/perfhack1/lib/backupclient/BackupStoreFilename.cpp 2010-10-05 14:44:40 UTC (rev 2779) +++ box/invisnet/perfhack1/lib/backupclient/BackupStoreFilename.cpp 2010-10-05 14:49:41 UTC (rev 2780) @@ -63,12 +63,14 @@ // -------------------------------------------------------------------------- bool BackupStoreFilename::CheckValid(bool ExceptionIfInvalid) const { - bool ok = true; - if(mEncryptedName.size() < 2) { // Isn't long enough to have a header - ok = false; + if(ExceptionIfInvalid) + { + THROW_EXCEPTION(BackupStoreException, InvalidBackupStoreFilename) + } + return false; } else { @@ -76,24 +78,26 @@ unsigned int dsize = BACKUPSTOREFILENAME_GET_SIZE(this->mEncryptedName); if(dsize != mEncryptedName.size()) { - ok = false; + if(ExceptionIfInvalid) + { + THROW_EXCEPTION(BackupStoreException, InvalidBackupStoreFilename) + } + return false; } - + // And encoding is an accepted value unsigned int encoding = BACKUPSTOREFILENAME_GET_ENCODING(this->mEncryptedName); if(encoding < Encoding_Min || encoding > Encoding_Max) { - ok = false; + if(ExceptionIfInvalid) + { + THROW_EXCEPTION(BackupStoreException, InvalidBackupStoreFilename) + } + return false; } } - - // Exception? - if(!ok && ExceptionIfInvalid) - { - THROW_EXCEPTION(BackupStoreException, InvalidBackupStoreFilename) - } - return ok; + return true; } @@ -110,21 +114,21 @@ // Read the header char hdr[2]; rProtocol.Read(hdr, 2); - + // How big is it? int dsize = BACKUPSTOREFILENAME_GET_SIZE(hdr); - + // Fetch rest of data, relying on the Protocol to error on stupidly large sizes for us std::string data; rProtocol.Read(data, dsize - 2); - + // assign to this string, storing the header and the extra data mEncryptedName.assign(hdr, 2); mEncryptedName.append(data.c_str(), data.size()); - + // Check it CheckValid(); - + // Alert derived classes EncodedFilenameChanged(); } @@ -140,7 +144,7 @@ void BackupStoreFilename::WriteToProtocol(Protocol &rProtocol) const { CheckValid(); - + rProtocol.Write(mEncryptedName.c_str(), mEncryptedName.size()); } @@ -160,10 +164,10 @@ { THROW_EXCEPTION(BackupStoreException, CouldntReadEntireStructureFromStream) } - + // How big is it? unsigned int dsize = BACKUPSTOREFILENAME_GET_SIZE(hdr); - + // Assume most filenames are small char buf[256]; if(dsize < sizeof(buf)) @@ -196,10 +200,10 @@ // assign to this string, storing the header and the extra data mEncryptedName.assign(data, dsize); } - + // Check it CheckValid(); - + // Alert derived classes EncodedFilenameChanged(); } @@ -215,7 +219,7 @@ void BackupStoreFilename::WriteToStream(IOStream &rStream) const { CheckValid(); - + rStream.Write(mEncryptedName.c_str(), mEncryptedName.size()); } @@ -268,10 +272,10 @@ std::string encoded(hdr, 2); encoded += toEncode; ASSERT(encoded.size() == toEncode.size() + 2); - + // Store the encoded string mEncryptedName.assign(encoded); - + // Stuff which must be done EncodedFilenameChanged(); CheckValid(false); From subversion at boxbackup.org Tue Oct 5 15:58:11 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Tue, 5 Oct 2010 15:58:11 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2781 - in box/invisnet/perfhack1/lib: common server Message-ID: <20101005145811.4988016A3A8@www.boxbackup.org> Author: invisnet Date: 2010-10-05 15:58:10 +0100 (Tue, 05 Oct 2010) New Revision: 2781 Modified: box/invisnet/perfhack1/lib/common/Logging.cpp box/invisnet/perfhack1/lib/common/Logging.h box/invisnet/perfhack1/lib/server/SocketStream.cpp box/invisnet/perfhack1/lib/server/SocketStream.h box/invisnet/perfhack1/lib/server/SocketStreamTLS.cpp Log: Add STATS level to logging so we can play nicer with e.g. MRTG Modified: box/invisnet/perfhack1/lib/common/Logging.cpp =================================================================== --- box/invisnet/perfhack1/lib/common/Logging.cpp 2010-10-05 14:49:41 UTC (rev 2780) +++ box/invisnet/perfhack1/lib/common/Logging.cpp 2010-10-05 14:58:10 UTC (rev 2781) @@ -69,12 +69,12 @@ { Add(spSyslog); } - + if (sLogToSyslog && !enabled) { Remove(spSyslog); } - + sLogToSyslog = enabled; } @@ -84,12 +84,12 @@ { Add(spConsole); } - + if (sLogToConsole && !enabled) { Remove(spConsole); } - + sLogToConsole = enabled; } @@ -113,7 +113,7 @@ return; } } - + sLoggers.insert(sLoggers.begin(), pNewLogger); } @@ -130,7 +130,7 @@ } } -void Logging::Log(Log::Level level, const std::string& rFile, +void Logging::Log(Log::Level level, const std::string& rFile, int line, const std::string& rMessage) { if (level > sGlobalLevel) @@ -139,14 +139,14 @@ } std::string newMessage; - + if (sContextSet) { newMessage += "[" + sContext + "] "; } - + newMessage += rMessage; - + for (std::vector::iterator i = sLoggers.begin(); i != sLoggers.end(); i++) { @@ -158,7 +158,7 @@ } } -void Logging::LogToSyslog(Log::Level level, const std::string& rFile, +void Logging::LogToSyslog(Log::Level level, const std::string& rFile, int line, const std::string& rMessage) { if (!sLogToSyslog) @@ -172,12 +172,12 @@ } std::string newMessage; - + if (sContextSet) { newMessage += "[" + sContext + "] "; } - + newMessage += rMessage; spSyslog->Log(level, rFile, line, newMessage); @@ -227,19 +227,19 @@ spSyslog->SetFacility(facility); } -Logger::Logger() -: mCurrentLevel(Log::EVERYTHING) +Logger::Logger() +: mCurrentLevel(Log::EVERYTHING) { Logging::Add(this); } -Logger::Logger(Log::Level Level) -: mCurrentLevel(Level) +Logger::Logger(Log::Level Level) +: mCurrentLevel(Level) { Logging::Add(this); } -Logger::~Logger() +Logger::~Logger() { Logging::Remove(this); } @@ -275,16 +275,16 @@ sShowPID = enabled; } -bool Console::Log(Log::Level level, const std::string& rFile, +bool Console::Log(Log::Level level, const std::string& rFile, int line, std::string& rMessage) { if (level > GetLevel()) { return true; } - + FILE* target = stdout; - + if (level <= Log::WARNING) { target = stderr; @@ -334,6 +334,10 @@ { buf << "INFO: "; } + else if (level <= Log::STATS) + { + buf << "STATS: "; + } else if (level <= Log::TRACE) { buf << "TRACE: "; @@ -348,20 +352,20 @@ #else fprintf(target, "%s\n", buf.str().c_str()); #endif - + return true; } -bool Syslog::Log(Log::Level level, const std::string& rFile, +bool Syslog::Log(Log::Level level, const std::string& rFile, int line, std::string& rMessage) { if (level > GetLevel()) { return true; } - + int syslogLevel = LOG_ERR; - + switch(level) { case Log::NOTHING: /* fall through */ @@ -397,7 +401,7 @@ msg += rMessage; syslog(syslogLevel, "%s", msg.c_str()); - + return true; } @@ -443,14 +447,14 @@ return LOG_LOCAL6; } -bool FileLogger::Log(Log::Level Level, const std::string& rFile, +bool FileLogger::Log(Log::Level Level, const std::string& rFile, int line, std::string& rMessage) { if (Level > GetLevel()) { return true; } - + /* avoid infinite loop if this throws an exception */ Logging::Remove(this); Modified: box/invisnet/perfhack1/lib/common/Logging.h =================================================================== --- box/invisnet/perfhack1/lib/common/Logging.h 2010-10-05 14:49:41 UTC (rev 2780) +++ box/invisnet/perfhack1/lib/common/Logging.h 2010-10-05 14:58:10 UTC (rev 2781) @@ -37,6 +37,7 @@ #define BOX_WARNING(stuff) BOX_LOG(Log::WARNING, stuff) #define BOX_NOTICE(stuff) BOX_LOG(Log::NOTICE, stuff) #define BOX_INFO(stuff) BOX_LOG(Log::INFO, stuff) +#define BOX_STATS(stuff) BOX_LOG(Log::STATS, stuff) #define BOX_TRACE(stuff) \ if (Logging::IsEnabled(Log::TRACE)) \ { BOX_LOG(Log::TRACE, stuff) } @@ -109,7 +110,7 @@ namespace Log { - enum Level + enum Level { NOTHING = 1, FATAL, @@ -117,7 +118,8 @@ WARNING, NOTICE, INFO, - TRACE, + STATS, + TRACE, EVERYTHING, INVALID = -1 }; @@ -136,15 +138,15 @@ { private: Log::Level mCurrentLevel; - + public: Logger(); Logger(Log::Level level); virtual ~Logger(); - - virtual bool Log(Log::Level level, const std::string& rFile, + + virtual bool Log(Log::Level level, const std::string& rFile, int line, std::string& rMessage) = 0; - + void Filter(Log::Level level) { mCurrentLevel = level; @@ -152,7 +154,7 @@ virtual const char* GetType() = 0; Log::Level GetLevel() { return mCurrentLevel; } - + virtual void SetProgramName(const std::string& rProgramName) = 0; }; @@ -175,7 +177,7 @@ static std::string sTag; public: - virtual bool Log(Log::Level level, const std::string& rFile, + virtual bool Log(Log::Level level, const std::string& rFile, int line, std::string& rMessage); virtual const char* GetType() { return "Console"; } virtual void SetProgramName(const std::string& rProgramName); @@ -204,8 +206,8 @@ public: Syslog(); virtual ~Syslog(); - - virtual bool Log(Log::Level level, const std::string& rFile, + + virtual bool Log(Log::Level level, const std::string& rFile, int line, std::string& rMessage); virtual const char* GetType() { return "Syslog"; } virtual void SetProgramName(const std::string& rProgramName); @@ -235,7 +237,7 @@ static Log::Level sGlobalLevel; static Logging sGlobalLogging; static std::string sProgramName; - + public: Logging (); ~Logging(); @@ -245,9 +247,9 @@ static void FilterConsole (Log::Level level); static void Add (Logger* pNewLogger); static void Remove (Logger* pOldLogger); - static void Log(Log::Level level, const std::string& rFile, + static void Log(Log::Level level, const std::string& rFile, int line, const std::string& rMessage); - static void LogToSyslog(Log::Level level, const std::string& rFile, + static void LogToSyslog(Log::Level level, const std::string& rFile, int line, const std::string& rMessage); static void SetContext(std::string context); static void ClearContext(); @@ -303,16 +305,16 @@ FileStream mLogFile; FileLogger(const FileLogger& forbidden) : mLogFile("") { /* do not call */ } - + public: FileLogger(const std::string& rFileName, Log::Level Level) : Logger(Level), mLogFile(rFileName, O_WRONLY | O_CREAT | O_APPEND) { } - - virtual bool Log(Log::Level Level, const std::string& rFile, + + virtual bool Log(Log::Level Level, const std::string& rFile, int Line, std::string& rMessage); - + virtual const char* GetType() { return "FileLogger"; } virtual void SetProgramName(const std::string& rProgramName) { } }; Modified: box/invisnet/perfhack1/lib/server/SocketStream.cpp =================================================================== --- box/invisnet/perfhack1/lib/server/SocketStream.cpp 2010-10-05 14:49:41 UTC (rev 2780) +++ box/invisnet/perfhack1/lib/server/SocketStream.cpp 2010-10-05 14:58:10 UTC (rev 2781) @@ -45,7 +45,9 @@ mReadClosed(false), mWriteClosed(false), mBytesRead(0), - mBytesWritten(0) + mBytesRead128k(0), + mBytesWritten(0), + mBytesWritten128k(0) { } @@ -62,7 +64,9 @@ mReadClosed(false), mWriteClosed(false), mBytesRead(0), - mBytesWritten(0) + mBytesRead128k(0), + mBytesWritten(0), + mBytesWritten128k(0) { if(socket < 0) { @@ -83,7 +87,9 @@ mReadClosed(rToCopy.mReadClosed), mWriteClosed(rToCopy.mWriteClosed), mBytesRead(rToCopy.mBytesRead), - mBytesWritten(rToCopy.mBytesWritten) + mBytesRead128k(rToCopy.mBytesRead128k), + mBytesWritten(rToCopy.mBytesWritten), + mBytesWritten128k(rToCopy.mBytesWritten128k) { if(rToCopy.mSocketHandle < 0) @@ -122,7 +128,7 @@ // -------------------------------------------------------------------------- void SocketStream::Attach(int socket) { - if(mSocketHandle != INVALID_SOCKET_VALUE) + if(mSocketHandle != INVALID_SOCKET_VALUE) { THROW_EXCEPTION(ServerException, SocketAlreadyOpen) } @@ -145,11 +151,11 @@ // -------------------------------------------------------------------------- void SocketStream::Open(Socket::Type Type, const std::string& rName, int Port) { - if(mSocketHandle != INVALID_SOCKET_VALUE) + if(mSocketHandle != INVALID_SOCKET_VALUE) { THROW_EXCEPTION(ServerException, SocketAlreadyOpen) } - + // Setup parameters based on type, looking up names if required int sockDomain = 0; SocketAllAddr addr; @@ -164,7 +170,7 @@ BOX_LOG_SYS_ERROR("Failed to create a network socket"); THROW_EXCEPTION(ServerException, SocketOpenError) } - + // Connect it if(::connect(mSocketHandle, &addr.sa_generic, addrLen) == -1) { @@ -172,7 +178,7 @@ #ifdef WIN32 DWORD err = WSAGetLastError(); ::closesocket(mSocketHandle); - BOX_LOG_WIN_ERROR_NUMBER("Failed to connect to socket " + BOX_LOG_WIN_ERROR_NUMBER("Failed to connect to socket " "(type " << Type << ", name " << rName << ", port " << Port << ")", err); #else // !WIN32 @@ -202,7 +208,7 @@ // -------------------------------------------------------------------------- int SocketStream::Read(void *pBuffer, int NBytes, int Timeout) { - if(mSocketHandle == INVALID_SOCKET_VALUE) + if(mSocketHandle == INVALID_SOCKET_VALUE) { THROW_EXCEPTION(ServerException, BadSocketHandle) } @@ -230,12 +236,12 @@ SocketPollError) } break; - + case 0: // no data return 0; break; - + default: // good to go! break; @@ -268,8 +274,14 @@ { mReadClosed = true; } - + mBytesRead += r; + mBytesRead128k += r; + if(mBytesRead128k > 128*1024) + { + BOX_STATS("IN+" << mBytesRead128k); + mBytesRead128k = 0; + } return r; } @@ -283,18 +295,18 @@ // -------------------------------------------------------------------------- void SocketStream::Write(const void *pBuffer, int NBytes) { - if(mSocketHandle == INVALID_SOCKET_VALUE) + if(mSocketHandle == INVALID_SOCKET_VALUE) { THROW_EXCEPTION(ServerException, BadSocketHandle) } - + // Buffer in byte sized type. ASSERT(sizeof(char) == 1); const char *buffer = (char *)pBuffer; - + // Bytes left to send int bytesLeft = NBytes; - + while(bytesLeft > 0) { // Try to send. @@ -311,27 +323,33 @@ THROW_EXCEPTION(ConnectionException, Conn_SocketWriteError); } - + // Knock off bytes sent bytesLeft -= sent; // Move buffer pointer buffer += sent; mBytesWritten += sent; - + mBytesWritten128k += sent; + if(mBytesWritten128k > 128*1024) + { + BOX_STATS("OUT+" << mBytesWritten128k); + mBytesWritten128k = 0; + } + // Need to wait until it can send again? if(bytesLeft > 0) { - BOX_TRACE("Waiting to send data on socket " << + BOX_TRACE("Waiting to send data on socket " << mSocketHandle << " (" << bytesLeft << " of " << NBytes << " bytes left)"); - + // Wait for data to send. struct pollfd p; p.fd = mSocketHandle; p.events = POLLOUT; p.revents = 0; - + if(::poll(&p, 1, 16000 /* 16 seconds */) == -1) { // Don't exception if it's just a signal @@ -357,7 +375,7 @@ // -------------------------------------------------------------------------- void SocketStream::Close() { - if(mSocketHandle == INVALID_SOCKET_VALUE) + if(mSocketHandle == INVALID_SOCKET_VALUE) { THROW_EXCEPTION(ServerException, BadSocketHandle) } @@ -372,6 +390,8 @@ // already closed or closing. } mSocketHandle = INVALID_SOCKET_VALUE; + + BOX_STATS("IN+" << mBytesRead128k << " OUT+" << mBytesWritten128k); } // -------------------------------------------------------------------------- @@ -384,18 +404,18 @@ // -------------------------------------------------------------------------- void SocketStream::Shutdown(bool Read, bool Write) { - if(mSocketHandle == INVALID_SOCKET_VALUE) + if(mSocketHandle == INVALID_SOCKET_VALUE) { THROW_EXCEPTION(ServerException, BadSocketHandle) } - + // Do anything? if(!Read && !Write) return; - + int how = SHUT_RDWR; if(Read && !Write) how = SHUT_RD; if(!Read && Write) how = SHUT_WR; - + // Shut it down! if(::shutdown(mSocketHandle, how) == -1) { @@ -443,7 +463,7 @@ // -------------------------------------------------------------------------- tOSSocketHandle SocketStream::GetSocketHandle() { - if(mSocketHandle == INVALID_SOCKET_VALUE) + if(mSocketHandle == INVALID_SOCKET_VALUE) { THROW_EXCEPTION(ServerException, BadSocketHandle) } Modified: box/invisnet/perfhack1/lib/server/SocketStream.h =================================================================== --- box/invisnet/perfhack1/lib/server/SocketStream.h 2010-10-05 14:49:41 UTC (rev 2780) +++ box/invisnet/perfhack1/lib/server/SocketStream.h 2010-10-05 14:58:10 UTC (rev 2781) @@ -36,7 +36,7 @@ SocketStream(int socket); SocketStream(const SocketStream &rToCopy); ~SocketStream(); - + void Open(Socket::Type Type, const std::string& rName, int Port = 0); void Attach(int socket); @@ -62,12 +62,14 @@ protected: off_t mBytesRead; + off_t mBytesRead128k; off_t mBytesWritten; + off_t mBytesWritten128k; public: off_t GetBytesRead() const {return mBytesRead;} off_t GetBytesWritten() const {return mBytesWritten;} - void ResetCounters() {mBytesRead = mBytesWritten = 0;} + void ResetCounters() {mBytesRead = mBytesRead128k = mBytesWritten = mBytesWritten128k = 0;} bool IsOpened() { return mSocketHandle != INVALID_SOCKET_VALUE; } }; Modified: box/invisnet/perfhack1/lib/server/SocketStreamTLS.cpp =================================================================== --- box/invisnet/perfhack1/lib/server/SocketStreamTLS.cpp 2010-10-05 14:49:41 UTC (rev 2780) +++ box/invisnet/perfhack1/lib/server/SocketStreamTLS.cpp 2010-10-05 14:58:10 UTC (rev 2781) @@ -72,7 +72,7 @@ { // Attempt to close to avoid problems Close(); - + // And if that didn't work... if(mpSSL) { @@ -81,7 +81,7 @@ mpBIO = 0; // implicity freed by the SSL_free call } } - + // If we only got to creating that BIO. if(mpBIO) { @@ -130,7 +130,7 @@ tOSSocketHandle socket = GetSocketHandle(); BIO_set_fd(mpBIO, socket, BIO_NOCLOSE); - + // Then the SSL object mpSSL = ::SSL_new(rContext.GetRawContext()); if(mpSSL == 0) @@ -153,7 +153,7 @@ THROW_EXCEPTION(ServerException, SocketSetNonBlockingFailed) } #endif - + // FIXME: This is less portable than the above. However, it MAY be needed // for cygwin, which has/had bugs with fcntl // @@ -198,7 +198,7 @@ THROW_EXCEPTION(ConnectionException, Conn_TLSHandshakeTimedOut) } break; - + default: // (and SSL_ERROR_ZERO_RETURN) // Error occured if(IsServer) @@ -213,7 +213,7 @@ } } } - + // And that's it } @@ -235,7 +235,7 @@ case SSL_ERROR_WANT_READ: p.events = POLLIN; break; - + case SSL_ERROR_WANT_WRITE: p.events = POLLOUT; break; @@ -303,7 +303,7 @@ { return 0; } - + while(true) { int r = ::SSL_read(mpSSL, pBuffer, NBytes); @@ -314,6 +314,12 @@ case SSL_ERROR_NONE: // No error, return number of bytes read mBytesRead += r; + mBytesRead128k += r; + if(mBytesRead128k > 128*1024) + { + BOX_STATS("IN+" << mBytesRead128k); + mBytesRead128k = 0; + } return r; break; @@ -333,7 +339,7 @@ return 0; } break; - + default: SSLLib::LogError("reading"); THROW_EXCEPTION(ConnectionException, Conn_TLSReadFailed) @@ -353,31 +359,37 @@ void SocketStreamTLS::Write(const void *pBuffer, int NBytes) { if(!mpSSL) {THROW_EXCEPTION(ServerException, TLSNoSSLObject)} - + // Make sure zero byte writes work as expected if(NBytes == 0) { return; } - + // from man SSL_write // // SSL_write() will only return with success, when the // complete contents of buf of length num has been written. // // So no worries about partial writes and moving the buffer around - + while(true) { // try the write int r = ::SSL_write(mpSSL, pBuffer, NBytes); - + int se; switch((se = ::SSL_get_error(mpSSL, r))) { case SSL_ERROR_NONE: // No error, data sent, return success mBytesWritten += r; + mBytesWritten128k += r; + if(mBytesWritten128k > 128*1024) + { + BOX_STATS("OUT+" << mBytesWritten128k); + mBytesWritten128k = 0; + } return; break; @@ -392,13 +404,13 @@ // wait for the requried data { #ifndef BOX_RELEASE_BUILD - bool conditionmet = + bool conditionmet = #endif WaitWhenRetryRequired(se, IOStream::TimeOutInfinite); ASSERT(conditionmet); } break; - + default: SSLLib::LogError("writing"); THROW_EXCEPTION(ConnectionException, Conn_TLSWriteFailed) @@ -469,14 +481,14 @@ THROW_EXCEPTION(ConnectionException, Conn_TLSNoPeerCertificate) } - // Subject details - X509_NAME *subject = ::X509_get_subject_name(cert); + // Subject details + X509_NAME *subject = ::X509_get_subject_name(cert); if(subject == 0) { ::X509_free(cert); THROW_EXCEPTION(ConnectionException, Conn_TLSPeerCertificateInvalid) } - + // Common name char commonName[256]; if(::X509_NAME_get_text_by_NID(subject, NID_commonName, commonName, sizeof(commonName)) <= 0) @@ -486,7 +498,7 @@ } // Terminate just in case commonName[sizeof(commonName)-1] = '\0'; - + // Done. return std::string(commonName); } From trac at boxbackup.org Wed Oct 6 12:50:06 2010 From: trac at boxbackup.org (Box Backup) Date: Wed, 06 Oct 2010 11:50:06 -0000 Subject: [Box Backup-commit] #76: "pwd" not working Message-ID: <042.c82e111f2207068e17613d342cea7a54@boxbackup.org> #76: "pwd" not working ---------------------+------------------------------------------------------ Reporter: achim | Type: defect Status: new | Priority: minor Milestone: | Component: bbackupquery Version: 0.11rc2 | Keywords: ---------------------+------------------------------------------------------ "pwd" always returns "" for the current directory. Expected result (according to "help pwd": Print current directory, always root relative.) -- Ticket URL: Box Backup An open source, completely automatic on-line backup system for UNIX. From subversion at boxbackup.org Thu Oct 7 14:40:00 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 7 Oct 2010 14:40:00 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2782 - box/RELEASE/0.11/bin/bbackupquery Message-ID: <20101007134000.F142616AFA5@www.boxbackup.org> Author: chris Date: 2010-10-07 14:40:00 +0100 (Thu, 07 Oct 2010) New Revision: 2782 Modified: box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp Log: Finish support for -i option in bbackupquery (thanks to Achim for noticing). Modified: box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp =================================================================== --- box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp 2010-10-05 14:58:10 UTC (rev 2781) +++ box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp 2010-10-07 13:40:00 UTC (rev 2782) @@ -223,8 +223,8 @@ { "restore", "drif" }, { "help", "" }, { "usage", "m" }, - { "undelete", "" }, - { "delete", "" }, + { "undelete", "i" }, + { "delete", "i" }, { NULL, NULL } }; @@ -1008,8 +1008,7 @@ // object ID, depending on opts['i'], where name can // include a path) and return the file ID, placing the // directory ID in *pDirIdOut and the filename part -// of the path (if not looking up by ID and not NULL) -// in *pFileNameOut. +// of the path in *pFileNameOut (if not NULL). // Created: 2008-09-12 // // -------------------------------------------------------------------------- @@ -1039,11 +1038,6 @@ return 0; } } - - if(pFileNameOut) - { - *pFileNameOut = fileName; - } } BackupStoreFilenameClear fn(fileName); @@ -1106,6 +1100,12 @@ *pFlagsOut = en->GetFlags(); } + if(pFileNameOut) + { + BackupStoreFilenameClear entryName(en->GetName()); + *pFileNameOut = entryName.GetClearFilename(); + } + return fileId; } From subversion at boxbackup.org Thu Oct 7 14:44:05 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 7 Oct 2010 14:44:05 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2783 - box/trunk/bin/bbackupquery Message-ID: <20101007134405.5A9FD16AFCB@www.boxbackup.org> Author: chris Date: 2010-10-07 14:44:04 +0100 (Thu, 07 Oct 2010) New Revision: 2783 Modified: box/trunk/bin/bbackupquery/BackupQueries.cpp Log: Finish support for -i option in bbackupquery (thanks to Achim for noticing) (forward port to trunk). Modified: box/trunk/bin/bbackupquery/BackupQueries.cpp =================================================================== --- box/trunk/bin/bbackupquery/BackupQueries.cpp 2010-10-07 13:40:00 UTC (rev 2782) +++ box/trunk/bin/bbackupquery/BackupQueries.cpp 2010-10-07 13:44:04 UTC (rev 2783) @@ -455,9 +455,9 @@ {CompleteRestoreRemoteDirOrId, CompleteLocalDir} }, { "help", "", Command_Help, {} }, { "usage", "m", Command_Usage, {} }, - { "undelete", "", Command_Undelete, + { "undelete", "i", Command_Undelete, {CompleteGetFileOrId} }, - { "delete", "", Command_Delete, {CompleteGetFileOrId} }, + { "delete", "i", Command_Delete, {CompleteGetFileOrId} }, { NULL, NULL, Command_Unknown, {} } }; @@ -1418,8 +1418,7 @@ // object ID, depending on opts['i'], where name can // include a path) and return the file ID, placing the // directory ID in *pDirIdOut and the filename part -// of the path (if not looking up by ID and not NULL) -// in *pFileNameOut. +// of the path in *pFileNameOut (if not NULL). // Created: 2008-09-12 // // -------------------------------------------------------------------------- @@ -1449,11 +1448,6 @@ return 0; } } - - if(pFileNameOut) - { - *pFileNameOut = fileName; - } } BackupStoreFilenameClear fn(fileName); @@ -1516,6 +1510,12 @@ *pFlagsOut = en->GetFlags(); } + if(pFileNameOut) + { + BackupStoreFilenameClear entryName(en->GetName()); + *pFileNameOut = entryName.GetClearFilename(); + } + return fileId; } From subversion at boxbackup.org Thu Oct 7 14:50:43 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 7 Oct 2010 14:50:43 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2784 - box/trunk/bin/bbackupd Message-ID: <20101007135043.3E49C16AFE9@www.boxbackup.org> Author: chris Date: 2010-10-07 14:50:42 +0100 (Thu, 07 Oct 2010) New Revision: 2784 Modified: box/trunk/bin/bbackupd/BackupDaemon.cpp Log: Quick fix to stop deletion of redundant locations when DeleteRedundantLocationsAfter is set to zero, which is supposed to mean that it's disabled. Modified: box/trunk/bin/bbackupd/BackupDaemon.cpp =================================================================== --- box/trunk/bin/bbackupd/BackupDaemon.cpp 2010-10-07 13:44:04 UTC (rev 2783) +++ box/trunk/bin/bbackupd/BackupDaemon.cpp 2010-10-07 13:50:42 UTC (rev 2784) @@ -1731,8 +1731,15 @@ } // Any entries in the root directory which need deleting? - if(dir.GetNumberOfEntries() > 0) + if(dir.GetNumberOfEntries() > 0 && + mDeleteRedundantLocationsAfter == 0) { + BOX_NOTICE(dir.GetNumberOfEntries() << " redundant locations " + "in root directory found, but will not delete because " + "DeleteRedundantLocationsAfter = 0"); + } + else if(dir.GetNumberOfEntries() > 0) + { box_time_t now = GetCurrentBoxTime(); // This should reset the timer if the list of unused From subversion at boxbackup.org Thu Oct 7 14:51:25 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 7 Oct 2010 14:51:25 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2785 - box/RELEASE/0.11/bin/bbackupd Message-ID: <20101007135125.2113A16A007@www.boxbackup.org> Author: chris Date: 2010-10-07 14:51:24 +0100 (Thu, 07 Oct 2010) New Revision: 2785 Modified: box/RELEASE/0.11/bin/bbackupd/BackupDaemon.cpp Log: Quick fix to stop deletion of redundant locations when DeleteRedundantLocationsAfter is set to zero, which is supposed to mean that it's disabled. (thanks to Achim for noticing) (backport to 0.11 branch). Modified: box/RELEASE/0.11/bin/bbackupd/BackupDaemon.cpp =================================================================== --- box/RELEASE/0.11/bin/bbackupd/BackupDaemon.cpp 2010-10-07 13:50:42 UTC (rev 2784) +++ box/RELEASE/0.11/bin/bbackupd/BackupDaemon.cpp 2010-10-07 13:51:24 UTC (rev 2785) @@ -1731,8 +1731,15 @@ } // Any entries in the root directory which need deleting? - if(dir.GetNumberOfEntries() > 0) + if(dir.GetNumberOfEntries() > 0 && + mDeleteRedundantLocationsAfter == 0) { + BOX_NOTICE(dir.GetNumberOfEntries() << " redundant locations " + "in root directory found, but will not delete because " + "DeleteRedundantLocationsAfter = 0"); + } + else if(dir.GetNumberOfEntries() > 0) + { box_time_t now = GetCurrentBoxTime(); // This should reset the timer if the list of unused From trac at boxbackup.org Thu Oct 7 15:05:21 2010 From: trac at boxbackup.org (Box Backup) Date: Thu, 07 Oct 2010 14:05:21 -0000 Subject: [Box Backup-commit] #75: Restore times wrong, times on store correct In-Reply-To: <042.5704aa61abe7b503a533346538413ddb@boxbackup.org> References: <042.5704aa61abe7b503a533346538413ddb@boxbackup.org> Message-ID: <051.82f1945df23254b6cec1b42ce28e2a19@boxbackup.org> #75: Restore times wrong, times on store correct ---------------------------------+------------------------------------------ Reporter: achim | Owner: ben Type: defect | Status: new Priority: normal | Milestone: Component: bbackupd | Version: trunk Keywords: Restore times wrong | ---------------------------------+------------------------------------------ Comment(by achim): Another example I just found that even shows 3 different times: query > list -t 0000acfa f----- 2010-10-06T18:00:02 timetest.txt query > list -T 0000acfa f----- 2010-10-06T16:00:02 timetest.txt query > get timetest.txt query > sh dir timetest.txt 06/10/2010 17:00 2.827.316 timetest.txt -- Ticket URL: Box Backup An open source, completely automatic on-line backup system for UNIX. From subversion at boxbackup.org Sat Oct 9 05:17:17 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sat, 9 Oct 2010 05:17:17 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2786 - box/invisnet/vs2010/0.11/lib/common Message-ID: <20101009041717.0171616A7EC@www.boxbackup.org> Author: invisnet Date: 2010-10-09 05:17:16 +0100 (Sat, 09 Oct 2010) New Revision: 2786 Modified: box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp Log: Ignore Windows-style INI headers; fix the parser to stay within bounds Modified: box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp 2010-10-07 13:51:24 UTC (rev 2785) +++ box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp 2010-10-09 04:17:16 UTC (rev 2786) @@ -165,11 +165,25 @@ { return r; } + // Skip Windows INI style headers + // r might be empty so can't use r[0] + else if(r.c_str()[0] == '[') + { + r.clear(); + return r; + } else { + // Remove whitespace + int size = r.size(); + int begin = 0; + while(begin < size && iw(r[begin])) + { + begin++; + } + // Check for comment char, but char before must be whitespace - int end = 0; - int size = r.size(); + int end = begin; while(end < size) { if(r[end] == '#' && (end == 0 || (iw(r[end-1])))) @@ -179,17 +193,7 @@ end++; } - // Remove whitespace - int begin = 0; - while(begin < size && iw(r[begin])) - { - begin++; - } - if(!iw(r[end])) end--; - while(end > begin && iw(r[end])) - { - end--; - } + for(end--; end > begin && iw(r[end]); end--); // Return a sub string return r.substr(begin, end - begin + 1); From subversion at boxbackup.org Sun Oct 10 00:36:01 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 10 Oct 2010 00:36:01 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2787 - in box/invisnet/vs2010/0.11: bin/bbackupd bin/bbackupd/win32 lib/backupclient lib/server Message-ID: <20101009233601.A9A3516AAAB@www.boxbackup.org> Author: invisnet Date: 2010-10-10 00:36:00 +0100 (Sun, 10 Oct 2010) New Revision: 2787 Modified: box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp box/invisnet/vs2010/0.11/bin/bbackupd/win32/bbackupd.conf box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.cpp box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp box/invisnet/vs2010/0.11/lib/server/TLSContext.h Log: Non-working commit. Some things have standard places under Windows: Keys belong in a named container, Certs belong in a cert store, Application data belongs in the appdata shell folder Modified: box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp =================================================================== --- box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp 2010-10-09 04:17:16 UTC (rev 2786) +++ box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp 2010-10-09 23:36:00 UTC (rev 2787) @@ -80,6 +80,8 @@ #ifdef WIN32 #include "Win32ServiceFunctions.h" #include "Win32BackupService.h" + #include "Shlobj.h" + #include "Shlwapi.h" extern Win32BackupService* gpDaemonService; #endif @@ -1904,9 +1906,31 @@ // -------------------------------------------------------------------------- void BackupDaemon::MakeMapBaseName(unsigned int MountNumber, std::string &rNameOut) const { + std::string dir; + // Get the directory for the maps +#ifdef WIN32 + // we just ask the system where to put the files... + char path[MAX_PATH]; + + if (SUCCEEDED(SHGetFolderPath(NULL,CSIDL_LOCAL_APPDATA,NULL,0,path))) + { + PathAppend(path,"Box Backup"); + if(FALSE == CreateDirectory(path, NULL) + && ERROR_ALREADY_EXISTS != GetLastError()) + { + THROW_EXCEPTION(CommonException, OSFileError); + } + dir.assign(path); + } + else + { + THROW_EXCEPTION(CommonException, Internal); + } +#else const Configuration &config(GetConfiguration()); - std::string dir(config.GetKeyValue("DataDirectory")); + dir.assign(config.GetKeyValue("DataDirectory")); +#endif // Make a leafname std::string leaf(mIDMapMounts[MountNumber]); Modified: box/invisnet/vs2010/0.11/bin/bbackupd/win32/bbackupd.conf =================================================================== --- box/invisnet/vs2010/0.11/bin/bbackupd/win32/bbackupd.conf 2010-10-09 04:17:16 UTC (rev 2786) +++ box/invisnet/vs2010/0.11/bin/bbackupd/win32/bbackupd.conf 2010-10-09 23:36:00 UTC (rev 2787) @@ -1,14 +1,7 @@ - +[BoxBackup] StoreHostname = yourhost AccountNumber = 0x1 -KeysFile = C:\Program Files\Box Backup\1-FileEncKeys.raw -CertificateFile = C:\Program Files\Box Backup\1-cert.pem -PrivateKeyFile = C:\Program Files\Box Backup\1-key.pem -TrustedCAsFile = C:\Program Files\Box Backup\serverCA.pem - -DataDirectory = C:\Program Files\Box Backup\bbackupd - # If you do not install it in the default location - also do not forget to # change the pid file location (below) Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.cpp 2010-10-09 04:17:16 UTC (rev 2786) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.cpp 2010-10-09 23:36:00 UTC (rev 2787) @@ -107,19 +107,20 @@ ConfigurationVerifyKey("KeepAliveTime", ConfigTest_IsInt), ConfigurationVerifyKey("StoreObjectInfoFile", 0), // optional - - ConfigurationVerifyKey("NotifyScript", 0), - // optional script to run when backup needs attention, eg store full ConfigurationVerifyKey("NotifyAlways", ConfigTest_IsBool, false), // option to disable the suppression of duplicate notifications +#ifndef WIN32 ConfigurationVerifyKey("CertificateFile", ConfigTest_Exists), ConfigurationVerifyKey("PrivateKeyFile", ConfigTest_Exists), ConfigurationVerifyKey("TrustedCAsFile", ConfigTest_Exists), ConfigurationVerifyKey("KeysFile", ConfigTest_Exists), - ConfigurationVerifyKey("DataDirectory", - ConfigTest_Exists | ConfigTest_LastEntry), + ConfigurationVerifyKey("DataDirectory", ConfigTest_Exists), +#endif + + ConfigurationVerifyKey("NotifyScript", ConfigTest_LastEntry), + // optional script to run when backup needs attention, eg store full }; const ConfigurationVerify BackupDaemonConfigVerify = Modified: box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp 2010-10-09 04:17:16 UTC (rev 2786) +++ box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp 2010-10-09 23:36:00 UTC (rev 2787) @@ -11,6 +11,9 @@ #define TLS_CLASS_IMPLEMENTATION_CPP #include +#ifdef WIN32 +#include +#endif #include "TLSContext.h" #include "ServerException.h" @@ -19,6 +22,10 @@ #include "MemLeakFindOn.h" +#ifdef WIN32 +#include +#endif + #define MAX_VERIFICATION_DEPTH 2 #define CIPHER_LIST "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH" @@ -73,6 +80,38 @@ } // Setup our identity +#ifdef WIN32 + X509 *x509 = GetCertificate(); + if(::SSL_CTX_use_certificate(mpContext, x509) != 1) + { + SSLLib::LogError("SSL_CTX_use_certificate"); + THROW_EXCEPTION(ServerException, TLSLoadCertificatesFailed) + } + X509_free(x509); + + EVP_PKEY *evpPK = GetPrivateKey(); + if(::SSL_CTX_use_PrivateKey(mpContext, evpPK) != 1) + { + SSLLib::LogError("SSL_CTX_use_PrivateKey"); + THROW_EXCEPTION(ServerException, TLSLoadPrivateKeyFailed) + } + EVP_PKEY_free(evpPK); + + x509 = GetTrustedCertificate(); + X509_LOOKUP *lookup = ::X509_STORE_add_lookup(mpContext->cert_store, X509_LOOKUP_file()); + if(lookup == NULL) + { + SSLLib::LogError("X509_STORE_add_lookup"); + THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed) + } + if(::X509_STORE_add_cert(lookup->store_ctx, x509) != 1) + { + SSLLib::LogError("X509_STORE_add_cert"); + THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed) + } + // don't free lookup + X509_free(x509); +#else if(::SSL_CTX_use_certificate_chain_file(mpContext, CertificatesFile) != 1) { std::string msg = "loading certificates from "; @@ -87,7 +126,7 @@ SSLLib::LogError(msg); THROW_EXCEPTION(ServerException, TLSLoadPrivateKeyFailed) } - + // Setup the identify of CAs we trust if(::SSL_CTX_load_verify_locations(mpContext, TrustedCAsFile, NULL) != 1) { @@ -96,7 +135,8 @@ SSLLib::LogError(msg); THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed) } - +#endif + // Setup options to require these certificates ::SSL_CTX_set_verify(mpContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); // and a sensible maximum depth @@ -128,4 +168,208 @@ } +#ifdef WIN32 +// -------------------------------------------------------------------------- +// +// Function +// Name: TLSContext::GetCertificate() +// Purpose: Get the certificate from the store +// Created: 2010/09/03 +// +// -------------------------------------------------------------------------- +X509* TLSContext::GetCertificate() +{ + HCRYPTPROV hCryptProv = NULL; + X509 *x509 = NULL; + if (FALSE == CryptAcquireContext(&hCryptProv,"BoxBackup",NULL,PROV_RSA_FULL,CRYPT_MACHINE_KEYSET)) + { + BOX_ERROR("CryptAcquireContext failed"); + } + else + { + DWORD cbPublicKeyInfo = 0; + + if(FALSE == CryptExportPublicKeyInfo(hCryptProv, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, &cbPublicKeyInfo)) + { + BOX_ERROR("Failed to get buffer length for public key"); + } + else + { + char *PublicKeyBuffer = new char[cbPublicKeyInfo]; + CERT_PUBLIC_KEY_INFO* pbPublicKeyInfo = (CERT_PUBLIC_KEY_INFO*) PublicKeyBuffer; + + if(FALSE == CryptExportPublicKeyInfo(hCryptProv, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbPublicKeyInfo, &cbPublicKeyInfo)) + { + BOX_ERROR("Failed to export public key"); + } + else + { + HCERTSTORE hSystemStore; + + if (NULL == (hSystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG, L"MY"))) + { + BOX_ERROR("Failed to open store"); + } + else + { + PCCERT_CONTEXT pDesiredCert = NULL; + + if(NULL == (pDesiredCert = CertFindCertificateInStore(hSystemStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_PUBLIC_KEY, pbPublicKeyInfo, NULL))) + { + BOX_ERROR("No matching certificate"); + } + else + { + const unsigned char *pbCertEncoded = pDesiredCert->pbCertEncoded; + + x509 = d2i_X509(NULL, &pbCertEncoded, pDesiredCert->cbCertEncoded); + + CertFreeCertificateContext(pDesiredCert); + } + + CertCloseStore(hSystemStore,CERT_CLOSE_STORE_CHECK_FLAG); // TODO: check this + } + } + + delete[] PublicKeyBuffer; + } + + CryptReleaseContext(hCryptProv,0); + } + + if(NULL == x509) + { + THROW_EXCEPTION(ServerException, TLSLoadCertificatesFailed) + } + + return x509; +} + + +// -------------------------------------------------------------------------- +// +// Function +// Name: TLSContext::GetTrustedCertificate() +// Purpose: Get the certificate from the store +// Created: 2010/10/09 +// +// -------------------------------------------------------------------------- +X509* TLSContext::GetTrustedCertificate() +{ + X509 *x509 = NULL; + HCERTSTORE hSystemStore; + + if (NULL == (hSystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG, L"MY"))) + { + BOX_ERROR("Failed to open store"); + } + else + { + PCCERT_CONTEXT pDesiredCert = NULL; + + if(NULL == (pDesiredCert = CertFindCertificateInStore(hSystemStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, L"Backup system server root", NULL))) + { + BOX_ERROR("No matching root certificate"); + } + else + { + const unsigned char *pbCertEncoded = pDesiredCert->pbCertEncoded; + + x509 = d2i_X509(NULL, &pbCertEncoded, pDesiredCert->cbCertEncoded); + + CertFreeCertificateContext(pDesiredCert); + } + + CertCloseStore(hSystemStore,CERT_CLOSE_STORE_CHECK_FLAG); // TODO: check this + } + + if(NULL == x509) + { + THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed) + } + + return x509; +} + + +// -------------------------------------------------------------------------- +// +// Function +// Name: TLSContext::GetPrivateKey() +// Purpose: Get the private key from the container +// Created: 2010/09/03 +// +// -------------------------------------------------------------------------- +EVP_PKEY* TLSContext::GetPrivateKey() +{ + HCRYPTPROV hCryptProv = NULL; + EVP_PKEY *evpPK = NULL; + + if (FALSE == CryptAcquireContext(&hCryptProv,"BoxBackup",NULL,PROV_RSA_FULL,CRYPT_MACHINE_KEYSET)) + { + BOX_ERROR("CryptAcquireContext failed"); + } + else + { + HCRYPTKEY hKey = NULL; + + if (FALSE == CryptGetUserKey(hCryptProv,AT_SIGNATURE,&hKey)) + { + BOX_ERROR("CryptGetUserKey failed"); + } + else + { + DWORD len = 0; + + if(FALSE == CryptExportKey(hKey,NULL,PRIVATEKEYBLOB,0,NULL,&len)) + { + BOX_ERROR("CryptExportKey failed (first pass)"); + } + else + { + BYTE *key = new BYTE[len]; + + if(FALSE == CryptExportKey(hKey,NULL,PRIVATEKEYBLOB,0,key,&len)) + { + BOX_ERROR("CryptExportKey failed (second pass)"); + } + else if(FALSE == CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, key, NULL, &len)) + { + BOX_ERROR("CryptEncodeObject failed (first pass)"); + } + else + { + BYTE *encodedKey = new BYTE[len]; + + if(FALSE == CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, key, encodedKey, &len)) + { + BOX_ERROR("CryptEncodeObject failed (second pass)"); + } + else + { + const unsigned char *pEncodedKey = encodedKey; + + d2i_PrivateKey(EVP_PKEY_RSA, &evpPK, &pEncodedKey, len); + } + + delete[] encodedKey; + } + + delete[] key; + } + + CryptDestroyKey(hKey); + } + CryptReleaseContext(hCryptProv,0); + } + + if(NULL == evpPK) + { + THROW_EXCEPTION(ServerException, TLSLoadPrivateKeyFailed) + } + + return evpPK; +} + +#endif \ No newline at end of file Modified: box/invisnet/vs2010/0.11/lib/server/TLSContext.h =================================================================== --- box/invisnet/vs2010/0.11/lib/server/TLSContext.h 2010-10-09 04:17:16 UTC (rev 2786) +++ box/invisnet/vs2010/0.11/lib/server/TLSContext.h 2010-10-09 23:36:00 UTC (rev 2787) @@ -12,6 +12,8 @@ #ifndef TLS_CLASS_IMPLEMENTATION_CPP class SSL_CTX; + class EVP_PKEY; + class X509; #endif // -------------------------------------------------------------------------- @@ -35,6 +37,13 @@ private: SSL_CTX *mpContext; + +#ifdef WIN32 +private: + EVP_PKEY *GetPrivateKey(); + X509 *GetCertificate(); + X509 *GetTrustedCertificate(); +#endif }; #endif // TLSCONTEXT__H From subversion at boxbackup.org Mon Oct 11 21:42:31 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Mon, 11 Oct 2010 21:42:31 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2788 - box/invisnet/vs2010/0.11/lib/win32 Message-ID: <20101011204231.EB79216A34B@www.boxbackup.org> Author: invisnet Date: 2010-10-11 21:42:31 +0100 (Mon, 11 Oct 2010) New Revision: 2788 Modified: box/invisnet/vs2010/0.11/lib/win32/emu.cpp Log: Out-by-one error! Modified: box/invisnet/vs2010/0.11/lib/win32/emu.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/win32/emu.cpp 2010-10-09 23:36:00 UTC (rev 2787) +++ box/invisnet/vs2010/0.11/lib/win32/emu.cpp 2010-10-11 20:42:31 UTC (rev 2788) @@ -988,7 +988,7 @@ std::string dirName(name); //append a '\' win32 findfirst is sensitive to this - if ( dirName[dirName.size()] != '\\' || dirName[dirName.size()] != '/' ) + if ( dirName[dirName.size()-1] != '\\' || dirName[dirName.size()-1] != '/' ) { dirName += '\\'; } From subversion at boxbackup.org Mon Oct 11 23:19:28 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Mon, 11 Oct 2010 23:19:28 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2789 - box/invisnet/vs2010/0.11/lib/backupclient Message-ID: <20101011221928.69FDE16A384@www.boxbackup.org> Author: invisnet Date: 2010-10-11 23:19:27 +0100 (Mon, 11 Oct 2010) New Revision: 2789 Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h Log: Undo type change; too many logic changes in sensitive areas Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h 2010-10-11 20:42:31 UTC (rev 2788) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h 2010-10-11 22:19:27 UTC (rev 2789) @@ -113,7 +113,7 @@ int64_t mTotalBlocks; // Total number of blocks in the file int64_t mAbsoluteBlockNumber; // The absolute block number currently being output // Instruction number - Recipe::size_type mInstructionNumber; + int64_t mInstructionNumber; // All the below are within the current instruction int64_t mNumBlocks; // number of blocks. Last one will be a different size to the rest in most cases int64_t mCurrentBlock; From subversion at boxbackup.org Tue Oct 12 00:28:19 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Tue, 12 Oct 2010 00:28:19 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2790 - in box/invisnet/vs2010/0.11: bin/bbackupd lib/backupclient lib/server lib/win32 Message-ID: <20101011232819.E436F16A49B@www.boxbackup.org> Author: invisnet Date: 2010-10-12 00:28:19 +0100 (Tue, 12 Oct 2010) New Revision: 2790 Modified: box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupClientCryptoKeys.cpp box/invisnet/vs2010/0.11/lib/server/ServerTLS.h box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp box/invisnet/vs2010/0.11/lib/server/TLSContext.h box/invisnet/vs2010/0.11/lib/win32/emu.cpp Log: Use standard directories for data files; "serverCA.pem" from local computer certificate store; "FileEncKeys" from registry Modified: box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp =================================================================== --- box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp 2010-10-11 22:19:27 UTC (rev 2789) +++ box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp 2010-10-11 23:28:19 UTC (rev 2790) @@ -411,14 +411,23 @@ { // Read in the certificates creating a TLS context const Configuration &conf(GetConfiguration()); + +#ifdef WIN32 + std::string certFile; + std::string keyFile; + std::string caFile; + std::string keysFile; +#else std::string certFile(conf.GetKeyValue("CertificateFile")); std::string keyFile(conf.GetKeyValue("PrivateKeyFile")); std::string caFile(conf.GetKeyValue("TrustedCAsFile")); + std::string keysFile(conf.GetKeyValue("KeysFile")); +#endif mTlsContext.Initialise(false /* as client */, certFile.c_str(), keyFile.c_str(), caFile.c_str()); // Set up the keys for various things - BackupClientCryptoKeys_Setup(conf.GetKeyValue("KeysFile").c_str()); + BackupClientCryptoKeys_Setup(keysFile.c_str()); } // -------------------------------------------------------------------------- @@ -1913,9 +1922,12 @@ // we just ask the system where to put the files... char path[MAX_PATH]; - if (SUCCEEDED(SHGetFolderPath(NULL,CSIDL_LOCAL_APPDATA,NULL,0,path))) + if(SUCCEEDED(SHGetFolderPath(NULL,CSIDL_COMMON_APPDATA,NULL,0,path))) { - PathAppend(path,"Box Backup"); + if(FALSE == PathAppend(path,"Box Backup")) + { + THROW_EXCEPTION(CommonException, Internal); + } if(FALSE == CreateDirectory(path, NULL) && ERROR_ALREADY_EXISTS != GetLastError()) { @@ -2131,9 +2143,32 @@ // -------------------------------------------------------------------------- void BackupDaemon::TouchFileInWorkingDir(const char *Filename) { + std::string fn; + +#ifdef WIN32 + // we just ask the system where to put the files... + char path[MAX_PATH]; + + if (SUCCEEDED(SHGetFolderPath(NULL,CSIDL_COMMON_APPDATA,NULL,0,path))) + { + PathAppend(path,"Box Backup"); + if(FALSE == CreateDirectory(path, NULL) + && ERROR_ALREADY_EXISTS != GetLastError()) + { + // TODO: throw something sensible; this really shouldn't be possible + } + fn.assign(path); + } + else + { + // TODO: need to throw something helpful + } +#else // Filename const Configuration &config(GetConfiguration()); - std::string fn(config.GetKeyValue("DataDirectory") + DIRECTORY_SEPARATOR_ASCHAR); + fn.assign(config.GetKeyValue("DataDirectory")); +#endif + fn += DIRECTORY_SEPARATOR_ASCHAR; fn += Filename; // Open and close it to update the timestamp Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupClientCryptoKeys.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupClientCryptoKeys.cpp 2010-10-11 22:19:27 UTC (rev 2789) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupClientCryptoKeys.cpp 2010-10-11 23:28:19 UTC (rev 2790) @@ -33,6 +33,30 @@ // Read in the key material unsigned char KeyMaterial[BACKUPCRYPTOKEYS_FILE_SIZE]; +#ifdef WIN32 + DWORD gle; + HKEY hKey; + + (void)rKeyMaterialFilename; + + if(ERROR_SUCCESS != (gle = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Box Backup",0,KEY_QUERY_VALUE,&hKey))) + { + THROW_EXCEPTION(BackupStoreException, CouldntLoadClientKeyMaterial) + } + else + { + DWORD lenKeyMaterial = BACKUPCRYPTOKEYS_FILE_SIZE; + + gle = RegQueryValueEx(hKey,"FileEncKeys",NULL,NULL,KeyMaterial,&lenKeyMaterial); + printf("gle: %d\n",gle); + RegCloseKey(hKey); + + if(ERROR_SUCCESS != gle) + { + THROW_EXCEPTION(BackupStoreException, CouldntLoadClientKeyMaterial) + } + } +#else // Open the file FileStream file(rKeyMaterialFilename); @@ -41,7 +65,8 @@ { THROW_EXCEPTION(BackupStoreException, CouldntLoadClientKeyMaterial) } - +#endif + // Setup keys and encoding method for filename encryption BackupStoreFilenameClear::SetBlowfishKey( KeyMaterial + BACKUPCRYPTOKEYS_FILENAME_KEY_START, Modified: box/invisnet/vs2010/0.11/lib/server/ServerTLS.h =================================================================== --- box/invisnet/vs2010/0.11/lib/server/ServerTLS.h 2010-10-11 22:19:27 UTC (rev 2789) +++ box/invisnet/vs2010/0.11/lib/server/ServerTLS.h 2010-10-11 23:28:19 UTC (rev 2790) @@ -49,9 +49,15 @@ // this-> in next line required to build under some gcc versions const Configuration &conf(this->GetConfiguration()); const Configuration &serverconf(conf.GetSubConfiguration("Server")); +#ifdef WIN32 + std::string certFile; + std::string keyFile; + std::string caFile; +#else std::string certFile(serverconf.GetKeyValue("CertificateFile")); std::string keyFile(serverconf.GetKeyValue("PrivateKeyFile")); std::string caFile(serverconf.GetKeyValue("TrustedCAsFile")); +#endif mContext.Initialise(true /* as server */, certFile.c_str(), keyFile.c_str(), caFile.c_str()); // Then do normal stream server stuff Modified: box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp 2010-10-11 22:19:27 UTC (rev 2789) +++ box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp 2010-10-11 23:28:19 UTC (rev 2790) @@ -81,36 +81,42 @@ // Setup our identity #ifdef WIN32 - X509 *x509 = GetCertificate(); - if(::SSL_CTX_use_certificate(mpContext, x509) != 1) { - SSLLib::LogError("SSL_CTX_use_certificate"); - THROW_EXCEPTION(ServerException, TLSLoadCertificatesFailed) + X509 *x509 = GetTrustedCertificate(); + X509_LOOKUP *lookup = ::X509_STORE_add_lookup(mpContext->cert_store, X509_LOOKUP_file()); + if(lookup == NULL) + { + SSLLib::LogError("X509_STORE_add_lookup"); + THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed) + } + if(::X509_STORE_add_cert(lookup->store_ctx, x509) != 1) + { + SSLLib::LogError("X509_STORE_add_cert"); + THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed) + } + // don't free lookup + X509_free(x509); } - X509_free(x509); - EVP_PKEY *evpPK = GetPrivateKey(); - if(::SSL_CTX_use_PrivateKey(mpContext, evpPK) != 1) { - SSLLib::LogError("SSL_CTX_use_PrivateKey"); - THROW_EXCEPTION(ServerException, TLSLoadPrivateKeyFailed) + X509 *x509 = GetCertificate(); + if(::SSL_CTX_use_certificate(mpContext, x509) != 1) + { + SSLLib::LogError("SSL_CTX_use_certificate"); + THROW_EXCEPTION(ServerException, TLSLoadCertificatesFailed) + } + X509_free(x509); } - EVP_PKEY_free(evpPK); - x509 = GetTrustedCertificate(); - X509_LOOKUP *lookup = ::X509_STORE_add_lookup(mpContext->cert_store, X509_LOOKUP_file()); - if(lookup == NULL) { - SSLLib::LogError("X509_STORE_add_lookup"); - THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed) + EVP_PKEY *evpPK = GetPrivateKey(); + if(::SSL_CTX_use_PrivateKey(mpContext, evpPK) != 1) + { + SSLLib::LogError("SSL_CTX_use_PrivateKey"); + THROW_EXCEPTION(ServerException, TLSLoadPrivateKeyFailed) + } + EVP_PKEY_free(evpPK); } - if(::X509_STORE_add_cert(lookup->store_ctx, x509) != 1) - { - SSLLib::LogError("X509_STORE_add_cert"); - THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed) - } - // don't free lookup - X509_free(x509); #else if(::SSL_CTX_use_certificate_chain_file(mpContext, CertificatesFile) != 1) { Modified: box/invisnet/vs2010/0.11/lib/server/TLSContext.h =================================================================== --- box/invisnet/vs2010/0.11/lib/server/TLSContext.h 2010-10-11 22:19:27 UTC (rev 2789) +++ box/invisnet/vs2010/0.11/lib/server/TLSContext.h 2010-10-11 23:28:19 UTC (rev 2790) @@ -14,6 +14,7 @@ class SSL_CTX; class EVP_PKEY; class X509; + class X509_LOOKUP; #endif // -------------------------------------------------------------------------- Modified: box/invisnet/vs2010/0.11/lib/win32/emu.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/win32/emu.cpp 2010-10-11 22:19:27 UTC (rev 2789) +++ box/invisnet/vs2010/0.11/lib/win32/emu.cpp 2010-10-11 23:28:19 UTC (rev 2790) @@ -11,6 +11,8 @@ #include #include #include +#include "Shlobj.h" +#include "Shlwapi.h" #ifdef HAVE_UNISTD_H #include @@ -32,7 +34,7 @@ TOKEN_PRIVILEGES token_priv; //open current process to adjust privileges - if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, + if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { ::syslog(LOG_ERR, "Failed to open process token: %s", @@ -40,7 +42,7 @@ return false; } - //let's build the token privilege struct - + //let's build the token privilege struct - //first, look up the LUID for the backup privilege if (!LookupPrivilegeValue( @@ -58,7 +60,7 @@ token_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // now set the privilege - // because we're going exit right after dumping the streams, there isn't + // because we're going exit right after dumping the streams, there isn't // any need to save current state if (!AdjustTokenPrivileges( @@ -98,34 +100,25 @@ // -------------------------------------------------------------------------- std::string GetDefaultConfigFilePath(const std::string& rName) { - WCHAR exePathWide[MAX_PATH]; - GetModuleFileNameW(NULL, exePathWide, MAX_PATH-1); + // we just ask the system where to get the file... + char path[MAX_PATH]; - char* exePathUtf8 = ConvertFromWideString(exePathWide, CP_UTF8); - if (exePathUtf8 == NULL) + if(FAILED(SHGetFolderPath(NULL,CSIDL_COMMON_APPDATA,NULL,0,path)) + || FALSE == PathAppend(path,"Box Backup") + || FALSE == PathAppend(path,rName.c_str())) { return ""; } - std::string configfile = exePathUtf8; - delete [] exePathUtf8; - - // make the default config file name, - // based on the program path - configfile = configfile.substr(0, - configfile.rfind('\\')); - configfile += "\\"; - configfile += rName; - - return configfile; + return std::string(path); } // -------------------------------------------------------------------------- // // Function // Name: ConvertToWideString -// Purpose: Converts a string from specified codepage to -// a wide string (WCHAR*). Returns a buffer which +// Purpose: Converts a string from specified codepage to +// a wide string (WCHAR*). Returns a buffer which // MUST be freed by the caller with delete[]. // In case of fire, logs the error and returns NULL. // Created: 4th February 2006 @@ -141,7 +134,7 @@ pString, // string to map -1, // number of bytes in string - auto detect NULL, // wide-character buffer - 0 // size of buffer - work out + 0 // size of buffer - work out // how much space we need ); @@ -150,7 +143,7 @@ winerrno = GetLastError(); if (logErrors) { - ::syslog(LOG_WARNING, + ::syslog(LOG_WARNING, "Failed to convert string to wide string: " "%s", GetErrorMessage(winerrno).c_str()); } @@ -164,7 +157,7 @@ { if (logErrors) { - ::syslog(LOG_WARNING, + ::syslog(LOG_WARNING, "Failed to convert string to wide string: " "out of memory"); } @@ -188,7 +181,7 @@ winerrno = GetLastError(); if (logErrors) { - ::syslog(LOG_WARNING, + ::syslog(LOG_WARNING, "Failed to convert string to wide string: " "%s", GetErrorMessage(winerrno).c_str()); } @@ -205,7 +198,7 @@ // Function // Name: ConvertUtf8ToWideString // Purpose: Converts a string from UTF-8 to a wide string. -// Returns a buffer which MUST be freed by the caller +// Returns a buffer which MUST be freed by the caller // with delete[]. // In case of fire, logs the error and returns NULL. // Created: 4th February 2006 @@ -221,7 +214,7 @@ // Function // Name: ConvertFromWideString // Purpose: Converts a wide string to a narrow string in the -// specified code page. Returns a buffer which MUST +// specified code page. Returns a buffer which MUST // be freed by the caller with delete[]. // In case of fire, logs the error and returns NULL. // Created: 4th February 2006 @@ -236,7 +229,7 @@ pString, // string to map -1, // number of bytes in string - auto detect NULL, // output buffer - 0, // size of buffer - work out + 0, // size of buffer - work out // how much space we need NULL, // replace unknown chars with system default NULL // don't tell us when that happened @@ -244,7 +237,7 @@ if (len == 0) { - ::syslog(LOG_WARNING, + ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " "error %d", GetLastError()); errno = EINVAL; @@ -255,7 +248,7 @@ if (buffer == NULL) { - ::syslog(LOG_WARNING, + ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " "out of memory"); errno = ENOMEM; @@ -276,7 +269,7 @@ if (len == 0) { - ::syslog(LOG_WARNING, + ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " "error %i", GetLastError()); errno = EACCES; @@ -290,11 +283,11 @@ // -------------------------------------------------------------------------- // // Function -// Name: ConvertEncoding(const std::string&, int, +// Name: ConvertEncoding(const std::string&, int, // std::string&, int) // Purpose: Converts a string from one code page to another. -// On success, replaces contents of rDest and returns -// true. In case of fire, logs the error and returns +// On success, replaces contents of rDest and returns +// true. In case of fire, logs the error and returns // false. // Created: 15th October 2006 // @@ -374,16 +367,16 @@ } std::string tmpStr("\\\\?\\"); - + // Is the path relative or absolute? // Absolute paths on Windows are always a drive letter // followed by ':' - + char wd[PATH_MAX]; if (::getcwd(wd, PATH_MAX) == 0) { - ::syslog(LOG_WARNING, - "Failed to open '%s': path too long", + ::syslog(LOG_WARNING, + "Failed to open '%s': path too long", pFileName); errno = ENAMETOOLONG; winerrno = ERROR_INVALID_NAME; @@ -407,7 +400,7 @@ } else if (filename.length() >= 2 && filename[1] != ':') { - // Must be relative. We need to get the + // Must be relative. We need to get the // current directory to make it absolute. tmpStr += wd; if (tmpStr[tmpStr.length()] != '\\') @@ -415,7 +408,7 @@ tmpStr += '\\'; } } - + tmpStr += filename; // We are using direct filename access, which does not support .., @@ -430,7 +423,7 @@ if (lastSlash == std::string::npos) { - // no previous directory, ignore it, + // no previous directory, ignore it, // CreateFile will fail with error 123 } else @@ -449,10 +442,10 @@ std::string GetErrorMessage(DWORD errorCode) { char* pMsgBuf = NULL; - + DWORD chars = FormatMessage ( - FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode, @@ -481,7 +474,7 @@ // // Function // Name: openfile -// Purpose: replacement for any open calls - handles unicode +// Purpose: replacement for any open calls - handles unicode // filenames - supplied in utf8 // Created: 25th October 2004 // @@ -490,18 +483,18 @@ { winerrno = ERROR_INVALID_FUNCTION; - std::string AbsPathWithUnicode = + std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName); - + if (AbsPathWithUnicode.size() == 0) { // error already logged by ConvertPathToAbsoluteUnicode() return INVALID_HANDLE_VALUE; } - + WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); // We are responsible for freeing pBuffer - + if (pBuffer == NULL) { // error already logged by ConvertUtf8ToWideString() @@ -510,9 +503,9 @@ // flags could be O_WRONLY | O_CREAT | O_RDONLY DWORD createDisposition = OPEN_EXISTING; - DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE + DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - DWORD accessRights = FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY + DWORD accessRights = FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA; if (flags & O_WRONLY) @@ -521,7 +514,7 @@ } else if (flags & O_RDWR) { - accessRights |= FILE_WRITE_ATTRIBUTES + accessRights |= FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA; } @@ -551,14 +544,14 @@ winFlags |= FILE_FLAG_DELETE_ON_CLOSE; } - HANDLE hdir = CreateFileW(pBuffer, - accessRights, - shareMode, - NULL, - createDisposition, + HANDLE hdir = CreateFileW(pBuffer, + accessRights, + shareMode, + NULL, + createDisposition, winFlags, NULL); - + delete [] pBuffer; if (hdir == INVALID_HANDLE_VALUE) @@ -575,7 +568,7 @@ } ::syslog(LOG_WARNING, "Failed to open file '%s': " - "%s", pFileName, + "%s", pFileName, GetErrorMessage(GetLastError()).c_str()); return INVALID_HANDLE_VALUE; @@ -708,7 +701,7 @@ // // Function // Name: OpenFileByNameUtf8 -// Purpose: Converts filename to Unicode and returns +// Purpose: Converts filename to Unicode and returns // a handle to it. In case of error, sets errno, // logs the error and returns NULL. // Created: 10th December 2004 @@ -716,43 +709,43 @@ // -------------------------------------------------------------------------- HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags) { - std::string AbsPathWithUnicode = + std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName); - + if (AbsPathWithUnicode.size() == 0) { // error already logged by ConvertPathToAbsoluteUnicode() return NULL; } - + WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); // We are responsible for freeing pBuffer - + if (pBuffer == NULL) { // error already logged by ConvertUtf8ToWideString() return NULL; } - HANDLE handle = CreateFileW(pBuffer, + HANDLE handle = CreateFileW(pBuffer, flags, - FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, + FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (handle == INVALID_HANDLE_VALUE) { - // if our open fails we should always be able to + // if our open fails we should always be able to // open in this mode - to get the inode information - // at least one process must have the file open - + // at least one process must have the file open - // in this case someone else does. - handle = CreateFileW(pBuffer, + handle = CreateFileW(pBuffer, READ_CONTROL, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } @@ -771,7 +764,7 @@ else { ::syslog(LOG_WARNING, "Failed to open '%s': " - "%s", pFileName, + "%s", pFileName, GetErrorMessage(err).c_str()); errno = EACCES; } @@ -785,8 +778,8 @@ // -------------------------------------------------------------------------- // // Function -// Name: emu_stat -// Purpose: replacement for the lstat and stat functions. +// Name: emu_stat +// Purpose: replacement for the lstat and stat functions. // Works with unicode filenames supplied in utf8. // Returns a struct emu_stat to have room for 64-bit // file identifier in st_ino (mingw allows only 16!) @@ -795,7 +788,7 @@ // -------------------------------------------------------------------------- int emu_stat(const char * pName, struct emu_stat * st) { - HANDLE handle = OpenFileByNameUtf8(pName, + HANDLE handle = OpenFileByNameUtf8(pName, FILE_READ_ATTRIBUTES | FILE_READ_EA); if (handle == NULL) @@ -822,7 +815,7 @@ // // Function // Name: statfs -// Purpose: returns the mount point of where a file is located - +// Purpose: returns the mount point of where a file is located - // in this case the volume serial number // Created: 25th October 2004 // @@ -917,18 +910,18 @@ // -------------------------------------------------------------------------- int emu_chmod(const char * pName, mode_t mode) { - std::string AbsPathWithUnicode = + std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pName); - + if (AbsPathWithUnicode.size() == 0) { // error already logged by ConvertPathToAbsoluteUnicode() return -1; } - + WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); // We are responsible for freeing pBuffer - + if (pBuffer == NULL) { // error already logged by ConvertUtf8ToWideString() @@ -984,7 +977,7 @@ errno = EINVAL; return NULL; } - + std::string dirName(name); //append a '\' win32 findfirst is sensitive to this @@ -1005,7 +998,7 @@ pDir->name = ConvertUtf8ToWideString(dirName.c_str()); // We are responsible for freeing dir->name with delete[] - + if (pDir->name == NULL) { delete pDir; @@ -1020,7 +1013,7 @@ delete pDir; return NULL; } - + pDir->result.d_name = 0; return pDir; } @@ -1045,14 +1038,14 @@ if (dp && dp->fd != -1) { - if (!dp->result.d_name || + if (!dp->result.d_name || _wfindnext(dp->fd, &dp->info) != -1) { den = &dp->result; std::wstring input(dp->info.name); memset(tempbuff, 0, sizeof(tempbuff)); - WideCharToMultiByte(CP_UTF8, 0, dp->info.name, - -1, &tempbuff[0], sizeof (tempbuff), + WideCharToMultiByte(CP_UTF8, 0, dp->info.name, + -1, &tempbuff[0], sizeof (tempbuff), NULL, NULL); //den->d_name = (char *)dp->info.name; den->d_name = &tempbuff[0]; @@ -1103,7 +1096,7 @@ delete dp; } - if (finres == -1) // errors go to EBADF + if (finres == -1) // errors go to EBADF { errno = EBADF; } @@ -1121,7 +1114,7 @@ // // Function // Name: poll -// Purpose: a weak implimentation (just enough for box) +// Purpose: a weak implimentation (just enough for box) // of the unix poll for winsock2 // Created: 25th October 2004 // @@ -1139,7 +1132,7 @@ // struct pollfd *ufdsTmp = ufds; timeval timOut; - timeval *tmpptr; + timeval *tmpptr; if (timeout == INFTIM) tmpptr = NULL; @@ -1169,7 +1162,7 @@ ufd->events); return -1; } - } + } int nready = select(0, &readfd, &writefd, 0, tmpptr); @@ -1234,86 +1227,86 @@ return FALSE; } - // Create the event source as a subkey of the log. + // Create the event source as a subkey of the log. std::string regkey("SYSTEM\\CurrentControlSet\\Services\\EventLog\\" "Application\\"); - regkey += pszSrcName; - + regkey += pszSrcName; + HKEY hk; DWORD dwDisp; - if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, regkey.c_str(), + if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, regkey.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_WRITE, NULL, &hk, &dwDisp)) + KEY_WRITE, NULL, &hk, &dwDisp)) { ::syslog(LOG_ERR, "Failed to create the registry key: %s", GetErrorMessage(GetLastError()).c_str()); return FALSE; } - // Set the name of the message file. - - if (RegSetValueExW(hk, // subkey handle - L"EventMessageFile", // value name - 0, // must be zero - REG_EXPAND_SZ, // value type - (LPBYTE)cmd, // pointer to value data + // Set the name of the message file. + + if (RegSetValueExW(hk, // subkey handle + L"EventMessageFile", // value name + 0, // must be zero + REG_EXPAND_SZ, // value type + (LPBYTE)cmd, // pointer to value data len*sizeof(WCHAR))) // data size { ::syslog(LOG_ERR, "Failed to set the event message file: %s", GetErrorMessage(GetLastError()).c_str()); - RegCloseKey(hk); + RegCloseKey(hk); return FALSE; } - - // Set the supported event types. - - DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | - EVENTLOG_INFORMATION_TYPE; - - if (RegSetValueEx(hk, // subkey handle - "TypesSupported", // value name - 0, // must be zero - REG_DWORD, // value type - (LPBYTE) &dwData, // pointer to value data - sizeof(DWORD))) // length of value data + + // Set the supported event types. + + DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | + EVENTLOG_INFORMATION_TYPE; + + if (RegSetValueEx(hk, // subkey handle + "TypesSupported", // value name + 0, // must be zero + REG_DWORD, // value type + (LPBYTE) &dwData, // pointer to value data + sizeof(DWORD))) // length of value data { ::syslog(LOG_ERR, "Failed to set the supported types: %s", GetErrorMessage(GetLastError()).c_str()); - RegCloseKey(hk); + RegCloseKey(hk); return FALSE; } - + // Set the category message file and number of categories. - if (RegSetValueExW(hk, // subkey handle - L"CategoryMessageFile", // value name - 0, // must be zero - REG_EXPAND_SZ, // value type - (LPBYTE)cmd, // pointer to value data + if (RegSetValueExW(hk, // subkey handle + L"CategoryMessageFile", // value name + 0, // must be zero + REG_EXPAND_SZ, // value type + (LPBYTE)cmd, // pointer to value data len*sizeof(WCHAR))) // data size { ::syslog(LOG_ERR, "Failed to set the category message file: " "%s", GetErrorMessage(GetLastError()).c_str()); - RegCloseKey(hk); + RegCloseKey(hk); return FALSE; } - - if (RegSetValueEx(hk, // subkey handle - "CategoryCount", // value name - 0, // must be zero - REG_DWORD, // value type - (LPBYTE) &dwNum, // pointer to value data - sizeof(DWORD))) // length of value data + + if (RegSetValueEx(hk, // subkey handle + "CategoryCount", // value name + 0, // must be zero + REG_DWORD, // value type + (LPBYTE) &dwNum, // pointer to value data + sizeof(DWORD))) // length of value data { ::syslog(LOG_ERR, "Failed to set the category count: %s", GetErrorMessage(GetLastError()).c_str()); - RegCloseKey(hk); + RegCloseKey(hk); return FALSE; } - RegCloseKey(hk); + RegCloseKey(hk); return TRUE; } @@ -1329,9 +1322,9 @@ // register a default event source, so that we can // log errors with the process of adding or registering our own. gSyslogH = RegisterEventSource( - NULL, // uses local computer + NULL, // uses local computer nameStr.c_str()); // source name - if (gSyslogH == NULL) + if (gSyslogH == NULL) { } @@ -1359,7 +1352,7 @@ void closelog(void) { - DeregisterEventSource(gSyslogH); + DeregisterEventSource(gSyslogH); } void syslog(int loglevel, const char *frmt, ...) @@ -1402,13 +1395,13 @@ int len = vsnprintf(buffer, sizeof(buffer)-1, sixfour.c_str(), args); assert(len >= 0); - if (len < 0) + if (len < 0) { printf("%s\r\n", buffer); fflush(stdout); return; } - + assert((size_t)len < sizeof(buffer)); buffer[sizeof(buffer)-1] = 0; @@ -1432,33 +1425,33 @@ buffer2 += " (failed to convert string encoding)"; LPCSTR strings[] = { buffer2.c_str(), NULL }; - result = ReportEventA(gSyslogH, // event log handle - errinfo, // event type - 0, // category zero - MSG_ERR, // event identifier - + result = ReportEventA(gSyslogH, // event log handle + errinfo, // event type + 0, // category zero + MSG_ERR, // event identifier - // we will call them all the same - NULL, // no user security identifier - 1, // one substitution string - 0, // no data - strings, // pointer to string array - NULL); // pointer to data + NULL, // no user security identifier + 1, // one substitution string + 0, // no data + strings, // pointer to string array + NULL); // pointer to data } else { LPCWSTR strings[] = { pWide, NULL }; - result = ReportEventW(gSyslogH, // event log handle - errinfo, // event type - 0, // category zero - MSG_ERR, // event identifier - + result = ReportEventW(gSyslogH, // event log handle + errinfo, // event type + 0, // category zero + MSG_ERR, // event identifier - // we will call them all the same - NULL, // no user security identifier - 1, // one substitution string - 0, // no data - strings, // pointer to string array - NULL); // pointer to data + NULL, // no user security identifier + 1, // one substitution string + 0, // no data + strings, // pointer to string array + NULL); // pointer to data delete [] pWide; } - + if (result == 0) { DWORD err = GetLastError(); @@ -1488,7 +1481,7 @@ int emu_chdir(const char* pDirName) { /* - std::string AbsPathWithUnicode = + std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pDirName); if (AbsPathWithUnicode.size() == 0) @@ -1561,7 +1554,7 @@ int emu_mkdir(const char* pPathName) { - std::string AbsPathWithUnicode = + std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pPathName); if (AbsPathWithUnicode.size() == 0) @@ -1590,7 +1583,7 @@ int emu_unlink(const char* pFileName) { - std::string AbsPathWithUnicode = + std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName); if (AbsPathWithUnicode.size() == 0) @@ -1626,7 +1619,7 @@ else { ::syslog(LOG_WARNING, "Failed to delete file " - "'%s': %s", pFileName, + "'%s': %s", pFileName, GetErrorMessage(err).c_str()); errno = ENOSYS; } @@ -1638,7 +1631,7 @@ int emu_rename(const char* pOldFileName, const char* pNewFileName) { - std::string OldPathWithUnicode = + std::string OldPathWithUnicode = ConvertPathToAbsoluteUnicode(pOldFileName); if (OldPathWithUnicode.size() == 0) @@ -1653,7 +1646,7 @@ return -1; } - std::string NewPathWithUnicode = + std::string NewPathWithUnicode = ConvertPathToAbsoluteUnicode(pNewFileName); if (NewPathWithUnicode.size() == 0) @@ -1730,7 +1723,7 @@ WideSize, // will not be null terminated by ReadConsole &numCharsRead, NULL // reserved - )) + )) { ::fprintf(stderr, "Failed to read from console: %s\n", GetErrorMessage(GetLastError()).c_str()); @@ -1751,10 +1744,10 @@ int readv (int filedes, const struct iovec *vector, size_t count) { int bytes = 0; - + for (size_t i = 0; i < count; i++) { - int result = read(filedes, vector[i].iov_base, + int result = read(filedes, vector[i].iov_base, vector[i].iov_len); if (result < 0) { @@ -1769,10 +1762,10 @@ int writev(int filedes, const struct iovec *vector, size_t count) { int bytes = 0; - + for (size_t i = 0; i < count; i++) { - int result = write(filedes, vector[i].iov_base, + int result = write(filedes, vector[i].iov_base, vector[i].iov_len); if (result < 0) { @@ -1793,7 +1786,7 @@ // Convert the last-write time to local time. FileTimeToSystemTime(fileTime, &stUTC); - memset(&timeinfo, 0, sizeof(timeinfo)); + memset(&timeinfo, 0, sizeof(timeinfo)); timeinfo.tm_sec = stUTC.wSecond; timeinfo.tm_min = stUTC.wMinute; timeinfo.tm_hour = stUTC.wHour; From subversion at boxbackup.org Sat Oct 16 18:31:20 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sat, 16 Oct 2010 18:31:20 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2791 - box/invisnet/vs2010/0.11/lib/server Message-ID: <20101016173120.393CB16A3A9@www.boxbackup.org> Author: invisnet Date: 2010-10-16 18:31:19 +0100 (Sat, 16 Oct 2010) New Revision: 2791 Modified: box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp Log: Associate the certificate and the private key Modified: box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp 2010-10-11 23:28:19 UTC (rev 2790) +++ box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp 2010-10-16 17:31:19 UTC (rev 2791) @@ -213,7 +213,7 @@ { HCERTSTORE hSystemStore; - if (NULL == (hSystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG, L"MY"))) + if (NULL == (hSystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY"))) { BOX_ERROR("Failed to open store"); } @@ -231,6 +231,25 @@ x509 = d2i_X509(NULL, &pbCertEncoded, pDesiredCert->cbCertEncoded); + DWORD pcbData = 0; + if (CertGetCertificateContextProperty(pDesiredCert,CERT_KEY_PROV_INFO_PROP_ID,NULL,&pcbData)) + { + BOX_TRACE("Certificate has associated Private Key"); + } + else + { + CRYPT_KEY_PROV_INFO cryptKeyProvInfo = { L"BoxBackup",MS_DEF_PROV_W,PROV_RSA_FULL,CRYPT_MACHINE_KEYSET,0,NULL,AT_SIGNATURE }; + + if (!CertSetCertificateContextProperty(pDesiredCert,CERT_KEY_PROV_INFO_PROP_ID,0,&cryptKeyProvInfo)) + { + BOX_ERROR("SetCertProp failed"); + } + else + { + BOX_INFO("Associated Private Key with certificate"); + } + } + CertFreeCertificateContext(pDesiredCert); } From subversion at boxbackup.org Sun Oct 17 22:31:29 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 17 Oct 2010 22:31:29 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2792 - in box/invisnet/vs2010/0.11/lib: backupclient common compress crypto server Message-ID: <20101017213129.50CF516A8A8@www.boxbackup.org> Author: invisnet Date: 2010-10-17 22:31:28 +0100 (Sun, 17 Oct 2010) New Revision: 2792 Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupClientFileAttributes.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupClientRestore.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.h box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCmbDiff.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCmbIdx.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCombine.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileDiff.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileRevDiff.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilename.h box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.cpp box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.h box/invisnet/vs2010/0.11/lib/common/Archive.h box/invisnet/vs2010/0.11/lib/common/BufferedStream.cpp box/invisnet/vs2010/0.11/lib/common/BufferedStream.h box/invisnet/vs2010/0.11/lib/common/CollectInBufferStream.cpp box/invisnet/vs2010/0.11/lib/common/CollectInBufferStream.h box/invisnet/vs2010/0.11/lib/common/ExcludeList.cpp box/invisnet/vs2010/0.11/lib/common/ExcludeList.h box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp box/invisnet/vs2010/0.11/lib/common/FileStream.cpp box/invisnet/vs2010/0.11/lib/common/FileStream.h box/invisnet/vs2010/0.11/lib/common/Guards.h box/invisnet/vs2010/0.11/lib/common/IOStream.cpp box/invisnet/vs2010/0.11/lib/common/IOStream.h box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.cpp box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.h box/invisnet/vs2010/0.11/lib/common/MemBlockStream.cpp box/invisnet/vs2010/0.11/lib/common/MemBlockStream.h box/invisnet/vs2010/0.11/lib/common/PartialReadStream.cpp box/invisnet/vs2010/0.11/lib/common/PartialReadStream.h box/invisnet/vs2010/0.11/lib/common/ReadGatherStream.cpp box/invisnet/vs2010/0.11/lib/common/ReadGatherStream.h box/invisnet/vs2010/0.11/lib/common/ReadLoggingStream.cpp box/invisnet/vs2010/0.11/lib/common/ReadLoggingStream.h box/invisnet/vs2010/0.11/lib/common/SelfFlushingStream.h box/invisnet/vs2010/0.11/lib/common/StreamableMemBlock.cpp box/invisnet/vs2010/0.11/lib/common/StreamableMemBlock.h box/invisnet/vs2010/0.11/lib/common/Utils.cpp box/invisnet/vs2010/0.11/lib/common/ZeroStream.cpp box/invisnet/vs2010/0.11/lib/common/ZeroStream.h box/invisnet/vs2010/0.11/lib/compress/Compress.h box/invisnet/vs2010/0.11/lib/compress/CompressStream.cpp box/invisnet/vs2010/0.11/lib/compress/CompressStream.h box/invisnet/vs2010/0.11/lib/crypto/CipherContext.cpp box/invisnet/vs2010/0.11/lib/crypto/CipherContext.h box/invisnet/vs2010/0.11/lib/crypto/MD5Digest.cpp box/invisnet/vs2010/0.11/lib/crypto/MD5Digest.h box/invisnet/vs2010/0.11/lib/crypto/RollingChecksum.cpp box/invisnet/vs2010/0.11/lib/crypto/RollingChecksum.h box/invisnet/vs2010/0.11/lib/server/Protocol.cpp box/invisnet/vs2010/0.11/lib/server/Protocol.h box/invisnet/vs2010/0.11/lib/server/ProtocolUncertainStream.cpp box/invisnet/vs2010/0.11/lib/server/ProtocolUncertainStream.h box/invisnet/vs2010/0.11/lib/server/SocketStreamTLS.cpp box/invisnet/vs2010/0.11/lib/server/SocketStreamTLS.h box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.cpp box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.h box/invisnet/vs2010/0.11/lib/server/makeprotocol.pl.in Log: Under Windows sizeof(int)==4 on both x86 and x64, so switch from int to size_t with checks for overflow. Add some overflow checks before calling malloc(). Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupClientFileAttributes.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupClientFileAttributes.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupClientFileAttributes.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -301,11 +301,11 @@ } // Check symlink string? - unsigned int size = mpClearAttributes->GetSize(); + size_t size = mpClearAttributes->GetSize(); if(size > sizeof(attr_StreamFormat)) { // Symlink strings don't match. This also compares xattrs - int datalen = size - sizeof(attr_StreamFormat); + size_t datalen = size - sizeof(attr_StreamFormat); if(::memcmp(a1 + 1, a2 + 1, datalen) != 0) { @@ -726,7 +726,7 @@ ASSERT(mpClearAttributes != 0); // Check if the decrypted attributes are small enough, and the type of attributes stored - if(mpClearAttributes->GetSize() < (int)sizeof(int32_t)) + if(mpClearAttributes->GetSize() < sizeof(int32_t)) { THROW_EXCEPTION(BackupStoreException, AttributesNotUnderstood); } @@ -739,7 +739,7 @@ } // Check there is enough space for an attributes block - if(mpClearAttributes->GetSize() < (int)sizeof(attr_StreamFormat)) + if(mpClearAttributes->GetSize() < sizeof(attr_StreamFormat)) { // Too small THROW_EXCEPTION(BackupStoreException, AttributesNotLoaded); @@ -747,14 +747,14 @@ // Get pointer to structure attr_StreamFormat *pattr = (attr_StreamFormat*)mpClearAttributes->GetBuffer(); - int xattrOffset = sizeof(attr_StreamFormat); + size_t xattrOffset = sizeof(attr_StreamFormat); // is it a symlink? int16_t mode = ntohs(pattr->Mode); if((mode & S_IFMT) == S_IFLNK) { // Check things are sensible - if(mpClearAttributes->GetSize() < (int)sizeof(attr_StreamFormat) + 1) + if(mpClearAttributes->GetSize() < sizeof(attr_StreamFormat) + 1) { // Too small THROW_EXCEPTION(BackupStoreException, AttributesNotLoaded); @@ -804,10 +804,12 @@ #endif } - if(static_cast(xattrOffset+sizeof(u_int32_t))<=mpClearAttributes->GetSize()) - { - WriteExtendedAttr(Filename, xattrOffset); - } + #ifdef HAVE_SYS_XATTR_H + if(static_cast(xattrOffset+sizeof(u_int32_t))<=mpClearAttributes->GetSize()) + { + WriteExtendedAttr(Filename, xattrOffset); + } + #endif // Stop now if symlink, because otherwise it'll just be applied to the target if((mode & S_IFMT) == S_IFLNK) @@ -1004,14 +1006,14 @@ try { // Check the block is big enough for IV and header - int ivSize = sBlowfishEncrypt.GetIVLength(); + size_t ivSize = sBlowfishEncrypt.GetIVLength(); if(rEncrypted.GetSize() <= (ivSize + 1)) { THROW_EXCEPTION(BackupStoreException, BadEncryptedAttributes); } // How much space is needed for the output? - int maxDecryptedSize = sBlowfishDecrypt.MaxOutSizeForInBufferSize(rEncrypted.GetSize() - ivSize); + size_t maxDecryptedSize = sBlowfishDecrypt.MaxOutSizeForInBufferSize(rEncrypted.GetSize() - ivSize); // Allocate it pdecrypted = new StreamableMemBlock(maxDecryptedSize); @@ -1029,7 +1031,7 @@ sBlowfishDecrypt.SetIV(encBlock + 1); // Decrypt - int decryptedSize = sBlowfishDecrypt.TransformBlock(pdecrypted->GetBuffer(), maxDecryptedSize, encBlock + 1 + ivSize, rEncrypted.GetSize() - (ivSize + 1)); + size_t decryptedSize = sBlowfishDecrypt.TransformBlock(pdecrypted->GetBuffer(), maxDecryptedSize, encBlock + 1 + ivSize, rEncrypted.GetSize() - (ivSize + 1)); // Resize block to fit pdecrypted->ResizeBlock(decryptedSize); @@ -1077,7 +1079,7 @@ FreeBlock(); // Work out the maximum amount of space we need - int maxEncryptedSize = sBlowfishEncrypt.MaxOutSizeForInBufferSize(rToEncrypt.GetSize()); + size_t maxEncryptedSize = sBlowfishEncrypt.MaxOutSizeForInBufferSize(rToEncrypt.GetSize()); // And the size of the IV int ivSize = sBlowfishEncrypt.GetIVLength(); @@ -1097,7 +1099,7 @@ ::memcpy(block + 1, iv, ivSize); // Do the transform - int encrytedSize = sBlowfishEncrypt.TransformBlock(block + 1 + ivSize, maxEncryptedSize, rToEncrypt.GetBuffer(), rToEncrypt.GetSize()); + size_t encrytedSize = sBlowfishEncrypt.TransformBlock(block + 1 + ivSize, maxEncryptedSize, rToEncrypt.GetBuffer(), rToEncrypt.GetSize()); // Resize this block ResizeBlock(encrytedSize + ivSize + 1); Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupClientRestore.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupClientRestore.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupClientRestore.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -105,7 +105,7 @@ // ID rWrite.Write(&mNextLevelID, sizeof(mNextLevelID)); // Name string - int32_t nsize = mNextLevelLocalName.size(); + size_t nsize = mNextLevelLocalName.size(); rWrite.Write(&nsize, sizeof(nsize)); rWrite.Write(mNextLevelLocalName.c_str(), nsize); // And then the level itself @@ -440,8 +440,8 @@ // list of files which is appropriate to the restore type rConnection.QueryListDirectory( DirectoryID, - Params.RestoreDeleted?(BackupProtocolClientListDirectory::Flags_Deleted):(BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING), - BackupProtocolClientListDirectory::Flags_OldVersion | (Params.RestoreDeleted?(0):(BackupProtocolClientListDirectory::Flags_Deleted)), + static_cast(Params.RestoreDeleted?(BackupProtocolClientListDirectory::Flags_Deleted):(BackupProtocolClientListDirectory::Flags_INCLUDE_EVERYTHING)), + static_cast(BackupProtocolClientListDirectory::Flags_OldVersion | (Params.RestoreDeleted?(0):(BackupProtocolClientListDirectory::Flags_Deleted))), true /* want attributes */); // Retrieve the directory from the stream following Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -146,7 +146,7 @@ mAttributes.ReadFromStream(rStream, Timeout); // Decode count - int count = ntohl(hdr.mNumEntries); + int32_t count = ntohl(hdr.mNumEntries); // Clear existing list for(std::vector::iterator i = mEntries.begin(); @@ -157,7 +157,7 @@ mEntries.clear(); // Read them in! - for(int c = 0; c < count; ++c) + for(int32_t c = 0; c < count; ++c) { Entry *pen = new Entry; try @@ -179,7 +179,7 @@ if(options & Option_DependencyInfoPresent) { // Read in extra dependency data - for(int c = 0; c < count; ++c) + for(int32_t c = 0; c < count; ++c) { mEntries[c]->ReadFromStreamDependencyInfo(rStream, Timeout); } @@ -197,7 +197,8 @@ void BackupStoreDirectory::WriteToStream(IOStream &rStream, int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet, bool StreamAttributes, bool StreamDependencyInfo) const { // Get count of entries - int32_t count = mEntries.size(); + size_t count = mEntries.size(); + ASSERT(count < (size_t)std::numeric_limits::max()); if(FlagsMustBeSet != Entry::Flags_INCLUDE_EVERYTHING || FlagsNotToBeSet != Entry::Flags_EXCLUDE_NOTHING) { // Need to count the entries @@ -235,7 +236,7 @@ // Build header dir_StreamFormat hdr; hdr.mMagicValue = htonl(OBJECTMAGIC_DIR_MAGIC_VALUE); - hdr.mNumEntries = htonl(count); + hdr.mNumEntries = htonl(static_cast(count)); hdr.mObjectID = box_hton64(mObjectID); hdr.mContainerID = box_hton64(mContainerID); hdr.mAttributesModTime = box_hton64(mAttributesModTime); Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -146,7 +146,7 @@ int64_t GetRevisionID() const {return mRevisionID;} void SetRevisionID(int64_t RevisionID) {mRevisionID = RevisionID;} - unsigned int GetNumberOfEntries() const {return mEntries.size();} + size_t GetNumberOfEntries() const {return mEntries.size();} // User info -- not serialised into streams int64_t GetUserInfo1_SizeInBlocks() const {return mUserInfo1;} Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -542,7 +542,7 @@ if(mNumBlocks > 0) { // Find the maximum encoded data size - int32_t maxEncodedDataSize = 0; + int64_t maxEncodedDataSize = 0; const file_BlockIndexEntry *entry = (file_BlockIndexEntry *)mpBlockIndex; ASSERT(entry != 0); for(int64_t e = 0; e < mNumBlocks; e++) @@ -554,9 +554,10 @@ // Larger? if(encodedSize > maxEncodedDataSize) maxEncodedDataSize = encodedSize; } - + // Allocate those blocks! - mpEncodedData = (uint8_t*)BackupStoreFile::CodingChunkAlloc(maxEncodedDataSize + 32); + ASSERT(maxEncodedDataSize+32 < SIZE_MAX); + mpEncodedData = (uint8_t*)BackupStoreFile::CodingChunkAlloc(static_cast(maxEncodedDataSize + 32)); // Allocate the block for the clear data, using the hint from the header. // If this is wrong, things will exception neatly later on, so it can't be used @@ -624,7 +625,11 @@ int64_t indexSize = sizeof(file_BlockIndexEntry) * mNumBlocks; // Allocate some memory - mpBlockIndex = ::malloc(indexSize); + if(indexSize >= SIZE_MAX) + { + throw std::bad_alloc(); + } + mpBlockIndex = ::malloc(static_cast(indexSize)); if(mpBlockIndex == 0) { throw std::bad_alloc(); @@ -648,7 +653,7 @@ // Created: 9/12/03 // // -------------------------------------------------------------------------- -int BackupStoreFile::DecodedStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t BackupStoreFile::DecodedStream::Read(void *pBuffer, size_t NBytes, int Timeout) { // Symlinks don't have data. So can't read it. Not even zero bytes. if(IsSymLink()) @@ -664,7 +669,7 @@ return 0; } - int bytesToRead = NBytes; + size_t bytesToRead = NBytes; uint8_t *output = (uint8_t*)pBuffer; while(bytesToRead > 0 && mCurrentBlock < mNumBlocks) @@ -673,7 +678,7 @@ if(mPositionInCurrentBlock < mCurrentBlockClearSize) { // Copy data out of this buffer - int s = mCurrentBlockClearSize - mPositionInCurrentBlock; + size_t s = mCurrentBlockClearSize - mPositionInCurrentBlock; if(s > bytesToRead) s = bytesToRead; // limit to requested data // Copy @@ -698,7 +703,7 @@ // Get the size from the block index const file_BlockIndexEntry *entry = (file_BlockIndexEntry *)mpBlockIndex; - int32_t encodedSize = box_ntoh64(entry[mCurrentBlock].mEncodedSize); + int64_t encodedSize = box_ntoh64(entry[mCurrentBlock].mEncodedSize); if(encodedSize <= 0) { // The caller is attempting to decode a file which is the direct result of a diff @@ -706,6 +711,11 @@ // It needs to be combined with the previous version first. THROW_EXCEPTION(BackupStoreException, CannotDecodeDiffedFilesWithoutCombining) } + if(encodedSize >= SIZE_MAX) + { + // We're on a 32bit machine and this block is too big for us to deal with + THROW_EXCEPTION(BackupStoreException, Internal) + } // Load in next block if(!mrEncodedFile.ReadFullBuffer(mpEncodedData, encodedSize, 0 /* not interested in bytes read if this fails */, mTimeout)) @@ -715,7 +725,7 @@ } // Decode the data - mCurrentBlockClearSize = BackupStoreFile::DecodeChunk(mpEncodedData, encodedSize, mpClearData, mClearDataSize); + mCurrentBlockClearSize = BackupStoreFile::DecodeChunk(mpEncodedData, static_cast(encodedSize), mpClearData, mClearDataSize); // Calculate IV for this entry uint64_t iv = mEntryIVBase; @@ -727,7 +737,7 @@ // Decrypt the encrypted section file_BlockIndexEntryEnc entryEnc; - int sectionSize = sBlowfishDecryptBlockEntry.TransformBlock(&entryEnc, sizeof(entryEnc), + size_t sectionSize = sBlowfishDecryptBlockEntry.TransformBlock(&entryEnc, sizeof(entryEnc), entry[mCurrentBlock].mEnEnc, sizeof(entry[mCurrentBlock].mEnEnc)); if(sectionSize != sizeof(entryEnc)) { @@ -746,7 +756,7 @@ // IV for the encrypted section. Try again, with the thing the other way round iv = box_swap64(iv); sBlowfishDecryptBlockEntry.SetIV(&iv); - int sectionSize = sBlowfishDecryptBlockEntry.TransformBlock(&entryEnc, sizeof(entryEnc), + size_t sectionSize = sBlowfishDecryptBlockEntry.TransformBlock(&entryEnc, sizeof(entryEnc), entry[mCurrentBlock].mEnEnc, sizeof(entry[mCurrentBlock].mEnEnc)); if(sectionSize != sizeof(entryEnc)) { @@ -826,7 +836,7 @@ // Created: 9/12/03 // // -------------------------------------------------------------------------- -void BackupStoreFile::DecodedStream::Write(const void *pBuffer, int NBytes) +void BackupStoreFile::DecodedStream::Write(const void *pBuffer, size_t NBytes) { THROW_EXCEPTION(BackupStoreException, CantWriteToDecodedFileStream) } @@ -922,7 +932,7 @@ // Created: 7/12/03 // // -------------------------------------------------------------------------- -int BackupStoreFile::MaxBlockSizeForChunkSize(int ChunkSize) +size_t BackupStoreFile::MaxBlockSizeForChunkSize(size_t ChunkSize) { // Calculate... the maximum size of output by first the largest it could be after compression, // which is encrypted, and has a 1 bytes header and the IV added, plus 1 byte for luck @@ -942,7 +952,7 @@ // Created: 8/12/03 // // -------------------------------------------------------------------------- -int BackupStoreFile::EncodeChunk(const void *Chunk, int ChunkSize, BackupStoreFile::EncodingBuffer &rOutput) +size_t BackupStoreFile::EncodeChunk(const void *Chunk, size_t ChunkSize, BackupStoreFile::EncodingBuffer &rOutput) { ASSERT(spEncrypt != 0); @@ -964,7 +974,7 @@ // Store header rOutput.mpBuffer[0] = header; - int outOffset = 1; + size_t outOffset = 1; // Setup cipher, and store the IV int ivLen = 0; @@ -977,6 +987,7 @@ #define ENCODECHUNK_CHECK_SPACE(ToEncryptSize) \ { \ + ASSERT(rOutput.mBufferSize >= outOffset); \ if((rOutput.mBufferSize - outOffset) < ((ToEncryptSize) + 128)) \ { \ rOutput.Reallocate(rOutput.mBufferSize + (ToEncryptSize) + 128); \ @@ -997,7 +1008,7 @@ // Get and encrypt output while(!compress.OutputHasFinished()) { - int s = compress.Output(buffer, sizeof(buffer)); + size_t s = compress.Output(buffer, sizeof(buffer)); if(s > 0) { ENCODECHUNK_CHECK_SPACE(s) @@ -1038,7 +1049,7 @@ // Created: 8/12/03 // // -------------------------------------------------------------------------- -int BackupStoreFile::DecodeChunk(const void *Encoded, int EncodedSize, void *Output, int OutputSize) +size_t BackupStoreFile::DecodeChunk(const void *Encoded, size_t EncodedSize, void *Output, size_t OutputSize) { // Check alignment of the encoded block ASSERT((((uint32_t)(long)Encoded) % BACKUPSTOREFILE_CODING_BLOCKSIZE) == BACKUPSTOREFILE_CODING_OFFSET); @@ -1073,8 +1084,8 @@ #endif // Check enough space for header, an IV and one byte of input - int ivLen = cipher.GetIVLength(); - if(EncodedSize < (1 + ivLen + 1)) + size_t ivLen = cipher.GetIVLength(); + if(EncodedSize < 1 + ivLen + 1) { THROW_EXCEPTION(BackupStoreException, BadEncodedChunk) } @@ -1084,16 +1095,16 @@ cipher.Begin(); // Setup vars for code - int inOffset = 1 + ivLen; + size_t inOffset = 1 + ivLen; uint8_t *output = (uint8_t*)Output; - int outOffset = 0; + size_t outOffset = 0; // Do action if(chunkCompressed) { // Do things in chunks uint8_t buffer[2048]; - int inputBlockLen = cipher.InSizeForOutBufferSize(sizeof(buffer)); + size_t inputBlockLen = cipher.InSizeForOutBufferSize(sizeof(buffer)); // Decompressor Compress decompress; @@ -1101,16 +1112,16 @@ while(inOffset < EncodedSize) { // Decrypt a block - int bl = inputBlockLen; + size_t bl = inputBlockLen; if(bl > (EncodedSize - inOffset)) bl = EncodedSize - inOffset; // not too long - int s = cipher.Transform(buffer, sizeof(buffer), input + inOffset, bl); + size_t s = cipher.Transform(buffer, sizeof(buffer), input + inOffset, bl); inOffset += bl; // Decompress the decrypted data if(s > 0) { decompress.Input(buffer, s); - int os = 0; + size_t os = 0; do { os = decompress.Output(output + outOffset, OutputSize - outOffset); @@ -1126,12 +1137,12 @@ } // Get any compressed data remaining in the cipher context and compression - int s = cipher.Final(buffer, sizeof(buffer)); + size_t s = cipher.Final(buffer, sizeof(buffer)); decompress.Input(buffer, s); decompress.FinishInput(); while(!decompress.OutputHasFinished()) { - int os = decompress.Output(output + outOffset, OutputSize - outOffset); + size_t os = decompress.Output(output + outOffset, OutputSize - outOffset); outOffset += os; // Check that there's space left in the output buffer -- there always should be @@ -1143,6 +1154,9 @@ } else { + ASSERT(OutputSize >= outOffset); + ASSERT(EncodedSize >= inOffset); + // Easy decryption outOffset += cipher.Transform(output + outOffset, OutputSize - outOffset, input + inOffset, EncodedSize - inOffset); outOffset += cipher.Final(output + outOffset, OutputSize - outOffset); @@ -1176,7 +1190,7 @@ } // Read the header - int bytesRead = 0; + size_t bytesRead = 0; file_StreamFormat hdr; bool readBlock = pStream->ReadFullBuffer(&hdr, sizeof(hdr), &bytesRead); @@ -1217,7 +1231,7 @@ // Set it up... ReadGatherStream &rreordered(*((ReadGatherStream*)reordered.get())); - int component = rreordered.AddComponent(pStream); + size_t component = rreordered.AddComponent(pStream); // Send out the block index rreordered.AddBlock(component, blockIndexSize, true, blockIndexLoc); // And then the rest of the file @@ -1339,7 +1353,7 @@ // Decrypt the encrypted section file_BlockIndexEntryEnc entryEnc; - int sectionSize = sBlowfishDecryptBlockEntry.TransformBlock(&entryEnc, sizeof(entryEnc), + size_t sectionSize = sBlowfishDecryptBlockEntry.TransformBlock(&entryEnc, sizeof(entryEnc), entry.mEnEnc, sizeof(entry.mEnEnc)); if(sectionSize != sizeof(entryEnc)) { @@ -1478,7 +1492,7 @@ // Created: 25/11/04 // // -------------------------------------------------------------------------- -void BackupStoreFile::EncodingBuffer::Allocate(int Size) +void BackupStoreFile::EncodingBuffer::Allocate(size_t Size) { ASSERT(mpBuffer == 0); uint8_t *buffer = (uint8_t*)BackupStoreFile::CodingChunkAlloc(Size); @@ -1500,7 +1514,7 @@ // Created: 25/11/04 // // -------------------------------------------------------------------------- -void BackupStoreFile::EncodingBuffer::Reallocate(int NewSize) +void BackupStoreFile::EncodingBuffer::Reallocate(size_t NewSize) { BOX_TRACE("Reallocating EncodingBuffer from " << mBufferSize << " to " << NewSize); Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -81,8 +81,8 @@ ~DecodedStream(); // Stream functions - virtual int Read(void *pBuffer, int NBytes, int Timeout); - virtual void Write(const void *pBuffer, int NBytes); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout); + virtual void Write(const void *pBuffer, size_t NBytes); virtual bool StreamDataLeft(); virtual bool StreamClosed(); @@ -106,10 +106,10 @@ void *mpBlockIndex; uint8_t *mpEncodedData; uint8_t *mpClearData; - int mClearDataSize; - int mCurrentBlock; - int mCurrentBlockClearSize; - int mPositionInCurrentBlock; + size_t mClearDataSize; + int64_t mCurrentBlock; + size_t mCurrentBlockClearSize; + size_t mPositionInCurrentBlock; uint64_t mEntryIVBase; #ifndef BOX_DISABLE_BACKWARDS_COMPATIBILITY_BACKUPSTOREFILE bool mIsOldVersion; @@ -153,14 +153,14 @@ #endif // Allocation of properly aligning chunks for decoding and encoding chunks - inline static void *CodingChunkAlloc(int Size) + inline static void *CodingChunkAlloc(size_t Size) { uint8_t *a = (uint8_t*)malloc((Size) + (BACKUPSTOREFILE_CODING_BLOCKSIZE * 3)); if(a == 0) return 0; // Align to main block size - ASSERT(sizeof(unsigned long) >= sizeof(void*)); // make sure casting the right pointer size + ASSERT(sizeof(size_t) >= sizeof(void*)); // make sure casting the right pointer size uint8_t adjustment = BACKUPSTOREFILE_CODING_BLOCKSIZE - - (uint8_t)(((unsigned long)a) % BACKUPSTOREFILE_CODING_BLOCKSIZE); + - (uint8_t)(((size_t)a) % BACKUPSTOREFILE_CODING_BLOCKSIZE); uint8_t *b = (a + adjustment); // Store adjustment *b = adjustment; @@ -170,8 +170,8 @@ inline static void CodingChunkFree(void *Block) { // Check alignment is as expected - ASSERT(sizeof(unsigned long) >= sizeof(void*)); // make sure casting the right pointer size - ASSERT((uint8_t)(((unsigned long)Block) % BACKUPSTOREFILE_CODING_BLOCKSIZE) == BACKUPSTOREFILE_CODING_OFFSET); + ASSERT(sizeof(size_t) >= sizeof(void*)); // make sure casting the right pointer size + ASSERT((uint8_t)(((size_t)Block) % BACKUPSTOREFILE_CODING_BLOCKSIZE) == BACKUPSTOREFILE_CODING_OFFSET); uint8_t *a = (uint8_t*)Block; a -= BACKUPSTOREFILE_CODING_OFFSET; // Adjust downwards... @@ -192,23 +192,23 @@ EncodingBuffer(const EncodingBuffer &); EncodingBuffer &operator=(const EncodingBuffer &); public: - void Allocate(int Size); - void Reallocate(int NewSize); + void Allocate(size_t Size); + void Reallocate(size_t NewSize); uint8_t *mpBuffer; - int mBufferSize; + size_t mBufferSize; }; - static int MaxBlockSizeForChunkSize(int ChunkSize); - static int EncodeChunk(const void *Chunk, int ChunkSize, BackupStoreFile::EncodingBuffer &rOutput); + static size_t MaxBlockSizeForChunkSize(size_t ChunkSize); + static size_t EncodeChunk(const void *Chunk, size_t ChunkSize, BackupStoreFile::EncodingBuffer &rOutput); // Caller should know how big the output size is, but also allocate a bit more memory to cover various // overheads allowed for in checks - static inline int OutputBufferSizeForKnownOutputSize(int KnownChunkSize) + static inline size_t OutputBufferSizeForKnownOutputSize(size_t KnownChunkSize) { // Plenty big enough return KnownChunkSize + 256; } - static int DecodeChunk(const void *Encoded, int EncodedSize, void *Output, int OutputSize); + static size_t DecodeChunk(const void *Encoded, size_t EncodedSize, void *Output, size_t OutputSize); // Statisitics, not designed to be completely reliable static void ResetStats(); Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCmbDiff.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCmbDiff.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCmbDiff.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -79,7 +79,12 @@ } int64_t diff1NumBlocks = box_ntoh64(diff1IdxHdr.mNumBlocks); // Allocate some memory - int64_t *diff1BlockStartPositions = (int64_t*)::malloc((diff1NumBlocks + 1) * sizeof(int64_t)); + uint64_t bytesToMalloc = (diff1NumBlocks + 1) * sizeof(int64_t); + if(bytesToMalloc >= SIZE_MAX) + { + throw std::bad_alloc(); + } + int64_t *diff1BlockStartPositions = (int64_t*)::malloc(static_cast(bytesToMalloc)); if(diff1BlockStartPositions == 0) { throw std::bad_alloc(); @@ -87,7 +92,7 @@ // Buffer data void *buffer = 0; - int bufferSize = 0; + size_t bufferSize = 0; try { @@ -172,7 +177,7 @@ // What do to next about copying data bool copyBlock = false; - int copySize = 0; + size_t copySize = 0; int64_t copyFrom = 0; bool fromFileDiff1 = false; @@ -191,24 +196,29 @@ else { // Block isn't present here -- is it present in the old one? - int64_t blockIndex = 0 - blockEn; - if(blockIndex < 0 || blockIndex > diff1NumBlocks) + int64_t blockIndex_ = 0 - blockEn; + if(blockIndex_ < 0 || blockIndex_ > diff1NumBlocks) { THROW_EXCEPTION(BackupStoreException, BadBackupStoreFile) } + if(blockIndex_ >= SIZE_MAX) + { + THROW_EXCEPTION(CommonException, Internal) + } + size_t blockIndex = static_cast(blockIndex_); if(diff1BlockStartPositions[blockIndex] > 0) { // Block is in the old diff file, copy it across copyBlock = true; copyFrom = diff1BlockStartPositions[blockIndex]; - int nb = blockIndex + 1; + size_t nb = blockIndex + 1; while(diff1BlockStartPositions[nb] <= 0) { // This is safe, because the last entry will terminate it properly! ++nb; - ASSERT(nb <= diff1NumBlocks); + ASSERT((int64_t)nb <= diff1NumBlocks); } - copySize = diff1BlockStartPositions[nb] - copyFrom; + copySize = static_cast(diff1BlockStartPositions[nb] - copyFrom); fromFileDiff1 = true; } } @@ -280,16 +290,17 @@ if(blockEn <= 0) { int64_t blockIndex = 0 - blockEn; + ASSERT(blockIndex < SIZE_MAX); // In another file. Need to translate this against the other diff if(diff1BlockStartPositions[blockIndex] > 0) { // Block is in the first diff file, stick in size - int nb = blockIndex + 1; + size_t nb = static_cast(blockIndex + 1); while(diff1BlockStartPositions[nb] <= 0) { // This is safe, because the last entry will terminate it properly! ++nb; - ASSERT(nb <= diff1NumBlocks); + ASSERT((int64_t)nb <= diff1NumBlocks); } int64_t size = diff1BlockStartPositions[nb] - diff1BlockStartPositions[blockIndex]; e.mEncodedSize = box_hton64(size); Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCmbIdx.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCmbIdx.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCmbIdx.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -31,8 +31,8 @@ BSFCombinedIndexStream(IOStream *pDiff); ~BSFCombinedIndexStream(); - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); - virtual void Write(const void *pBuffer, int NBytes); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual void Write(const void *pBuffer, size_t NBytes); virtual bool StreamDataLeft(); virtual bool StreamClosed(); virtual void Initialise(IOStream &rFrom); @@ -174,7 +174,12 @@ // Then... allocate memory for the list of sizes mNumEntriesInFromFile = box_ntoh64(fromHdr.mNumBlocks); - mFromBlockSizes = (int64_t*)::malloc(mNumEntriesInFromFile * sizeof(int64_t)); + uint64_t bytesToMalloc = mNumEntriesInFromFile * sizeof(int64_t); + if(bytesToMalloc >= SIZE_MAX) + { + throw std::bad_alloc(); + } + mFromBlockSizes = (int64_t*)::malloc(static_cast(bytesToMalloc)); if(mFromBlockSizes == 0) { throw std::bad_alloc(); @@ -212,7 +217,7 @@ // Created: 8/7/04 // // -------------------------------------------------------------------------- -int BSFCombinedIndexStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t BSFCombinedIndexStream::Read(void *pBuffer, size_t NBytes, int Timeout) { // Paranoia is good. if(!mIsInitialised || mFromBlockSizes == 0 || mpDiff == 0) @@ -220,13 +225,13 @@ THROW_EXCEPTION(BackupStoreException, Internal) } - int written = 0; + size_t written = 0; // Header output yet? if(!mHeaderWritten) { // Enough space? - if(NBytes < (int)sizeof(mHeader)) return 0; + if(NBytes < sizeof(mHeader)) return 0; // Copy in ::memcpy(pBuffer, &mHeader, sizeof(mHeader)); @@ -238,17 +243,17 @@ } // How many entries can be written? - int entriesToWrite = NBytes / sizeof(file_BlockIndexEntry); - if(entriesToWrite > mNumEntriesToGo) + size_t entriesToWrite = NBytes / sizeof(file_BlockIndexEntry); + if(entriesToWrite > static_cast(mNumEntriesToGo)) { - entriesToWrite = mNumEntriesToGo; + entriesToWrite = static_cast(mNumEntriesToGo); } // Setup ready to go file_BlockIndexEntry *poutput = (file_BlockIndexEntry*)(((uint8_t*)pBuffer) + written); // Write entries - for(int b = 0; b < entriesToWrite; ++b) + for(size_t b = 0; b < entriesToWrite; ++b) { if(!mpDiff->ReadFullBuffer(&(poutput[b]), sizeof(file_BlockIndexEntry), 0)) { @@ -256,11 +261,11 @@ } // Does this need adjusting? - int s = box_ntoh64(poutput[b].mEncodedSize); + int64_t s = box_ntoh64(poutput[b].mEncodedSize); if(s <= 0) { // A reference to a block in the from file - int block = 0 - s; + int64_t block = 0 - s; ASSERT(block >= 0); if(block >= mNumEntriesInFromFile) { @@ -289,7 +294,7 @@ // Created: 8/7/04 // // -------------------------------------------------------------------------- -void BSFCombinedIndexStream::Write(const void *pBuffer, int NBytes) +void BSFCombinedIndexStream::Write(const void *pBuffer, size_t NBytes) { THROW_EXCEPTION(BackupStoreException, StreamDoesntHaveRequiredFeatures) } Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCombine.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCombine.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileCombine.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -88,7 +88,7 @@ { THROW_EXCEPTION(CommonException, StreamableMemBlockIncompleteRead) } - int size = ntohl(size_s); + int32_t size = ntohl(size_s); // Skip forward the size rFrom.Seek(size, IOStream::SeekType_Relative); } @@ -96,7 +96,12 @@ // Allocate memory for the block index of the From file int64_t fromNumBlocks = box_ntoh64(fromHdr.mNumBlocks); // NOTE: An extra entry is required so that the length of the last block can be calculated - FromIndexEntry *pFromIndex = (FromIndexEntry*)::malloc((fromNumBlocks+1) * sizeof(FromIndexEntry)); + uint64_t bytesToMalloc = (fromNumBlocks+1) * sizeof(FromIndexEntry); + if(bytesToMalloc >= SIZE_MAX) + { + throw std::bad_alloc(); + } + FromIndexEntry *pFromIndex = (FromIndexEntry*)::malloc(static_cast(bytesToMalloc)); if(pFromIndex == 0) { throw std::bad_alloc(); @@ -226,11 +231,11 @@ } // Record where the From file is - int64_t fromPos = rFrom.GetPosition(); + IOStream::pos_type fromPos = rFrom.GetPosition(); // Buffer data void *buffer = 0; - int bufferSize = 0; + int64_t bufferSize = 0; try { @@ -248,7 +253,7 @@ int64_t encodedSize = box_ntoh64(en.mEncodedSize); // How much data will be read? - int32_t blockSize = 0; + int64_t blockSize = 0; if(encodedSize > 0) { // The block is actually in the diff file @@ -279,7 +284,11 @@ bufferSize = 0; } // Allocate new block - buffer = ::malloc(blockSize); + if(blockSize >= SIZE_MAX) + { + throw std::bad_alloc(); + } + buffer = ::malloc(static_cast(blockSize)); if(buffer == 0) { throw std::bad_alloc(); @@ -394,9 +403,9 @@ THROW_EXCEPTION(BackupStoreException, BadBackupStoreFile) } // Calculate size. This operation is safe because of the extra entry at the end - int32_t blockSize = pFromIndex[blockIdx + 1].mFilePosition - pFromIndex[blockIdx].mFilePosition; + int64_t blockSize = pFromIndex[blockIdx + 1].mFilePosition - pFromIndex[blockIdx].mFilePosition; // Then replace entry - en.mEncodedSize = box_hton64(((uint64_t)blockSize)); + en.mEncodedSize = box_hton64(blockSize); } // Write entry Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileDiff.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileDiff.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileDiff.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -53,7 +53,7 @@ int64_t NumBlocks, int32_t Sizes[BACKUP_FILE_DIFF_MAX_BLOCK_SIZES], DiffTimer *pDiffTimer); static void SetupHashTable(BlocksAvailableEntry *pIndex, int64_t NumBlocks, int32_t BlockSize, BlocksAvailableEntry **pHashTable); -static bool SecondStageMatch(BlocksAvailableEntry *pFirstInHashList, RollingChecksum &fastSum, uint8_t *pBeginnings, uint8_t *pEndings, int Offset, int32_t BlockSize, int64_t FileBlockNumber, +static bool SecondStageMatch(BlocksAvailableEntry *pFirstInHashList, RollingChecksum &fastSum, uint8_t *pBeginnings, uint8_t *pEndings, size_t Offset, int32_t BlockSize, int64_t FileBlockNumber, BlocksAvailableEntry *pIndex, std::map &rFoundBlocks); static void GenerateRecipe(BackupStoreFileEncodeStream::Recipe &rRecipe, BlocksAvailableEntry *pIndex, int64_t NumBlocks, std::map &rFoundBlocks, int64_t SizeOfInputFile); @@ -302,7 +302,12 @@ //TODO: Verify that these sizes look reasonable // Allocate space for the index - BlocksAvailableEntry *pindex = (BlocksAvailableEntry*)::malloc(sizeof(BlocksAvailableEntry) * numBlocks); + uint64_t bytesToMalloc = sizeof(BlocksAvailableEntry) * numBlocks; + if(bytesToMalloc >= SIZE_MAX) + { + throw std::bad_alloc(); + } + BlocksAvailableEntry *pindex = (BlocksAvailableEntry*)::malloc(static_cast(bytesToMalloc)); if(pindex == 0) { throw std::bad_alloc(); @@ -329,7 +334,7 @@ // Decrypt the encrypted section file_BlockIndexEntryEnc entryEnc; - int sectionSize = sBlowfishDecryptBlockEntry.TransformBlock(&entryEnc, sizeof(entryEnc), + size_t sectionSize = sBlowfishDecryptBlockEntry.TransformBlock(&entryEnc, sizeof(entryEnc), entry.mEnEnc, sizeof(entry.mEnEnc)); if(sectionSize != sizeof(entryEnc)) { @@ -545,7 +550,7 @@ // Setup block pointers uint8_t *beginnings = pbuffer0; uint8_t *endings = pbuffer1; - int offset = 0; + int32_t offset = 0; // Calculate the first checksum, ready for rolling RollingChecksum rolling(beginnings, Sizes[s]); @@ -553,7 +558,7 @@ // Then roll, until the file is exhausted int64_t fileBlockNumber = 0; int64_t fileOffset = 0; - int rollOverInitialBytes = 0; + int32_t rollOverInitialBytes = 0; while(true) { if(maximumDiffingTime.HasExpired()) @@ -571,14 +576,14 @@ } // Load in another block of data, and record how big it is - int bytesInEndings = rFile.Read(endings, Sizes[s]); + int32_t bytesInEndings = rFile.Read(endings, Sizes[s]); int tmp; // Skip any bytes from a previous matched block if(rollOverInitialBytes > 0 && offset < bytesInEndings) { - int spaceLeft = bytesInEndings - offset; - int thisRoll = (rollOverInitialBytes > spaceLeft) ? spaceLeft : rollOverInitialBytes; + int32_t spaceLeft = bytesInEndings - offset; + int32_t thisRoll = (rollOverInitialBytes > spaceLeft) ? spaceLeft : rollOverInitialBytes; rolling.RollForwardSeveral(beginnings+offset, endings+offset, Sizes[s], thisRoll); @@ -605,8 +610,8 @@ { // Skip over bigger ready-matched blocks completely rollOverInitialBytes = tmp; - int spaceLeft = bytesInEndings - offset; - int thisRoll = (rollOverInitialBytes > spaceLeft) ? spaceLeft : rollOverInitialBytes; + int32_t spaceLeft = bytesInEndings - offset; + int32_t thisRoll = (rollOverInitialBytes > spaceLeft) ? spaceLeft : rollOverInitialBytes; rolling.RollForwardSeveral(beginnings+offset, endings+offset, Sizes[s], thisRoll); @@ -635,11 +640,11 @@ // any more comparisons, because these are pointless (as any more matches will be ignored when // the recipe is generated) and just take up valuable processor time. Edge cases are // especially nasty, using huge amounts of time and memory. - int skip = Sizes[s]; + int32_t skip = Sizes[s]; if(offset < bytesInEndings && skip > 0) { - int spaceLeft = bytesInEndings - offset; - int thisRoll = (skip > spaceLeft) ? spaceLeft : skip; + int32_t spaceLeft = bytesInEndings - offset; + int32_t thisRoll = (skip > spaceLeft) ? spaceLeft : skip; rolling.RollForwardSeveral(beginnings+offset, endings+offset, Sizes[s], thisRoll); @@ -802,7 +807,7 @@ // // -------------------------------------------------------------------------- static bool SecondStageMatch(BlocksAvailableEntry *pFirstInHashList, RollingChecksum &fastSum, uint8_t *pBeginnings, uint8_t *pEndings, - int Offset, int32_t BlockSize, int64_t FileBlockNumber, BlocksAvailableEntry *pIndex, std::map &rFoundBlocks) + size_t Offset, int32_t BlockSize, int64_t FileBlockNumber, BlocksAvailableEntry *pIndex, std::map &rFoundBlocks) { // Check parameters ASSERT(pBeginnings != 0); Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -48,7 +48,7 @@ mSendData(true), mTotalBlocks(0), mAbsoluteBlockNumber(-1), - mInstructionNumber(-1), + mInstructionNumber(SIZE_MAX), mNumBlocks(0), mCurrentBlock(-1), mCurrentBlockEncodedSize(0), @@ -150,7 +150,7 @@ // Go through each instruction in the recipe and work out how many blocks // it will add, and the max clear size of these blocks - int maxBlockClearSize = 0; + int32_t maxBlockClearSize = 0; for(Recipe::size_type inst = 0; inst < pRecipe->size(); ++inst) { if((*pRecipe)[inst].mSpaceBefore > 0) @@ -301,7 +301,7 @@ } while(rBlockSizeOut < BACKUP_FILE_MAX_BLOCK_SIZE && rNumBlocksOut > BACKUP_FILE_INCREASE_BLOCK_SIZE_AFTER); // Last block size - rLastBlockSizeOut = DataSize - ((rNumBlocksOut - 1) * rBlockSizeOut); + rLastBlockSizeOut = static_cast(DataSize - ((rNumBlocksOut - 1) * rBlockSizeOut)); // Avoid small blocks? if(rLastBlockSizeOut < BACKUP_FILE_AVOID_BLOCKS_LESS_THAN @@ -313,7 +313,7 @@ } // checks! - ASSERT((((rNumBlocksOut-1) * rBlockSizeOut) + rLastBlockSizeOut) == DataSize); + ASSERT(static_cast(((rNumBlocksOut-1) * rBlockSizeOut) + rLastBlockSizeOut) == DataSize); //TRACE4("CalcBlockSize, sz %lld, num %lld, blocksize %d, last %d\n", DataSize, rNumBlocksOut, (int32_t)rBlockSizeOut, (int32_t)rLastBlockSizeOut); } @@ -327,7 +327,7 @@ // Created: 8/12/03 // // -------------------------------------------------------------------------- -int BackupStoreFileEncodeStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t BackupStoreFileEncodeStream::Read(void *pBuffer, size_t NBytes, int Timeout) { // Check there's something to do. if(mStatus == Status_Finished) @@ -340,7 +340,7 @@ THROW_EXCEPTION(BackupStoreException, SignalReceived); } - int bytesToRead = NBytes; + size_t bytesToRead = NBytes; uint8_t *buffer = (uint8_t*)pBuffer; while(bytesToRead > 0 && mStatus != Status_Finished) @@ -350,7 +350,7 @@ // Header or block listing phase -- send from the buffered stream // Send bytes from the data buffer - int b = mData.Read(buffer, bytesToRead, Timeout); + size_t b = mData.Read(buffer, bytesToRead, Timeout); bytesToRead -= b; buffer += b; @@ -400,7 +400,7 @@ if(mCurrentBlock >= mNumBlocks) { // Output extra blocks for this instruction and move forward in file - if(mInstructionNumber >= 0) + if(mInstructionNumber < SIZE_MAX) { SkipPreviousBlocksInInstruction(); } @@ -409,14 +409,14 @@ ++mInstructionNumber; // Skip instructions which don't contain any data - while(mInstructionNumber < static_cast(mpRecipe->size()) + while(mInstructionNumber < mpRecipe->size() && (*mpRecipe)[mInstructionNumber].mSpaceBefore == 0) { SkipPreviousBlocksInInstruction(); ++mInstructionNumber; } - if(mInstructionNumber >= static_cast(mpRecipe->size())) + if(mInstructionNumber >= mpRecipe->size()) { // End of blocks, go to next phase ++mStatus; @@ -442,7 +442,7 @@ if(mPositionInCurrentBlock < mCurrentBlockEncodedSize) { // How much data to put in the buffer? - int s = mCurrentBlockEncodedSize - mPositionInCurrentBlock; + size_t s = mCurrentBlockEncodedSize - mPositionInCurrentBlock; if(s > bytesToRead) s = bytesToRead; // Copy it in @@ -487,7 +487,7 @@ } // Index of the first block in old file (being diffed from) - int firstIndex = mpRecipe->BlockPtrToIndex((*mpRecipe)[mInstructionNumber].mpStartBlock); + int64_t firstIndex = mpRecipe->BlockPtrToIndex((*mpRecipe)[mInstructionNumber].mpStartBlock); int64_t sizeToSkip = 0; @@ -546,12 +546,12 @@ void BackupStoreFileEncodeStream::EncodeCurrentBlock() { // How big is the block, raw? - int blockRawSize = mBlockSize; + int32_t blockRawSize = mBlockSize; if(mCurrentBlock == (mNumBlocks - 1)) { blockRawSize = mLastBlockSize; } - ASSERT(blockRawSize < mAllocatedBufferSize); + ASSERT((size_t)blockRawSize < mAllocatedBufferSize); // Check file open if(mpLogging == 0) @@ -624,7 +624,7 @@ sBlowfishEncryptBlockEntry.SetIV(&iv); // Encode the data - int encodedSize = sBlowfishEncryptBlockEntry.TransformBlock(entry.mEnEnc, sizeof(entry.mEnEnc), &entryEnc, sizeof(entryEnc)); + size_t encodedSize = sBlowfishEncryptBlockEntry.TransformBlock(entry.mEnEnc, sizeof(entry.mEnEnc), &entryEnc, sizeof(entryEnc)); if(encodedSize != sizeof(entry.mEnEnc)) { THROW_EXCEPTION(BackupStoreException, BlockEntryEncodingDidntGiveExpectedLength) @@ -643,7 +643,7 @@ // Created: 8/12/03 // // -------------------------------------------------------------------------- -void BackupStoreFileEncodeStream::Write(const void *pBuffer, int NBytes) +void BackupStoreFileEncodeStream::Write(const void *pBuffer, size_t NBytes) { THROW_EXCEPTION(BackupStoreException, CantWriteToEncodedFileStream) } Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -81,8 +81,8 @@ ReadLoggingStream::Logger* pLogger = NULL, RunStatusProvider* pRunStatusProvider = NULL); - virtual int Read(void *pBuffer, int NBytes, int Timeout); - virtual void Write(const void *pBuffer, int NBytes); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout); + virtual void Write(const void *pBuffer, size_t NBytes); virtual bool StreamDataLeft(); virtual bool StreamClosed(); @@ -113,19 +113,19 @@ int64_t mTotalBlocks; // Total number of blocks in the file int64_t mAbsoluteBlockNumber; // The absolute block number currently being output // Instruction number - int64_t mInstructionNumber; + size_t mInstructionNumber; // All the below are within the current instruction int64_t mNumBlocks; // number of blocks. Last one will be a different size to the rest in most cases int64_t mCurrentBlock; - int32_t mCurrentBlockEncodedSize; - int32_t mPositionInCurrentBlock; // for reading out + size_t mCurrentBlockEncodedSize; + size_t mPositionInCurrentBlock; // for reading out int32_t mBlockSize; // Basic block size of most of the blocks in the file int32_t mLastBlockSize; // the size (unencoded) of the last block in the file // Buffers uint8_t *mpRawBuffer; // buffer for raw data BackupStoreFile::EncodingBuffer mEncodedBuffer; // buffer for encoded data - int32_t mAllocatedBufferSize; // size of above two allocated blocks + size_t mAllocatedBufferSize; // size of above two allocated blocks uint64_t mEntryIVBase; // base for block entry IV }; Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileRevDiff.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileRevDiff.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileRevDiff.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -60,7 +60,12 @@ // For each block in the from file, we want to know it's index in the // diff file. Allocate memory for this information. int64_t fromNumBlocks = box_ntoh64(hdr.mNumBlocks); - int64_t *pfromIndexInfo = (int64_t*)::malloc(fromNumBlocks * sizeof(int64_t)); + uint64_t bytesToMalloc = fromNumBlocks * sizeof(int64_t); + if(bytesToMalloc >= SIZE_MAX) + { + throw std::bad_alloc(); + } + int64_t *pfromIndexInfo = (int64_t*)::malloc(static_cast(bytesToMalloc)); if(pfromIndexInfo == 0) { throw std::bad_alloc(); @@ -68,7 +73,7 @@ // Buffer data void *buffer = 0; - int bufferSize = 0; + int64_t bufferSize = 0; // flag bool isCompletelyDifferent = true; @@ -176,7 +181,11 @@ bufferSize = 0; } // Allocate new block - buffer = ::malloc(blockSize); + if(blockSize >= SIZE_MAX) + { + throw std::bad_alloc(); + } + buffer = ::malloc(static_cast(blockSize)); if(buffer == 0) { throw std::bad_alloc(); Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilename.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilename.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilename.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -101,7 +101,7 @@ #define BACKUPSTOREFILENAME_GET_SIZE(hdr) (( ((uint8_t)((hdr)[0])) | ( ((uint8_t)((hdr)[1])) << 8)) >> 2) #define BACKUPSTOREFILENAME_GET_ENCODING(hdr) (((hdr)[0]) & 0x3) -#define BACKUPSTOREFILENAME_MAKE_HDR(hdr, size, encoding) {uint16_t h = (((uint16_t)size) << 2) | (encoding); ((hdr)[0]) = h & 0xff; ((hdr)[1]) = h >> 8;} +#define BACKUPSTOREFILENAME_MAKE_HDR(hdr, size, encoding) {uint16_t h = (((uint16_t)size) << 2) | (uint16_t)(encoding); ((hdr)[0]) = h & 0xff; ((hdr)[1]) = h >> 8;} #endif // BACKUPSTOREFILENAME__H Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -187,10 +187,10 @@ // Buffer for encoding and decoding -- do this all in one single buffer to // avoid lots of string allocation, which stuffs up memory usage. // These static memory vars are, of course, not thread safe, but we don't use threads. -static int sEncDecBufferSize = 0; +static size_t sEncDecBufferSize = 0; static MemoryBlockGuard *spEncDecBuffer = 0; -static void EnsureEncDecBufferSize(int BufSize) +static void EnsureEncDecBufferSize(size_t BufSize) { if(spEncDecBuffer == 0) { @@ -228,7 +228,7 @@ void BackupStoreFilenameClear::EncryptClear(const std::string &rToEncode, CipherContext &rCipherContext, int StoreAsEncoding) { // Work out max size - int maxOutSize = rCipherContext.MaxOutSizeForInBufferSize(rToEncode.size()) + 4; + size_t maxOutSize = rCipherContext.MaxOutSizeForInBufferSize(rToEncode.size()) + 4; // Make sure encode/decode buffer has enough space EnsureEncDecBufferSize(maxOutSize); @@ -237,7 +237,7 @@ uint8_t *buffer = *spEncDecBuffer; // Encode -- do entire block in one go - int encSize = rCipherContext.TransformBlock(buffer + 2, sEncDecBufferSize - 2, rToEncode.c_str(), rToEncode.size()); + size_t encSize = rCipherContext.TransformBlock(buffer + 2, sEncDecBufferSize - 2, rToEncode.c_str(), rToEncode.size()); // and add in header size encSize += 2; @@ -262,7 +262,7 @@ const std::string& rEncoded = GetEncodedFilename(); // Work out max size - int maxOutSize = rCipherContext.MaxOutSizeForInBufferSize(rEncoded.size()) + 4; + size_t maxOutSize = rCipherContext.MaxOutSizeForInBufferSize(rEncoded.size()) + 4; // Make sure encode/decode buffer has enough space EnsureEncDecBufferSize(maxOutSize); @@ -272,7 +272,7 @@ // Decrypt const char *str = rEncoded.c_str() + 2; - int sizeOut = rCipherContext.TransformBlock(buffer, sEncDecBufferSize, str, rEncoded.size() - 2); + size_t sizeOut = rCipherContext.TransformBlock(buffer, sEncDecBufferSize, str, rEncoded.size() - 2); // Assign to this mClearFilename.assign((char*)buffer, sizeOut); @@ -304,7 +304,7 @@ // Created: 1/12/03 // // -------------------------------------------------------------------------- -void BackupStoreFilenameClear::SetBlowfishKey(const void *pKey, int KeyLength, const void *pIV, int IVLength) +void BackupStoreFilenameClear::SetBlowfishKey(const void *pKey, int8_t KeyLength, const void *pIV, int8_t IVLength) { // Initialisation vector not used. Can't use a different vector for each filename as // that would stop comparisions on the server working. Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -42,7 +42,7 @@ void SetClearFilename(const std::string &rToEncode); // Setup for encryption of filenames - static void SetBlowfishKey(const void *pKey, int KeyLength, const void *pIV, int IVLength); + static void SetBlowfishKey(const void *pKey, int8_t KeyLength, const void *pIV, int8_t IVLength); static void SetEncodingMethod(int Method); protected: Modified: box/invisnet/vs2010/0.11/lib/common/Archive.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/Archive.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/Archive.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -67,7 +67,7 @@ } void Write(const std::string &Item) { - int size = Item.size(); + int size = static_cast(Item.size()); Write(size); mrStream.Write(Item.c_str(), size); } @@ -119,7 +119,7 @@ { int privItem; Read(privItem); - rItemOut = privItem; + rItemOut = static_cast(privItem); } void Read(std::string &rItemOut) { Modified: box/invisnet/vs2010/0.11/lib/common/BufferedStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/BufferedStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/BufferedStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -36,13 +36,13 @@ // Created: 2007/01/16 // // -------------------------------------------------------------------------- -int BufferedStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t BufferedStream::Read(void *pBuffer, size_t NBytes, int Timeout) { if (mBufferSize == mBufferPosition) { // buffer is empty, fill it. - int numBytesRead = mrSource.Read(mBuffer, sizeof(mBuffer), + size_t numBytesRead = mrSource.Read(mBuffer, sizeof(mBuffer), Timeout); if (numBytesRead < 0) @@ -53,7 +53,7 @@ mBufferSize = numBytesRead; } - int sizeToReturn = mBufferSize - mBufferPosition; + size_t sizeToReturn = mBufferSize - mBufferPosition; if (sizeToReturn > NBytes) { @@ -96,7 +96,7 @@ // Created: 2003/07/31 // // -------------------------------------------------------------------------- -void BufferedStream::Write(const void *pBuffer, int NBytes) +void BufferedStream::Write(const void *pBuffer, size_t NBytes) { THROW_EXCEPTION(CommonException, NotSupported); } Modified: box/invisnet/vs2010/0.11/lib/common/BufferedStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/BufferedStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/BufferedStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -17,15 +17,15 @@ private: IOStream& mrSource; char mBuffer[4096]; - int mBufferSize; - int mBufferPosition; + size_t mBufferSize; + size_t mBufferPosition; public: BufferedStream(IOStream& rSource); - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); virtual pos_type BytesLeftToRead(); - virtual void Write(const void *pBuffer, int NBytes); + virtual void Write(const void *pBuffer, size_t NBytes); virtual pos_type GetPosition() const; virtual void Seek(IOStream::pos_type Offset, int SeekType); virtual void Close(); Modified: box/invisnet/vs2010/0.11/lib/common/CollectInBufferStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/CollectInBufferStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/CollectInBufferStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -56,14 +56,14 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -int CollectInBufferStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t CollectInBufferStream::Read(void *pBuffer, size_t NBytes, int Timeout) { if(mInWritePhase != false) { THROW_EXCEPTION(CommonException, CollectInBufferStreamNotInCorrectPhase) } // Adjust to number of bytes left if(NBytes > (mBytesInBuffer - mReadPosition)) { - NBytes = (mBytesInBuffer - mReadPosition); + NBytes = static_cast(mBytesInBuffer - mReadPosition); } ASSERT(NBytes >= 0); if(NBytes <= 0) return 0; // careful now @@ -98,7 +98,7 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -void CollectInBufferStream::Write(const void *pBuffer, int NBytes) +void CollectInBufferStream::Write(const void *pBuffer, size_t NBytes) { if(mInWritePhase != true) { THROW_EXCEPTION(CommonException, CollectInBufferStreamNotInCorrectPhase) } @@ -106,14 +106,14 @@ if((mBytesInBuffer + NBytes) > mBufferSize) { // Need to reallocate... what's the block size we'll use? - int allocateBlockSize = mBufferSize; + size_t allocateBlockSize = mBufferSize; if(allocateBlockSize > MAX_BUFFER_ADDITION) { allocateBlockSize = MAX_BUFFER_ADDITION; } // Write it the easy way. Although it's not the most efficient... - int newSize = mBufferSize; + size_t newSize = mBufferSize; while(newSize < (mBytesInBuffer + NBytes)) { newSize += allocateBlockSize; @@ -157,7 +157,7 @@ { if(mInWritePhase != false) { THROW_EXCEPTION(CommonException, CollectInBufferStreamNotInCorrectPhase) } - int newPos = 0; + pos_type newPos = 0; switch(SeekType) { case IOStream::SeekType_Absolute: @@ -175,7 +175,7 @@ } // Make sure it doesn't go over - if(newPos > mBytesInBuffer) + if(newPos > static_cast(mBytesInBuffer)) { newPos = mBytesInBuffer; } @@ -199,7 +199,7 @@ // -------------------------------------------------------------------------- bool CollectInBufferStream::StreamDataLeft() { - return mInWritePhase?(false):(mReadPosition < mBytesInBuffer); + return mInWritePhase?(false):(mReadPosition < static_cast(mBytesInBuffer)); } // -------------------------------------------------------------------------- @@ -252,7 +252,7 @@ // Created: 2003/09/05 // // -------------------------------------------------------------------------- -int CollectInBufferStream::GetSize() const +size_t CollectInBufferStream::GetSize() const { return mBytesInBuffer; } Modified: box/invisnet/vs2010/0.11/lib/common/CollectInBufferStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/CollectInBufferStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/CollectInBufferStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -32,9 +32,9 @@ CollectInBufferStream(const IOStream &); public: - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); virtual pos_type BytesLeftToRead(); - virtual void Write(const void *pBuffer, int NBytes); + virtual void Write(const void *pBuffer, size_t NBytes); virtual pos_type GetPosition() const; virtual void Seek(pos_type Offset, int SeekType); virtual bool StreamDataLeft(); @@ -45,14 +45,14 @@ void Reset(); void *GetBuffer() const; - int GetSize() const; + size_t GetSize() const; bool IsSetForReading() const {return !mInWritePhase;} private: MemoryBlockGuard mBuffer; - int mBufferSize; - int mBytesInBuffer; - int mReadPosition; + size_t mBufferSize; + size_t mBytesInBuffer; + pos_type mReadPosition; bool mInWritePhase; }; Modified: box/invisnet/vs2010/0.11/lib/common/ExcludeList.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/ExcludeList.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/ExcludeList.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -84,7 +84,7 @@ for (std::string::iterator i = output.begin(); i != output.end(); i++) { - *i = tolower(*i); + *i = static_cast(tolower(*i)); } return output; @@ -103,7 +103,7 @@ for (std::string::iterator i = output.begin(); i != output.end(); i++) { - *i = tolower(*i); + *i = static_cast(tolower(*i)); } return output; Modified: box/invisnet/vs2010/0.11/lib/common/ExcludeList.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/ExcludeList.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/ExcludeList.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -48,8 +48,8 @@ bool IsExcluded(const std::string &rTest) const; // Mainly for tests - unsigned int SizeOfDefiniteList() const {return mDefinite.size();} - unsigned int SizeOfRegexList() const + size_t SizeOfDefiniteList() const {return mDefinite.size();} + size_t SizeOfRegexList() const #ifdef HAVE_REGEX_SUPPORT {return mRegex.size();} #else Modified: box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -175,15 +175,15 @@ else { // Remove whitespace - int size = r.size(); - int begin = 0; + size_t size = r.size(); + size_t begin = 0; while(begin < size && iw(r[begin])) { begin++; } // Check for comment char, but char before must be whitespace - int end = begin; + size_t end = begin; while(end < size) { if(r[end] == '#' && (end == 0 || (iw(r[end-1])))) Modified: box/invisnet/vs2010/0.11/lib/common/FileStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/FileStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/FileStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -162,7 +162,7 @@ // Created: 2003/07/31 // // -------------------------------------------------------------------------- -int FileStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t FileStream::Read(void *pBuffer, size_t NBytes, int Timeout) { if(mOSFileHandle == INVALID_FILE) { @@ -170,12 +170,13 @@ } #ifdef WIN32 + ASSERT(NBytes <= std::numeric_limits::max()); int r; DWORD numBytesRead = 0; BOOL valid = ReadFile( this->mOSFileHandle, pBuffer, - NBytes, + static_cast(NBytes), &numBytesRead, NULL ); @@ -243,7 +244,7 @@ // Created: 2003/07/31 // // -------------------------------------------------------------------------- -void FileStream::Write(const void *pBuffer, int NBytes) +void FileStream::Write(const void *pBuffer, size_t NBytes) { if(mOSFileHandle == INVALID_FILE) { @@ -251,11 +252,12 @@ } #ifdef WIN32 + ASSERT(NBytes <= std::numeric_limits::max()); DWORD numBytesWritten = 0; BOOL res = WriteFile( this->mOSFileHandle, pBuffer, - NBytes, + static_cast(NBytes), &numBytesWritten, NULL ); @@ -423,7 +425,7 @@ char buf2[2048]; while(StreamDataLeft() && rOther.StreamDataLeft()) { - int readSize = rOther.Read(buf1, sizeof(buf1), Timeout); + size_t readSize = rOther.Read(buf1, sizeof(buf1), Timeout); otherSize += readSize; if(Read(buf2, readSize) != readSize || Modified: box/invisnet/vs2010/0.11/lib/common/FileStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/FileStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/FileStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -38,9 +38,9 @@ virtual ~FileStream(); - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); virtual pos_type BytesLeftToRead(); - virtual void Write(const void *pBuffer, int NBytes); + virtual void Write(const void *pBuffer, size_t NBytes); virtual pos_type GetPosition() const; virtual void Seek(IOStream::pos_type Offset, int SeekType); virtual void Close(); @@ -58,6 +58,13 @@ // for debugging.. std::string mFileName; + +public: + template + inline T Read(void *pBuffer, T NBytes, int Timeout = IOStream::TimeOutInfinite) + { + return IOStream::Read(pBuffer,NBytes,Timeout); + } }; Modified: box/invisnet/vs2010/0.11/lib/common/Guards.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/Guards.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/Guards.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -77,7 +77,7 @@ class MemoryBlockGuard { public: - MemoryBlockGuard(int BlockSize) + MemoryBlockGuard(size_t BlockSize) : mpBlock(::malloc(BlockSize)) { if(mpBlock == 0) @@ -101,7 +101,7 @@ return (type)mpBlock; } - void Resize(int NewSize) + void Resize(size_t NewSize) { void *ptrn = ::realloc(mpBlock, NewSize); if(ptrn == 0) Modified: box/invisnet/vs2010/0.11/lib/common/IOStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/IOStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/IOStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -132,15 +132,15 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -bool IOStream::ReadFullBuffer(void *pBuffer, int NBytes, int *pNBytesRead, int Timeout) +bool IOStream::mReadFullBuffer(void *pBuffer, size_t NBytes, size_t *pNBytesRead, int Timeout) { - int bytesToGo = NBytes; + size_t bytesToGo = NBytes; char *buffer = (char*)pBuffer; if(pNBytesRead) (*pNBytesRead) = 0; while(bytesToGo > 0) { - int bytesRead = Read(buffer, bytesToGo, Timeout); + size_t bytesRead = Read(buffer, bytesToGo, Timeout); if(bytesRead == 0) { // Timeout or something @@ -194,7 +194,7 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -bool IOStream::CopyStreamTo(IOStream &rCopyTo, int Timeout, int BufferSize) +bool IOStream::CopyStreamTo(IOStream &rCopyTo, int Timeout, size_t BufferSize) { // Make sure there's something to do before allocating that buffer if(!StreamDataLeft()) @@ -209,7 +209,7 @@ while(StreamDataLeft()) { // Read some data - int bytes = Read(buffer, BufferSize, Timeout); + size_t bytes = Read(buffer, BufferSize, Timeout); if(bytes == 0 && StreamDataLeft()) { return false; // incomplete, timed out Modified: box/invisnet/vs2010/0.11/lib/common/IOStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/IOStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/IOStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -45,9 +45,9 @@ // Timeout in milliseconds // Read may return 0 -- does not mean end of stream. typedef int64_t pos_type; - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite) = 0; + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite) = 0; virtual pos_type BytesLeftToRead(); // may return IOStream::SizeOfStreamUnknown (and will for most stream types) - virtual void Write(const void *pBuffer, int NBytes) = 0; + virtual void Write(const void *pBuffer, size_t NBytes) = 0; virtual void Write(const char *pBuffer); virtual void WriteAllBuffered(); virtual pos_type GetPosition() const; @@ -60,11 +60,41 @@ virtual bool StreamClosed() = 0; // Utility functions - bool ReadFullBuffer(void *pBuffer, int NBytes, int *pNBytesRead, int Timeout = IOStream::TimeOutInfinite); - bool CopyStreamTo(IOStream &rCopyTo, int Timeout = IOStream::TimeOutInfinite, int BufferSize = 1024); + bool CopyStreamTo(IOStream &rCopyTo, int Timeout = IOStream::TimeOutInfinite, size_t BufferSize = 1024); void Flush(int Timeout = IOStream::TimeOutInfinite); static int ConvertSeekTypeToOSWhence(int SeekType); + + + // things to make the compiler happier + template + inline T Read(void *pBuffer, T NBytes, int Timeout = IOStream::TimeOutInfinite) + { + if (NBytes >= SIZE_MAX) + throw std::bad_cast(); + return static_cast(Read(pBuffer,static_cast(NBytes),Timeout)); + } + template + inline void Write(const void *pBuffer, T NBytes) + { + if (NBytes >= SIZE_MAX) + throw std::bad_cast(); + Write(pBuffer,static_cast(NBytes)); + } + template + inline bool ReadFullBuffer(void *pBuffer, T NBytes, void *pNBytesRead, int Timeout = IOStream::TimeOutInfinite) + { + if (NBytes >= SIZE_MAX) + throw std::bad_cast(); + size_t n; + bool b = mReadFullBuffer(pBuffer,static_cast(NBytes),&n,Timeout); + if(pNBytesRead) + *static_cast(pNBytesRead) = static_cast(n); + return b; + } + +protected: + bool mReadFullBuffer(void *pBuffer, size_t NBytes, size_t *pNBytesRead, int Timeout = IOStream::TimeOutInfinite); }; Modified: box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -113,7 +113,7 @@ // Read more in? if(!foundLineEnd && mBufferBegin >= mBytesInBuffer && !mPendingEOF) { - int bytes = mrStream.Read(mBuffer, sizeof(mBuffer), Timeout); + size_t bytes = mrStream.Read(mBuffer, sizeof(mBuffer), Timeout); // Adjust buffer info mBytesInBuffer = bytes; @@ -151,8 +151,8 @@ else { // Check for comment char, but char before must be whitespace - int end = 0; - int size = r.size(); + size_t end = 0; + size_t size = r.size(); while(end < size) { if(r[end] == '#' && (end == 0 || (iw(r[end-1])))) @@ -163,7 +163,7 @@ } // Remove whitespace - int begin = 0; + size_t begin = 0; while(begin < size && iw(r[begin])) { begin++; @@ -193,7 +193,7 @@ void IOStreamGetLine::DetachFile() { // Adjust file pointer - int bytesOver = mBytesInBuffer - mBufferBegin; + size_t bytesOver = mBytesInBuffer - mBufferBegin; ASSERT(bytesOver >= 0); if(bytesOver > 0) { @@ -213,9 +213,9 @@ // Created: 22/12/04 // // -------------------------------------------------------------------------- -void IOStreamGetLine::IgnoreBufferedData(int BytesToIgnore) +void IOStreamGetLine::IgnoreBufferedData(size_t BytesToIgnore) { - int bytesInBuffer = mBytesInBuffer - mBufferBegin; + size_t bytesInBuffer = mBytesInBuffer - mBufferBegin; if(BytesToIgnore < 0 || BytesToIgnore > bytesInBuffer) { THROW_EXCEPTION(CommonException, IOStreamGetLineNotEnoughDataToIgnore) Modified: box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/IOStreamGetLine.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -53,16 +53,16 @@ // For doing interesting stuff with the remaining data... // Be careful with this! const void *GetBufferedData() const {return mBuffer + mBufferBegin;} - int GetSizeOfBufferedData() const {return mBytesInBuffer - mBufferBegin;} - void IgnoreBufferedData(int BytesToIgnore); + size_t GetSizeOfBufferedData() const {return mBytesInBuffer - mBufferBegin;} + void IgnoreBufferedData(size_t BytesToIgnore); IOStream &GetUnderlyingStream() {return mrStream;} private: char mBuffer[IOSTREAMGETLINE_BUFFER_SIZE]; IOStream &mrStream; int mLineNumber; - int mBufferBegin; - int mBytesInBuffer; + size_t mBufferBegin; + size_t mBytesInBuffer; bool mPendingEOF; bool mEOF; std::string mPendingString; Modified: box/invisnet/vs2010/0.11/lib/common/MemBlockStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/MemBlockStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/MemBlockStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -26,7 +26,7 @@ // Created: 2003/09/05 // // -------------------------------------------------------------------------- -MemBlockStream::MemBlockStream(const void *pBuffer, int Size) +MemBlockStream::MemBlockStream(const void *pBuffer, size_t Size) : mpBuffer((char*)pBuffer), mBytesInBuffer(Size), mReadPosition(0) @@ -108,12 +108,12 @@ // Created: 2003/09/05 // // -------------------------------------------------------------------------- -int MemBlockStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t MemBlockStream::Read(void *pBuffer, size_t NBytes, int Timeout) { // Adjust to number of bytes left if(NBytes > (mBytesInBuffer - mReadPosition)) { - NBytes = (mBytesInBuffer - mReadPosition); + NBytes = static_cast(mBytesInBuffer - mReadPosition); } ASSERT(NBytes >= 0); if(NBytes <= 0) return 0; // careful now @@ -146,7 +146,7 @@ // Created: 2003/09/05 // // -------------------------------------------------------------------------- -void MemBlockStream::Write(const void *pBuffer, int NBytes) +void MemBlockStream::Write(const void *pBuffer, size_t NBytes) { THROW_EXCEPTION(CommonException, MemBlockStreamNotSupported) } @@ -175,7 +175,7 @@ // -------------------------------------------------------------------------- void MemBlockStream::Seek(pos_type Offset, int SeekType) { - int newPos = 0; + pos_type newPos = 0; switch(SeekType) { case IOStream::SeekType_Absolute: @@ -193,7 +193,7 @@ } // Make sure it doesn't go over - if(newPos > mBytesInBuffer) + if(newPos > static_cast(mBytesInBuffer)) { newPos = mBytesInBuffer; } @@ -217,7 +217,7 @@ // -------------------------------------------------------------------------- bool MemBlockStream::StreamDataLeft() { - return mReadPosition < mBytesInBuffer; + return mReadPosition < static_cast(mBytesInBuffer); } // -------------------------------------------------------------------------- Modified: box/invisnet/vs2010/0.11/lib/common/MemBlockStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/MemBlockStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/MemBlockStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -27,16 +27,16 @@ class MemBlockStream : public IOStream { public: - MemBlockStream(const void *pBuffer, int Size); + MemBlockStream(const void *pBuffer, size_t Size); MemBlockStream(const StreamableMemBlock &rBlock); MemBlockStream(const CollectInBufferStream &rBuffer); MemBlockStream(const MemBlockStream &rToCopy); ~MemBlockStream(); public: - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); virtual pos_type BytesLeftToRead(); - virtual void Write(const void *pBuffer, int NBytes); + virtual void Write(const void *pBuffer, size_t NBytes); virtual pos_type GetPosition() const; virtual void Seek(pos_type Offset, int SeekType); virtual bool StreamDataLeft(); @@ -44,8 +44,8 @@ private: const char *mpBuffer; - int mBytesInBuffer; - int mReadPosition; + size_t mBytesInBuffer; + pos_type mReadPosition; }; #endif // MEMBLOCKSTREAM__H Modified: box/invisnet/vs2010/0.11/lib/common/PartialReadStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/PartialReadStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/PartialReadStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -57,7 +57,7 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -int PartialReadStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t PartialReadStream::Read(void *pBuffer, size_t NBytes, int Timeout) { // Finished? if(mBytesLeft <= 0) @@ -66,15 +66,15 @@ } // Asking for more than is allowed? - if(NBytes > mBytesLeft) + if(static_cast(NBytes) > mBytesLeft) { // Adjust downwards - NBytes = mBytesLeft; + NBytes = static_cast(mBytesLeft); } // Route the request to the source - int read = mrSource.Read(pBuffer, NBytes, Timeout); - ASSERT(read <= mBytesLeft); + size_t read = mrSource.Read(pBuffer, NBytes, Timeout); + ASSERT(static_cast(read) <= mBytesLeft); // Adjust the count mBytesLeft -= read; @@ -104,7 +104,7 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -void PartialReadStream::Write(const void *pBuffer, int NBytes) +void PartialReadStream::Write(const void *pBuffer, size_t NBytes) { THROW_EXCEPTION(CommonException, CantWriteToPartialReadStream) } Modified: box/invisnet/vs2010/0.11/lib/common/PartialReadStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/PartialReadStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/PartialReadStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -31,9 +31,9 @@ PartialReadStream(const PartialReadStream &); public: - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); virtual pos_type BytesLeftToRead(); - virtual void Write(const void *pBuffer, int NBytes); + virtual void Write(const void *pBuffer, size_t NBytes); virtual bool StreamDataLeft(); virtual bool StreamClosed(); Modified: box/invisnet/vs2010/0.11/lib/common/ReadGatherStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/ReadGatherStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/ReadGatherStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -65,12 +65,12 @@ // Created: 10/12/03 // // -------------------------------------------------------------------------- -int ReadGatherStream::AddComponent(IOStream *pStream) +size_t ReadGatherStream::AddComponent(IOStream *pStream) { ASSERT(pStream != 0); // Just add the component to the list, returning it's index. - int index = mComponents.size(); + size_t index = mComponents.size(); mComponents.push_back(pStream); return index; } @@ -87,10 +87,10 @@ // Created: 10/12/03 // // -------------------------------------------------------------------------- -void ReadGatherStream::AddBlock(int Component, pos_type Length, bool Seek, pos_type SeekTo) +void ReadGatherStream::AddBlock(size_t Component, pos_type Length, bool Seek, pos_type SeekTo) { // Check block - if(Component < 0 || Component >= (int)mComponents.size() || Length < 0 || SeekTo < 0) + if(Component < 0 || Component >= mComponents.size() || Length < 0 || SeekTo < 0) { THROW_EXCEPTION(CommonException, ReadGatherStreamAddingBadBlock); } @@ -117,9 +117,9 @@ // Created: 10/12/03 // // -------------------------------------------------------------------------- -int ReadGatherStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t ReadGatherStream::Read(void *pBuffer, size_t NBytes, int Timeout) { - int bytesToRead = NBytes; + size_t bytesToRead = NBytes; uint8_t *buffer = (uint8_t*)pBuffer; while(bytesToRead > 0) @@ -147,14 +147,14 @@ { // Read! pos_type s = mBlocks[mCurrentBlock].mLength - mPositionInCurrentBlock; - if(s > bytesToRead) s = bytesToRead; + if(s > static_cast(bytesToRead)) s = bytesToRead; pos_type r = mComponents[mBlocks[mCurrentBlock].mComponent]->Read(buffer, s, Timeout); // update variables mPositionInCurrentBlock += r; buffer += r; - bytesToRead -= r; + bytesToRead -= static_cast(r); mCurrentPosition += r; if(r != s) @@ -213,7 +213,7 @@ // Created: 10/12/03 // // -------------------------------------------------------------------------- -void ReadGatherStream::Write(const void *pBuffer, int NBytes) +void ReadGatherStream::Write(const void *pBuffer, size_t NBytes) { THROW_EXCEPTION(CommonException, CannotWriteToReadGatherStream); } Modified: box/invisnet/vs2010/0.11/lib/common/ReadGatherStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/ReadGatherStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/ReadGatherStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -32,12 +32,12 @@ ReadGatherStream &operator=(const ReadGatherStream &); public: - int AddComponent(IOStream *pStream); - void AddBlock(int Component, pos_type Length, bool Seek = false, pos_type SeekTo = 0); + size_t AddComponent(IOStream *pStream); + void AddBlock(size_t Component, pos_type Length, bool Seek = false, pos_type SeekTo = 0); - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); virtual pos_type BytesLeftToRead(); - virtual void Write(const void *pBuffer, int NBytes); + virtual void Write(const void *pBuffer, size_t NBytes); virtual bool StreamDataLeft(); virtual bool StreamClosed(); virtual pos_type GetPosition() const; @@ -50,7 +50,7 @@ { pos_type mLength; pos_type mSeekTo; - int mComponent; + size_t mComponent; bool mSeek; } Block; Modified: box/invisnet/vs2010/0.11/lib/common/ReadLoggingStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/ReadLoggingStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/ReadLoggingStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -43,9 +43,9 @@ // Created: 2007/01/16 // // -------------------------------------------------------------------------- -int ReadLoggingStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t ReadLoggingStream::Read(void *pBuffer, size_t NBytes, int Timeout) { - int numBytesRead = mrSource.Read(pBuffer, NBytes, Timeout); + size_t numBytesRead = mrSource.Read(pBuffer, NBytes, Timeout); if (numBytesRead > 0) { @@ -96,7 +96,7 @@ // Created: 2003/07/31 // // -------------------------------------------------------------------------- -void ReadLoggingStream::Write(const void *pBuffer, int NBytes) +void ReadLoggingStream::Write(const void *pBuffer, size_t NBytes) { THROW_EXCEPTION(CommonException, NotSupported); } Modified: box/invisnet/vs2010/0.11/lib/common/ReadLoggingStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/ReadLoggingStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/ReadLoggingStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -37,9 +37,9 @@ public: ReadLoggingStream(IOStream& rSource, Logger& rLogger); - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); virtual pos_type BytesLeftToRead(); - virtual void Write(const void *pBuffer, int NBytes); + virtual void Write(const void *pBuffer, size_t NBytes); virtual pos_type GetPosition() const; virtual void Seek(IOStream::pos_type Offset, int SeekType); virtual void Close(); Modified: box/invisnet/vs2010/0.11/lib/common/SelfFlushingStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/SelfFlushingStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/SelfFlushingStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -41,7 +41,7 @@ SelfFlushingStream(const IOStream& rToCopy); public: - virtual int Read(void *pBuffer, int NBytes, + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite) { return mrSource.Read(pBuffer, NBytes, Timeout); @@ -50,7 +50,7 @@ { return mrSource.BytesLeftToRead(); } - virtual void Write(const void *pBuffer, int NBytes) + virtual void Write(const void *pBuffer, size_t NBytes) { mrSource.Write(pBuffer, NBytes); } Modified: box/invisnet/vs2010/0.11/lib/common/StreamableMemBlock.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/StreamableMemBlock.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/StreamableMemBlock.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -40,7 +40,7 @@ // Created: 2003/09/05 // // -------------------------------------------------------------------------- -StreamableMemBlock::StreamableMemBlock(void *pBuffer, int Size) +StreamableMemBlock::StreamableMemBlock(void *pBuffer, size_t Size) : mpBuffer(0), mSize(0) { @@ -56,7 +56,7 @@ // Created: 2003/09/05 // // -------------------------------------------------------------------------- -StreamableMemBlock::StreamableMemBlock(int Size) +StreamableMemBlock::StreamableMemBlock(size_t Size) : mpBuffer(0), mSize(0) { @@ -89,7 +89,7 @@ // Created: 2003/09/05 // // -------------------------------------------------------------------------- -void StreamableMemBlock::Set(void *pBuffer, int Size) +void StreamableMemBlock::Set(void *pBuffer, size_t Size) { FreeBlock(); AllocateBlock(Size); @@ -115,7 +115,11 @@ } // Allocate a new block (this way to be exception safe) - char *pblock = (char*)malloc(size); + if(size >= SIZE_MAX) + { + throw std::bad_alloc(); + } + char *pblock = (char*)malloc(static_cast(size)); if(pblock == 0) { throw std::bad_alloc(); @@ -141,7 +145,7 @@ // store... ASSERT(mpBuffer == 0); mpBuffer = pblock; - mSize = size; + mSize = static_cast(size); } @@ -200,7 +204,7 @@ // Created: 2003/09/05 // // -------------------------------------------------------------------------- -void StreamableMemBlock::AllocateBlock(int Size) +void StreamableMemBlock::AllocateBlock(size_t Size) { ASSERT(mpBuffer == 0); if(Size > 0) @@ -223,7 +227,7 @@ // Created: 3/12/03 // // -------------------------------------------------------------------------- -void StreamableMemBlock::ResizeBlock(int Size) +void StreamableMemBlock::ResizeBlock(size_t Size) { ASSERT(Size > 0); if(Size > 0) @@ -299,7 +303,8 @@ // -------------------------------------------------------------------------- void StreamableMemBlock::WriteToStream(IOStream &rStream) const { - int32_t sizenbo = htonl(mSize); + ASSERT(mSize <= (size_t)std::numeric_limits::max()); + int32_t sizenbo = htonl(static_cast(mSize)); // Size rStream.Write(&sizenbo, sizeof(sizenbo)); // Buffer Modified: box/invisnet/vs2010/0.11/lib/common/StreamableMemBlock.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/StreamableMemBlock.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/StreamableMemBlock.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -24,13 +24,13 @@ { public: StreamableMemBlock(); - StreamableMemBlock(int Size); - StreamableMemBlock(void *pBuffer, int Size); + StreamableMemBlock(size_t Size); + StreamableMemBlock(void *pBuffer, size_t Size); StreamableMemBlock(const StreamableMemBlock &rToCopy); ~StreamableMemBlock(); void Set(const StreamableMemBlock &rBlock); - void Set(void *pBuffer, int Size); + void Set(void *pBuffer, size_t Size); void Set(IOStream &rStream, int Timeout); StreamableMemBlock &operator=(const StreamableMemBlock &rBlock) { @@ -46,7 +46,7 @@ void *GetBuffer() const; // Size of block - int GetSize() const {return mSize;} + size_t GetSize() const {return mSize;} // Buffer empty? bool IsEmpty() const {return mSize == 0;} @@ -56,15 +56,15 @@ bool operator==(const StreamableMemBlock &rCompare) const; - void ResizeBlock(int Size); + void ResizeBlock(size_t Size); protected: // be careful with these! - void AllocateBlock(int Size); + void AllocateBlock(size_t Size); void FreeBlock(); private: void *mpBuffer; - int mSize; + size_t mSize; }; #endif // STREAMABLEMEMBLOCK__H Modified: box/invisnet/vs2010/0.11/lib/common/Utils.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/Utils.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/Utils.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -51,7 +51,7 @@ while(e = String.find_first_of(SplitOn, b), e != String.npos) { // Get this string - unsigned int len = e - b; + size_t len = e - b; if(len >= 1) { rOutput.push_back(String.substr(b, len)); Modified: box/invisnet/vs2010/0.11/lib/common/ZeroStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/ZeroStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/ZeroStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -36,15 +36,15 @@ // Created: 2007/01/16 // // -------------------------------------------------------------------------- -int ZeroStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t ZeroStream::Read(void *pBuffer, size_t NBytes, int Timeout) { ASSERT(NBytes > 0); - int bytesToRead = NBytes; + size_t bytesToRead = NBytes; - if (bytesToRead > mSize - mPosition) + if (static_cast(bytesToRead) > mSize - mPosition) { - bytesToRead = mSize - mPosition; + bytesToRead = static_cast(mSize - mPosition); } memset(pBuffer, 0, bytesToRead); @@ -76,7 +76,7 @@ // Created: 2003/07/31 // // -------------------------------------------------------------------------- -void ZeroStream::Write(const void *pBuffer, int NBytes) +void ZeroStream::Write(const void *pBuffer, size_t NBytes) { THROW_EXCEPTION(CommonException, NotSupported); } Modified: box/invisnet/vs2010/0.11/lib/common/ZeroStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/ZeroStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/common/ZeroStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -20,9 +20,9 @@ public: ZeroStream(IOStream::pos_type mSize); - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); virtual pos_type BytesLeftToRead(); - virtual void Write(const void *pBuffer, int NBytes); + virtual void Write(const void *pBuffer, size_t NBytes); virtual pos_type GetPosition() const; virtual void Seek(IOStream::pos_type Offset, int SeekType); virtual void Close(); Modified: box/invisnet/vs2010/0.11/lib/compress/Compress.h =================================================================== --- box/invisnet/vs2010/0.11/lib/compress/Compress.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/compress/Compress.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -87,8 +87,10 @@ // Created: 5/12/03 // // -------------------------------------------------------------------------- - void Input(const void *pInBuffer, int InLength) + void Input(const void *pInBuffer, size_t InLength) { + ASSERT(InLength <= std::numeric_limits::max()); + // Check usage if(mStream.avail_in != 0) { @@ -97,7 +99,7 @@ // Store info mStream.next_in = (unsigned char *)pInBuffer; - mStream.avail_in = InLength; + mStream.avail_in = static_cast(InLength); } // -------------------------------------------------------------------------- @@ -121,17 +123,19 @@ // Created: 5/12/03 // // -------------------------------------------------------------------------- - int Output(void *pOutBuffer, int OutLength, bool SyncFlush = false) + size_t Output(void *pOutBuffer, size_t OutLength, bool SyncFlush = false) { // need more input? if(mStream.avail_in == 0 && mFlush != Z_FINISH && !SyncFlush) { return 0; } + + ASSERT(OutLength <= std::numeric_limits::max()); // Buffers mStream.next_out = (unsigned char *)pOutBuffer; - mStream.avail_out = OutLength; + mStream.avail_out = static_cast(OutLength); // Call one of the functions int flush = mFlush; @@ -188,7 +192,7 @@ Integer Compress_MaxSizeForCompressedData(Integer InLen) { // Conservative rendition of the info found here: http://www.gzip.org/zlib/zlib_tech.html - int blocks = (InLen + 32*1024 - 1) / (32*1024); + Integer blocks = (InLen + 32*1024 - 1) / (32*1024); return InLen + (blocks * 6) + 8; } Modified: box/invisnet/vs2010/0.11/lib/compress/CompressStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/compress/CompressStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/compress/CompressStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -136,7 +136,7 @@ // Created: 27/5/04 // // -------------------------------------------------------------------------- -int CompressStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t CompressStream::Read(void *pBuffer, size_t NBytes, int Timeout) { USE_READ_COMPRESSOR if(pDecompress == 0) @@ -155,7 +155,7 @@ } // Read data into the buffer -- read as much as possible in one go - int s = mpStream->Read(pbuf, BUFFER_SIZE, Timeout); + size_t s = mpStream->Read(pbuf, BUFFER_SIZE, Timeout); if(s == 0) { return 0; @@ -177,7 +177,7 @@ // Created: 27/5/04 // // -------------------------------------------------------------------------- -void CompressStream::Write(const void *pBuffer, int NBytes) +void CompressStream::Write(const void *pBuffer, size_t NBytes) { USE_WRITE_COMPRESSOR if(pCompress == 0) @@ -262,7 +262,7 @@ USE_WRITE_COMPRESSOR if(pCompress == 0) {THROW_EXCEPTION(CompressException, Internal)} - int s = 0; + size_t s = 0; do { s = pCompress->Output(mpBuffer, BUFFER_SIZE, SyncFlush); Modified: box/invisnet/vs2010/0.11/lib/compress/CompressStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/compress/CompressStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/compress/CompressStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -32,8 +32,8 @@ CompressStream &operator=(const CompressStream &); public: - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); - virtual void Write(const void *pBuffer, int NBytes); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual void Write(const void *pBuffer, size_t NBytes); virtual void WriteAllBuffered(); virtual void Close(); virtual bool StreamDataLeft(); Modified: box/invisnet/vs2010/0.11/lib/crypto/CipherContext.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/crypto/CipherContext.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/crypto/CipherContext.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -193,7 +193,7 @@ // Created: 1/12/03 // // -------------------------------------------------------------------------- -int CipherContext::Transform(void *pOutBuffer, int OutLength, const void *pInBuffer, int InLength) +size_t CipherContext::Transform(void *pOutBuffer, size_t OutLength, const void *pInBuffer, size_t InLength) { if(!mInitialised) { @@ -206,7 +206,8 @@ } // Check parameters - if(pOutBuffer == 0 || OutLength < 0 || (pInBuffer != 0 && InLength <= 0) || (pInBuffer == 0 && InLength != 0)) + if(pOutBuffer == NULL || (pInBuffer != NULL && InLength == 0) || (pInBuffer == NULL && InLength != 0) + || OutLength > INT_MAX || InLength > INT_MAX) { THROW_EXCEPTION(CipherException, BadArguments) } @@ -224,8 +225,8 @@ } // Do the transform - int outLength = OutLength; - if(EVP_CipherUpdate(&ctx, (unsigned char*)pOutBuffer, &outLength, (unsigned char*)pInBuffer, InLength) != 1) + int outLength = static_cast(OutLength); + if(EVP_CipherUpdate(&ctx, (unsigned char*)pOutBuffer, &outLength, (unsigned char*)pInBuffer, static_cast(InLength)) != 1) { THROW_EXCEPTION(CipherException, EVPUpdateFailure) } @@ -246,7 +247,7 @@ // Created: 1/12/03 // // -------------------------------------------------------------------------- -int CipherContext::Final(void *pOutBuffer, int OutLength) +size_t CipherContext::Final(void *pOutBuffer, size_t OutLength) { if(!mInitialised) { @@ -259,19 +260,19 @@ } // Check parameters - if(pOutBuffer == 0 || OutLength < 0) + if(pOutBuffer == NULL || OutLength > INT_MAX) { THROW_EXCEPTION(CipherException, BadArguments) } // Check output buffer size - if(OutLength < (2 * EVP_CIPHER_CTX_block_size(&ctx))) + int outLength = static_cast(OutLength); + if(outLength < (2 * EVP_CIPHER_CTX_block_size(&ctx))) { THROW_EXCEPTION(CipherException, OutputBufferTooSmall); } // Do the transform - int outLength = OutLength; #ifndef HAVE_OLD_SSL if(EVP_CipherFinal_ex(&ctx, (unsigned char*)pOutBuffer, &outLength) != 1) { @@ -373,7 +374,7 @@ // Created: 1/12/03 // // -------------------------------------------------------------------------- -int CipherContext::InSizeForOutBufferSize(int OutLength) +size_t CipherContext::InSizeForOutBufferSize(size_t OutLength) { if(!mInitialised) { @@ -394,7 +395,7 @@ // Created: 3/12/03 // // -------------------------------------------------------------------------- -int CipherContext::MaxOutSizeForInBufferSize(int InLength) +size_t CipherContext::MaxOutSizeForInBufferSize(size_t InLength) { if(!mInitialised) { @@ -415,13 +416,18 @@ // Created: 1/12/03 // // -------------------------------------------------------------------------- -int CipherContext::TransformBlock(void *pOutBuffer, int OutLength, const void *pInBuffer, int InLength) +size_t CipherContext::TransformBlock(void *pOutBuffer, size_t OutLength, const void *pInBuffer, size_t InLength) { if(!mInitialised) { THROW_EXCEPTION(CipherException, NotInitialised) } - + + if(OutLength > INT_MAX || InLength > INT_MAX) + { + THROW_EXCEPTION(CipherException, BadArguments) + } + // Warn if in a transformation if(mWithinTransform) { @@ -454,13 +460,13 @@ try { // Update - outLength = OutLength; - if(EVP_CipherUpdate(&ctx, (unsigned char*)pOutBuffer, &outLength, (unsigned char*)pInBuffer, InLength) != 1) + outLength = static_cast(OutLength); + if(EVP_CipherUpdate(&ctx, (unsigned char*)pOutBuffer, &outLength, (unsigned char*)pInBuffer, static_cast(InLength)) != 1) { THROW_EXCEPTION(CipherException, EVPUpdateFailure) } // Finalise - int outLength2 = OutLength - outLength; + int outLength2 = static_cast(OutLength - outLength); #ifndef HAVE_OLD_SSL if(EVP_CipherFinal_ex(&ctx, ((unsigned char*)pOutBuffer) + outLength, &outLength2) != 1) { @@ -474,7 +480,7 @@ catch(...) { // Finalise the context, so definately ready for the next caller - int outs = OutLength; + int outs = static_cast(OutLength); #ifndef HAVE_OLD_SSL EVP_CipherFinal_ex(&ctx, (unsigned char*)pOutBuffer, &outs); #else Modified: box/invisnet/vs2010/0.11/lib/crypto/CipherContext.h =================================================================== --- box/invisnet/vs2010/0.11/lib/crypto/CipherContext.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/crypto/CipherContext.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -47,12 +47,12 @@ void Reset(); void Begin(); - int Transform(void *pOutBuffer, int OutLength, const void *pInBuffer, int InLength); - int Final(void *pOutBuffer, int OutLength); - int InSizeForOutBufferSize(int OutLength); - int MaxOutSizeForInBufferSize(int InLength); + size_t Transform(void *pOutBuffer, size_t OutLength, const void *pInBuffer, size_t InLength); + size_t Final(void *pOutBuffer, size_t OutLength); + size_t InSizeForOutBufferSize(size_t OutLength); + size_t MaxOutSizeForInBufferSize(size_t InLength); - int TransformBlock(void *pOutBuffer, int OutLength, const void *pInBuffer, int InLength); + size_t TransformBlock(void *pOutBuffer, size_t OutLength, const void *pInBuffer, size_t InLength); bool IsInitialised() {return mInitialised;} Modified: box/invisnet/vs2010/0.11/lib/crypto/MD5Digest.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/crypto/MD5Digest.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/crypto/MD5Digest.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -33,7 +33,7 @@ MD5_Update(&md5, rString.c_str(), rString.size()); } -void MD5Digest::Add(const void *pData, int Length) +void MD5Digest::Add(const void *pData, size_t Length) { MD5_Update(&md5, pData, Length); } @@ -58,7 +58,7 @@ return r; } -int MD5Digest::CopyDigestTo(uint8_t *to) +size_t MD5Digest::CopyDigestTo(uint8_t *to) { for(int l = 0; l < MD5_DIGEST_LENGTH; ++l) { Modified: box/invisnet/vs2010/0.11/lib/crypto/MD5Digest.h =================================================================== --- box/invisnet/vs2010/0.11/lib/crypto/MD5Digest.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/crypto/MD5Digest.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -28,12 +28,12 @@ virtual ~MD5Digest(); void Add(const std::string &rString); - void Add(const void *pData, int Length); + void Add(const void *pData, size_t Length); void Finish(); std::string DigestAsString(); - uint8_t *DigestAsData(int *pLength = 0) + uint8_t *DigestAsData(size_t *pLength = 0) { if(pLength) *pLength = sizeof(mDigest); return mDigest; @@ -44,7 +44,7 @@ DigestLength = MD5_DIGEST_LENGTH }; - int CopyDigestTo(uint8_t *to); + size_t CopyDigestTo(uint8_t *to); bool DigestMatches(uint8_t *pCompareWith) const; Modified: box/invisnet/vs2010/0.11/lib/crypto/RollingChecksum.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/crypto/RollingChecksum.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/crypto/RollingChecksum.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -20,15 +20,15 @@ // Created: 6/12/03 // // -------------------------------------------------------------------------- -RollingChecksum::RollingChecksum(const void * const data, const unsigned int Length) +RollingChecksum::RollingChecksum(const void * const data, const size_t Length) : a(0), b(0) { const uint8_t *block = (const uint8_t *)data; - for(unsigned int x = Length; x >= 1; --x) + for(size_t x = Length; x >= 1; --x) { a += (*block); - b += x * (*block); + b = static_cast(b + x * (*block)); ++block; } @@ -43,7 +43,7 @@ // Created: 7/14/05 // // -------------------------------------------------------------------------- -void RollingChecksum::RollForwardSeveral(const uint8_t * const StartOfThisBlock, const uint8_t * const LastOfNextBlock, const unsigned int Length, const unsigned int Skip) +void RollingChecksum::RollForwardSeveral(const uint8_t * const StartOfThisBlock, const uint8_t * const LastOfNextBlock, const size_t Length, const size_t Skip) { // IMPLEMENTATION NOTE: Everything is implicitly mod 2^16 -- uint16_t's will overflow nicely. unsigned int i; @@ -58,5 +58,5 @@ b += a; } - b -= Length * sumBegin; + b = static_cast(b - Length * sumBegin); } Modified: box/invisnet/vs2010/0.11/lib/crypto/RollingChecksum.h =================================================================== --- box/invisnet/vs2010/0.11/lib/crypto/RollingChecksum.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/crypto/RollingChecksum.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -24,7 +24,7 @@ class RollingChecksum { public: - RollingChecksum(const void * const data, const unsigned int Length); + RollingChecksum(const void * const data, const size_t Length); // -------------------------------------------------------------------------- // @@ -35,12 +35,12 @@ // Created: 6/12/03 // // -------------------------------------------------------------------------- - inline void RollForward(const uint8_t StartOfThisBlock, const uint8_t LastOfNextBlock, const unsigned int Length) + inline void RollForward(const uint8_t StartOfThisBlock, const uint8_t LastOfNextBlock, const size_t Length) { // IMPLEMENTATION NOTE: Everything is implicitly mod 2^16 -- uint16_t's will overflow nicely. a -= StartOfThisBlock; a += LastOfNextBlock; - b -= Length * StartOfThisBlock; + b -= static_cast(Length * StartOfThisBlock); b += a; } @@ -53,7 +53,7 @@ // Created: 7/14/05 // // -------------------------------------------------------------------------- - void RollForwardSeveral(const uint8_t * const StartOfThisBlock, const uint8_t * const LastOfNextBlock, const unsigned int Length, const unsigned int Skip); + void RollForwardSeveral(const uint8_t * const StartOfThisBlock, const uint8_t * const LastOfNextBlock, const size_t Length, const size_t Skip); // -------------------------------------------------------------------------- // Modified: box/invisnet/vs2010/0.11/lib/server/Protocol.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/server/Protocol.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/server/Protocol.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -50,9 +50,9 @@ mTimeout(PROTOCOL_DEFAULT_TIMEOUT), mpBuffer(0), mBufferSize(0), - mReadOffset(-1), - mWriteOffset(-1), - mValidDataSize(-1), + mReadOffset(SIZE_MAX), + mWriteOffset(SIZE_MAX), + mValidDataSize(SIZE_MAX), mLastErrorType(NoError), mLastErrorSubType(NoError) { @@ -137,11 +137,11 @@ PW_Handshake hsReceive; ::memset(&hsReceive, 0, sizeof(hsReceive)); char *readInto = (char*)&hsReceive; - int bytesToRead = sizeof(hsReceive); + size_t bytesToRead = sizeof(hsReceive); while(bytesToRead > 0) { // Get some data from the stream - int bytesRead = mrStream.Read(readInto, bytesToRead, mTimeout); + size_t bytesRead = mrStream.Read(readInto, bytesToRead, mTimeout); if(bytesRead == 0) { THROW_EXCEPTION(ConnectionException, Conn_Protocol_Timeout) @@ -173,7 +173,7 @@ void Protocol::CheckAndReadHdr(void *hdr) { // Check usage - if(mValidDataSize != -1 || mWriteOffset != -1 || mReadOffset != -1) + if(mValidDataSize != SIZE_MAX || mWriteOffset != SIZE_MAX || mReadOffset != SIZE_MAX) { THROW_EXCEPTION(ServerException, Protocol_BadUsage) } @@ -243,8 +243,8 @@ catch(...) { // Make sure state is reset! - mValidDataSize = -1; - mReadOffset = -1; + mValidDataSize = SIZE_MAX; + mReadOffset = SIZE_MAX; throw; } @@ -252,8 +252,8 @@ bool dataLeftOver = (mValidDataSize != mReadOffset); // Unset read state, so future read calls don't fail - mValidDataSize = -1; - mReadOffset = -1; + mValidDataSize = SIZE_MAX; + mReadOffset = SIZE_MAX; // Exception if not all the data was consumed if(dataLeftOver) @@ -275,7 +275,7 @@ void Protocol::Send(const ProtocolObject &rObject) { // Check usage - if(mValidDataSize != -1 || mWriteOffset != -1 || mReadOffset != -1) + if(mValidDataSize != SIZE_MAX || mWriteOffset != SIZE_MAX || mReadOffset != SIZE_MAX) { THROW_EXCEPTION(ServerException, Protocol_BadUsage) } @@ -288,7 +288,7 @@ // Make sure there's a little bit of space allocated EnsureBufferAllocated(((sizeof(PW_ObjectHeader) + PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK - 1) / PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK) * PROTOCOL_ALLOCATE_SEND_BLOCK_CHUNK); - ASSERT(mBufferSize >= (int)sizeof(PW_ObjectHeader)); + ASSERT(mBufferSize >= sizeof(PW_ObjectHeader)); // Setup for write operation mValidDataSize = 0; // Not used, but must not be -1 @@ -301,17 +301,18 @@ catch(...) { // Make sure state is reset! - mValidDataSize = -1; - mWriteOffset = -1; + mValidDataSize = SIZE_MAX; + mWriteOffset = SIZE_MAX; throw; } // How big? - int writtenSize = mWriteOffset; + ASSERT(mWriteOffset <= UINT_MAX); + u_int32_t writtenSize = static_cast(mWriteOffset); // Reset write state - mValidDataSize = -1; - mWriteOffset = -1; + mValidDataSize = SIZE_MAX; + mWriteOffset = SIZE_MAX; // Make header in the existing block PW_ObjectHeader *pobjHeader = (PW_ObjectHeader*)(mpBuffer); @@ -331,7 +332,7 @@ // Created: 2003/08/19 // // -------------------------------------------------------------------------- -void Protocol::EnsureBufferAllocated(int Size) +void Protocol::EnsureBufferAllocated(size_t Size) { if(mpBuffer != 0 && mBufferSize >= Size) { @@ -365,13 +366,13 @@ #define READ_START_CHECK \ - if(mValidDataSize == -1 || mWriteOffset != -1 || mReadOffset == -1) \ + if(mValidDataSize == SIZE_MAX || mWriteOffset != SIZE_MAX || mReadOffset == SIZE_MAX) \ { \ THROW_EXCEPTION(ServerException, Protocol_BadUsage) \ } #define READ_CHECK_BYTES_AVAILABLE(bytesRequired) \ - if((mReadOffset + (int)(bytesRequired)) > mValidDataSize) \ + if(mReadOffset + bytesRequired > mValidDataSize) \ { \ THROW_EXCEPTION(ConnectionException, Conn_Protocol_BadCommandRecieved) \ } @@ -384,7 +385,7 @@ // Created: 2003/08/19 // // -------------------------------------------------------------------------- -void Protocol::Read(void *Buffer, int Size) +void Protocol::Read(void *Buffer, size_t Size) { READ_START_CHECK READ_CHECK_BYTES_AVAILABLE(Size) @@ -402,7 +403,7 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -void Protocol::Read(std::string &rOut, int Size) +void Protocol::Read(std::string &rOut, size_t Size) { READ_START_CHECK READ_CHECK_BYTES_AVAILABLE(Size) @@ -518,7 +519,7 @@ #define WRITE_START_CHECK \ - if(mValidDataSize == -1 || mWriteOffset == -1 || mReadOffset != -1) \ + if(mValidDataSize == SIZE_MAX || mWriteOffset == SIZE_MAX || mReadOffset != SIZE_MAX) \ { \ THROW_EXCEPTION(ServerException, Protocol_BadUsage) \ } @@ -538,7 +539,7 @@ // Created: 2003/08/19 // // -------------------------------------------------------------------------- -void Protocol::Write(const void *Buffer, int Size) +void Protocol::Write(const void *Buffer, size_t Size) { WRITE_START_CHECK WRITE_ENSURE_BYTES_AVAILABLE(Size) @@ -695,7 +696,7 @@ void Protocol::SendStream(IOStream &rStream) { // Check usage - if(mValidDataSize != -1 || mWriteOffset != -1 || mReadOffset != -1) + if(mValidDataSize != SIZE_MAX || mWriteOffset != SIZE_MAX || mReadOffset != SIZE_MAX) { THROW_EXCEPTION(ServerException, Protocol_BadUsage) } @@ -721,7 +722,7 @@ // Make header PW_ObjectHeader objHeader; - objHeader.mObjSize = htonl(uncertainSize?(ProtocolStream_SizeUncertain):streamSize); + objHeader.mObjSize = htonl(static_cast(uncertainSize?(ProtocolStream_SizeUncertain):streamSize)); objHeader.mObjType = htonl(SPECIAL_STREAM_OBJECT_TYPE); // Write header @@ -741,7 +742,7 @@ try { - int bytesInBlock = 0; + size_t bytesInBlock = 0; while(rStream.StreamDataLeft()) { // Read some of it @@ -794,7 +795,7 @@ // Created: 5/12/03 // // -------------------------------------------------------------------------- -int Protocol::SendStreamSendBlock(uint8_t *Block, int BytesInBlock) +size_t Protocol::SendStreamSendBlock(uint8_t *Block, size_t BytesInBlock) { // Quick sanity check if(BytesInBlock == 0) @@ -805,7 +806,7 @@ // Work out the header byte uint8_t header = 0; - int writeSize = 0; + size_t writeSize = 0; if(BytesInBlock >= (64*1024)) { header = ProtocolStreamHeader_SizeIs64k; @@ -852,7 +853,7 @@ // Created: 2003/10/27 // // -------------------------------------------------------------------------- -void Protocol::InformStreamReceiving(u_int32_t Size) +void Protocol::InformStreamReceiving(IOStream::pos_type Size) { // Do nothing } @@ -865,7 +866,7 @@ // Created: 2003/10/27 // // -------------------------------------------------------------------------- -void Protocol::InformStreamSending(u_int32_t Size) +void Protocol::InformStreamSending(IOStream::pos_type Size) { // Do nothing } Modified: box/invisnet/vs2010/0.11/lib/server/Protocol.h =================================================================== --- box/invisnet/vs2010/0.11/lib/server/Protocol.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/server/Protocol.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -89,8 +89,8 @@ void SetMaxObjectSize(unsigned int NewMaxObjSize) {mMaxObjectSize = NewMaxObjSize;} // For ProtocolObject derived classes - void Read(void *Buffer, int Size); - void Read(std::string &rOut, int Size); + void Read(void *Buffer, size_t Size); + void Read(std::string &rOut, size_t Size); void Read(int64_t &rOut); void Read(int32_t &rOut); void Read(int16_t &rOut); @@ -124,7 +124,7 @@ } } - void Write(const void *Buffer, int Size); + void Write(const void *Buffer, size_t Size); void Write(int64_t Value); void Write(int32_t Value); void Write(int16_t Value); @@ -177,12 +177,12 @@ void CheckAndReadHdr(void *hdr); // don't use type here to avoid dependency // Will be used for logging - virtual void InformStreamReceiving(u_int32_t Size); - virtual void InformStreamSending(u_int32_t Size); + virtual void InformStreamReceiving(IOStream::pos_type Size); + virtual void InformStreamSending(IOStream::pos_type Size); private: - void EnsureBufferAllocated(int Size); - int SendStreamSendBlock(uint8_t *Block, int BytesInBlock); + void EnsureBufferAllocated(size_t Size); + size_t SendStreamSendBlock(uint8_t *Block, size_t BytesInBlock); private: IOStream &mrStream; @@ -190,10 +190,10 @@ unsigned int mMaxObjectSize; int mTimeout; char *mpBuffer; - int mBufferSize; - int mReadOffset; - int mWriteOffset; - int mValidDataSize; + size_t mBufferSize; + size_t mReadOffset; + size_t mWriteOffset; + size_t mValidDataSize; int mLastErrorType; int mLastErrorSubType; }; Modified: box/invisnet/vs2010/0.11/lib/server/ProtocolUncertainStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/server/ProtocolUncertainStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/server/ProtocolUncertainStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -54,7 +54,7 @@ // Created: 2003/12/05 // // -------------------------------------------------------------------------- -int ProtocolUncertainStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t ProtocolUncertainStream::Read(void *pBuffer, size_t NBytes, int Timeout) { // Finished? if(mFinished) @@ -62,7 +62,7 @@ return 0; } - int read = 0; + size_t read = 0; while(read < NBytes) { // Anything we can get from the current block? @@ -70,7 +70,7 @@ if(mBytesLeftInCurrentBlock > 0) { // Yes, let's use some of these up - int toRead = (NBytes - read); + size_t toRead = (NBytes - read); if(toRead > mBytesLeftInCurrentBlock) { // Adjust downwards to only read stuff out of the current block @@ -80,7 +80,7 @@ BOX_TRACE("Reading " << toRead << " bytes from stream"); // Read it - int r = mrSource.Read(((uint8_t*)pBuffer) + read, toRead, Timeout); + size_t r = mrSource.Read(((uint8_t*)pBuffer) + read, toRead, Timeout); // Give up now if it didn't return anything if(r == 0) { @@ -172,7 +172,7 @@ // Created: 2003/12/05 // // -------------------------------------------------------------------------- -void ProtocolUncertainStream::Write(const void *pBuffer, int NBytes) +void ProtocolUncertainStream::Write(const void *pBuffer, size_t NBytes) { THROW_EXCEPTION(ServerException, CantWriteToProtocolUncertainStream) } Modified: box/invisnet/vs2010/0.11/lib/server/ProtocolUncertainStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/server/ProtocolUncertainStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/server/ProtocolUncertainStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -31,15 +31,15 @@ ProtocolUncertainStream(const ProtocolUncertainStream &); public: - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); virtual pos_type BytesLeftToRead(); - virtual void Write(const void *pBuffer, int NBytes); + virtual void Write(const void *pBuffer, size_t NBytes); virtual bool StreamDataLeft(); virtual bool StreamClosed(); private: IOStream &mrSource; - int mBytesLeftInCurrentBlock; + size_t mBytesLeftInCurrentBlock; bool mFinished; }; Modified: box/invisnet/vs2010/0.11/lib/server/SocketStreamTLS.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/server/SocketStreamTLS.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/server/SocketStreamTLS.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -294,10 +294,13 @@ // Created: 2003/08/06 // // -------------------------------------------------------------------------- -int SocketStreamTLS::Read(void *pBuffer, int NBytes, int Timeout) +size_t SocketStreamTLS::Read(void *pBuffer, size_t NBytes_, int Timeout) { if(!mpSSL) {THROW_EXCEPTION(ServerException, TLSNoSSLObject)} + ASSERT(NBytes_ < INT_MAX); + int NBytes = static_cast(NBytes_); + // Make sure zero byte reads work as expected if(NBytes == 0) { @@ -350,9 +353,12 @@ // Created: 2003/08/06 // // -------------------------------------------------------------------------- -void SocketStreamTLS::Write(const void *pBuffer, int NBytes) +void SocketStreamTLS::Write(const void *pBuffer, size_t NBytes_) { if(!mpSSL) {THROW_EXCEPTION(ServerException, TLSNoSSLObject)} + + ASSERT(NBytes_ < INT_MAX); + int NBytes = static_cast(NBytes_); // Make sure zero byte writes work as expected if(NBytes == 0) Modified: box/invisnet/vs2010/0.11/lib/server/SocketStreamTLS.h =================================================================== --- box/invisnet/vs2010/0.11/lib/server/SocketStreamTLS.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/server/SocketStreamTLS.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -42,8 +42,8 @@ const std::string& rName, int Port = 0); void Handshake(const TLSContext &rContext, bool IsServer = false); - virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); - virtual void Write(const void *pBuffer, int NBytes); + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); + virtual void Write(const void *pBuffer, size_t NBytes); virtual void Close(); virtual void Shutdown(bool Read = true, bool Write = true); Modified: box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.cpp 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.cpp 2010-10-17 21:31:28 UTC (rev 2792) @@ -247,7 +247,7 @@ // Created: 2003/07/31 // // -------------------------------------------------------------------------- -int WinNamedPipeStream::Read(void *pBuffer, int NBytes, int Timeout) +size_t WinNamedPipeStream::Read(void *pBuffer, size_t NBytes, int Timeout) { // TODO no support for timeouts yet if (!mIsServer && Timeout != IOStream::TimeOutInfinite) @@ -445,7 +445,7 @@ // Created: 2003/07/31 // // -------------------------------------------------------------------------- -void WinNamedPipeStream::Write(const void *pBuffer, int NBytes) +void WinNamedPipeStream::Write(const void *pBuffer, size_t NBytes) { if (mSocketHandle == INVALID_HANDLE_VALUE || !mIsConnected) { Modified: box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.h 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/server/WinNamedPipeStream.h 2010-10-17 21:31:28 UTC (rev 2792) @@ -34,9 +34,9 @@ void Connect(const std::string& rName); // both sides - virtual int Read(void *pBuffer, int NBytes, + virtual size_t Read(void *pBuffer, size_t NBytes, int Timeout = IOStream::TimeOutInfinite); - virtual void Write(const void *pBuffer, int NBytes); + virtual void Write(const void *pBuffer, size_t NBytes); virtual void WriteAllBuffered(); virtual void Close(); virtual bool StreamDataLeft(); Modified: box/invisnet/vs2010/0.11/lib/server/makeprotocol.pl.in =================================================================== --- box/invisnet/vs2010/0.11/lib/server/makeprotocol.pl.in 2010-10-16 17:31:19 UTC (rev 2791) +++ box/invisnet/vs2010/0.11/lib/server/makeprotocol.pl.in 2010-10-17 21:31:28 UTC (rev 2792) @@ -625,8 +625,8 @@ if($implement_filelog || $implement_syslog) { print H <<__E; - virtual void InformStreamReceiving(u_int32_t Size); - virtual void InformStreamSending(u_int32_t Size); + virtual void InformStreamReceiving(IOStream::pos_type Size); + virtual void InformStreamSending(IOStream::pos_type Size); __E } @@ -864,11 +864,11 @@ print CPP <<__E; -void ${prefix}InformStreamReceiving(u_int32_t Size) +void ${prefix}InformStreamReceiving(IOStream::pos_type Size) { $fR} -void ${prefix}InformStreamSending(u_int32_t Size) +void ${prefix}InformStreamSending(IOStream::pos_type Size) { $fS} From subversion at boxbackup.org Mon Oct 18 21:32:52 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Mon, 18 Oct 2010 21:32:52 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2793 - box/trunk/test/bbackupd Message-ID: <20101018203252.C6D5716A0B5@www.boxbackup.org> Author: chris Date: 2010-10-18 21:32:52 +0100 (Mon, 18 Oct 2010) New Revision: 2793 Modified: box/trunk/test/bbackupd/testbbackupd.cpp Log: Fix location of memleaks file to fix test/bbackupd again. Modified: box/trunk/test/bbackupd/testbbackupd.cpp =================================================================== --- box/trunk/test/bbackupd/testbbackupd.cpp 2010-10-17 21:31:28 UTC (rev 2792) +++ box/trunk/test/bbackupd/testbbackupd.cpp 2010-10-18 20:32:52 UTC (rev 2793) @@ -2083,7 +2083,8 @@ "quit"); TEST_RETURN(compareReturnValue, BackupQueries::ReturnCode::Command_OK); - TestRemoteProcessMemLeaks("bbackupquery.memleaks"); + TestRemoteProcessMemLeaks("testfiles/restore-test/" + "bbackupquery.memleaks"); // check that it restored properly compareReturnValue = ::system(BBACKUPQUERY " " From subversion at boxbackup.org Mon Oct 18 21:34:26 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Mon, 18 Oct 2010 21:34:26 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2794 - in box/trunk: . bin/bbackupd bundled infrastructure qdbm qdbm/misc Message-ID: <20101018203426.4B07E16A23C@www.boxbackup.org> Author: chris Date: 2010-10-18 21:34:25 +0100 (Mon, 18 Oct 2010) New Revision: 2794 Added: box/trunk/qdbm/ box/trunk/qdbm/COPYING box/trunk/qdbm/ChangeLog box/trunk/qdbm/LTmakefile.in box/trunk/qdbm/Makefile.in box/trunk/qdbm/NEWS box/trunk/qdbm/README box/trunk/qdbm/RISCmakefile box/trunk/qdbm/THANKS box/trunk/qdbm/VCmakefile box/trunk/qdbm/cabin.c box/trunk/qdbm/cabin.h box/trunk/qdbm/cbcodec.c box/trunk/qdbm/cbtest.c box/trunk/qdbm/configure box/trunk/qdbm/configure.in box/trunk/qdbm/crmgr.c box/trunk/qdbm/crtest.c box/trunk/qdbm/crtsv.c box/trunk/qdbm/curia.c box/trunk/qdbm/curia.h box/trunk/qdbm/depot.c box/trunk/qdbm/depot.h box/trunk/qdbm/dpmgr.c box/trunk/qdbm/dptest.c box/trunk/qdbm/dptsv.c box/trunk/qdbm/hovel.c box/trunk/qdbm/hovel.h box/trunk/qdbm/hvmgr.c box/trunk/qdbm/hvtest.c box/trunk/qdbm/misc/ box/trunk/qdbm/misc/COPYING.txt box/trunk/qdbm/misc/README-win32.txt box/trunk/qdbm/misc/VCmakefile-old box/trunk/qdbm/misc/benchmark.pdf box/trunk/qdbm/misc/icon16.png box/trunk/qdbm/misc/icon20.png box/trunk/qdbm/misc/index.html box/trunk/qdbm/misc/index.ja.html box/trunk/qdbm/misc/logo.png box/trunk/qdbm/misc/makevcdef box/trunk/qdbm/misc/mymemo-ja.html box/trunk/qdbm/misc/tutorial-ja.html box/trunk/qdbm/misc/win32check.bat box/trunk/qdbm/myconf.c box/trunk/qdbm/myconf.h box/trunk/qdbm/odeum.c box/trunk/qdbm/odeum.h box/trunk/qdbm/odidx.c box/trunk/qdbm/odmgr.c box/trunk/qdbm/odtest.c box/trunk/qdbm/qdbm.def box/trunk/qdbm/qdbm.pc.in box/trunk/qdbm/qdbm.spec.in box/trunk/qdbm/qmttest.c box/trunk/qdbm/relic.c box/trunk/qdbm/relic.h box/trunk/qdbm/rlmgr.c box/trunk/qdbm/rltest.c box/trunk/qdbm/spex-ja.html box/trunk/qdbm/spex.html box/trunk/qdbm/villa.c box/trunk/qdbm/villa.h box/trunk/qdbm/vista.c box/trunk/qdbm/vista.h box/trunk/qdbm/vlmgr.c box/trunk/qdbm/vltest.c box/trunk/qdbm/vltsv.c Removed: box/trunk/bundled/replace/ box/trunk/bundled/tdb/ box/trunk/qdbm/COPYING box/trunk/qdbm/ChangeLog box/trunk/qdbm/LTmakefile.in box/trunk/qdbm/Makefile.in box/trunk/qdbm/NEWS box/trunk/qdbm/README box/trunk/qdbm/RISCmakefile box/trunk/qdbm/THANKS box/trunk/qdbm/VCmakefile box/trunk/qdbm/cabin.c box/trunk/qdbm/cabin.h box/trunk/qdbm/cbcodec.c box/trunk/qdbm/cbtest.c box/trunk/qdbm/configure box/trunk/qdbm/configure.in box/trunk/qdbm/crmgr.c box/trunk/qdbm/crtest.c box/trunk/qdbm/crtsv.c box/trunk/qdbm/curia.c box/trunk/qdbm/curia.h box/trunk/qdbm/depot.c box/trunk/qdbm/depot.h box/trunk/qdbm/dpmgr.c box/trunk/qdbm/dptest.c box/trunk/qdbm/dptsv.c box/trunk/qdbm/hovel.c box/trunk/qdbm/hovel.h box/trunk/qdbm/hvmgr.c box/trunk/qdbm/hvtest.c box/trunk/qdbm/misc/ box/trunk/qdbm/misc/COPYING.txt box/trunk/qdbm/misc/README-win32.txt box/trunk/qdbm/misc/VCmakefile-old box/trunk/qdbm/misc/benchmark.pdf box/trunk/qdbm/misc/icon16.png box/trunk/qdbm/misc/icon20.png box/trunk/qdbm/misc/index.html box/trunk/qdbm/misc/index.ja.html box/trunk/qdbm/misc/logo.png box/trunk/qdbm/misc/makevcdef box/trunk/qdbm/misc/mymemo-ja.html box/trunk/qdbm/misc/tutorial-ja.html box/trunk/qdbm/misc/win32check.bat box/trunk/qdbm/myconf.c box/trunk/qdbm/myconf.h box/trunk/qdbm/odeum.c box/trunk/qdbm/odeum.h box/trunk/qdbm/odidx.c box/trunk/qdbm/odmgr.c box/trunk/qdbm/odtest.c box/trunk/qdbm/qdbm.def box/trunk/qdbm/qdbm.pc.in box/trunk/qdbm/qdbm.spec.in box/trunk/qdbm/qmttest.c box/trunk/qdbm/relic.c box/trunk/qdbm/relic.h box/trunk/qdbm/rlmgr.c box/trunk/qdbm/rltest.c box/trunk/qdbm/spex-ja.html box/trunk/qdbm/spex.html box/trunk/qdbm/villa.c box/trunk/qdbm/villa.h box/trunk/qdbm/vista.c box/trunk/qdbm/vista.h box/trunk/qdbm/vlmgr.c box/trunk/qdbm/vltest.c box/trunk/qdbm/vltsv.c Modified: box/trunk/bin/bbackupd/BackupClientInodeToIDMap.cpp box/trunk/bin/bbackupd/BackupClientInodeToIDMap.h box/trunk/bootstrap box/trunk/configure.ac box/trunk/infrastructure/makebuildenv.pl.in box/trunk/infrastructure/makeparcels.pl.in box/trunk/modules.txt box/trunk/parcels.txt Log: Revert [2710] and [2717], remove TDB and replace with QDBM again, to fix build on Windows and make it easier to merge Charles' work. Modified: box/trunk/bin/bbackupd/BackupClientInodeToIDMap.cpp =================================================================== --- box/trunk/bin/bbackupd/BackupClientInodeToIDMap.cpp 2010-10-18 20:32:52 UTC (rev 2793) +++ box/trunk/bin/bbackupd/BackupClientInodeToIDMap.cpp 2010-10-18 20:34:25 UTC (rev 2794) @@ -10,10 +10,8 @@ #include "Box.h" #include +#include -#define _PUBLIC_ -#include "tdb.h" - #define BACKIPCLIENTINODETOIDMAP_IMPLEMENTATION #include "BackupClientInodeToIDMap.h" #undef BACKIPCLIENTINODETOIDMAP_IMPLEMENTATION @@ -28,7 +26,7 @@ int64_t mInDirectory; } IDBRecord; -#define BOX_DBM_MESSAGE(stuff) stuff << " (tdb): " << tdb_error(mpContext) +#define BOX_DBM_MESSAGE(stuff) stuff << " (qdbm): " << dperrmsg(dpecode) #define BOX_LOG_DBM_ERROR(stuff) \ BOX_ERROR(BOX_DBM_MESSAGE(stuff)) @@ -38,21 +36,21 @@ THROW_EXCEPTION_MESSAGE(exception, subtype, \ BOX_DBM_MESSAGE(message << ": " << filename)); -#define ASSERT_DBM(success, message, exception, subtype) \ - if(!(success)) \ +#define ASSERT_DBM_OK(operation, message, filename, exception, subtype) \ + if(!(operation)) \ { \ - THROW_DBM_ERROR(message, mFilename, exception, subtype); \ + THROW_DBM_ERROR(message, filename, exception, subtype); \ } #define ASSERT_DBM_OPEN() \ - if(mpContext == 0) \ + if(mpDepot == 0) \ { \ THROW_EXCEPTION_MESSAGE(BackupStoreException, InodeMapNotOpen, \ "Inode database not open"); \ } #define ASSERT_DBM_CLOSED() \ - if(mpContext != 0) \ + if(mpDepot != 0) \ { \ THROW_EXCEPTION_MESSAGE(CommonException, Internal, \ "Inode database already open: " << mFilename); \ @@ -69,7 +67,7 @@ BackupClientInodeToIDMap::BackupClientInodeToIDMap() : mReadOnly(true), mEmpty(false), - mpContext(NULL) + mpDepot(0) { } @@ -83,7 +81,7 @@ // -------------------------------------------------------------------------- BackupClientInodeToIDMap::~BackupClientInodeToIDMap() { - if(mpContext != NULL) + if(mpDepot != 0) { Close(); } @@ -110,15 +108,15 @@ ASSERT(!mEmpty); // Open the database file - int mode = ReadOnly ? O_RDONLY : O_RDWR; + int mode = ReadOnly ? DP_OREADER : DP_OWRITER; if(CreateNew) { - mode |= O_CREAT; + mode |= DP_OCREAT; } - mpContext = tdb_open(Filename, 0, 0, mode, 0700); + mpDepot = dpopen(Filename, mode, 0); - ASSERT_DBM(mpContext != NULL, "Failed to open inode database", + ASSERT_DBM_OK(mpDepot, "Failed to open inode database", mFilename, BackupStoreException, BerkelyDBFailure); // Read only flag @@ -139,7 +137,7 @@ void BackupClientInodeToIDMap::OpenEmpty() { ASSERT_DBM_CLOSED(); - ASSERT(mpContext == NULL); + ASSERT(mpDepot == 0); mEmpty = true; mReadOnly = true; } @@ -155,22 +153,11 @@ void BackupClientInodeToIDMap::Close() { ASSERT_DBM_OPEN(); - ASSERT_DBM(tdb_close(mpContext) == 0, "Failed to close inode database", - BackupStoreException, BerkelyDBFailure); - mpContext = NULL; + ASSERT_DBM_OK(dpclose(mpDepot), "Failed to close inode database", + mFilename, BackupStoreException, BerkelyDBFailure); + mpDepot = 0; } -static TDB_DATA GetDatum(void* dptr, size_t dsize) -{ - TDB_DATA datum; - datum.dptr = (unsigned char *)dptr; - datum.dsize = dsize; - return datum; -} - -#define GET_STRUCT_DATUM(structure) \ - GetDatum(&structure, sizeof(structure)) - // -------------------------------------------------------------------------- // // Function @@ -189,7 +176,7 @@ THROW_EXCEPTION(BackupStoreException, InodeMapIsReadOnly); } - if(mpContext == 0) + if(mpDepot == 0) { THROW_EXCEPTION(BackupStoreException, InodeMapNotOpen); } @@ -201,9 +188,9 @@ rec.mObjectID = ObjectID; rec.mInDirectory = InDirectory; - ASSERT_DBM(tdb_store(mpContext, GET_STRUCT_DATUM(InodeRef), - GET_STRUCT_DATUM(rec), 0) == 0, - "Failed to add record to inode database", + ASSERT_DBM_OK(dpput(mpDepot, (const char *)&InodeRef, sizeof(InodeRef), + (const char *)&rec, sizeof(rec), DP_DOVER), + "Failed to add record to inode database", mFilename, BackupStoreException, BerkelyDBFailure); } @@ -227,33 +214,22 @@ return false; } - if(mpContext == 0) + if(mpDepot == 0) { THROW_EXCEPTION(BackupStoreException, InodeMapNotOpen); } ASSERT_DBM_OPEN(); - TDB_DATA datum = tdb_fetch(mpContext, GET_STRUCT_DATUM(InodeRef)); - if(datum.dptr == NULL) + IDBRecord rec; + + if(dpgetwb(mpDepot, (const char *)&InodeRef, sizeof(InodeRef), + 0, sizeof(IDBRecord), (char *)&rec) == -1) { // key not in file return false; } - - IDBRecord rec; - if(datum.dsize != sizeof(rec)) - { - THROW_EXCEPTION_MESSAGE(CommonException, Internal, - "Failed to get inode database entry: " - "record has wrong size: expected " << - sizeof(rec) << " but was " << datum.dsize << - " in " << mFilename); - } - rec = *(IDBRecord *)datum.dptr; - free(datum.dptr); - // Return data rObjectIDOut = rec.mObjectID; rInDirectoryOut = rec.mInDirectory; Modified: box/trunk/bin/bbackupd/BackupClientInodeToIDMap.h =================================================================== --- box/trunk/bin/bbackupd/BackupClientInodeToIDMap.h 2010-10-18 20:32:52 UTC (rev 2793) +++ box/trunk/bin/bbackupd/BackupClientInodeToIDMap.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -17,8 +17,7 @@ // avoid having to include the DB files when not necessary #ifndef BACKIPCLIENTINODETOIDMAP_IMPLEMENTATION - struct TDB_CONTEXT; - struct TDB_DATUM; + class DEPOT; #endif // -------------------------------------------------------------------------- @@ -50,7 +49,7 @@ bool mReadOnly; bool mEmpty; std::string mFilename; - TDB_CONTEXT *mpContext; + DEPOT *mpDepot; }; #endif // BACKUPCLIENTINODETOIDMAP_H Modified: box/trunk/bootstrap =================================================================== --- box/trunk/bootstrap 2010-10-18 20:32:52 UTC (rev 2793) +++ box/trunk/bootstrap 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,8 +1,5 @@ #!/bin/sh -set -e - aclocal -I infrastructure/m4 autoheader autoconf -( cd bundled/tdb; ./autogen.sh; ) Modified: box/trunk/configure.ac =================================================================== --- box/trunk/configure.ac 2010-10-18 20:32:52 UTC (rev 2793) +++ box/trunk/configure.ac 2010-10-18 20:34:25 UTC (rev 2794) @@ -388,7 +388,7 @@ fi cat parcels.txt | sed -e 's/#.*//' | while read cmd subdir configure_args; do - if test "$cmd" = "configure"; then + if test "$cmd" = "subdir"; then echo export CC CXX CXXFLAGS LDFLAGS LIBS args="$configure_args --target=$target_alias" Modified: box/trunk/infrastructure/makebuildenv.pl.in =================================================================== --- box/trunk/infrastructure/makebuildenv.pl.in 2010-10-18 20:32:52 UTC (rev 2793) +++ box/trunk/infrastructure/makebuildenv.pl.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -252,9 +252,6 @@ # check directory exists die "Module $mod can't be found\n" unless -d $mod; - - # skip bundled libraries with their own Makefile process - next if ($mod =~ m|^bundled/|); # and put in lists push @modules,$mod; @@ -513,21 +510,10 @@ } } + # make include path - my $include_paths = ""; + my $include_paths = join(' ',map {'-I../../'.$_} @all_deps_for_module); - foreach my $mod (@all_deps_for_module) - { - if ($mod =~ m|^bundled/| and -d "$mod/include") - { - $include_paths .= "-I../../$mod/include "; - } - else - { - $include_paths .= "-I../../$mod "; - } - } - # is target a library? my $target_is_library = ($type ne 'bin' && $type ne 'test'); @@ -788,18 +774,13 @@ { $dep_target = "\$(OUTBASE)/$dep/$1.a"; } - elsif ($dep =~ m|^bundled/(.*)|) + elsif ($dep =~ m|^.*/(.*)|) { - $dep_target = "lib$1.a"; - } - elsif ($dep =~ m|^bin/(.*)|) - { $dep_target = "\$(OUTBASE)/$dep/$1$platform_exe_ext"; } else { - die "Don't know how to add compile-time " . - "dependency on $dep"; + $dep_target = "lib$dep.a"; } $deps_makeinfo .= < - Copyright (C) - - This library 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 (at your option) any later version. - - This library 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 this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - Copied: box/trunk/qdbm/COPYING (from rev 2716, box/trunk/qdbm/COPYING) =================================================================== --- box/trunk/qdbm/COPYING (rev 0) +++ box/trunk/qdbm/COPYING 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library 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 (at your option) any later version. + + This library 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 this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + Deleted: box/trunk/qdbm/ChangeLog =================================================================== --- box/trunk/qdbm/ChangeLog 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/ChangeLog 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,990 +0,0 @@ -2007-10-18 Mikio Hirabayashi - - - A potential defect related to leaf division of B+ tree was cleared. - - Release: 1.8.77 - -2007-03-07 Mikio Hirabayashi - - - The hash function of on-memory map was optimized. - - A bug related to large object was fixed. - - Release: 1.8.76 - -2006-11-10 Mikio Hirabayashi - - - The utility API was enhanced. - - A bug related to B+ tree API for Ruby was fixed. - - Release: 1.8.75 - -2006-11-02 Mikio Hirabayashi - - - A bug related to optimization on Intel Mac series was escaped. - - Release: 1.8.74 - -2006-10-20 Mikio Hirabayashi - - - A bug related to BZIP2 encoding was fixed. - - Release: 1.8.73 - -2006-10-06 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.8.72 - -2006-08-24 Mikio Hirabayashi - - - Makefile was modified to assure portability. - - Silent flag was added to the C++ API, the Java API, and the Ruby API. - - Release: 1.8.71 - -2006-08-18 Mikio Hirabayashi - - - A bug of segmentation fault on BSD was fixed. - - A test command for checking multi thread safety was added. - - Release: 1.8.70 - -2006-08-15 Mikio Hirabayashi - - - Mutex controll in C++ API became refined. - - Release: 1.8.69 - -2006-08-08 Mikio Hirabayashi - - - A bug about memory alignment was fixed. - - A bug of handling meta data on big endian platforms was fixed. - - Release: 1.8.68 - -2006-08-05 Mikio Hirabayashi - - - A bug about memory alignment was fixed. - - A bug about parsing MIME was fixed. - - Release: 1.8.67 - -2006-08-05 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.8.66 - -2006-08-03 Mikio Hirabayashi - - - The extended API was enhanced. - - The extended advanced API was enhanced. - - Release: 1.8.65 - -2006-07-28 Mikio Hirabayashi - - - A bug of Makefile ralated to optimization was fixed. - - Release: 1.8.64 - -2006-07-24 Mikio Hirabayashi - - - A lot of functions were replaced by macros. - - The utility API was enhanced. - - Release: 1.8.63 - -2006-07-20 Mikio Hirabayashi - - - A lot of functions were replaced by macros. - - The URL resolver was to allow unescaped meta characters. - - The advanced API was enhanced. - - Release: 1.8.62 - -2006-07-14 Mikio Hirabayashi - - - A bug of the size checking function of the extended API was fixed. - - The advanced API was enhanced. - - Release: 1.8.61 - -2006-06-03 Mikio Hirabayashi - - - The basic API was enhanced. - - The extended API was enhanced. - - The advanced API was enhanced. - - Multiple cursor class is now supported on the java API. - - Release: 1.8.60 - -2006-05-30 Mikio Hirabayashi - - - The basic API was enhanced. - - The extended API was enhanced. - - The advanced API was enhanced. - - A bug of Makefile for Mac OS X support was fixed. - - Release: 1.8.59 - -2006-05-28 Mikio Hirabayashi - - - The basic API was enhanced. - - The advanced API was enhanced. - - Release: 1.8.58 - -2006-05-20 Mikio Hirabayashi - - - The basic API was enhanced. - - The utility API was enhanced. - - Release: 1.8.57 - -2006-05-17 Mikio Hirabayashi - - - A bug of URL decoder was fixed. - - Release: 1.8.56 - -2006-05-15 Mikio Hirabayashi - - - The extended API was enhanced. - - The utility API was enhanced. - - Release: 1.8.55 - -2006-05-15 Mikio Hirabayashi - - - The basic API was enhanced. - - Release: 1.8.54 - -2006-05-10 Mikio Hirabayashi - - - AIX is now supported. - - The utility API was enhanced. - - Release: 1.8.53 - -2006-05-04 Mikio Hirabayashi - - - A bug about evaluating RFC822 date format was fixed. - - Release: 1.8.52 - -2006-05-02 Mikio Hirabayashi - - - A bug about evaluating RFC822 date format was fixed. - - Warings from GCC 4.1.x were dealt with. - - Missing functions in qdbm.def were supplied. - - Release: 1.8.51 - -2006-04-28 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.8.50 - -2006-04-19 Mikio Hirabayashi - - - A parameter of dynamic linking library on Mac OS X was modified. - - The utility API was enhanced. - - Release: 1.8.49 - -2006-03-27 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.8.48 - -2006-03-10 Mikio Hirabayashi - - - LTmakefile was modified. - - The utility API was enhanced. - - Release: 1.8.47 - -2006-02-20 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.8.46 - -2006-01-28 Mikio Hirabayashi - - - Alignment algorithm was improved. - - A bug of mmap emulation on Windows was fixed. - - Release: 1.8.45 - -2006-01-24 Mikio Hirabayashi - - - A bug of handling meta data on big endian platforms was fixed. - - The advanced API was enhanced. - - Release: 1.8.44 - -2006-01-24 Mikio Hirabayashi - - - A bug of mmap emulation on Windows was fixed. - - Release: 1.8.43 - -2006-01-22 Mikio Hirabayashi - - - mmap emulation on Windows was enhanced. - - Release: 1.8.42 - -2006-01-13 Mikio Hirabayashi - - - Compression of pages of B+ tree with LZO and BZIP was added. - - Release: 1.8.41 - -2006-01-08 Mikio Hirabayashi - - - Configuration for VC++ was to build DLL. - - Release: 1.8.40 - -2006-01-04 Mikio Hirabayashi - - - The advanced API was enhanced. - - Release: 1.8.39 - -2006-01-01 Mikio Hirabayashi - - - The advanced API was enhanced. - - Release: 1.8.38 - -2005-12-26 Mikio Hirabayashi - - - Functions to set the size of the free block pool were added. - - Commands line tools were enhanced. - - Release: 1.8.37 - -2005-12-24 Mikio Hirabayashi - - - Free block pool was enhanced. - - Commands line tools were enhanced. - - Release: 1.8.36 - -2005-11-30 Mikio Hirabayashi - - - The utility API was enhanced. - - The extended advanced API was enhanced. - - All stat calls were replaced with lstat calls. - - Release: 1.8.35 - -2005-11-22 Mikio Hirabayashi - - - A bug of i-node duplication on MinGW was fixed. - - Release: 1.8.34 - -2005-09-09 Mikio Hirabayashi - - - Compressing options of ZLIB was changed. - - The utility API was enhanced. - - Release: 1.8.33 - -2005-08-30 Mikio Hirabayashi - - - A bug of backward string matching was fixed. - - The utility API was enhanced. - - Release: 1.8.32 - -2005-06-19 Mikio Hirabayashi - - - A bug of the MIME parser was fixed. - - A bug about database repair on Win32 was fixed. - - A bug of Makefile for Mac OS X support was fixed. - - The type of error codes of GDBM-compatibility API was changed. - - Release: 1.8.31 - -2005-06-09 Mikio Hirabayashi - - - A Bug of APIs for C++ related to namespace was fixed. - - The library of shared objects of C++ APIs was added. - - The utility API was enhanced. - - Release: 1.8.30 - -2005-06-01 Mikio Hirabayashi - - - A bug about file locking on Win32 was fixed. - - Manuals of command line tools were added. - - The utility API was enhanced. - - Release: 1.8.29 - -2005-05-27 Mikio Hirabayashi - - - A compilation problem on hppa-linux was fixed. - - A configuration file for pkg-config was added. - - Release: 1.8.28 - -2005-05-18 Mikio Hirabayashi - - - Non-blocking lock was featured. - - Release: 1.8.27 - -2005-05-12 Mikio Hirabayashi - - - The inverted API was enhanced. - - The utility API was enhanced. - - Release: 1.8.26 - -2005-05-10 Mikio Hirabayashi - - - The inverted API was enhanced. - - The utility API was enhanced. - - Release: 1.8.25 - -2005-04-25 Mikio Hirabayashi - - - The utility API was enhanced. - - A bug about database repair on Win32 was fixed. - - Release: 1.8.24 - -2005-04-01 Mikio Hirabayashi - - - The utility API was enhanced. - - The extended advanced API was enhanced. - - Release: 1.8.23 - -2005-03-24 Mikio Hirabayashi - - - The extended advanced API was enhanced. - - The utility API was enhanced. - - The inverted API was enhanced. - - Test commands were enhanced. - - Release: 1.8.22 - -2005-01-22 Mikio Hirabayashi - - - Functions to dump endian independent data was added. - - Release: 1.8.21 - -2005-01-05 Mikio Hirabayashi - - - Sparse file support was added. - - Release: 1.8.20 - -2005-01-02 Mikio Hirabayashi - - - The utility API was enhanced. - - Building configurations were enhanced. - - Release: 1.8.19 - -2004-11-10 Mikio Hirabayashi - - - The utility API was enhanced. - - The extended advanced API was enhanced. - - The inverted API was enhanced. - - Release: 1.8.18 - -2004-09-20 Mikio Hirabayashi - - - The utility API was enhanced. - - The CGI script for file upload was enhanced. - - The spec file for RPM packages was enhanced. - - Release: 1.8.17 - -2004-08-17 Mikio Hirabayashi - - - A bug in the extended API was fixed. - - A bug about seek on Windows 9x was fixed. - - The CGI script for file upload was enhanced. - - Release: 1.8.16 - -2004-08-04 Mikio Hirabayashi - - - The utility API was enhanced. - - A bug about mmap on Mac OS X was fixed. - - A CGI script for file upload was added. - - Building configurations were enhanced. - - Release: 1.8.15 - -2004-07-19 Mikio Hirabayashi - - - The basic API was enhanced. - - The extended API was enhanced. - - The advanced API was enhanced. - - The inverted API was enhanced. - - Building configurations were enhanced. - - Release: 1.8.14 - -2004-07-07 Mikio Hirabayashi - - - The utility API was enhanced. - - The inverted API was enhanced. - - Release: 1.8.13 - -2004-05-18 Mikio Hirabayashi - - - The utility API was enhanced. - - The inverted API was enhanced. - - Building configurations were enhanced. - - Release: 1.8.12 - -2004-05-12 Mikio Hirabayashi - - - The utility API was enhanced. - - Source codes were cleaned up for Visual C++. - - Test commands were enhanced. - - Building configurations were enhanced. - - Release: 1.8.11 - -2004-04-23 Mikio Hirabayashi - - - Utility for performance test was enhanced. - - It was escaped from a bug about mmap on FreeBSD and NetBSD. - - Release: 1.8.10 - -2004-04-20 Mikio Hirabayashi - - - Logger for debugging is now featured. - - It was escaped from a bug about mmap on OpenBSD. - - Release: 1.8.9 - -2004-04-11 Mikio Hirabayashi - - - Processing speed was improved. - - The basic API was enhanced. - - The extended API was enhanced. - - The configuration for VC++ was enhanced. - - Release: 1.8.8 - -2004-03-25 Mikio Hirabayashi - - - The configuration of C++ API escaped from a bug of pthread. - - Release: 1.8.7 - -2004-03-21 Mikio Hirabayashi - - - The extended API was enhanced. - - Bugs in the utility API about memory management were fixed. - - Release: 1.8.6 - -2004-03-12 Mikio Hirabayashi - - - A bug in the utility API for 64-bit platforms was fixed. - - The utility API was enhanced. - - Release: 1.8.5 - -2004-03-09 Mikio Hirabayashi - - - Runtime switching of whether to use ZLIB was featured. - - The binary package for Win32 now features ZLIB and ICONV. - - The utility API was enhanced. - - Release: 1.8.4 - -2004-03-06 Mikio Hirabayashi - - - The utility API was enhanced. - - A utility class of Java API was enhanced. - - Test commands were enhanced. - - Release: 1.8.3 - -2004-03-01 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.8.2 - -2004-02-22 Mikio Hirabayashi - - - Processing speed of multi-thread support was improved. - - Release: 1.8.1 - -2004-02-21 Mikio Hirabayashi - - - Switch to make API for C thread-safe was added. - - Release: 1.8.0 - -2004-02-18 Mikio Hirabayashi - - - The utility API was enhanced. - - Potential bugs in APIs for C++ were fixed. - - Release: 1.7.34 - -2004-01-28 Mikio Hirabayashi - - - The extended API was enhanced. - - The inverted API was enhanced. - - Release: 1.7.33 - -2004-01-17 Mikio Hirabayashi - - - The inverted API was enhanced. - - Release: 1.7.32 - -2004-01-16 Mikio Hirabayashi - - - The inverted API was enhanced. - - Release: 1.7.31 - -2004-01-12 Mikio Hirabayashi - - - The inverted API was enhanced. - - Release: 1.7.30 - -2004-01-11 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.7.29 - -2004-01-09 Mikio Hirabayashi - - - A bug in the utility API was fixed. - - Release: 1.7.28 - -2004-01-06 Mikio Hirabayashi - - - A bug in the advanced API was fixed. - - The utility API was enhanced. - - Release: 1.7.27 - -2004-01-04 Mikio Hirabayashi - - - The inverted API was enhanced. - - Release: 1.7.26 - -2004-01-01 Mikio Hirabayashi - - - The inverted API was enhanced. - - The utility API was enhanced. - - Release: 1.7.25 - -2003-12-26 Mikio Hirabayashi - - - C++ export was supported in header files. - - The utility API was enhanced. - - Release: 1.7.24 - -2003-12-21 Mikio Hirabayashi - - - Repairing utility was added to the advanced API. - - The basic API was enhanced. - - The utility API was enhanced. - - Release: 1.7.23 - -2003-12-16 Mikio Hirabayashi - - - Repairing utility was added to the extended API. - - The utility API was enhanced. - - Release: 1.7.22 - -2003-12-14 Mikio Hirabayashi - - - A utility to repair a broken database file was added. - - A ulitity command for full-text search was enhanced. - - Release: 1.7.21 - -2003-12-10 Mikio Hirabayashi - - - Character encoding converter was added. - - Release: 1.7.20 - -2003-12-10 Mikio Hirabayashi - - - Format converter for older versions than 1.7.13 was added. - - Tuning paramters of the inverted API were modified. - - A CGI script for full-text search was enhanced. - - Release: 1.7.19 - -2003-12-08 Mikio Hirabayashi - - - The utility API was enhanced. - - The GDBM-compatible API was enhanced. - - Release: 1.7.18 - -2003-12-05 Mikio Hirabayashi - - - The utility API was enhanced. - - A CGI script for full-text search was enhanced. - - Release: 1.7.17 - -2003-12-01 Mikio Hirabayashi - - - A CGI script for full-text search was enhanced. - - A ulitity command for full-text search was enhanced. - - Building configuration files were modified. - - Release: 1.7.16 - -2003-11-30 Mikio Hirabayashi - - - A CGI script for full-text search was enhanced. - - A ulitity command for full-text search was enhanced. - - Release: 1.7.15 - -2003-11-29 Mikio Hirabayashi - - - The inverted API was enhanced. - - A ulitity command for full-text search was enhanced. - - A CGI script for full-text search was enhanced. - - Release: 1.7.14 - -2003-11-27 Mikio Hirabayashi - - - Format of headers of database was modified. - - Supporting endian conversion was abolished. - - Import/export features were added to utility commands. - - A ulitity command for full-text search was enhanced. - - A CGI script for full-text search was enhanced. - - Release: 1.7.13 - -2003-11-25 Mikio Hirabayashi - - - The utility API was enhanced. - - The inverted API was enhanced. - - A ulitity command for full-text search was enhanced. - - A CGI script for full-text search was enhanced. - - Release: 1.7.12 - -2003-11-23 Mikio Hirabayashi - - - The inverted API was enhanced. - - A ulitity command for full-text search was enhanced. - - A CGI script for full-text search was enhanced. - - A utility class of Java API was enhanced. - - Release: 1.7.11 - -2003-11-20 Mikio Hirabayashi - - - A utility class of Java API was enhanced. - - Building configuration for CGI scripts was modified. - - Release: 1.7.10 - -2003-11-20 Mikio Hirabayashi - - - Tuning paramters of the inverted API were modified. - - A ulitity command for full-text search was enhanced. - - Release: 1.7.9 - -2003-11-16 Mikio Hirabayashi - - - Optional features of compressing with ZLIB were added. - - Release: 1.7.8 - -2003-11-05 Mikio Hirabayashi - - - The extended advanced API, Vista was added. - - Release: 1.7.7 - -2003-11-03 Mikio Hirabayashi - - - C API compilation using Visual C++ was supported. - - Odeum and its commands were enhanced. - - Release: 1.7.6 - -2003-10-25 Mikio Hirabayashi - - - A ulitity command for full-text search was enhanced. - - A CGI script for full-text search was enhanced. - - Release: 1.7.5 - -2003-10-23 Mikio Hirabayashi - - - A CGI script for full-text search was added. - - A bug of BSD support in Makefile was fixed. - - Release: 1.7.4 - -2003-10-19 Mikio Hirabayashi - - - Processing speed of the inverted API was improved. - - A ulitity command for full-text search was enhanced. - - Release: 1.7.3 - -2003-10-17 Mikio Hirabayashi - - - The license was changed to LGPL. - - An indexing command for the inverted API was added. - - Release: 1.7.2 - -2003-10-14 Mikio Hirabayashi - - - A test command for the inverted API was added. - - A bug about optimization in the inverted API was fixed. - - Tuning paramters of the inverted API were modified. - - Release: 1.7.1 - -2003-10-13 Mikio Hirabayashi - - - The inverted API, Odeum was added. - - Comments in source codes increased. - - Release: 1.7.0 - -2003-10-05 Mikio Hirabayashi - - - Executable commands were modified for RISC OS. - - Release: 1.6.22 - -2003-10-05 Mikio Hirabayashi - - - Executable commands were modified for RISC OS. - - Release: 1.6.21 - -2003-09-30 Mikio Hirabayashi - - - Naming file in RISC OS style was supported. - - Hash functions were enhanced. - - Release: 1.6.20 - -2003-09-26 Mikio Hirabayashi - - - The utility API was enhanced. - - Test commands were added. - - Release: 1.6.19 - -2003-09-22 Mikio Hirabayashi - - - Makefile for RISC OS was added. - - C++ API was enhanced. - - Release: 1.6.18 - -2003-09-14 Mikio Hirabayashi - - - Test commands were enhanced. - - Source codes and Makefile were modified for RISC OS. - - The CGI script was enhanced. - - Release: 1.6.17 - -2003-09-13 Mikio Hirabayashi - - - The CGI script for administration was added. - - C++ API was enhanced. - - Release: 1.6.16 - -2003-08-28 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.6.15 - -2003-08-16 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.6.14 - -2003-08-11 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.6.13 - -2003-08-05 Mikio Hirabayashi - - - A bug in the utility API was fixed. - - Test commands were enhanced. - - Release: 1.6.12 - -2003-07-31 Mikio Hirabayashi - - - C and Java APIs support compilation using MinGW. - - Release: 1.6.11 - -2003-07-27 Mikio Hirabayashi - - - Perl and Ruby APIs support transaction. - - Release: 1.6.10 - -2003-07-26 Mikio Hirabayashi - - - Speed of transaction was improved. - - Release: 1.6.9 - -2003-07-24 Mikio Hirabayashi - - - C++ and Java APIs of B+ tree support transaction. - - Release: 1.6.8 - -2003-07-21 Mikio Hirabayashi - - - C API of B+ tree supports transaction. - - Bugs about Mutex in C++ and Java APIs were fixed. - - Release: 1.6.7 - -2003-07-18 Mikio Hirabayashi - - - C++ and Java APIs of database abstraction were simplified. - - Ruby API of B+ tree was simplified. - - Release: 1.6.6 - -2003-07-16 Mikio Hirabayashi - - - Ruby API of B+ tree was added. - - C, C++, Java and Perl APIs of B+ tree were enhanced. - - Release: 1.6.5 - -2003-07-13 Mikio Hirabayashi - - - Perl API of B+ tree was added. - - C, C++ and Java APIs of B+ tree were enhanced. - - Release: 1.6.4 - -2003-07-08 Mikio Hirabayashi - - - Java API of B++ tree was added. - - C API of B+ tree was enhanced. - - C++ API of B+ tree was enhanced. - - Release: 1.6.3 - -2003-07-05 Mikio Hirabayashi - - - Debug routines were removed and speed was improved. - - No locking mode was added. - - Endian converter of Villa was added. - - C++ API of B++ tree was added. - - Release: 1.6.2 - -2003-07-03 Mikio Hirabayashi - - - The advanced API was enhanced to improve its speed. - - Makefiles were enhanced for HP-UX. - - Release: 1.6.1 - -2003-06-28 Mikio Hirabayashi - - - The advanced API for B+ tree database is added. - - Release: 1.6.0 - -2003-06-23 Mikio Hirabayashi - - - Makefiles were enhanced for Mac OS X. - - Release: 1.5.13 - -2003-06-18 Mikio Hirabayashi - - - Makefile was enhanced for Solaris and Mac OS X. - - Release: 1.5.12 - -2003-06-06 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.5.11 - -2003-05-31 Mikio Hirabayashi - - - The utility API was enhanced. - - Release: 1.5.10 - -2003-05-29 Mikio Hirabayashi - - - The utility API was changed. - - Release: 1.5.9 - -2003-05-25 Mikio Hirabayashi - - - Alignment mechanism was simplified. - - Release: 1.5.8 - -2003-05-17 Mikio Hirabayashi - - - Makefile was updated - - Release: 1.5.7 - -2003-05-16 Mikio Hirabayashi - - - Test tools were enhanced. - - Release: 1.5.6 - -2003-05-14 Mikio Hirabayashi - - - Makefile using libtool was added. - - Release: 1.5.5 - -2003-05-12 Mikio Hirabayashi - - - API for Ruby was enhanced. - - Release: 1.5.4 - -2003-05-08 Mikio Hirabayashi - - - API for Ruby was added. - - Release: 1.5.3 - -2003-05-04 Mikio Hirabayashi - - - API for Perl was enhanced. - - Release: 1.5.2 - -2003-04-30 Mikio Hirabayashi - - - API for Perl was enhanced. - - Release: 1.5.1 - -2003-04-29 Mikio Hirabayashi - - - API for Perl was added. - - Release: 1.5.0 - -2003-04-25 Mikio Hirabayashi - - - The package was reorganized to be a GNU package. - - Release: 1.4.11 - -2003-04-21 Mikio Hirabayashi - - - The utility API was added. - - Release: 1.4.10 - -2003-04-15 Mikio Hirabayashi - - - Endian converters were added. - - Release: 1.4.9 - -2003-04-12 Mikio Hirabayashi - - - The GDBM-compatible API was enhanced. - - Release: 1.4.8 - -2003-04-10 Mikio Hirabayashi - - - Some bugs were fixed and C++ API was enhanced. - - Release: 1.4.7 - -2003-04-09 Mikio Hirabayashi - - - Coalescence of dead regions and reuse of them were featured. - - Release: 1.4.6 - -2003-04-06 Mikio Hirabayashi - - - The GDBM-compatible API and the C++ API were enhanced. - - Release: 1.4.5 - -2003-04-04 Mikio Hirabayashi - - - The API for C++ and the API for Java were enhanced. - - Release: 1.4.4 - -2003-04-02 Mikio Hirabayashi - - - Documents for C++ was enhanced. - - Release: 1.4.3 - -2003-04-01 Mikio Hirabayashi - - - The API for Java was enhanced. - - Release: 1.4.2 - -2003-03-23 Mikio Hirabayashi - - - Makefiles were modified. - - Release: 1.4.1 - -2003-03-23 Mikio Hirabayashi - - - APIs for C++ and Java was enhanced. - - Release: 1.4.0 - -2003-03-15 Mikio Hirabayashi - - - The API for C++ was added. - - Release: 1.3.2 - -2003-03-11 Mikio Hirabayashi - - - The API for Java was supported on Solaris and Windows. - - Release: 1.3.1 - -2003-03-04 Mikio Hirabayashi - - - The API for Java was added. - - Release: 1.3.0 - -2003-02-23 Mikio Hirabayashi - - - The GDBM-compatible API was added. - - Release: 1.2.0 - -2003-02-21 Mikio Hirabayashi - - - Compatibility with NDBM was improved. - - Release: 1.1.3 - -2003-02-18 Mikio Hirabayashi - - - Optimizing suppoted on Windows. DLL is supported. - - Release: 1.1.2 - -2003-02-15 Mikio Hirabayashi - - - Windows is now supported. - - The compatible API was enhanced. - - Release: 1.1.1 - -2003-02-11 Mikio Hirabayashi - - - The NDBM-compatible API was added. - - Release: 1.1.0 - -2003-02-08 Mikio Hirabayashi - - - The initial version. - - Release: 1.0.0 - Copied: box/trunk/qdbm/ChangeLog (from rev 2716, box/trunk/qdbm/ChangeLog) =================================================================== --- box/trunk/qdbm/ChangeLog (rev 0) +++ box/trunk/qdbm/ChangeLog 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,990 @@ +2007-10-18 Mikio Hirabayashi + + - A potential defect related to leaf division of B+ tree was cleared. + - Release: 1.8.77 + +2007-03-07 Mikio Hirabayashi + + - The hash function of on-memory map was optimized. + - A bug related to large object was fixed. + - Release: 1.8.76 + +2006-11-10 Mikio Hirabayashi + + - The utility API was enhanced. + - A bug related to B+ tree API for Ruby was fixed. + - Release: 1.8.75 + +2006-11-02 Mikio Hirabayashi + + - A bug related to optimization on Intel Mac series was escaped. + - Release: 1.8.74 + +2006-10-20 Mikio Hirabayashi + + - A bug related to BZIP2 encoding was fixed. + - Release: 1.8.73 + +2006-10-06 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.8.72 + +2006-08-24 Mikio Hirabayashi + + - Makefile was modified to assure portability. + - Silent flag was added to the C++ API, the Java API, and the Ruby API. + - Release: 1.8.71 + +2006-08-18 Mikio Hirabayashi + + - A bug of segmentation fault on BSD was fixed. + - A test command for checking multi thread safety was added. + - Release: 1.8.70 + +2006-08-15 Mikio Hirabayashi + + - Mutex controll in C++ API became refined. + - Release: 1.8.69 + +2006-08-08 Mikio Hirabayashi + + - A bug about memory alignment was fixed. + - A bug of handling meta data on big endian platforms was fixed. + - Release: 1.8.68 + +2006-08-05 Mikio Hirabayashi + + - A bug about memory alignment was fixed. + - A bug about parsing MIME was fixed. + - Release: 1.8.67 + +2006-08-05 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.8.66 + +2006-08-03 Mikio Hirabayashi + + - The extended API was enhanced. + - The extended advanced API was enhanced. + - Release: 1.8.65 + +2006-07-28 Mikio Hirabayashi + + - A bug of Makefile ralated to optimization was fixed. + - Release: 1.8.64 + +2006-07-24 Mikio Hirabayashi + + - A lot of functions were replaced by macros. + - The utility API was enhanced. + - Release: 1.8.63 + +2006-07-20 Mikio Hirabayashi + + - A lot of functions were replaced by macros. + - The URL resolver was to allow unescaped meta characters. + - The advanced API was enhanced. + - Release: 1.8.62 + +2006-07-14 Mikio Hirabayashi + + - A bug of the size checking function of the extended API was fixed. + - The advanced API was enhanced. + - Release: 1.8.61 + +2006-06-03 Mikio Hirabayashi + + - The basic API was enhanced. + - The extended API was enhanced. + - The advanced API was enhanced. + - Multiple cursor class is now supported on the java API. + - Release: 1.8.60 + +2006-05-30 Mikio Hirabayashi + + - The basic API was enhanced. + - The extended API was enhanced. + - The advanced API was enhanced. + - A bug of Makefile for Mac OS X support was fixed. + - Release: 1.8.59 + +2006-05-28 Mikio Hirabayashi + + - The basic API was enhanced. + - The advanced API was enhanced. + - Release: 1.8.58 + +2006-05-20 Mikio Hirabayashi + + - The basic API was enhanced. + - The utility API was enhanced. + - Release: 1.8.57 + +2006-05-17 Mikio Hirabayashi + + - A bug of URL decoder was fixed. + - Release: 1.8.56 + +2006-05-15 Mikio Hirabayashi + + - The extended API was enhanced. + - The utility API was enhanced. + - Release: 1.8.55 + +2006-05-15 Mikio Hirabayashi + + - The basic API was enhanced. + - Release: 1.8.54 + +2006-05-10 Mikio Hirabayashi + + - AIX is now supported. + - The utility API was enhanced. + - Release: 1.8.53 + +2006-05-04 Mikio Hirabayashi + + - A bug about evaluating RFC822 date format was fixed. + - Release: 1.8.52 + +2006-05-02 Mikio Hirabayashi + + - A bug about evaluating RFC822 date format was fixed. + - Warings from GCC 4.1.x were dealt with. + - Missing functions in qdbm.def were supplied. + - Release: 1.8.51 + +2006-04-28 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.8.50 + +2006-04-19 Mikio Hirabayashi + + - A parameter of dynamic linking library on Mac OS X was modified. + - The utility API was enhanced. + - Release: 1.8.49 + +2006-03-27 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.8.48 + +2006-03-10 Mikio Hirabayashi + + - LTmakefile was modified. + - The utility API was enhanced. + - Release: 1.8.47 + +2006-02-20 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.8.46 + +2006-01-28 Mikio Hirabayashi + + - Alignment algorithm was improved. + - A bug of mmap emulation on Windows was fixed. + - Release: 1.8.45 + +2006-01-24 Mikio Hirabayashi + + - A bug of handling meta data on big endian platforms was fixed. + - The advanced API was enhanced. + - Release: 1.8.44 + +2006-01-24 Mikio Hirabayashi + + - A bug of mmap emulation on Windows was fixed. + - Release: 1.8.43 + +2006-01-22 Mikio Hirabayashi + + - mmap emulation on Windows was enhanced. + - Release: 1.8.42 + +2006-01-13 Mikio Hirabayashi + + - Compression of pages of B+ tree with LZO and BZIP was added. + - Release: 1.8.41 + +2006-01-08 Mikio Hirabayashi + + - Configuration for VC++ was to build DLL. + - Release: 1.8.40 + +2006-01-04 Mikio Hirabayashi + + - The advanced API was enhanced. + - Release: 1.8.39 + +2006-01-01 Mikio Hirabayashi + + - The advanced API was enhanced. + - Release: 1.8.38 + +2005-12-26 Mikio Hirabayashi + + - Functions to set the size of the free block pool were added. + - Commands line tools were enhanced. + - Release: 1.8.37 + +2005-12-24 Mikio Hirabayashi + + - Free block pool was enhanced. + - Commands line tools were enhanced. + - Release: 1.8.36 + +2005-11-30 Mikio Hirabayashi + + - The utility API was enhanced. + - The extended advanced API was enhanced. + - All stat calls were replaced with lstat calls. + - Release: 1.8.35 + +2005-11-22 Mikio Hirabayashi + + - A bug of i-node duplication on MinGW was fixed. + - Release: 1.8.34 + +2005-09-09 Mikio Hirabayashi + + - Compressing options of ZLIB was changed. + - The utility API was enhanced. + - Release: 1.8.33 + +2005-08-30 Mikio Hirabayashi + + - A bug of backward string matching was fixed. + - The utility API was enhanced. + - Release: 1.8.32 + +2005-06-19 Mikio Hirabayashi + + - A bug of the MIME parser was fixed. + - A bug about database repair on Win32 was fixed. + - A bug of Makefile for Mac OS X support was fixed. + - The type of error codes of GDBM-compatibility API was changed. + - Release: 1.8.31 + +2005-06-09 Mikio Hirabayashi + + - A Bug of APIs for C++ related to namespace was fixed. + - The library of shared objects of C++ APIs was added. + - The utility API was enhanced. + - Release: 1.8.30 + +2005-06-01 Mikio Hirabayashi + + - A bug about file locking on Win32 was fixed. + - Manuals of command line tools were added. + - The utility API was enhanced. + - Release: 1.8.29 + +2005-05-27 Mikio Hirabayashi + + - A compilation problem on hppa-linux was fixed. + - A configuration file for pkg-config was added. + - Release: 1.8.28 + +2005-05-18 Mikio Hirabayashi + + - Non-blocking lock was featured. + - Release: 1.8.27 + +2005-05-12 Mikio Hirabayashi + + - The inverted API was enhanced. + - The utility API was enhanced. + - Release: 1.8.26 + +2005-05-10 Mikio Hirabayashi + + - The inverted API was enhanced. + - The utility API was enhanced. + - Release: 1.8.25 + +2005-04-25 Mikio Hirabayashi + + - The utility API was enhanced. + - A bug about database repair on Win32 was fixed. + - Release: 1.8.24 + +2005-04-01 Mikio Hirabayashi + + - The utility API was enhanced. + - The extended advanced API was enhanced. + - Release: 1.8.23 + +2005-03-24 Mikio Hirabayashi + + - The extended advanced API was enhanced. + - The utility API was enhanced. + - The inverted API was enhanced. + - Test commands were enhanced. + - Release: 1.8.22 + +2005-01-22 Mikio Hirabayashi + + - Functions to dump endian independent data was added. + - Release: 1.8.21 + +2005-01-05 Mikio Hirabayashi + + - Sparse file support was added. + - Release: 1.8.20 + +2005-01-02 Mikio Hirabayashi + + - The utility API was enhanced. + - Building configurations were enhanced. + - Release: 1.8.19 + +2004-11-10 Mikio Hirabayashi + + - The utility API was enhanced. + - The extended advanced API was enhanced. + - The inverted API was enhanced. + - Release: 1.8.18 + +2004-09-20 Mikio Hirabayashi + + - The utility API was enhanced. + - The CGI script for file upload was enhanced. + - The spec file for RPM packages was enhanced. + - Release: 1.8.17 + +2004-08-17 Mikio Hirabayashi + + - A bug in the extended API was fixed. + - A bug about seek on Windows 9x was fixed. + - The CGI script for file upload was enhanced. + - Release: 1.8.16 + +2004-08-04 Mikio Hirabayashi + + - The utility API was enhanced. + - A bug about mmap on Mac OS X was fixed. + - A CGI script for file upload was added. + - Building configurations were enhanced. + - Release: 1.8.15 + +2004-07-19 Mikio Hirabayashi + + - The basic API was enhanced. + - The extended API was enhanced. + - The advanced API was enhanced. + - The inverted API was enhanced. + - Building configurations were enhanced. + - Release: 1.8.14 + +2004-07-07 Mikio Hirabayashi + + - The utility API was enhanced. + - The inverted API was enhanced. + - Release: 1.8.13 + +2004-05-18 Mikio Hirabayashi + + - The utility API was enhanced. + - The inverted API was enhanced. + - Building configurations were enhanced. + - Release: 1.8.12 + +2004-05-12 Mikio Hirabayashi + + - The utility API was enhanced. + - Source codes were cleaned up for Visual C++. + - Test commands were enhanced. + - Building configurations were enhanced. + - Release: 1.8.11 + +2004-04-23 Mikio Hirabayashi + + - Utility for performance test was enhanced. + - It was escaped from a bug about mmap on FreeBSD and NetBSD. + - Release: 1.8.10 + +2004-04-20 Mikio Hirabayashi + + - Logger for debugging is now featured. + - It was escaped from a bug about mmap on OpenBSD. + - Release: 1.8.9 + +2004-04-11 Mikio Hirabayashi + + - Processing speed was improved. + - The basic API was enhanced. + - The extended API was enhanced. + - The configuration for VC++ was enhanced. + - Release: 1.8.8 + +2004-03-25 Mikio Hirabayashi + + - The configuration of C++ API escaped from a bug of pthread. + - Release: 1.8.7 + +2004-03-21 Mikio Hirabayashi + + - The extended API was enhanced. + - Bugs in the utility API about memory management were fixed. + - Release: 1.8.6 + +2004-03-12 Mikio Hirabayashi + + - A bug in the utility API for 64-bit platforms was fixed. + - The utility API was enhanced. + - Release: 1.8.5 + +2004-03-09 Mikio Hirabayashi + + - Runtime switching of whether to use ZLIB was featured. + - The binary package for Win32 now features ZLIB and ICONV. + - The utility API was enhanced. + - Release: 1.8.4 + +2004-03-06 Mikio Hirabayashi + + - The utility API was enhanced. + - A utility class of Java API was enhanced. + - Test commands were enhanced. + - Release: 1.8.3 + +2004-03-01 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.8.2 + +2004-02-22 Mikio Hirabayashi + + - Processing speed of multi-thread support was improved. + - Release: 1.8.1 + +2004-02-21 Mikio Hirabayashi + + - Switch to make API for C thread-safe was added. + - Release: 1.8.0 + +2004-02-18 Mikio Hirabayashi + + - The utility API was enhanced. + - Potential bugs in APIs for C++ were fixed. + - Release: 1.7.34 + +2004-01-28 Mikio Hirabayashi + + - The extended API was enhanced. + - The inverted API was enhanced. + - Release: 1.7.33 + +2004-01-17 Mikio Hirabayashi + + - The inverted API was enhanced. + - Release: 1.7.32 + +2004-01-16 Mikio Hirabayashi + + - The inverted API was enhanced. + - Release: 1.7.31 + +2004-01-12 Mikio Hirabayashi + + - The inverted API was enhanced. + - Release: 1.7.30 + +2004-01-11 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.7.29 + +2004-01-09 Mikio Hirabayashi + + - A bug in the utility API was fixed. + - Release: 1.7.28 + +2004-01-06 Mikio Hirabayashi + + - A bug in the advanced API was fixed. + - The utility API was enhanced. + - Release: 1.7.27 + +2004-01-04 Mikio Hirabayashi + + - The inverted API was enhanced. + - Release: 1.7.26 + +2004-01-01 Mikio Hirabayashi + + - The inverted API was enhanced. + - The utility API was enhanced. + - Release: 1.7.25 + +2003-12-26 Mikio Hirabayashi + + - C++ export was supported in header files. + - The utility API was enhanced. + - Release: 1.7.24 + +2003-12-21 Mikio Hirabayashi + + - Repairing utility was added to the advanced API. + - The basic API was enhanced. + - The utility API was enhanced. + - Release: 1.7.23 + +2003-12-16 Mikio Hirabayashi + + - Repairing utility was added to the extended API. + - The utility API was enhanced. + - Release: 1.7.22 + +2003-12-14 Mikio Hirabayashi + + - A utility to repair a broken database file was added. + - A ulitity command for full-text search was enhanced. + - Release: 1.7.21 + +2003-12-10 Mikio Hirabayashi + + - Character encoding converter was added. + - Release: 1.7.20 + +2003-12-10 Mikio Hirabayashi + + - Format converter for older versions than 1.7.13 was added. + - Tuning paramters of the inverted API were modified. + - A CGI script for full-text search was enhanced. + - Release: 1.7.19 + +2003-12-08 Mikio Hirabayashi + + - The utility API was enhanced. + - The GDBM-compatible API was enhanced. + - Release: 1.7.18 + +2003-12-05 Mikio Hirabayashi + + - The utility API was enhanced. + - A CGI script for full-text search was enhanced. + - Release: 1.7.17 + +2003-12-01 Mikio Hirabayashi + + - A CGI script for full-text search was enhanced. + - A ulitity command for full-text search was enhanced. + - Building configuration files were modified. + - Release: 1.7.16 + +2003-11-30 Mikio Hirabayashi + + - A CGI script for full-text search was enhanced. + - A ulitity command for full-text search was enhanced. + - Release: 1.7.15 + +2003-11-29 Mikio Hirabayashi + + - The inverted API was enhanced. + - A ulitity command for full-text search was enhanced. + - A CGI script for full-text search was enhanced. + - Release: 1.7.14 + +2003-11-27 Mikio Hirabayashi + + - Format of headers of database was modified. + - Supporting endian conversion was abolished. + - Import/export features were added to utility commands. + - A ulitity command for full-text search was enhanced. + - A CGI script for full-text search was enhanced. + - Release: 1.7.13 + +2003-11-25 Mikio Hirabayashi + + - The utility API was enhanced. + - The inverted API was enhanced. + - A ulitity command for full-text search was enhanced. + - A CGI script for full-text search was enhanced. + - Release: 1.7.12 + +2003-11-23 Mikio Hirabayashi + + - The inverted API was enhanced. + - A ulitity command for full-text search was enhanced. + - A CGI script for full-text search was enhanced. + - A utility class of Java API was enhanced. + - Release: 1.7.11 + +2003-11-20 Mikio Hirabayashi + + - A utility class of Java API was enhanced. + - Building configuration for CGI scripts was modified. + - Release: 1.7.10 + +2003-11-20 Mikio Hirabayashi + + - Tuning paramters of the inverted API were modified. + - A ulitity command for full-text search was enhanced. + - Release: 1.7.9 + +2003-11-16 Mikio Hirabayashi + + - Optional features of compressing with ZLIB were added. + - Release: 1.7.8 + +2003-11-05 Mikio Hirabayashi + + - The extended advanced API, Vista was added. + - Release: 1.7.7 + +2003-11-03 Mikio Hirabayashi + + - C API compilation using Visual C++ was supported. + - Odeum and its commands were enhanced. + - Release: 1.7.6 + +2003-10-25 Mikio Hirabayashi + + - A ulitity command for full-text search was enhanced. + - A CGI script for full-text search was enhanced. + - Release: 1.7.5 + +2003-10-23 Mikio Hirabayashi + + - A CGI script for full-text search was added. + - A bug of BSD support in Makefile was fixed. + - Release: 1.7.4 + +2003-10-19 Mikio Hirabayashi + + - Processing speed of the inverted API was improved. + - A ulitity command for full-text search was enhanced. + - Release: 1.7.3 + +2003-10-17 Mikio Hirabayashi + + - The license was changed to LGPL. + - An indexing command for the inverted API was added. + - Release: 1.7.2 + +2003-10-14 Mikio Hirabayashi + + - A test command for the inverted API was added. + - A bug about optimization in the inverted API was fixed. + - Tuning paramters of the inverted API were modified. + - Release: 1.7.1 + +2003-10-13 Mikio Hirabayashi + + - The inverted API, Odeum was added. + - Comments in source codes increased. + - Release: 1.7.0 + +2003-10-05 Mikio Hirabayashi + + - Executable commands were modified for RISC OS. + - Release: 1.6.22 + +2003-10-05 Mikio Hirabayashi + + - Executable commands were modified for RISC OS. + - Release: 1.6.21 + +2003-09-30 Mikio Hirabayashi + + - Naming file in RISC OS style was supported. + - Hash functions were enhanced. + - Release: 1.6.20 + +2003-09-26 Mikio Hirabayashi + + - The utility API was enhanced. + - Test commands were added. + - Release: 1.6.19 + +2003-09-22 Mikio Hirabayashi + + - Makefile for RISC OS was added. + - C++ API was enhanced. + - Release: 1.6.18 + +2003-09-14 Mikio Hirabayashi + + - Test commands were enhanced. + - Source codes and Makefile were modified for RISC OS. + - The CGI script was enhanced. + - Release: 1.6.17 + +2003-09-13 Mikio Hirabayashi + + - The CGI script for administration was added. + - C++ API was enhanced. + - Release: 1.6.16 + +2003-08-28 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.6.15 + +2003-08-16 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.6.14 + +2003-08-11 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.6.13 + +2003-08-05 Mikio Hirabayashi + + - A bug in the utility API was fixed. + - Test commands were enhanced. + - Release: 1.6.12 + +2003-07-31 Mikio Hirabayashi + + - C and Java APIs support compilation using MinGW. + - Release: 1.6.11 + +2003-07-27 Mikio Hirabayashi + + - Perl and Ruby APIs support transaction. + - Release: 1.6.10 + +2003-07-26 Mikio Hirabayashi + + - Speed of transaction was improved. + - Release: 1.6.9 + +2003-07-24 Mikio Hirabayashi + + - C++ and Java APIs of B+ tree support transaction. + - Release: 1.6.8 + +2003-07-21 Mikio Hirabayashi + + - C API of B+ tree supports transaction. + - Bugs about Mutex in C++ and Java APIs were fixed. + - Release: 1.6.7 + +2003-07-18 Mikio Hirabayashi + + - C++ and Java APIs of database abstraction were simplified. + - Ruby API of B+ tree was simplified. + - Release: 1.6.6 + +2003-07-16 Mikio Hirabayashi + + - Ruby API of B+ tree was added. + - C, C++, Java and Perl APIs of B+ tree were enhanced. + - Release: 1.6.5 + +2003-07-13 Mikio Hirabayashi + + - Perl API of B+ tree was added. + - C, C++ and Java APIs of B+ tree were enhanced. + - Release: 1.6.4 + +2003-07-08 Mikio Hirabayashi + + - Java API of B++ tree was added. + - C API of B+ tree was enhanced. + - C++ API of B+ tree was enhanced. + - Release: 1.6.3 + +2003-07-05 Mikio Hirabayashi + + - Debug routines were removed and speed was improved. + - No locking mode was added. + - Endian converter of Villa was added. + - C++ API of B++ tree was added. + - Release: 1.6.2 + +2003-07-03 Mikio Hirabayashi + + - The advanced API was enhanced to improve its speed. + - Makefiles were enhanced for HP-UX. + - Release: 1.6.1 + +2003-06-28 Mikio Hirabayashi + + - The advanced API for B+ tree database is added. + - Release: 1.6.0 + +2003-06-23 Mikio Hirabayashi + + - Makefiles were enhanced for Mac OS X. + - Release: 1.5.13 + +2003-06-18 Mikio Hirabayashi + + - Makefile was enhanced for Solaris and Mac OS X. + - Release: 1.5.12 + +2003-06-06 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.5.11 + +2003-05-31 Mikio Hirabayashi + + - The utility API was enhanced. + - Release: 1.5.10 + +2003-05-29 Mikio Hirabayashi + + - The utility API was changed. + - Release: 1.5.9 + +2003-05-25 Mikio Hirabayashi + + - Alignment mechanism was simplified. + - Release: 1.5.8 + +2003-05-17 Mikio Hirabayashi + + - Makefile was updated + - Release: 1.5.7 + +2003-05-16 Mikio Hirabayashi + + - Test tools were enhanced. + - Release: 1.5.6 + +2003-05-14 Mikio Hirabayashi + + - Makefile using libtool was added. + - Release: 1.5.5 + +2003-05-12 Mikio Hirabayashi + + - API for Ruby was enhanced. + - Release: 1.5.4 + +2003-05-08 Mikio Hirabayashi + + - API for Ruby was added. + - Release: 1.5.3 + +2003-05-04 Mikio Hirabayashi + + - API for Perl was enhanced. + - Release: 1.5.2 + +2003-04-30 Mikio Hirabayashi + + - API for Perl was enhanced. + - Release: 1.5.1 + +2003-04-29 Mikio Hirabayashi + + - API for Perl was added. + - Release: 1.5.0 + +2003-04-25 Mikio Hirabayashi + + - The package was reorganized to be a GNU package. + - Release: 1.4.11 + +2003-04-21 Mikio Hirabayashi + + - The utility API was added. + - Release: 1.4.10 + +2003-04-15 Mikio Hirabayashi + + - Endian converters were added. + - Release: 1.4.9 + +2003-04-12 Mikio Hirabayashi + + - The GDBM-compatible API was enhanced. + - Release: 1.4.8 + +2003-04-10 Mikio Hirabayashi + + - Some bugs were fixed and C++ API was enhanced. + - Release: 1.4.7 + +2003-04-09 Mikio Hirabayashi + + - Coalescence of dead regions and reuse of them were featured. + - Release: 1.4.6 + +2003-04-06 Mikio Hirabayashi + + - The GDBM-compatible API and the C++ API were enhanced. + - Release: 1.4.5 + +2003-04-04 Mikio Hirabayashi + + - The API for C++ and the API for Java were enhanced. + - Release: 1.4.4 + +2003-04-02 Mikio Hirabayashi + + - Documents for C++ was enhanced. + - Release: 1.4.3 + +2003-04-01 Mikio Hirabayashi + + - The API for Java was enhanced. + - Release: 1.4.2 + +2003-03-23 Mikio Hirabayashi + + - Makefiles were modified. + - Release: 1.4.1 + +2003-03-23 Mikio Hirabayashi + + - APIs for C++ and Java was enhanced. + - Release: 1.4.0 + +2003-03-15 Mikio Hirabayashi + + - The API for C++ was added. + - Release: 1.3.2 + +2003-03-11 Mikio Hirabayashi + + - The API for Java was supported on Solaris and Windows. + - Release: 1.3.1 + +2003-03-04 Mikio Hirabayashi + + - The API for Java was added. + - Release: 1.3.0 + +2003-02-23 Mikio Hirabayashi + + - The GDBM-compatible API was added. + - Release: 1.2.0 + +2003-02-21 Mikio Hirabayashi + + - Compatibility with NDBM was improved. + - Release: 1.1.3 + +2003-02-18 Mikio Hirabayashi + + - Optimizing suppoted on Windows. DLL is supported. + - Release: 1.1.2 + +2003-02-15 Mikio Hirabayashi + + - Windows is now supported. + - The compatible API was enhanced. + - Release: 1.1.1 + +2003-02-11 Mikio Hirabayashi + + - The NDBM-compatible API was added. + - Release: 1.1.0 + +2003-02-08 Mikio Hirabayashi + + - The initial version. + - Release: 1.0.0 + Deleted: box/trunk/qdbm/LTmakefile.in =================================================================== --- box/trunk/qdbm/LTmakefile.in 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/LTmakefile.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,318 +0,0 @@ -# Makefile to build QDBM using libtool - - - -#================================================================ -# Setting variables -#================================================================ - - -# Generic settings -SHELL = @SHELL@ - -# Packaging -PACKAGE = @PACKAGE_NAME@ -VERSION = @PACKAGE_VERSION@ -LIBVER = @LIBVER@ -LIBREV = @LIBREV@ - -# Targets -MYHEADS = depot.h curia.h relic.h hovel.h cabin.h villa.h vista.h odeum.h -MYLIBOBJS = depot.lo curia.lo relic.lo hovel.lo cabin.lo villa.lo vista.lo odeum.lo myconf.lo -MYLIBS = libqdbm.la -MYBINS = dpmgr dptest dptsv crmgr crtest crtsv rlmgr rltest hvmgr hvtest \ - cbtest cbcodec vlmgr vltest vltsv odmgr odtest odidx qmttest -MYMAN1S = dpmgr.1 dptest.1 dptsv.1 crmgr.1 crtest.1 crtsv.1 rlmgr.1 rltest.1 hvmgr.1 hvtest.1 \ - cbtest.1 cbcodec.1 vlmgr.1 vltest.1 vltsv.1 odmgr.1 odtest.1 odidx.1 qmttest.1 -MYMAN3S = qdbm.3 depot.3 dpopen.3 curia.3 cropen.3 relic.3 hovel.3 \ - cabin.3 villa.3 vlopen.3 vista.3 odeum.3 odopen.3 -MYDOCS = spex.html spex-ja.html COPYING ChangeLog NEWS THANKS -MYPCS = qdbm.pc - -# Install destinations -prefix = @prefix@ -exec_prefix = @exec_prefix@ -MYHEADDIR = @includedir@ -MYLIBDIR = @libdir@ -MYBINDIR = @bindir@ -MYMAN1DIR = @mandir@/man1 -MYMAN3DIR = @mandir@/man3 -MYSHAREDIR = $(prefix)/share/$(PACKAGE) -MYPCDIR = @libdir@/pkgconfig - -# Building binaries -LIBTOOL = libtool -CC = gcc -CFLAGS = -I. -I$(MYHEADDIR) -I$(HOME)/include -I/usr/local/include @MYDEFS@ \ - -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \ - -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 \ - -DPIC=1 -D_THREAD_SAFE=1 -D_REENTRANT=1 -DNDEBUG -O3 -LD = gcc -LIBLDFLAGS = -rpath $(MYLIBDIR) -R $(MYLIBDIR) \ - -version-info $$(($(LIBVER)+$(LIBREV))):0:$(LIBREV) @LIBS@ -LDFLAGS = -rpath $(MYLIBDIR) -R $(MYLIBDIR) -L. -lqdbm @LIBS@ -INSTALL = install -MKDIR = mkdir -p -CP = cp -rf -RM = rm -rf - - - -#================================================================ -# Suffix rules -#================================================================ - - -.SUFFIXES : -.SUFFIXES : .c .lo - -.c.lo : - $(LIBTOOL) --mode=compile --tag=CC $(CC) -c $(CFLAGS) $< - - - -#================================================================ -# Actions -#================================================================ - - -all : $(MYLIBS) $(MYBINS) - @printf '\n' - @printf '#================================================================\n' - @printf '# Ready to install.\n' - @printf '#================================================================\n' - - -clean : - $(RM) $(MYLIBS) $(MYBINS) *.o *.a *.so *.lo *.la a.out .libs \ - *.exe *.dll.a *.dll TAGS srcdoc gmon.out leak.log casket casket.* *~ - - -install : - $(LIBTOOL) --mode=install $(INSTALL) $(MYHEADS) $(MYHEADDIR) - $(LIBTOOL) --mode=install $(INSTALL) $(MYLIBS) $(MYLIBDIR) - $(LIBTOOL) --mode=install $(INSTALL) $(MYBINS) $(MYBINDIR) - $(MKDIR) $(MYMAN1DIR) - cd man && $(CP) $(MYMAN1S) $(MYMAN1DIR) - $(MKDIR) $(MYMAN3DIR) - cd man && $(CP) $(MYMAN3S) $(MYMAN3DIR) - $(MKDIR) $(MYSHAREDIR) - $(CP) $(MYDOCS) $(MYSHAREDIR) - $(MKDIR) $(MYPCDIR) - $(CP) $(MYPCS) $(MYPCDIR) - @printf '\n' - @printf '#================================================================\n' - @printf '# Thanks for using QDBM.\n' - @printf '#================================================================\n' - - -uninstall : - cd $(MYHEADDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYHEADS) - cd $(MYLIBDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYLIBS) - cd $(MYBINDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYBINS) - cd $(MYMAN1DIR) && $(RM) $(MYMAN1S) - cd $(MYMAN3DIR) && $(RM) $(MYMAN3S) - $(RM) $(MYSHAREDIR) - cd $(MYPCDIR) && $(RM) $(MYPCS) - - -distclean : clean - $(RM) Makefile LTmakefile rpmspec config.cache config.log config.status autom4te.cache - - -check : - $(RM) casket* - $(LIBTOOL) --mode=execute ./dptest write -s casket 500 500000 - $(LIBTOOL) --mode=execute ./dptest write casket 50000 5000 - $(LIBTOOL) --mode=execute ./dptest read casket - $(LIBTOOL) --mode=execute ./dptest read -wb casket - $(LIBTOOL) --mode=execute ./dptest rcat -c casket 50000 50 500 32 8 - $(LIBTOOL) --mode=execute ./dptest combo casket - $(LIBTOOL) --mode=execute ./dptest wicked -c casket 5000 - $(LIBTOOL) --mode=execute ./dptest wicked casket 500 - $(LIBTOOL) --mode=execute ./dpmgr repair casket - $(LIBTOOL) --mode=execute ./dpmgr optimize casket - $(LIBTOOL) --mode=execute ./dpmgr list casket - $(RM) casket* - $(LIBTOOL) --mode=execute ./crtest write -s casket 500 100000 5 - $(LIBTOOL) --mode=execute ./crtest write casket 50000 500 10 - $(LIBTOOL) --mode=execute ./crtest read casket - $(LIBTOOL) --mode=execute ./crtest read -wb casket - $(LIBTOOL) --mode=execute ./crtest rcat -c casket 50000 5 10 500 32 8 - $(LIBTOOL) --mode=execute ./crtest combo casket - $(LIBTOOL) --mode=execute ./crtest wicked -c casket 5000 - $(LIBTOOL) --mode=execute ./crtest wicked casket 500 - $(LIBTOOL) --mode=execute ./crmgr repair casket - $(LIBTOOL) --mode=execute ./crmgr optimize casket - $(LIBTOOL) --mode=execute ./crmgr list casket - $(RM) casket* - $(LIBTOOL) --mode=execute ./crtest write -lob casket 1000 50 10 - $(LIBTOOL) --mode=execute ./crtest read -lob casket - $(RM) casket* - $(LIBTOOL) --mode=execute ./rltest write casket 5000 - $(LIBTOOL) --mode=execute ./rltest read casket 5000 - $(LIBTOOL) --mode=execute ./rlmgr list casket - $(RM) casket* - $(LIBTOOL) --mode=execute ./hvtest write casket 5000 - $(LIBTOOL) --mode=execute ./hvtest read casket 5000 - $(LIBTOOL) --mode=execute ./hvmgr optimize casket - $(LIBTOOL) --mode=execute ./hvmgr list casket - $(RM) casket* - $(LIBTOOL) --mode=execute ./hvtest write -qdbm -s casket 500 - $(LIBTOOL) --mode=execute ./hvtest write -qdbm casket 5000 - $(LIBTOOL) --mode=execute ./hvtest read -qdbm casket 5000 - $(RM) casket* - $(LIBTOOL) --mode=execute ./cbtest sort 5000 - $(LIBTOOL) --mode=execute ./cbtest strstr 500 - $(LIBTOOL) --mode=execute ./cbtest list 50000 - $(LIBTOOL) --mode=execute ./cbtest list -d 500 - $(LIBTOOL) --mode=execute ./cbtest map 50000 500 - $(LIBTOOL) --mode=execute ./cbtest map -d 500 5 - $(LIBTOOL) --mode=execute ./cbtest heap 50000 500 - $(LIBTOOL) --mode=execute ./cbtest heap -d 500 50 - $(LIBTOOL) --mode=execute ./cbtest wicked 5000 - $(LIBTOOL) --mode=execute ./cbtest misc - $(RM) casket* - $(LIBTOOL) --mode=execute ./vltest write -tune 32 31 32 32 casket 50000 - $(LIBTOOL) --mode=execute ./vltest read casket - $(LIBTOOL) --mode=execute ./vltest rdup -tune 32 31 512 256 casket 50000 50000 - $(LIBTOOL) --mode=execute ./vltest combo casket - $(LIBTOOL) --mode=execute ./vltest wicked -c casket 5000 - $(LIBTOOL) --mode=execute ./vltest wicked casket 500 - $(LIBTOOL) --mode=execute ./vlmgr repair casket - $(LIBTOOL) --mode=execute ./vlmgr optimize casket - $(LIBTOOL) --mode=execute ./vlmgr list casket - $(RM) casket* - $(LIBTOOL) --mode=execute ./vltest write -int -cz -tune 32 31 32 32 casket 50000 - $(LIBTOOL) --mode=execute ./vltest read -int -vc casket - $(LIBTOOL) --mode=execute ./vltest rdup -int -cz -cc -tune 32 31 512 256 casket 50000 50000 - $(LIBTOOL) --mode=execute ./vltest combo -cz casket - $(LIBTOOL) --mode=execute ./vltest wicked -cz -c casket 5000 - $(LIBTOOL) --mode=execute ./vltest combo -cy casket - $(LIBTOOL) --mode=execute ./vltest wicked -cy -c casket 5000 - $(LIBTOOL) --mode=execute ./vltest combo -cx casket - $(LIBTOOL) --mode=execute ./vltest wicked -cx -c casket 5000 - $(RM) casket* - $(LIBTOOL) --mode=execute ./odtest write casket 500 50 5000 - $(LIBTOOL) --mode=execute ./odtest read casket - $(LIBTOOL) --mode=execute ./odtest combo casket - $(LIBTOOL) --mode=execute ./odtest wicked casket 500 - $(RM) casket* - $(LIBTOOL) --mode=execute ./qmttest casket 50000 10 - $(RM) casket* - @printf '\n' - @printf '#================================================================\n' - @printf '# Checking completed.\n' - @printf '#================================================================\n' - - -.PHONY : all clean install check - - - -#================================================================ -# Building binaries -#================================================================ - - -libqdbm.la : $(MYLIBOBJS) - $(LIBTOOL) --mode=link --tag=CC $(LD) $(MYLIBOBJS) -o $@ $(LIBLDFLAGS) - - -dpmgr : dpmgr.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dpmgr.lo $(LDFLAGS) - - -dptest : dptest.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dptest.lo $(LDFLAGS) - - -dptsv : dptsv.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dptsv.lo $(LDFLAGS) - - -crmgr : crmgr.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crmgr.lo $(LDFLAGS) - - -crtest : crtest.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crtest.lo $(LDFLAGS) - - -crtsv : crtsv.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crtsv.lo $(LDFLAGS) - - -rlmgr : rlmgr.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ rlmgr.lo $(LDFLAGS) - - -rltest : rltest.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ rltest.lo $(LDFLAGS) - - -hvmgr : hvmgr.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ hvmgr.lo $(LDFLAGS) - - -hvtest : hvtest.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ hvtest.lo $(LDFLAGS) - - -cbtest : cbtest.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ cbtest.lo $(LDFLAGS) - - -cbcodec : cbcodec.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ cbcodec.lo $(LDFLAGS) - - -vlmgr : vlmgr.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vlmgr.lo $(LDFLAGS) - - -vltest : vltest.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vltest.lo $(LDFLAGS) - - -vltsv : vltsv.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vltsv.lo $(LDFLAGS) - - -odmgr : odmgr.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odmgr.lo $(LDFLAGS) - - -odtest : odtest.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odtest.lo $(LDFLAGS) - - -odidx : odidx.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odidx.lo $(LDFLAGS) - - -qmttest : qmttest.lo $(MYLIBS) - $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ qmttest.lo $(LDFLAGS) - - -depot.lo dpmgr.lo dptest.lo dptsv.lo : depot.h myconf.h - -curia.lo crmgr.lo crtest.lo crtsv.lo : curia.h depot.h myconf.h - -relic.lo rlmgr.lo rltest.lo : relic.h depot.h myconf.h - -hovel.lo hvmgr.lo hvtest.lo : hovel.h depot.h curia.h myconf.h - -cabin.lo cbtest.lo : cabin.h myconf.h - -villa.lo vlmgr.lo vltest.lo vltsv.lo : villa.h depot.h cabin.h myconf.h - -vista.lo : vista.h villa.h depot.h curia.h cabin.h myconf.h villa.c - -odeum.lo odmgr.lo odtest.lo odidx.lo : odeum.h depot.h curia.h cabin.h villa.h myconf.h - -myconf.lo : myconf.h - - - -# END OF FILE Copied: box/trunk/qdbm/LTmakefile.in (from rev 2716, box/trunk/qdbm/LTmakefile.in) =================================================================== --- box/trunk/qdbm/LTmakefile.in (rev 0) +++ box/trunk/qdbm/LTmakefile.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,318 @@ +# Makefile to build QDBM using libtool + + + +#================================================================ +# Setting variables +#================================================================ + + +# Generic settings +SHELL = @SHELL@ + +# Packaging +PACKAGE = @PACKAGE_NAME@ +VERSION = @PACKAGE_VERSION@ +LIBVER = @LIBVER@ +LIBREV = @LIBREV@ + +# Targets +MYHEADS = depot.h curia.h relic.h hovel.h cabin.h villa.h vista.h odeum.h +MYLIBOBJS = depot.lo curia.lo relic.lo hovel.lo cabin.lo villa.lo vista.lo odeum.lo myconf.lo +MYLIBS = libqdbm.la +MYBINS = dpmgr dptest dptsv crmgr crtest crtsv rlmgr rltest hvmgr hvtest \ + cbtest cbcodec vlmgr vltest vltsv odmgr odtest odidx qmttest +MYMAN1S = dpmgr.1 dptest.1 dptsv.1 crmgr.1 crtest.1 crtsv.1 rlmgr.1 rltest.1 hvmgr.1 hvtest.1 \ + cbtest.1 cbcodec.1 vlmgr.1 vltest.1 vltsv.1 odmgr.1 odtest.1 odidx.1 qmttest.1 +MYMAN3S = qdbm.3 depot.3 dpopen.3 curia.3 cropen.3 relic.3 hovel.3 \ + cabin.3 villa.3 vlopen.3 vista.3 odeum.3 odopen.3 +MYDOCS = spex.html spex-ja.html COPYING ChangeLog NEWS THANKS +MYPCS = qdbm.pc + +# Install destinations +prefix = @prefix@ +exec_prefix = @exec_prefix@ +MYHEADDIR = @includedir@ +MYLIBDIR = @libdir@ +MYBINDIR = @bindir@ +MYMAN1DIR = @mandir@/man1 +MYMAN3DIR = @mandir@/man3 +MYSHAREDIR = $(prefix)/share/$(PACKAGE) +MYPCDIR = @libdir@/pkgconfig + +# Building binaries +LIBTOOL = libtool +CC = gcc +CFLAGS = -I. -I$(MYHEADDIR) -I$(HOME)/include -I/usr/local/include @MYDEFS@ \ + -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \ + -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 \ + -DPIC=1 -D_THREAD_SAFE=1 -D_REENTRANT=1 -DNDEBUG -O3 +LD = gcc +LIBLDFLAGS = -rpath $(MYLIBDIR) -R $(MYLIBDIR) \ + -version-info $$(($(LIBVER)+$(LIBREV))):0:$(LIBREV) @LIBS@ +LDFLAGS = -rpath $(MYLIBDIR) -R $(MYLIBDIR) -L. -lqdbm @LIBS@ +INSTALL = install +MKDIR = mkdir -p +CP = cp -rf +RM = rm -rf + + + +#================================================================ +# Suffix rules +#================================================================ + + +.SUFFIXES : +.SUFFIXES : .c .lo + +.c.lo : + $(LIBTOOL) --mode=compile --tag=CC $(CC) -c $(CFLAGS) $< + + + +#================================================================ +# Actions +#================================================================ + + +all : $(MYLIBS) $(MYBINS) + @printf '\n' + @printf '#================================================================\n' + @printf '# Ready to install.\n' + @printf '#================================================================\n' + + +clean : + $(RM) $(MYLIBS) $(MYBINS) *.o *.a *.so *.lo *.la a.out .libs \ + *.exe *.dll.a *.dll TAGS srcdoc gmon.out leak.log casket casket.* *~ + + +install : + $(LIBTOOL) --mode=install $(INSTALL) $(MYHEADS) $(MYHEADDIR) + $(LIBTOOL) --mode=install $(INSTALL) $(MYLIBS) $(MYLIBDIR) + $(LIBTOOL) --mode=install $(INSTALL) $(MYBINS) $(MYBINDIR) + $(MKDIR) $(MYMAN1DIR) + cd man && $(CP) $(MYMAN1S) $(MYMAN1DIR) + $(MKDIR) $(MYMAN3DIR) + cd man && $(CP) $(MYMAN3S) $(MYMAN3DIR) + $(MKDIR) $(MYSHAREDIR) + $(CP) $(MYDOCS) $(MYSHAREDIR) + $(MKDIR) $(MYPCDIR) + $(CP) $(MYPCS) $(MYPCDIR) + @printf '\n' + @printf '#================================================================\n' + @printf '# Thanks for using QDBM.\n' + @printf '#================================================================\n' + + +uninstall : + cd $(MYHEADDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYHEADS) + cd $(MYLIBDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYLIBS) + cd $(MYBINDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYBINS) + cd $(MYMAN1DIR) && $(RM) $(MYMAN1S) + cd $(MYMAN3DIR) && $(RM) $(MYMAN3S) + $(RM) $(MYSHAREDIR) + cd $(MYPCDIR) && $(RM) $(MYPCS) + + +distclean : clean + $(RM) Makefile LTmakefile rpmspec config.cache config.log config.status autom4te.cache + + +check : + $(RM) casket* + $(LIBTOOL) --mode=execute ./dptest write -s casket 500 500000 + $(LIBTOOL) --mode=execute ./dptest write casket 50000 5000 + $(LIBTOOL) --mode=execute ./dptest read casket + $(LIBTOOL) --mode=execute ./dptest read -wb casket + $(LIBTOOL) --mode=execute ./dptest rcat -c casket 50000 50 500 32 8 + $(LIBTOOL) --mode=execute ./dptest combo casket + $(LIBTOOL) --mode=execute ./dptest wicked -c casket 5000 + $(LIBTOOL) --mode=execute ./dptest wicked casket 500 + $(LIBTOOL) --mode=execute ./dpmgr repair casket + $(LIBTOOL) --mode=execute ./dpmgr optimize casket + $(LIBTOOL) --mode=execute ./dpmgr list casket + $(RM) casket* + $(LIBTOOL) --mode=execute ./crtest write -s casket 500 100000 5 + $(LIBTOOL) --mode=execute ./crtest write casket 50000 500 10 + $(LIBTOOL) --mode=execute ./crtest read casket + $(LIBTOOL) --mode=execute ./crtest read -wb casket + $(LIBTOOL) --mode=execute ./crtest rcat -c casket 50000 5 10 500 32 8 + $(LIBTOOL) --mode=execute ./crtest combo casket + $(LIBTOOL) --mode=execute ./crtest wicked -c casket 5000 + $(LIBTOOL) --mode=execute ./crtest wicked casket 500 + $(LIBTOOL) --mode=execute ./crmgr repair casket + $(LIBTOOL) --mode=execute ./crmgr optimize casket + $(LIBTOOL) --mode=execute ./crmgr list casket + $(RM) casket* + $(LIBTOOL) --mode=execute ./crtest write -lob casket 1000 50 10 + $(LIBTOOL) --mode=execute ./crtest read -lob casket + $(RM) casket* + $(LIBTOOL) --mode=execute ./rltest write casket 5000 + $(LIBTOOL) --mode=execute ./rltest read casket 5000 + $(LIBTOOL) --mode=execute ./rlmgr list casket + $(RM) casket* + $(LIBTOOL) --mode=execute ./hvtest write casket 5000 + $(LIBTOOL) --mode=execute ./hvtest read casket 5000 + $(LIBTOOL) --mode=execute ./hvmgr optimize casket + $(LIBTOOL) --mode=execute ./hvmgr list casket + $(RM) casket* + $(LIBTOOL) --mode=execute ./hvtest write -qdbm -s casket 500 + $(LIBTOOL) --mode=execute ./hvtest write -qdbm casket 5000 + $(LIBTOOL) --mode=execute ./hvtest read -qdbm casket 5000 + $(RM) casket* + $(LIBTOOL) --mode=execute ./cbtest sort 5000 + $(LIBTOOL) --mode=execute ./cbtest strstr 500 + $(LIBTOOL) --mode=execute ./cbtest list 50000 + $(LIBTOOL) --mode=execute ./cbtest list -d 500 + $(LIBTOOL) --mode=execute ./cbtest map 50000 500 + $(LIBTOOL) --mode=execute ./cbtest map -d 500 5 + $(LIBTOOL) --mode=execute ./cbtest heap 50000 500 + $(LIBTOOL) --mode=execute ./cbtest heap -d 500 50 + $(LIBTOOL) --mode=execute ./cbtest wicked 5000 + $(LIBTOOL) --mode=execute ./cbtest misc + $(RM) casket* + $(LIBTOOL) --mode=execute ./vltest write -tune 32 31 32 32 casket 50000 + $(LIBTOOL) --mode=execute ./vltest read casket + $(LIBTOOL) --mode=execute ./vltest rdup -tune 32 31 512 256 casket 50000 50000 + $(LIBTOOL) --mode=execute ./vltest combo casket + $(LIBTOOL) --mode=execute ./vltest wicked -c casket 5000 + $(LIBTOOL) --mode=execute ./vltest wicked casket 500 + $(LIBTOOL) --mode=execute ./vlmgr repair casket + $(LIBTOOL) --mode=execute ./vlmgr optimize casket + $(LIBTOOL) --mode=execute ./vlmgr list casket + $(RM) casket* + $(LIBTOOL) --mode=execute ./vltest write -int -cz -tune 32 31 32 32 casket 50000 + $(LIBTOOL) --mode=execute ./vltest read -int -vc casket + $(LIBTOOL) --mode=execute ./vltest rdup -int -cz -cc -tune 32 31 512 256 casket 50000 50000 + $(LIBTOOL) --mode=execute ./vltest combo -cz casket + $(LIBTOOL) --mode=execute ./vltest wicked -cz -c casket 5000 + $(LIBTOOL) --mode=execute ./vltest combo -cy casket + $(LIBTOOL) --mode=execute ./vltest wicked -cy -c casket 5000 + $(LIBTOOL) --mode=execute ./vltest combo -cx casket + $(LIBTOOL) --mode=execute ./vltest wicked -cx -c casket 5000 + $(RM) casket* + $(LIBTOOL) --mode=execute ./odtest write casket 500 50 5000 + $(LIBTOOL) --mode=execute ./odtest read casket + $(LIBTOOL) --mode=execute ./odtest combo casket + $(LIBTOOL) --mode=execute ./odtest wicked casket 500 + $(RM) casket* + $(LIBTOOL) --mode=execute ./qmttest casket 50000 10 + $(RM) casket* + @printf '\n' + @printf '#================================================================\n' + @printf '# Checking completed.\n' + @printf '#================================================================\n' + + +.PHONY : all clean install check + + + +#================================================================ +# Building binaries +#================================================================ + + +libqdbm.la : $(MYLIBOBJS) + $(LIBTOOL) --mode=link --tag=CC $(LD) $(MYLIBOBJS) -o $@ $(LIBLDFLAGS) + + +dpmgr : dpmgr.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dpmgr.lo $(LDFLAGS) + + +dptest : dptest.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dptest.lo $(LDFLAGS) + + +dptsv : dptsv.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dptsv.lo $(LDFLAGS) + + +crmgr : crmgr.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crmgr.lo $(LDFLAGS) + + +crtest : crtest.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crtest.lo $(LDFLAGS) + + +crtsv : crtsv.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crtsv.lo $(LDFLAGS) + + +rlmgr : rlmgr.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ rlmgr.lo $(LDFLAGS) + + +rltest : rltest.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ rltest.lo $(LDFLAGS) + + +hvmgr : hvmgr.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ hvmgr.lo $(LDFLAGS) + + +hvtest : hvtest.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ hvtest.lo $(LDFLAGS) + + +cbtest : cbtest.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ cbtest.lo $(LDFLAGS) + + +cbcodec : cbcodec.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ cbcodec.lo $(LDFLAGS) + + +vlmgr : vlmgr.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vlmgr.lo $(LDFLAGS) + + +vltest : vltest.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vltest.lo $(LDFLAGS) + + +vltsv : vltsv.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vltsv.lo $(LDFLAGS) + + +odmgr : odmgr.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odmgr.lo $(LDFLAGS) + + +odtest : odtest.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odtest.lo $(LDFLAGS) + + +odidx : odidx.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odidx.lo $(LDFLAGS) + + +qmttest : qmttest.lo $(MYLIBS) + $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ qmttest.lo $(LDFLAGS) + + +depot.lo dpmgr.lo dptest.lo dptsv.lo : depot.h myconf.h + +curia.lo crmgr.lo crtest.lo crtsv.lo : curia.h depot.h myconf.h + +relic.lo rlmgr.lo rltest.lo : relic.h depot.h myconf.h + +hovel.lo hvmgr.lo hvtest.lo : hovel.h depot.h curia.h myconf.h + +cabin.lo cbtest.lo : cabin.h myconf.h + +villa.lo vlmgr.lo vltest.lo vltsv.lo : villa.h depot.h cabin.h myconf.h + +vista.lo : vista.h villa.h depot.h curia.h cabin.h myconf.h villa.c + +odeum.lo odmgr.lo odtest.lo odidx.lo : odeum.h depot.h curia.h cabin.h villa.h myconf.h + +myconf.lo : myconf.h + + + +# END OF FILE Deleted: box/trunk/qdbm/Makefile.in =================================================================== --- box/trunk/qdbm/Makefile.in 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/Makefile.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,646 +0,0 @@ -# Makefile for QDBM - - - -#================================================================ -# Setting variables -#================================================================ - - -# Generic settings -SHELL = @SHELL@ -srcdir = @srcdir@ -VPATH = @srcdir@ -SUBDIRS = - -# Packaging -PACKAGE = @PACKAGE_NAME@ -VERSION = @PACKAGE_VERSION@ -PACKAGEDIR = $(PACKAGE)-$(VERSION) -PACKAGETGZ = $(PACKAGE)-$(VERSION).tar.gz -LIBVER = @LIBVER@ -LIBREV = @LIBREV@ - -# Targets -MYHEADS = depot.h curia.h relic.h hovel.h cabin.h villa.h vista.h odeum.h -MYLIBOBJS = depot.o curia.o relic.o hovel.o cabin.o villa.o vista.o odeum.o myconf.o -MYLIBS = libqdbm.a libqdbm.so.$(LIBVER).$(LIBREV).0 libqdbm.so.$(LIBVER) libqdbm.so -MYBINS = dpmgr dptest dptsv crmgr crtest crtsv rlmgr rltest hvmgr hvtest \ - cbtest cbcodec vlmgr vltest vltsv odmgr odtest odidx qmttest -MYMAN1S = dpmgr.1 dptest.1 dptsv.1 crmgr.1 crtest.1 crtsv.1 rlmgr.1 rltest.1 hvmgr.1 hvtest.1 \ - cbtest.1 cbcodec.1 vlmgr.1 vltest.1 vltsv.1 odmgr.1 odtest.1 odidx.1 qmttest.1 -MYMAN3S = qdbm.3 depot.3 dpopen.3 curia.3 cropen.3 relic.3 hovel.3 \ - cabin.3 villa.3 vlopen.3 vista.3 odeum.3 odopen.3 -MYDOCS = spex.html spex-ja.html COPYING ChangeLog NEWS THANKS -MYPCS = qdbm.pc -MYWINLIBS = libqdbm.a libqdbm.dll.a -MYMACLIBS = libqdbm.a libqdbm.$(LIBVER).$(LIBREV).0.dylib libqdbm.$(LIBVER).dylib libqdbm.dylib -MYHPUXLIBS = libqdbm.a libqdbm.sl - -# Install destinations -prefix = @prefix@ -exec_prefix = @exec_prefix@ -MYHEADDIR = @includedir@ -MYLIBDIR = @libdir@ -MYBINDIR = @bindir@ -MYMAN1DIR = @mandir@/man1 -MYMAN3DIR = @mandir@/man3 -MYDATADIR = @datadir@/$(PACKAGE) -MYPCDIR = @libdir@/pkgconfig -DESTDIR = - -# Building binaries -CC = @CC@ -CPPFLAGS = @CPPFLAGS@ -I$(srcdir) -I$(MYHEADDIR) \ - -I$(HOME)/include -I/usr/local/include @MYDEFS@ \ - -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \ - -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 \ - -DPIC=1 -D_THREAD_SAFE=1 -D_REENTRANT=1 -DNDEBUG -CFLAGS = @CFLAGS@ -Wall -pedantic -fPIC -fsigned-char -O0 -fforce-addr @MYOPTS@ -LD = @LD@ -LIBS = -lqdbm @LIBS@ -LIBLDFLAGS = @LDFLAGS@ -L. -L$(MYLIBDIR) -L$(HOME)/lib -L/usr/local/lib @LIBS@ -LDFLAGS = @LDFLAGS@ -L. -L$(MYLIBDIR) -L$(HOME)/lib -L/usr/local/lib $(LIBS) -LDENV = LD_RUN_PATH=/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib -AR = @AR@ -ARFLAGS = rcsv -RUNENV = LD_LIBRARY_PATH=.:/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib - - - -#================================================================ -# Suffix rules -#================================================================ - - -.SUFFIXES : -.SUFFIXES : .c .o - -.c.o : - $(CC) -c $(CPPFLAGS) $(CFLAGS) $< - - - -#================================================================ -# Actions -#================================================================ - - -targets : @TARGETS@ - - -all : $(MYLIBS) $(MYBINS) - @printf '\n' - @printf '#================================================================\n' - @printf '# Ready to install.\n' - @printf '#================================================================\n' - - -static : - make MYLIBS="$(MYLIBS)" LDFLAGS="-static $(LDFLAGS)" all - - -debug : - make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ - CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -g" \ - LDFLAGS="-static $(LDFLAGS)" all - - -devel : - make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ - CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -g -pipe" all - sync ; sync - - -stable : - make MYLIBS="$(MYLIBS)" CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2" all - - -profile : - make MYLIBS="$(MYLIBS)" \ - CFLAGS="-Wall -pedantic -fPIC -fsigned-char -O3 -pg -g -Werror" \ - LDFLAGS="-static $(LDFLAGS)" all - - -unsigned : - make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ - CFLAGS="-Wall -ansi -pedantic -fPIC -funsigned-char -g -O2" all - - -m64 : - make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ - CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -m64 -g" all - - -pen4 : - stdopt="-O3 -fomit-frame-pointer -minline-all-stringops" ; \ - exopt="-march=pentium4 -minline-all-stringops -fprefetch-loop-arrays" ; \ - make MYLIBS="$(MYLIBS)" \ - CFLAGS="-Wall -pedantic -fPIC -fsigned-char $$stdopt $$exopt" all - - -k8 : - stdopt="-O3 -fomit-frame-pointer -minline-all-stringops" ; \ - exopt="-march=k8 -minline-all-stringops -fprefetch-loop-arrays" ; \ - make MYLIBS="$(MYLIBS)" \ - CFLAGS="-Wall -pedantic -fPIC -fsigned-char $$stdopt $$exopt" all - - -clean : - rm -rf $(MYLIBS) $(MYBINS) *.o *.a *.so *.lo *.la a.out .libs \ - *.exe *.dll.a *.dll *.dylib *.sl TAGS srcdoc gmon.out leak.log \ - casket casket.* casket-* *~ - - -version : - vernum=`expr $(LIBVER)00 + $(LIBREV)` ; \ - sed -e 's/_QDBM_VERSION.*/_QDBM_VERSION "$(VERSION)"/' \ - -e "s/_QDBM_LIBVER.*/_QDBM_LIBVER $$vernum/" depot.h > depot.h~ - [ -f depot.h~ ] && mv -f depot.h~ depot.h - - -install : - mkdir -p $(DESTDIR)$(MYHEADDIR) - cd $(srcdir) && cp -Rf $(MYHEADS) $(DESTDIR)$(MYHEADDIR) - mkdir -p $(DESTDIR)$(MYLIBDIR) - cp -Rf $(MYLIBS) $(DESTDIR)$(MYLIBDIR) - mkdir -p $(DESTDIR)$(MYBINDIR) - cp -Rf $(MYBINS) $(DESTDIR)$(MYBINDIR) - mkdir -p $(DESTDIR)$(MYMAN1DIR) - cd $(srcdir)/man && cp -Rf $(MYMAN1S) $(DESTDIR)$(MYMAN1DIR) - mkdir -p $(DESTDIR)$(MYMAN3DIR) - cd $(srcdir)/man && cp -Rf $(MYMAN3S) $(DESTDIR)$(MYMAN3DIR) - mkdir -p $(DESTDIR)$(MYDATADIR) - cd $(srcdir) && cp -Rf $(MYDOCS) $(DESTDIR)$(MYDATADIR) - mkdir -p $(DESTDIR)$(MYPCDIR) - cd $(srcdir) && cp -Rf $(MYPCS) $(DESTDIR)$(MYPCDIR) - @printf '\n' - @printf '#================================================================\n' - @printf '# Thanks for using QDBM.\n' - @printf '#================================================================\n' - - -install-strip : - make DESTDIR=$(DESTDIR) install - cd $(DESTDIR)$(MYBINDIR) && strip $(MYBINS) - - -uninstall : - cd $(DESTDIR)$(MYHEADDIR) && rm -f $(MYHEADS) - cd $(DESTDIR)$(MYLIBDIR) && rm -f $(MYLIBS) - cd $(DESTDIR)$(MYBINDIR) && rm -f $(MYBINS) - cd $(DESTDIR)$(MYMAN1DIR) && rm -f $(MYMAN1S) - cd $(DESTDIR)$(MYMAN3DIR) && rm -f $(MYMAN3S) - rm -rf $(DESTDIR)$(MYDATADIR) - cd $(DESTDIR)$(MYPCDIR) && rm -f $(MYPCS) - - -dist : - sync ; sync - for dir in $(SUBDIRS) ; \ - do \ - if [ -d $$dir ] ; \ - then \ - echo Making $@ in $$dir ; \ - ( cd $$dir && if [ -f configure.in ] ; then autoconf ; ./configure ; \ - make dist ; fi ) ; \ - fi ; \ - done - make version - make distclean - cd .. && tar cvf - $(PACKAGEDIR) | gzip -c > $(PACKAGETGZ) - sync ; sync - - -distclean : clean - for dir in $(SUBDIRS) ; \ - do \ - if [ -d $$dir ] ; \ - then \ - echo Making $@ in $$dir ; \ - ( cd $$dir && if [ -f Makefile ] ; then make distclean ; fi ) ; \ - fi ; \ - done - rm -rf Makefile LTmakefile qdbm.spec qdbm.pc config.cache config.log config.status \ - autom4te.cache rpm-tmp *-win32 - - -TAGS : - etags -o $@ *.c *.h - - -sdoc : - rm -rf srcdoc - ./lab/ccdoc -d srcdoc -t "Source Documents of QDBM" *.h *.c - - -check : - sync ; sync - rm -rf casket* - $(RUNENV) $(RUNCMD) ./dptest write -s casket 500 500000 - $(RUNENV) $(RUNCMD) ./dptest write casket 50000 5000 - $(RUNENV) $(RUNCMD) ./dptest read casket - $(RUNENV) $(RUNCMD) ./dptest read -wb casket - $(RUNENV) $(RUNCMD) ./dptest rcat -c casket 50000 50 500 32 8 - $(RUNENV) $(RUNCMD) ./dptest combo casket - $(RUNENV) $(RUNCMD) ./dptest wicked -c casket 5000 - $(RUNENV) $(RUNCMD) ./dptest wicked casket 500 - $(RUNENV) $(RUNCMD) ./dpmgr repair casket - $(RUNENV) $(RUNCMD) ./dpmgr optimize casket - $(RUNENV) $(RUNCMD) ./dpmgr list casket - rm -rf casket* - $(RUNENV) $(RUNCMD) ./crtest write -s casket 500 100000 5 - $(RUNENV) $(RUNCMD) ./crtest write casket 50000 500 10 - $(RUNENV) $(RUNCMD) ./crtest read casket - $(RUNENV) $(RUNCMD) ./crtest read -wb casket - $(RUNENV) $(RUNCMD) ./crtest rcat -c casket 50000 5 10 500 32 8 - $(RUNENV) $(RUNCMD) ./crtest combo casket - $(RUNENV) $(RUNCMD) ./crtest wicked -c casket 5000 - $(RUNENV) $(RUNCMD) ./crtest wicked casket 500 - $(RUNENV) $(RUNCMD) ./crmgr repair casket - $(RUNENV) $(RUNCMD) ./crmgr optimize casket - $(RUNENV) $(RUNCMD) ./crmgr list casket - rm -rf casket* - $(RUNENV) $(RUNCMD) ./crtest write -lob casket 1000 50 10 - $(RUNENV) $(RUNCMD) ./crtest read -lob casket - rm -rf casket* - $(RUNENV) $(RUNCMD) ./rltest write casket 5000 - $(RUNENV) $(RUNCMD) ./rltest read casket 5000 - $(RUNENV) $(RUNCMD) ./rlmgr list casket - rm -rf casket* - $(RUNENV) $(RUNCMD) ./hvtest write casket 5000 - $(RUNENV) $(RUNCMD) ./hvtest read casket 5000 - $(RUNENV) $(RUNCMD) ./hvmgr optimize casket - $(RUNENV) $(RUNCMD) ./hvmgr list casket - rm -rf casket* - $(RUNENV) $(RUNCMD) ./hvtest write -qdbm -s casket 500 - $(RUNENV) $(RUNCMD) ./hvtest write -qdbm casket 5000 - $(RUNENV) $(RUNCMD) ./hvtest read -qdbm casket 5000 - rm -rf casket* - $(RUNENV) $(RUNCMD) ./cbtest sort 5000 - $(RUNENV) $(RUNCMD) ./cbtest strstr 500 - $(RUNENV) $(RUNCMD) ./cbtest list 50000 - $(RUNENV) $(RUNCMD) ./cbtest list -d 500 - $(RUNENV) $(RUNCMD) ./cbtest map 50000 500 - $(RUNENV) $(RUNCMD) ./cbtest map -d 500 5 - $(RUNENV) $(RUNCMD) ./cbtest heap 50000 500 - $(RUNENV) $(RUNCMD) ./cbtest heap -d 500 50 - $(RUNENV) $(RUNCMD) ./cbtest wicked 5000 - $(RUNENV) $(RUNCMD) ./cbtest misc - rm -rf casket* - $(RUNENV) $(RUNCMD) ./vltest write -tune 32 31 32 32 casket 50000 - $(RUNENV) $(RUNCMD) ./vltest read casket - $(RUNENV) $(RUNCMD) ./vltest rdup -tune 32 31 512 256 casket 50000 50000 - $(RUNENV) $(RUNCMD) ./vltest combo casket - $(RUNENV) $(RUNCMD) ./vltest wicked -c casket 5000 - $(RUNENV) $(RUNCMD) ./vltest wicked casket 500 - $(RUNENV) $(RUNCMD) ./vlmgr repair casket - $(RUNENV) $(RUNCMD) ./vlmgr optimize casket - $(RUNENV) $(RUNCMD) ./vlmgr list casket - rm -rf casket* - $(RUNENV) $(RUNCMD) ./vltest write -int -cz -tune 32 31 32 32 casket 50000 - $(RUNENV) $(RUNCMD) ./vltest read -int -vc casket - $(RUNENV) $(RUNCMD) ./vltest rdup -int -cz -cc -tune 32 31 512 256 casket 50000 50000 - $(RUNENV) $(RUNCMD) ./vltest combo -cz casket - $(RUNENV) $(RUNCMD) ./vltest wicked -cz -c casket 5000 - $(RUNENV) $(RUNCMD) ./vltest combo -cy casket - $(RUNENV) $(RUNCMD) ./vltest wicked -cy -c casket 5000 - $(RUNENV) $(RUNCMD) ./vltest combo -cx casket - $(RUNENV) $(RUNCMD) ./vltest wicked -cx -c casket 5000 - rm -rf casket* - $(RUNENV) $(RUNCMD) ./odtest write casket 500 50 5000 - $(RUNENV) $(RUNCMD) ./odtest read casket - $(RUNENV) $(RUNCMD) ./odtest combo casket - $(RUNENV) $(RUNCMD) ./odtest wicked casket 500 - rm -rf casket* - $(RUNENV) $(RUNCMD) ./qmttest casket 50000 10 - rm -rf casket* - @printf '\n' - @printf '#================================================================\n' - @printf '# Checking completed.\n' - @printf '#================================================================\n' - - -check-valgrind : - make RUNCMD="valgrind --tool=memcheck --log-fd=1" check | tee leak.log - grep ERROR leak.log - grep 'at exit' leak.log - - -world : - make clean ; make - cd plus ; [ -f Makefile ] || ./configure ; make clean ; make - cd java ; [ -f Makefile ] || ./configure ; make clean ; make - cd perl ; [ -f Makefile ] || ./configure ; make clean ; make - cd ruby ; [ -f Makefile ] || ./configure ; make clean ; make - cd cgi ; [ -f Makefile ] || ./configure ; make clean ; make - - -install-world : - make install - cd plus ; [ -f Makefile ] || ./configure ; make install - cd java ; [ -f Makefile ] || ./configure ; make install - cd perl ; [ -f Makefile ] || ./configure ; make install - cd ruby ; [ -f Makefile ] || ./configure ; make install - cd cgi ; [ -f Makefile ] || ./configure ; make install - - -uninstall-world : - make uninstall - cd plus ; [ -f Makefile ] || ./configure ; make uninstall - cd java ; [ -f Makefile ] || ./configure ; make uninstall - cd perl ; [ -f Makefile ] || ./configure ; make uninstall - cd ruby ; [ -f Makefile ] || ./configure ; make uninstall - cd cgi ; [ -f Makefile ] || ./configure ; make uninstall - - -check-world : - make check - cd plus ; [ -f Makefile ] || ./configure ; make check - cd java ; [ -f Makefile ] || ./configure ; make check - cd perl ; [ -f Makefile ] || ./configure ; make check - cd ruby ; [ -f Makefile ] || ./configure ; make check - - -rpm : ../$(PACKAGETGZ) qdbm.spec - mkdir -p rpm-tmp/{BUILD,RPMS,SOURCES,SPECS,SRPMS} - mkdir -p rpm-tmp/RPMS/i386 - cp ../$(PACKAGETGZ) rpm-tmp/SOURCES - rpmbuild -bb --target i386 --define "_topdir `pwd`/rpm-tmp" qdbm.spec - mv -f rpm-tmp/RPMS/i386/$(PACKAGE)-*$(VERSION)*.rpm .. - rm -rf rpm-tmp - - -win32pkg : - test -f /bin/mgwz.dll - test -f /bin/libiconv-2.dll - make uninstall && make uninstall-win && make clean - make mingw && strip *.exe && make install-win - cd java && ./configure - cd java && make uninstall && make uninstall-win && make clean - cd java && make mingw - cd cgi && ./configure - cd cgi && make clean - cd cgi && make mingw && strip *.cgi - mkdir -p $(PACKAGE)-$(VERSION)-win32 - cp -Rf $(MYHEADS) libqdbm.dll.a qdbm.dll *.exe *.html \ - misc/README-win32.txt misc/COPYING.txt misc/win32check.bat \ - /bin/mgwz.dll /bin/libiconv-2.dll \ - $(PACKAGE)-$(VERSION)-win32 - cp -Rf java/jqdbm.dll java/qdbm.jar java/*.html java/japidoc $(PACKAGE)-$(VERSION)-win32 - mkdir -p $(PACKAGE)-$(VERSION)-win32/cgi - cp -Rf cgi/*.cgi cgi/*.conf cgi/*.html $(PACKAGE)-$(VERSION)-win32/cgi - zip -r $(PACKAGE)-$(VERSION)-win32.zip $(PACKAGE)-$(VERSION)-win32 - mv -f $(PACKAGE)-$(VERSION)-win32.zip .. - rm -rf $(PACKAGE)-$(VERSION)-win32 - make uninstall && make uninstall-win && make clean - cd java ; make uninstall && make uninstall-win && make clean - - -win : - make MYLIBS="$(MYWINLIBS)" CFLAGS="-Wall -ansi -pedantic -fsigned-char -O2" - - -mingw : - make CC="gcc -mno-cygwin" MYLIBS="$(MYWINLIBS)" \ - CFLAGS="-Wall -fsigned-char -O2" LIBLDFLAGS="@MGWLIBS@" LDFLAGS="-L. -lqdbm @MGWLIBS@" - - -check-win : - make check - - -install-win : - make MYBINS="`for file in $(MYBINS) ; do echo $$file.exe ; done | tr '\n' ' '`" \ - MYLIBS="$(MYWINLIBS)" install - cp -Rf qdbm.dll $(DESTDIR)$(MYBINDIR) - - -uninstall-win : - make MYBINS="`for file in $(MYBINS) ; do echo $$file.exe ; done | tr '\n' ' '`" \ - MYLIBS="$(MYWINLIBS)" uninstall - rm -f $(DESTDIR)$(MYBINDIR)/qdbm.dll - - -def : libqdbm.a - ./misc/makevcdef libqdbm.a > qdbm.def - - -mac : - make MYLIBS="$(MYMACLIBS)" CFLAGS="-Wall -fsigned-char -fno-common -O2" - - -check-mac : - make RUNENV="DYLD_LIBRARY_PATH=." check - - -install-mac : - make MYLIBS="$(MYMACLIBS)" install - - -uninstall-mac : - make MYLIBS="$(MYMACLIBS)" uninstall - - -hpux : - make MYLIBS="$(MYHPUXLIBS)" - - -check-hpux : - make RUNENV="SHLIB_PATH=." check - - -install-hpux : - make MYLIBS="$(MYHPUXLIBS)" install - - -uninstall-hpux : - make MYLIBS="$(MYHPUXLIBS)" uninstall - - -no-so : - make MYLIBS="libqdbm.a" all - - -install-no-so : - make MYLIBS="libqdbm.a" install - - -uninstall-no-so : - make MYLIBS="libqdbm.a" uninstall - - -.PHONY : all clean install check - - - -#================================================================ -# Building binaries -#================================================================ - - -libqdbm.a : $(MYLIBOBJS) - $(AR) $(ARFLAGS) $@ $(MYLIBOBJS) - - -libqdbm.so.$(LIBVER).$(LIBREV).0 : $(MYLIBOBJS) - if uname -a | egrep -i 'SunOS' > /dev/null ; \ - then \ - $(CC) -shared -Wl,-G,-h,libqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \ - else \ - $(CC) -shared -Wl,-soname,libqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \ - fi - - -libqdbm.so.$(LIBVER) : libqdbm.so.$(LIBVER).$(LIBREV).0 - ln -f -s libqdbm.so.$(LIBVER).$(LIBREV).0 $@ - - -libqdbm.so : libqdbm.so.$(LIBVER).$(LIBREV).0 - ln -f -s libqdbm.so.$(LIBVER).$(LIBREV).0 $@ - - -libqdbm.dll.a : qdbm.dll - - -qdbm.dll : $(MYLIBOBJS) - $(CC) -shared -o $@ \ - -Wl,--out-implib=lib$@.a \ - -Wl,--export-all-symbols \ - -Wl,--enable-auto-import \ - -Wl,--add-stdcall-alias \ - -Wl,--whole-archive \ - -Wl,--no-whole-archive $(MYLIBOBJS) $(LIBLDFLAGS) - - -libqdbm.$(LIBVER).$(LIBREV).0.dylib : $(MYLIBOBJS) - $(CC) -dynamiclib -o $@ \ - -install_name $(MYLIBDIR)/libqdbm.$(LIBVER).dylib \ - -current_version $(LIBVER).$(LIBREV).0 \ - -compatibility_version $(LIBVER) \ - $(MYLIBOBJS) $(LIBLDFLAGS) - - -libqdbm.$(LIBVER).dylib : libqdbm.$(LIBVER).$(LIBREV).0.dylib - ln -f -s libqdbm.$(LIBVER).$(LIBREV).0.dylib $@ - - -libqdbm.dylib : libqdbm.$(LIBVER).$(LIBREV).0.dylib - ln -f -s libqdbm.$(LIBVER).$(LIBREV).0.dylib $@ - - -libqdbm.sl : $(MYLIBOBJS) - $(CC) -shared -Wl,-b -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) - - -dpmgr : dpmgr.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ dpmgr.o $(LDFLAGS) - - -dptest : dptest.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ dptest.o $(LDFLAGS) - - -dptsv : dptsv.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ dptsv.o $(LDFLAGS) - - -crmgr : crmgr.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ crmgr.o $(LDFLAGS) - - -crtest : crtest.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ crtest.o $(LDFLAGS) - - -crtsv : crtsv.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ crtsv.o $(LDFLAGS) - - -rlmgr : rlmgr.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ rlmgr.o $(LDFLAGS) - - -rltest : rltest.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ rltest.o $(LDFLAGS) - - -hvmgr : hvmgr.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ hvmgr.o $(LDFLAGS) - - -hvtest : hvtest.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ hvtest.o $(LDFLAGS) - - -cbtest : cbtest.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ cbtest.o $(LDFLAGS) - - -cbcodec : cbcodec.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ cbcodec.o $(LDFLAGS) - - -vlmgr : vlmgr.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ vlmgr.o $(LDFLAGS) - - -vltest : vltest.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ vltest.o $(LDFLAGS) - - -vltsv : vltsv.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ vltsv.o $(LDFLAGS) - - -odmgr : odmgr.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ odmgr.o $(LDFLAGS) - - -odtest : odtest.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ odtest.o $(LDFLAGS) - - -odidx : odidx.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ odidx.o $(LDFLAGS) - - -qmttest : qmttest.o $(MYLIBS) - $(LDENV) $(CC) $(CFLAGS) -o $@ qmttest.o $(LDFLAGS) - - -depot.o : depot.h myconf.h - -curia.o : depot.h curia.h myconf.h - -relic.o : depot.h relic.h myconf.h - -hovel.o : depot.h curia.h hovel.h myconf.h - -cabin.o : cabin.h myconf.h - -villa.o : depot.h cabin.h villa.h myconf.h - -vista.o : depot.h curia.h cabin.h villa.h vista.h myconf.h villa.c - -odeum.o : depot.h curia.h cabin.h villa.h myconf.h - -myconf.o : myconf.h - -dpmgr.o dptest.o dptsv.o : depot.h cabin.h - -crmgr.o crtest.o crtsv.o : depot.h curia.h cabin.h - -rlmgr.o rltest.o : depot.h relic.h cabin.h - -hvmgr.o hvtest.o : depot.h curia.h hovel.h cabin.h - -cbtest.o cbcodec.o : cabin.h - -vlmgr.o vltest.o vltsv.o : depot.h cabin.h villa.h - -odmgr.o odtest.o odidx.o : depot.h curia.h cabin.h villa.h odeum.h - - - -# END OF FILE Copied: box/trunk/qdbm/Makefile.in (from rev 2716, box/trunk/qdbm/Makefile.in) =================================================================== --- box/trunk/qdbm/Makefile.in (rev 0) +++ box/trunk/qdbm/Makefile.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,646 @@ +# Makefile for QDBM + + + +#================================================================ +# Setting variables +#================================================================ + + +# Generic settings +SHELL = @SHELL@ +srcdir = @srcdir@ +VPATH = @srcdir@ +SUBDIRS = + +# Packaging +PACKAGE = @PACKAGE_NAME@ +VERSION = @PACKAGE_VERSION@ +PACKAGEDIR = $(PACKAGE)-$(VERSION) +PACKAGETGZ = $(PACKAGE)-$(VERSION).tar.gz +LIBVER = @LIBVER@ +LIBREV = @LIBREV@ + +# Targets +MYHEADS = depot.h curia.h relic.h hovel.h cabin.h villa.h vista.h odeum.h +MYLIBOBJS = depot.o curia.o relic.o hovel.o cabin.o villa.o vista.o odeum.o myconf.o +MYLIBS = libqdbm.a libqdbm.so.$(LIBVER).$(LIBREV).0 libqdbm.so.$(LIBVER) libqdbm.so +MYBINS = dpmgr dptest dptsv crmgr crtest crtsv rlmgr rltest hvmgr hvtest \ + cbtest cbcodec vlmgr vltest vltsv odmgr odtest odidx qmttest +MYMAN1S = dpmgr.1 dptest.1 dptsv.1 crmgr.1 crtest.1 crtsv.1 rlmgr.1 rltest.1 hvmgr.1 hvtest.1 \ + cbtest.1 cbcodec.1 vlmgr.1 vltest.1 vltsv.1 odmgr.1 odtest.1 odidx.1 qmttest.1 +MYMAN3S = qdbm.3 depot.3 dpopen.3 curia.3 cropen.3 relic.3 hovel.3 \ + cabin.3 villa.3 vlopen.3 vista.3 odeum.3 odopen.3 +MYDOCS = spex.html spex-ja.html COPYING ChangeLog NEWS THANKS +MYPCS = qdbm.pc +MYWINLIBS = libqdbm.a libqdbm.dll.a +MYMACLIBS = libqdbm.a libqdbm.$(LIBVER).$(LIBREV).0.dylib libqdbm.$(LIBVER).dylib libqdbm.dylib +MYHPUXLIBS = libqdbm.a libqdbm.sl + +# Install destinations +prefix = @prefix@ +exec_prefix = @exec_prefix@ +MYHEADDIR = @includedir@ +MYLIBDIR = @libdir@ +MYBINDIR = @bindir@ +MYMAN1DIR = @mandir@/man1 +MYMAN3DIR = @mandir@/man3 +MYDATADIR = @datadir@/$(PACKAGE) +MYPCDIR = @libdir@/pkgconfig +DESTDIR = + +# Building binaries +CC = @CC@ +CPPFLAGS = @CPPFLAGS@ -I$(srcdir) -I$(MYHEADDIR) \ + -I$(HOME)/include -I/usr/local/include @MYDEFS@ \ + -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \ + -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 \ + -DPIC=1 -D_THREAD_SAFE=1 -D_REENTRANT=1 -DNDEBUG +CFLAGS = @CFLAGS@ -Wall -pedantic -fPIC -fsigned-char -O0 -fforce-addr @MYOPTS@ +LD = @LD@ +LIBS = -lqdbm @LIBS@ +LIBLDFLAGS = @LDFLAGS@ -L. -L$(MYLIBDIR) -L$(HOME)/lib -L/usr/local/lib @LIBS@ +LDFLAGS = @LDFLAGS@ -L. -L$(MYLIBDIR) -L$(HOME)/lib -L/usr/local/lib $(LIBS) +LDENV = LD_RUN_PATH=/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib +AR = @AR@ +ARFLAGS = rcsv +RUNENV = LD_LIBRARY_PATH=.:/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib + + + +#================================================================ +# Suffix rules +#================================================================ + + +.SUFFIXES : +.SUFFIXES : .c .o + +.c.o : + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< + + + +#================================================================ +# Actions +#================================================================ + + +targets : @TARGETS@ + + +all : $(MYLIBS) $(MYBINS) + @printf '\n' + @printf '#================================================================\n' + @printf '# Ready to install.\n' + @printf '#================================================================\n' + + +static : + make MYLIBS="$(MYLIBS)" LDFLAGS="-static $(LDFLAGS)" all + + +debug : + make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ + CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -g" \ + LDFLAGS="-static $(LDFLAGS)" all + + +devel : + make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ + CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -g -pipe" all + sync ; sync + + +stable : + make MYLIBS="$(MYLIBS)" CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2" all + + +profile : + make MYLIBS="$(MYLIBS)" \ + CFLAGS="-Wall -pedantic -fPIC -fsigned-char -O3 -pg -g -Werror" \ + LDFLAGS="-static $(LDFLAGS)" all + + +unsigned : + make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ + CFLAGS="-Wall -ansi -pedantic -fPIC -funsigned-char -g -O2" all + + +m64 : + make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ + CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -m64 -g" all + + +pen4 : + stdopt="-O3 -fomit-frame-pointer -minline-all-stringops" ; \ + exopt="-march=pentium4 -minline-all-stringops -fprefetch-loop-arrays" ; \ + make MYLIBS="$(MYLIBS)" \ + CFLAGS="-Wall -pedantic -fPIC -fsigned-char $$stdopt $$exopt" all + + +k8 : + stdopt="-O3 -fomit-frame-pointer -minline-all-stringops" ; \ + exopt="-march=k8 -minline-all-stringops -fprefetch-loop-arrays" ; \ + make MYLIBS="$(MYLIBS)" \ + CFLAGS="-Wall -pedantic -fPIC -fsigned-char $$stdopt $$exopt" all + + +clean : + rm -rf $(MYLIBS) $(MYBINS) *.o *.a *.so *.lo *.la a.out .libs \ + *.exe *.dll.a *.dll *.dylib *.sl TAGS srcdoc gmon.out leak.log \ + casket casket.* casket-* *~ + + +version : + vernum=`expr $(LIBVER)00 + $(LIBREV)` ; \ + sed -e 's/_QDBM_VERSION.*/_QDBM_VERSION "$(VERSION)"/' \ + -e "s/_QDBM_LIBVER.*/_QDBM_LIBVER $$vernum/" depot.h > depot.h~ + [ -f depot.h~ ] && mv -f depot.h~ depot.h + + +install : + mkdir -p $(DESTDIR)$(MYHEADDIR) + cd $(srcdir) && cp -Rf $(MYHEADS) $(DESTDIR)$(MYHEADDIR) + mkdir -p $(DESTDIR)$(MYLIBDIR) + cp -Rf $(MYLIBS) $(DESTDIR)$(MYLIBDIR) + mkdir -p $(DESTDIR)$(MYBINDIR) + cp -Rf $(MYBINS) $(DESTDIR)$(MYBINDIR) + mkdir -p $(DESTDIR)$(MYMAN1DIR) + cd $(srcdir)/man && cp -Rf $(MYMAN1S) $(DESTDIR)$(MYMAN1DIR) + mkdir -p $(DESTDIR)$(MYMAN3DIR) + cd $(srcdir)/man && cp -Rf $(MYMAN3S) $(DESTDIR)$(MYMAN3DIR) + mkdir -p $(DESTDIR)$(MYDATADIR) + cd $(srcdir) && cp -Rf $(MYDOCS) $(DESTDIR)$(MYDATADIR) + mkdir -p $(DESTDIR)$(MYPCDIR) + cd $(srcdir) && cp -Rf $(MYPCS) $(DESTDIR)$(MYPCDIR) + @printf '\n' + @printf '#================================================================\n' + @printf '# Thanks for using QDBM.\n' + @printf '#================================================================\n' + + +install-strip : + make DESTDIR=$(DESTDIR) install + cd $(DESTDIR)$(MYBINDIR) && strip $(MYBINS) + + +uninstall : + cd $(DESTDIR)$(MYHEADDIR) && rm -f $(MYHEADS) + cd $(DESTDIR)$(MYLIBDIR) && rm -f $(MYLIBS) + cd $(DESTDIR)$(MYBINDIR) && rm -f $(MYBINS) + cd $(DESTDIR)$(MYMAN1DIR) && rm -f $(MYMAN1S) + cd $(DESTDIR)$(MYMAN3DIR) && rm -f $(MYMAN3S) + rm -rf $(DESTDIR)$(MYDATADIR) + cd $(DESTDIR)$(MYPCDIR) && rm -f $(MYPCS) + + +dist : + sync ; sync + for dir in $(SUBDIRS) ; \ + do \ + if [ -d $$dir ] ; \ + then \ + echo Making $@ in $$dir ; \ + ( cd $$dir && if [ -f configure.in ] ; then autoconf ; ./configure ; \ + make dist ; fi ) ; \ + fi ; \ + done + make version + make distclean + cd .. && tar cvf - $(PACKAGEDIR) | gzip -c > $(PACKAGETGZ) + sync ; sync + + +distclean : clean + for dir in $(SUBDIRS) ; \ + do \ + if [ -d $$dir ] ; \ + then \ + echo Making $@ in $$dir ; \ + ( cd $$dir && if [ -f Makefile ] ; then make distclean ; fi ) ; \ + fi ; \ + done + rm -rf Makefile LTmakefile qdbm.spec qdbm.pc config.cache config.log config.status \ + autom4te.cache rpm-tmp *-win32 + + +TAGS : + etags -o $@ *.c *.h + + +sdoc : + rm -rf srcdoc + ./lab/ccdoc -d srcdoc -t "Source Documents of QDBM" *.h *.c + + +check : + sync ; sync + rm -rf casket* + $(RUNENV) $(RUNCMD) ./dptest write -s casket 500 500000 + $(RUNENV) $(RUNCMD) ./dptest write casket 50000 5000 + $(RUNENV) $(RUNCMD) ./dptest read casket + $(RUNENV) $(RUNCMD) ./dptest read -wb casket + $(RUNENV) $(RUNCMD) ./dptest rcat -c casket 50000 50 500 32 8 + $(RUNENV) $(RUNCMD) ./dptest combo casket + $(RUNENV) $(RUNCMD) ./dptest wicked -c casket 5000 + $(RUNENV) $(RUNCMD) ./dptest wicked casket 500 + $(RUNENV) $(RUNCMD) ./dpmgr repair casket + $(RUNENV) $(RUNCMD) ./dpmgr optimize casket + $(RUNENV) $(RUNCMD) ./dpmgr list casket + rm -rf casket* + $(RUNENV) $(RUNCMD) ./crtest write -s casket 500 100000 5 + $(RUNENV) $(RUNCMD) ./crtest write casket 50000 500 10 + $(RUNENV) $(RUNCMD) ./crtest read casket + $(RUNENV) $(RUNCMD) ./crtest read -wb casket + $(RUNENV) $(RUNCMD) ./crtest rcat -c casket 50000 5 10 500 32 8 + $(RUNENV) $(RUNCMD) ./crtest combo casket + $(RUNENV) $(RUNCMD) ./crtest wicked -c casket 5000 + $(RUNENV) $(RUNCMD) ./crtest wicked casket 500 + $(RUNENV) $(RUNCMD) ./crmgr repair casket + $(RUNENV) $(RUNCMD) ./crmgr optimize casket + $(RUNENV) $(RUNCMD) ./crmgr list casket + rm -rf casket* + $(RUNENV) $(RUNCMD) ./crtest write -lob casket 1000 50 10 + $(RUNENV) $(RUNCMD) ./crtest read -lob casket + rm -rf casket* + $(RUNENV) $(RUNCMD) ./rltest write casket 5000 + $(RUNENV) $(RUNCMD) ./rltest read casket 5000 + $(RUNENV) $(RUNCMD) ./rlmgr list casket + rm -rf casket* + $(RUNENV) $(RUNCMD) ./hvtest write casket 5000 + $(RUNENV) $(RUNCMD) ./hvtest read casket 5000 + $(RUNENV) $(RUNCMD) ./hvmgr optimize casket + $(RUNENV) $(RUNCMD) ./hvmgr list casket + rm -rf casket* + $(RUNENV) $(RUNCMD) ./hvtest write -qdbm -s casket 500 + $(RUNENV) $(RUNCMD) ./hvtest write -qdbm casket 5000 + $(RUNENV) $(RUNCMD) ./hvtest read -qdbm casket 5000 + rm -rf casket* + $(RUNENV) $(RUNCMD) ./cbtest sort 5000 + $(RUNENV) $(RUNCMD) ./cbtest strstr 500 + $(RUNENV) $(RUNCMD) ./cbtest list 50000 + $(RUNENV) $(RUNCMD) ./cbtest list -d 500 + $(RUNENV) $(RUNCMD) ./cbtest map 50000 500 + $(RUNENV) $(RUNCMD) ./cbtest map -d 500 5 + $(RUNENV) $(RUNCMD) ./cbtest heap 50000 500 + $(RUNENV) $(RUNCMD) ./cbtest heap -d 500 50 + $(RUNENV) $(RUNCMD) ./cbtest wicked 5000 + $(RUNENV) $(RUNCMD) ./cbtest misc + rm -rf casket* + $(RUNENV) $(RUNCMD) ./vltest write -tune 32 31 32 32 casket 50000 + $(RUNENV) $(RUNCMD) ./vltest read casket + $(RUNENV) $(RUNCMD) ./vltest rdup -tune 32 31 512 256 casket 50000 50000 + $(RUNENV) $(RUNCMD) ./vltest combo casket + $(RUNENV) $(RUNCMD) ./vltest wicked -c casket 5000 + $(RUNENV) $(RUNCMD) ./vltest wicked casket 500 + $(RUNENV) $(RUNCMD) ./vlmgr repair casket + $(RUNENV) $(RUNCMD) ./vlmgr optimize casket + $(RUNENV) $(RUNCMD) ./vlmgr list casket + rm -rf casket* + $(RUNENV) $(RUNCMD) ./vltest write -int -cz -tune 32 31 32 32 casket 50000 + $(RUNENV) $(RUNCMD) ./vltest read -int -vc casket + $(RUNENV) $(RUNCMD) ./vltest rdup -int -cz -cc -tune 32 31 512 256 casket 50000 50000 + $(RUNENV) $(RUNCMD) ./vltest combo -cz casket + $(RUNENV) $(RUNCMD) ./vltest wicked -cz -c casket 5000 + $(RUNENV) $(RUNCMD) ./vltest combo -cy casket + $(RUNENV) $(RUNCMD) ./vltest wicked -cy -c casket 5000 + $(RUNENV) $(RUNCMD) ./vltest combo -cx casket + $(RUNENV) $(RUNCMD) ./vltest wicked -cx -c casket 5000 + rm -rf casket* + $(RUNENV) $(RUNCMD) ./odtest write casket 500 50 5000 + $(RUNENV) $(RUNCMD) ./odtest read casket + $(RUNENV) $(RUNCMD) ./odtest combo casket + $(RUNENV) $(RUNCMD) ./odtest wicked casket 500 + rm -rf casket* + $(RUNENV) $(RUNCMD) ./qmttest casket 50000 10 + rm -rf casket* + @printf '\n' + @printf '#================================================================\n' + @printf '# Checking completed.\n' + @printf '#================================================================\n' + + +check-valgrind : + make RUNCMD="valgrind --tool=memcheck --log-fd=1" check | tee leak.log + grep ERROR leak.log + grep 'at exit' leak.log + + +world : + make clean ; make + cd plus ; [ -f Makefile ] || ./configure ; make clean ; make + cd java ; [ -f Makefile ] || ./configure ; make clean ; make + cd perl ; [ -f Makefile ] || ./configure ; make clean ; make + cd ruby ; [ -f Makefile ] || ./configure ; make clean ; make + cd cgi ; [ -f Makefile ] || ./configure ; make clean ; make + + +install-world : + make install + cd plus ; [ -f Makefile ] || ./configure ; make install + cd java ; [ -f Makefile ] || ./configure ; make install + cd perl ; [ -f Makefile ] || ./configure ; make install + cd ruby ; [ -f Makefile ] || ./configure ; make install + cd cgi ; [ -f Makefile ] || ./configure ; make install + + +uninstall-world : + make uninstall + cd plus ; [ -f Makefile ] || ./configure ; make uninstall + cd java ; [ -f Makefile ] || ./configure ; make uninstall + cd perl ; [ -f Makefile ] || ./configure ; make uninstall + cd ruby ; [ -f Makefile ] || ./configure ; make uninstall + cd cgi ; [ -f Makefile ] || ./configure ; make uninstall + + +check-world : + make check + cd plus ; [ -f Makefile ] || ./configure ; make check + cd java ; [ -f Makefile ] || ./configure ; make check + cd perl ; [ -f Makefile ] || ./configure ; make check + cd ruby ; [ -f Makefile ] || ./configure ; make check + + +rpm : ../$(PACKAGETGZ) qdbm.spec + mkdir -p rpm-tmp/{BUILD,RPMS,SOURCES,SPECS,SRPMS} + mkdir -p rpm-tmp/RPMS/i386 + cp ../$(PACKAGETGZ) rpm-tmp/SOURCES + rpmbuild -bb --target i386 --define "_topdir `pwd`/rpm-tmp" qdbm.spec + mv -f rpm-tmp/RPMS/i386/$(PACKAGE)-*$(VERSION)*.rpm .. + rm -rf rpm-tmp + + +win32pkg : + test -f /bin/mgwz.dll + test -f /bin/libiconv-2.dll + make uninstall && make uninstall-win && make clean + make mingw && strip *.exe && make install-win + cd java && ./configure + cd java && make uninstall && make uninstall-win && make clean + cd java && make mingw + cd cgi && ./configure + cd cgi && make clean + cd cgi && make mingw && strip *.cgi + mkdir -p $(PACKAGE)-$(VERSION)-win32 + cp -Rf $(MYHEADS) libqdbm.dll.a qdbm.dll *.exe *.html \ + misc/README-win32.txt misc/COPYING.txt misc/win32check.bat \ + /bin/mgwz.dll /bin/libiconv-2.dll \ + $(PACKAGE)-$(VERSION)-win32 + cp -Rf java/jqdbm.dll java/qdbm.jar java/*.html java/japidoc $(PACKAGE)-$(VERSION)-win32 + mkdir -p $(PACKAGE)-$(VERSION)-win32/cgi + cp -Rf cgi/*.cgi cgi/*.conf cgi/*.html $(PACKAGE)-$(VERSION)-win32/cgi + zip -r $(PACKAGE)-$(VERSION)-win32.zip $(PACKAGE)-$(VERSION)-win32 + mv -f $(PACKAGE)-$(VERSION)-win32.zip .. + rm -rf $(PACKAGE)-$(VERSION)-win32 + make uninstall && make uninstall-win && make clean + cd java ; make uninstall && make uninstall-win && make clean + + +win : + make MYLIBS="$(MYWINLIBS)" CFLAGS="-Wall -ansi -pedantic -fsigned-char -O2" + + +mingw : + make CC="gcc -mno-cygwin" MYLIBS="$(MYWINLIBS)" \ + CFLAGS="-Wall -fsigned-char -O2" LIBLDFLAGS="@MGWLIBS@" LDFLAGS="-L. -lqdbm @MGWLIBS@" + + +check-win : + make check + + +install-win : + make MYBINS="`for file in $(MYBINS) ; do echo $$file.exe ; done | tr '\n' ' '`" \ + MYLIBS="$(MYWINLIBS)" install + cp -Rf qdbm.dll $(DESTDIR)$(MYBINDIR) + + +uninstall-win : + make MYBINS="`for file in $(MYBINS) ; do echo $$file.exe ; done | tr '\n' ' '`" \ + MYLIBS="$(MYWINLIBS)" uninstall + rm -f $(DESTDIR)$(MYBINDIR)/qdbm.dll + + +def : libqdbm.a + ./misc/makevcdef libqdbm.a > qdbm.def + + +mac : + make MYLIBS="$(MYMACLIBS)" CFLAGS="-Wall -fsigned-char -fno-common -O2" + + +check-mac : + make RUNENV="DYLD_LIBRARY_PATH=." check + + +install-mac : + make MYLIBS="$(MYMACLIBS)" install + + +uninstall-mac : + make MYLIBS="$(MYMACLIBS)" uninstall + + +hpux : + make MYLIBS="$(MYHPUXLIBS)" + + +check-hpux : + make RUNENV="SHLIB_PATH=." check + + +install-hpux : + make MYLIBS="$(MYHPUXLIBS)" install + + +uninstall-hpux : + make MYLIBS="$(MYHPUXLIBS)" uninstall + + +no-so : + make MYLIBS="libqdbm.a" all + + +install-no-so : + make MYLIBS="libqdbm.a" install + + +uninstall-no-so : + make MYLIBS="libqdbm.a" uninstall + + +.PHONY : all clean install check + + + +#================================================================ +# Building binaries +#================================================================ + + +libqdbm.a : $(MYLIBOBJS) + $(AR) $(ARFLAGS) $@ $(MYLIBOBJS) + + +libqdbm.so.$(LIBVER).$(LIBREV).0 : $(MYLIBOBJS) + if uname -a | egrep -i 'SunOS' > /dev/null ; \ + then \ + $(CC) -shared -Wl,-G,-h,libqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \ + else \ + $(CC) -shared -Wl,-soname,libqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \ + fi + + +libqdbm.so.$(LIBVER) : libqdbm.so.$(LIBVER).$(LIBREV).0 + ln -f -s libqdbm.so.$(LIBVER).$(LIBREV).0 $@ + + +libqdbm.so : libqdbm.so.$(LIBVER).$(LIBREV).0 + ln -f -s libqdbm.so.$(LIBVER).$(LIBREV).0 $@ + + +libqdbm.dll.a : qdbm.dll + + +qdbm.dll : $(MYLIBOBJS) + $(CC) -shared -o $@ \ + -Wl,--out-implib=lib$@.a \ + -Wl,--export-all-symbols \ + -Wl,--enable-auto-import \ + -Wl,--add-stdcall-alias \ + -Wl,--whole-archive \ + -Wl,--no-whole-archive $(MYLIBOBJS) $(LIBLDFLAGS) + + +libqdbm.$(LIBVER).$(LIBREV).0.dylib : $(MYLIBOBJS) + $(CC) -dynamiclib -o $@ \ + -install_name $(MYLIBDIR)/libqdbm.$(LIBVER).dylib \ + -current_version $(LIBVER).$(LIBREV).0 \ + -compatibility_version $(LIBVER) \ + $(MYLIBOBJS) $(LIBLDFLAGS) + + +libqdbm.$(LIBVER).dylib : libqdbm.$(LIBVER).$(LIBREV).0.dylib + ln -f -s libqdbm.$(LIBVER).$(LIBREV).0.dylib $@ + + +libqdbm.dylib : libqdbm.$(LIBVER).$(LIBREV).0.dylib + ln -f -s libqdbm.$(LIBVER).$(LIBREV).0.dylib $@ + + +libqdbm.sl : $(MYLIBOBJS) + $(CC) -shared -Wl,-b -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) + + +dpmgr : dpmgr.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ dpmgr.o $(LDFLAGS) + + +dptest : dptest.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ dptest.o $(LDFLAGS) + + +dptsv : dptsv.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ dptsv.o $(LDFLAGS) + + +crmgr : crmgr.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ crmgr.o $(LDFLAGS) + + +crtest : crtest.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ crtest.o $(LDFLAGS) + + +crtsv : crtsv.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ crtsv.o $(LDFLAGS) + + +rlmgr : rlmgr.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ rlmgr.o $(LDFLAGS) + + +rltest : rltest.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ rltest.o $(LDFLAGS) + + +hvmgr : hvmgr.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ hvmgr.o $(LDFLAGS) + + +hvtest : hvtest.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ hvtest.o $(LDFLAGS) + + +cbtest : cbtest.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ cbtest.o $(LDFLAGS) + + +cbcodec : cbcodec.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ cbcodec.o $(LDFLAGS) + + +vlmgr : vlmgr.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ vlmgr.o $(LDFLAGS) + + +vltest : vltest.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ vltest.o $(LDFLAGS) + + +vltsv : vltsv.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ vltsv.o $(LDFLAGS) + + +odmgr : odmgr.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ odmgr.o $(LDFLAGS) + + +odtest : odtest.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ odtest.o $(LDFLAGS) + + +odidx : odidx.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ odidx.o $(LDFLAGS) + + +qmttest : qmttest.o $(MYLIBS) + $(LDENV) $(CC) $(CFLAGS) -o $@ qmttest.o $(LDFLAGS) + + +depot.o : depot.h myconf.h + +curia.o : depot.h curia.h myconf.h + +relic.o : depot.h relic.h myconf.h + +hovel.o : depot.h curia.h hovel.h myconf.h + +cabin.o : cabin.h myconf.h + +villa.o : depot.h cabin.h villa.h myconf.h + +vista.o : depot.h curia.h cabin.h villa.h vista.h myconf.h villa.c + +odeum.o : depot.h curia.h cabin.h villa.h myconf.h + +myconf.o : myconf.h + +dpmgr.o dptest.o dptsv.o : depot.h cabin.h + +crmgr.o crtest.o crtsv.o : depot.h curia.h cabin.h + +rlmgr.o rltest.o : depot.h relic.h cabin.h + +hvmgr.o hvtest.o : depot.h curia.h hovel.h cabin.h + +cbtest.o cbcodec.o : cabin.h + +vlmgr.o vltest.o vltsv.o : depot.h cabin.h villa.h + +odmgr.o odtest.o odidx.o : depot.h curia.h cabin.h villa.h odeum.h + + + +# END OF FILE Deleted: box/trunk/qdbm/NEWS =================================================================== --- box/trunk/qdbm/NEWS 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/NEWS 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,43 +0,0 @@ -== Thu, 08 Sep 2005 13:13:58 +0900 == - -Compressing options of ZLIB was changed. If you use villa with the option -`VL_OZCOMP', databases of the earlier versions are not compatible with the -current version of QDBM. To convert the old database to new format, -export endian independent data by "vlmgr exportdb" with the old version, -and then import it by "vlmgr importdb" with the latest version. - - - -== Wed, 10 Mar 2004 23:24:24 +0900 == - -API of B+ tree was changed a bit. Even if you build QDBM with ZLIB -enabled, records are not compressed. Instead of it, the function `vlopen' -has the option `VL_OZCOMP'. If it is specified, records are compressed. -So, you can switch whether to compress records or not, on runtime. - -Users who have used ZLIB feature should modify their source codes to -specify that option. - - - -== Wed, 10 Dec 2003 09:24:12 +0900 == - -The database format was changed with QDBM 1.7.13. Newer versions do not -have backward compatibility to old format. You can convert old databases -with the command `fmtcnv031127' in the sub directory `lab'. To build it, -perform the following steps. - - cd lab - make fmtcnv031127 - -About usage of it, see the file `README' in `lab'. Typically, to convert -a Depot database named as `old' and create a database named as `new', -perform the following step. - - ./fmtcnv031127 < old > new - -I'm sorry for bothering you. - - - -== END OF FILE == Copied: box/trunk/qdbm/NEWS (from rev 2716, box/trunk/qdbm/NEWS) =================================================================== --- box/trunk/qdbm/NEWS (rev 0) +++ box/trunk/qdbm/NEWS 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,43 @@ +== Thu, 08 Sep 2005 13:13:58 +0900 == + +Compressing options of ZLIB was changed. If you use villa with the option +`VL_OZCOMP', databases of the earlier versions are not compatible with the +current version of QDBM. To convert the old database to new format, +export endian independent data by "vlmgr exportdb" with the old version, +and then import it by "vlmgr importdb" with the latest version. + + + +== Wed, 10 Mar 2004 23:24:24 +0900 == + +API of B+ tree was changed a bit. Even if you build QDBM with ZLIB +enabled, records are not compressed. Instead of it, the function `vlopen' +has the option `VL_OZCOMP'. If it is specified, records are compressed. +So, you can switch whether to compress records or not, on runtime. + +Users who have used ZLIB feature should modify their source codes to +specify that option. + + + +== Wed, 10 Dec 2003 09:24:12 +0900 == + +The database format was changed with QDBM 1.7.13. Newer versions do not +have backward compatibility to old format. You can convert old databases +with the command `fmtcnv031127' in the sub directory `lab'. To build it, +perform the following steps. + + cd lab + make fmtcnv031127 + +About usage of it, see the file `README' in `lab'. Typically, to convert +a Depot database named as `old' and create a database named as `new', +perform the following step. + + ./fmtcnv031127 < old > new + +I'm sorry for bothering you. + + + +== END OF FILE == Deleted: box/trunk/qdbm/README =================================================================== --- box/trunk/qdbm/README 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/README 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,50 +0,0 @@ -================================================================ - QDBM: Quick Database Manager - Copyright (C) 2000-2007 Mikio Hirabayashi -================================================================ - - -Please read the following documents with a WWW browser. -How to install QDBM is explained in the specification. - - README - this file - COPYING - license - ChangeLog - history of enhancement - NEWS - news for users - THANKS - list of contributors - spex.html - specification - spex-ja.html - specification in Japanese - - -Contents of the directory tree is below. - - ./ - sources of QDBM - ./plus/ - API for C++ (read `./plus/xspex.html') - ./java/ - API for Java (read `./java/jspex.html') - ./perl/ - API for Perl (read `./perl/plspex.html') - ./ruby/ - API for Ruby (read `./ruby/rbspex.html') - ./cgi/ - CGI scripts (read `./cgi/cgispex.html') - ./man1/ - manual pages for commands - ./man3/ - manual pages for C API - ./lab/ - for test and experiment - ./bros/ - for comparison with other database managers - ./misc/ - miscellaneous files - - -QDBM is released under the terms of the GNU Lesser General Public -License. See the file `COPYING' for details. - -QDBM was written by Mikio Hirabayashi. You can contact the author -by e-mail to `mikio at users.sourceforge.net'. However, as for -topics which can be shared among other users, pleae send it to -the mailing list. To join the mailing list, refer to the following -URL. - - http://lists.sourceforge.net/lists/listinfo/qdbm-users - - -Thanks. - - - -== END OF FILE == Copied: box/trunk/qdbm/README (from rev 2716, box/trunk/qdbm/README) =================================================================== --- box/trunk/qdbm/README (rev 0) +++ box/trunk/qdbm/README 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,50 @@ +================================================================ + QDBM: Quick Database Manager + Copyright (C) 2000-2007 Mikio Hirabayashi +================================================================ + + +Please read the following documents with a WWW browser. +How to install QDBM is explained in the specification. + + README - this file + COPYING - license + ChangeLog - history of enhancement + NEWS - news for users + THANKS - list of contributors + spex.html - specification + spex-ja.html - specification in Japanese + + +Contents of the directory tree is below. + + ./ - sources of QDBM + ./plus/ - API for C++ (read `./plus/xspex.html') + ./java/ - API for Java (read `./java/jspex.html') + ./perl/ - API for Perl (read `./perl/plspex.html') + ./ruby/ - API for Ruby (read `./ruby/rbspex.html') + ./cgi/ - CGI scripts (read `./cgi/cgispex.html') + ./man1/ - manual pages for commands + ./man3/ - manual pages for C API + ./lab/ - for test and experiment + ./bros/ - for comparison with other database managers + ./misc/ - miscellaneous files + + +QDBM is released under the terms of the GNU Lesser General Public +License. See the file `COPYING' for details. + +QDBM was written by Mikio Hirabayashi. You can contact the author +by e-mail to `mikio at users.sourceforge.net'. However, as for +topics which can be shared among other users, pleae send it to +the mailing list. To join the mailing list, refer to the following +URL. + + http://lists.sourceforge.net/lists/listinfo/qdbm-users + + +Thanks. + + + +== END OF FILE == Deleted: box/trunk/qdbm/RISCmakefile =================================================================== --- box/trunk/qdbm/RISCmakefile 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/RISCmakefile 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,140 +0,0 @@ -# Makefile for the RISC OS version of QDBM - - -# Define which compiler to use: - -CC = cc -#CC = gcc - - -######################################### -# DO NOT EDIT ANYTHING BELOW THIS LINE! # -######################################### - -ifeq (${CC},cc) -CC = cc -LD = link -AR = libfile -DEPEND = -depend !Depend -CC_FLAGS = -Wdp -throwback -Otime -I@,Unix: -JUnix -UNIXLIB = Unix:o.UnixLib -else -ifeq (${CC},gcc) -CC = gcc -LD = gcc -AR = ar -CC_FLAGS = -mthrowback -O3 -I. -else -# No other compiler supported! -endif -endif - -QDBM_OBJS = o.depot o.curia o.relic o.hovel o.cabin o.villa o.vista o.odeum o.myconf - -.INIT : - @cdir o - -## Rule Patterns ## - -.SUFFIXES : .c .o - -.c.o : - $(CC) $(CC_FLAGS) $(DEPEND) -c -o $@ $< - -# Static dependencies: - -all : libqdbm testcases managers converters - -libqdbm : $(QDBM_OBJS) - $(AR) $(AR_FLAGS) -c -o libqdbm $(QDBM_OBJS) - -testcases : dptest crtest rltest hvtest cbtest vltest odtest - create testcases - -managers : dpmgr crmgr rlmgr hvmgr vlmgr odmgr - create managers - -converters : dptsv crtsv cbcodec vltsv odidx - create converters - -dptest : o.dptest libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -crtest : o.crtest libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -rltest : o.rltest libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -hvtest : o.hvtest libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -cbtest : o.cbtest libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -vltest : o.vltest libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -odtest : o.odtest libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -dpmgr : o.dpmgr libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -crmgr : o.crmgr libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -rlmgr : o.rlmgr libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -hvmgr : o.hvmgr libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -vlmgr : o.vlmgr libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -odmgr : o.odmgr libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -dptsv : o.dptsv libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -crtsv : o.crtsv libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -cbcodec : o.cbcodec libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -vltsv : o.vltsv libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -odidx : o.odidx libqdbm - $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) - -clean: - -ifthere libqdbm then wipe libqdbm ~CFR~V - -ifthere dptest then wipe dptest ~CFR~V - -ifthere crtest then wipe crtest ~CFR~V - -ifthere rltest then wipe rltest ~CFR~V - -ifthere hvtest then wipe hvtest ~CFR~V - -ifthere cbtest then wipe cbtest ~CFR~V - -ifthere vltest then wipe vltest ~CFR~V - -ifthere odtest then wipe odtest ~CFR~V - -ifthere dpmgr then wipe dpmgr ~CFR~V - -ifthere crmgr then wipe crmgr ~CFR~V - -ifthere rlmgr then wipe rlmgr ~CFR~V - -ifthere hvmgr then wipe hvmgr ~CFR~V - -ifthere cbmgr then wipe cbmgr ~CFR~V - -ifthere vlmgr then wipe vlmgr ~CFR~V - -ifthere odmgr then wipe odmgr ~CFR~V - -ifthere dptsv then wipe dptsv ~CFR~V - -ifthere crtsv then wipe crtsv ~CFR~V - -ifthere cbcodec then wipe cbcodec ~CFR~V - -ifthere vltsv then wipe vltsv ~CFR~V - -ifthere odidx then wipe odidx ~CFR~V - -ifthere testcases then wipe testcases ~CFR~V - -ifthere managers then wipe managers ~CFR~V - -ifthere converters then wipe converters ~CFR~V - -ifthere o.* then wipe o.* ~CFR~V - -# Dynamic dependencies: Copied: box/trunk/qdbm/RISCmakefile (from rev 2716, box/trunk/qdbm/RISCmakefile) =================================================================== --- box/trunk/qdbm/RISCmakefile (rev 0) +++ box/trunk/qdbm/RISCmakefile 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,140 @@ +# Makefile for the RISC OS version of QDBM + + +# Define which compiler to use: + +CC = cc +#CC = gcc + + +######################################### +# DO NOT EDIT ANYTHING BELOW THIS LINE! # +######################################### + +ifeq (${CC},cc) +CC = cc +LD = link +AR = libfile +DEPEND = -depend !Depend +CC_FLAGS = -Wdp -throwback -Otime -I@,Unix: -JUnix +UNIXLIB = Unix:o.UnixLib +else +ifeq (${CC},gcc) +CC = gcc +LD = gcc +AR = ar +CC_FLAGS = -mthrowback -O3 -I. +else +# No other compiler supported! +endif +endif + +QDBM_OBJS = o.depot o.curia o.relic o.hovel o.cabin o.villa o.vista o.odeum o.myconf + +.INIT : + @cdir o + +## Rule Patterns ## + +.SUFFIXES : .c .o + +.c.o : + $(CC) $(CC_FLAGS) $(DEPEND) -c -o $@ $< + +# Static dependencies: + +all : libqdbm testcases managers converters + +libqdbm : $(QDBM_OBJS) + $(AR) $(AR_FLAGS) -c -o libqdbm $(QDBM_OBJS) + +testcases : dptest crtest rltest hvtest cbtest vltest odtest + create testcases + +managers : dpmgr crmgr rlmgr hvmgr vlmgr odmgr + create managers + +converters : dptsv crtsv cbcodec vltsv odidx + create converters + +dptest : o.dptest libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +crtest : o.crtest libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +rltest : o.rltest libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +hvtest : o.hvtest libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +cbtest : o.cbtest libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +vltest : o.vltest libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +odtest : o.odtest libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +dpmgr : o.dpmgr libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +crmgr : o.crmgr libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +rlmgr : o.rlmgr libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +hvmgr : o.hvmgr libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +vlmgr : o.vlmgr libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +odmgr : o.odmgr libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +dptsv : o.dptsv libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +crtsv : o.crtsv libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +cbcodec : o.cbcodec libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +vltsv : o.vltsv libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +odidx : o.odidx libqdbm + $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) + +clean: + -ifthere libqdbm then wipe libqdbm ~CFR~V + -ifthere dptest then wipe dptest ~CFR~V + -ifthere crtest then wipe crtest ~CFR~V + -ifthere rltest then wipe rltest ~CFR~V + -ifthere hvtest then wipe hvtest ~CFR~V + -ifthere cbtest then wipe cbtest ~CFR~V + -ifthere vltest then wipe vltest ~CFR~V + -ifthere odtest then wipe odtest ~CFR~V + -ifthere dpmgr then wipe dpmgr ~CFR~V + -ifthere crmgr then wipe crmgr ~CFR~V + -ifthere rlmgr then wipe rlmgr ~CFR~V + -ifthere hvmgr then wipe hvmgr ~CFR~V + -ifthere cbmgr then wipe cbmgr ~CFR~V + -ifthere vlmgr then wipe vlmgr ~CFR~V + -ifthere odmgr then wipe odmgr ~CFR~V + -ifthere dptsv then wipe dptsv ~CFR~V + -ifthere crtsv then wipe crtsv ~CFR~V + -ifthere cbcodec then wipe cbcodec ~CFR~V + -ifthere vltsv then wipe vltsv ~CFR~V + -ifthere odidx then wipe odidx ~CFR~V + -ifthere testcases then wipe testcases ~CFR~V + -ifthere managers then wipe managers ~CFR~V + -ifthere converters then wipe converters ~CFR~V + -ifthere o.* then wipe o.* ~CFR~V + +# Dynamic dependencies: Deleted: box/trunk/qdbm/THANKS =================================================================== --- box/trunk/qdbm/THANKS 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/THANKS 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,45 +0,0 @@ -================================================================ - Thanks to all of the following for their valuable suggestions - or contributions. -================================================================ - - -Kang-Jin Lee - - suggestions about the GDBM-compatible API - - contributions about Makefile - -Pat Podenski - - suggestions about porting to Mac OS X, Solaris, and HP-UX - -BERO - - contributions about supporting MinGW - -Stefan Bellon - - contributions about porting to RISC OS - -Donald Gobin - - contributions about supporting Visual C++ - -Emanuel Dejanu - - contributions about supporting Visual C++ - -Keith Bostic - - suggestions about the performance test suite - -William Lachance - - contributions about RPM spec file - -Zed A. Shaw - - contributions about a text analyzer in Odeum - - contributions about a query language in Odeum - -Chris Bilderback - - contributions about cursor functions in Villa. - -Fumitoshi Ukai - - contributions of troff manuals - - making Debian packages - - - -== END OF FILE == Copied: box/trunk/qdbm/THANKS (from rev 2716, box/trunk/qdbm/THANKS) =================================================================== --- box/trunk/qdbm/THANKS (rev 0) +++ box/trunk/qdbm/THANKS 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,45 @@ +================================================================ + Thanks to all of the following for their valuable suggestions + or contributions. +================================================================ + + +Kang-Jin Lee + - suggestions about the GDBM-compatible API + - contributions about Makefile + +Pat Podenski + - suggestions about porting to Mac OS X, Solaris, and HP-UX + +BERO + - contributions about supporting MinGW + +Stefan Bellon + - contributions about porting to RISC OS + +Donald Gobin + - contributions about supporting Visual C++ + +Emanuel Dejanu + - contributions about supporting Visual C++ + +Keith Bostic + - suggestions about the performance test suite + +William Lachance + - contributions about RPM spec file + +Zed A. Shaw + - contributions about a text analyzer in Odeum + - contributions about a query language in Odeum + +Chris Bilderback + - contributions about cursor functions in Villa. + +Fumitoshi Ukai + - contributions of troff manuals + - making Debian packages + + + +== END OF FILE == Deleted: box/trunk/qdbm/VCmakefile =================================================================== --- box/trunk/qdbm/VCmakefile 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/VCmakefile 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,248 +0,0 @@ -# Makefile to build QDBM using Microsoft Visual C++ - - - -#================================================================ -# Setting variables -#================================================================ - - -# VC++ directory -VCPATH = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7 - -# User options -YOUR_CLFLAGS = -YOUR_LIBFLAGS = -YOUR_LINKFLAGS= - -# Configurations -!IF "$(CFG)" == "ld" -!MESSAGE Build using static debug configuration -BASE_FLAGS = /MLd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" -BASE_DEFS = /D_DEBUG /D__DEBUG__ -OUTDIR = .\tmp_ld -LIB_APPEND = _ld -EXE_APPEND = _ld -!ELSEIF "$(CFG)" == "l" -!MESSAGE Build using static release configuration -BASE_DEFS = /DNDEBUG -BASE_FLAGS = /ML /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" -OUTDIR = .\tmp_l -LIB_APPEND = _l -EXE_APPEND = _l -!ELSEIF "$(CFG)" == "td" -!MESSAGE Build using static threaded debug configuration -BASE_FLAGS = /MTd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" -BASE_DEFS = /D_DEBUG /D__DEBUG__ -OUTDIR = .\tmp_td -LIB_APPEND = _td -EXE_APPEND = _td -!ELSEIF "$(CFG)" == "t" -!MESSAGE Build using static threaded release configuration -BASE_DEFS = /DNDEBUG -BASE_FLAGS = /MT /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" -OUTDIR = .\tmp_t -LIB_APPEND = _t -EXE_APPEND = _t -!ELSEIF "$(CFG)" == "dd" -!MESSAGE Build using dynamic threaded debug configuration -BASE_FLAGS = /MDd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" -BASE_DEFS = /D_DEBUG /D__DEBUG__ -OUTDIR = .\tmp_dd -LIB_APPEND = _dd -EXE_APPEND = _dd -!ELSE -!MESSAGE Build using dynamic threaded release configuration -BASE_DEFS = /DNDEBUG -BASE_FLAGS = /MD /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" -OUTDIR = .\tmp -LIB_APPEND = -EXE_APPEND = -!ENDIF - -# Building binaries -CLFLAGS = /I "$(VCPATH)\Include" /I "$(VCPATH)\PlatformSDK\Include" /I "." \ - /nologo $(YOUR_CLFLAGS) $(BASE_FLAGS) $(BASE_DEFS) /D_CRT_SECURE_NO_DEPRECATE=1 -LIBFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." \ - /nologo $(YOUR_LIBFLAGS) -LINKFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." \ - /nologo $(YOUR_LINKFLAGS) - -# Targets -MYLIBS = qdbm$(LIB_APPEND).dll qdbm$(LIB_APPEND).lib qdbm$(LIB_APPEND)_static.lib -LIBOBJS = $(OUTDIR)\depot.obj $(OUTDIR)\curia.obj $(OUTDIR)\relic.obj \ - $(OUTDIR)\hovel.obj $(OUTDIR)\cabin.obj $(OUTDIR)\villa.obj \ - $(OUTDIR)\vista.obj $(OUTDIR)\odeum.obj $(OUTDIR)\myconf.obj -MYBINS = dpmgr$(EXE_APPEND).exe dptest$(EXE_APPEND).exe dptsv$(EXE_APPEND).exe \ - crmgr$(EXE_APPEND).exe crtest$(EXE_APPEND).exe crtsv$(EXE_APPEND).exe \ - rlmgr$(EXE_APPEND).exe rltest$(EXE_APPEND).exe hvmgr$(EXE_APPEND).exe \ - hvtest$(EXE_APPEND).exe cbtest$(EXE_APPEND).exe cbcodec$(EXE_APPEND).exe \ - vlmgr$(EXE_APPEND).exe vltest$(EXE_APPEND).exe vltsv$(EXE_APPEND).exe \ - odmgr$(EXE_APPEND).exe odtest$(EXE_APPEND).exe odidx$(EXE_APPEND).exe - - - -#================================================================ -# Suffix rules -#================================================================ - - -.SUFFIXES : -.SUFFIXES : .c .obj - -.c{$(OUTDIR)}.obj : - cl /c $(CLFLAGS) $< - -.c.obj: - cl /c $(CLFLAGS) $< - - - -#================================================================ -# Actions -#================================================================ - - -all : $(OUTDIR) $(MYLIBS) $(MYBINS) - - -allcfg: - nmake /NOLOGO /f VCmakefile CFG=ld - nmake /NOLOGO /f VCmakefile CFG=l - nmake /NOLOGO /f VCmakefile CFG=td - nmake /NOLOGO /f VCmakefile CFG=t - nmake /NOLOGO /f VCmakefile CFG=dd - nmake /NOLOGO /f VCmakefile - - -clean : - -rd tmp_ld /S /Q > NUL: 2>&1 - -rd tmp_l /S /Q > NUL: 2>&1 - -rd tmp_td /S /Q > NUL: 2>&1 - -rd tmp_t /S /Q > NUL: 2>&1 - -rd tmp_dd /S /Q > NUL: 2>&1 - -rd tmp /S /Q > NUL: 2>&1 - -del *.obj *.lib *.dll *.exp *.exe casket /F /Q > NUL: 2>&1 - - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/" mkdir "$(OUTDIR)" - - - -#================================================================ -# Building binaries -#================================================================ - - -qdbm$(LIB_APPEND).dll : $(LIBOBJS) qdbm.def - link /DLL /DEF:qdbm.def $(LINKFLAGS) /OUT:$@ /IMPLIB:qdbm$(LIB_APPEND).lib $(LIBOBJS) - - -qdbm$(LIB_APPEND).lib : qdbm$(LIB_APPEND).dll - - -qdbm$(LIB_APPEND)_static.lib : $(LIBOBJS) - lib $(LIBFLAGS) /OUT:$@ $(LIBOBJS) - - -dpmgr$(EXE_APPEND).exe : $(OUTDIR)\dpmgr.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dpmgr.obj qdbm$(LIB_APPEND).lib - - -dptest$(EXE_APPEND).exe : $(OUTDIR)\dptest.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dptest.obj qdbm$(LIB_APPEND).lib - - -dptsv$(EXE_APPEND).exe : $(OUTDIR)\dptsv.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dptsv.obj qdbm$(LIB_APPEND).lib - - -crmgr$(EXE_APPEND).exe : $(OUTDIR)\crmgr.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crmgr.obj qdbm$(LIB_APPEND).lib - - -crtest$(EXE_APPEND).exe : $(OUTDIR)\crtest.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crtest.obj qdbm$(LIB_APPEND).lib - - -crtsv$(EXE_APPEND).exe : $(OUTDIR)\crtsv.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crtsv.obj qdbm$(LIB_APPEND).lib - - -rlmgr$(EXE_APPEND).exe : $(OUTDIR)\rlmgr.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\rlmgr.obj qdbm$(LIB_APPEND).lib - - -rltest$(EXE_APPEND).exe : $(OUTDIR)\rltest.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\rltest.obj qdbm$(LIB_APPEND).lib - - -hvmgr$(EXE_APPEND).exe : $(OUTDIR)\hvmgr.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\hvmgr.obj qdbm$(LIB_APPEND).lib - - -hvtest$(EXE_APPEND).exe : $(OUTDIR)\hvtest.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\hvtest.obj qdbm$(LIB_APPEND).lib - - -cbtest$(EXE_APPEND).exe : $(OUTDIR)\cbtest.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\cbtest.obj qdbm$(LIB_APPEND).lib - - -cbcodec$(EXE_APPEND).exe : $(OUTDIR)\cbcodec.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\cbcodec.obj qdbm$(LIB_APPEND).lib - - -vlmgr$(EXE_APPEND).exe : $(OUTDIR)\vlmgr.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vlmgr.obj qdbm$(LIB_APPEND).lib - - -vltest$(EXE_APPEND).exe : $(OUTDIR)\vltest.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vltest.obj qdbm$(LIB_APPEND).lib - - -vltsv$(EXE_APPEND).exe : $(OUTDIR)\vltsv.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vltsv.obj qdbm$(LIB_APPEND).lib - - -odmgr$(EXE_APPEND).exe : $(OUTDIR)\odmgr.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odmgr.obj qdbm$(LIB_APPEND).lib - - -odtest$(EXE_APPEND).exe : $(OUTDIR)\odtest.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odtest.obj qdbm$(LIB_APPEND).lib - - -odidx$(EXE_APPEND).exe : $(OUTDIR)\odidx.obj qdbm$(LIB_APPEND).lib - link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odidx.obj qdbm$(LIB_APPEND).lib - - -$(OUTDIR)\depot.obj $(OUTDIR)\dpmgr.obj $(OUTDIR)\dptest.obj $(OUTDIR)\dptsv.obj : \ - depot.h myconf.h - -$(OUTDIR)\curia.obj $(OUTDIR)\crmgr.obj $(OUTDIR)\crtest.obj $(OUTDIR)\crtsv.obj : \ - curia.h depot.h myconf.h - -$(OUTDIR)\relic.obj $(OUTDIR)\rlmgr.obj $(OUTDIR)\rltest.obj : \ - relic.h depot.h myconf.h - -$(OUTDIR)\hovel.obj $(OUTDIR)\hvmgr.obj $(OUTDIR)\hvtest.obj : \ - hovel.h depot.h curia.h myconf.h - -$(OUTDIR)\cabin.obj $(OUTDIR)\cbtest.obj $(OUTDIR)\cbcodec.obj : \ - cabin.h myconf.h - -$(OUTDIR)\villa.obj $(OUTDIR)\vlmgr.obj $(OUTDIR)\vltest.obj $(OUTDIR)\vltsv.obj : \ - villa.h depot.h cabin.h myconf.h - -$(OUTDIR)\vista.obj : vista.h villa.h depot.h curia.h cabin.h myconf.h - -$(OUTDIR)\odeum.obj $(OUTDIR)\odmgr.obj $(OUTDIR)\odtest.obj $(OUTDIR)\odidx.obj : \ - odeum.h depot.h curia.h cabin.h villa.h myconf.h - -$(OUTDIR)\myconf.obj : myconf.h - - - -# END OF FILE Copied: box/trunk/qdbm/VCmakefile (from rev 2716, box/trunk/qdbm/VCmakefile) =================================================================== --- box/trunk/qdbm/VCmakefile (rev 0) +++ box/trunk/qdbm/VCmakefile 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,248 @@ +# Makefile to build QDBM using Microsoft Visual C++ + + + +#================================================================ +# Setting variables +#================================================================ + + +# VC++ directory +VCPATH = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7 + +# User options +YOUR_CLFLAGS = +YOUR_LIBFLAGS = +YOUR_LINKFLAGS= + +# Configurations +!IF "$(CFG)" == "ld" +!MESSAGE Build using static debug configuration +BASE_FLAGS = /MLd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" +BASE_DEFS = /D_DEBUG /D__DEBUG__ +OUTDIR = .\tmp_ld +LIB_APPEND = _ld +EXE_APPEND = _ld +!ELSEIF "$(CFG)" == "l" +!MESSAGE Build using static release configuration +BASE_DEFS = /DNDEBUG +BASE_FLAGS = /ML /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" +OUTDIR = .\tmp_l +LIB_APPEND = _l +EXE_APPEND = _l +!ELSEIF "$(CFG)" == "td" +!MESSAGE Build using static threaded debug configuration +BASE_FLAGS = /MTd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" +BASE_DEFS = /D_DEBUG /D__DEBUG__ +OUTDIR = .\tmp_td +LIB_APPEND = _td +EXE_APPEND = _td +!ELSEIF "$(CFG)" == "t" +!MESSAGE Build using static threaded release configuration +BASE_DEFS = /DNDEBUG +BASE_FLAGS = /MT /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" +OUTDIR = .\tmp_t +LIB_APPEND = _t +EXE_APPEND = _t +!ELSEIF "$(CFG)" == "dd" +!MESSAGE Build using dynamic threaded debug configuration +BASE_FLAGS = /MDd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" +BASE_DEFS = /D_DEBUG /D__DEBUG__ +OUTDIR = .\tmp_dd +LIB_APPEND = _dd +EXE_APPEND = _dd +!ELSE +!MESSAGE Build using dynamic threaded release configuration +BASE_DEFS = /DNDEBUG +BASE_FLAGS = /MD /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" +OUTDIR = .\tmp +LIB_APPEND = +EXE_APPEND = +!ENDIF + +# Building binaries +CLFLAGS = /I "$(VCPATH)\Include" /I "$(VCPATH)\PlatformSDK\Include" /I "." \ + /nologo $(YOUR_CLFLAGS) $(BASE_FLAGS) $(BASE_DEFS) /D_CRT_SECURE_NO_DEPRECATE=1 +LIBFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." \ + /nologo $(YOUR_LIBFLAGS) +LINKFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." \ + /nologo $(YOUR_LINKFLAGS) + +# Targets +MYLIBS = qdbm$(LIB_APPEND).dll qdbm$(LIB_APPEND).lib qdbm$(LIB_APPEND)_static.lib +LIBOBJS = $(OUTDIR)\depot.obj $(OUTDIR)\curia.obj $(OUTDIR)\relic.obj \ + $(OUTDIR)\hovel.obj $(OUTDIR)\cabin.obj $(OUTDIR)\villa.obj \ + $(OUTDIR)\vista.obj $(OUTDIR)\odeum.obj $(OUTDIR)\myconf.obj +MYBINS = dpmgr$(EXE_APPEND).exe dptest$(EXE_APPEND).exe dptsv$(EXE_APPEND).exe \ + crmgr$(EXE_APPEND).exe crtest$(EXE_APPEND).exe crtsv$(EXE_APPEND).exe \ + rlmgr$(EXE_APPEND).exe rltest$(EXE_APPEND).exe hvmgr$(EXE_APPEND).exe \ + hvtest$(EXE_APPEND).exe cbtest$(EXE_APPEND).exe cbcodec$(EXE_APPEND).exe \ + vlmgr$(EXE_APPEND).exe vltest$(EXE_APPEND).exe vltsv$(EXE_APPEND).exe \ + odmgr$(EXE_APPEND).exe odtest$(EXE_APPEND).exe odidx$(EXE_APPEND).exe + + + +#================================================================ +# Suffix rules +#================================================================ + + +.SUFFIXES : +.SUFFIXES : .c .obj + +.c{$(OUTDIR)}.obj : + cl /c $(CLFLAGS) $< + +.c.obj: + cl /c $(CLFLAGS) $< + + + +#================================================================ +# Actions +#================================================================ + + +all : $(OUTDIR) $(MYLIBS) $(MYBINS) + + +allcfg: + nmake /NOLOGO /f VCmakefile CFG=ld + nmake /NOLOGO /f VCmakefile CFG=l + nmake /NOLOGO /f VCmakefile CFG=td + nmake /NOLOGO /f VCmakefile CFG=t + nmake /NOLOGO /f VCmakefile CFG=dd + nmake /NOLOGO /f VCmakefile + + +clean : + -rd tmp_ld /S /Q > NUL: 2>&1 + -rd tmp_l /S /Q > NUL: 2>&1 + -rd tmp_td /S /Q > NUL: 2>&1 + -rd tmp_t /S /Q > NUL: 2>&1 + -rd tmp_dd /S /Q > NUL: 2>&1 + -rd tmp /S /Q > NUL: 2>&1 + -del *.obj *.lib *.dll *.exp *.exe casket /F /Q > NUL: 2>&1 + + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/" mkdir "$(OUTDIR)" + + + +#================================================================ +# Building binaries +#================================================================ + + +qdbm$(LIB_APPEND).dll : $(LIBOBJS) qdbm.def + link /DLL /DEF:qdbm.def $(LINKFLAGS) /OUT:$@ /IMPLIB:qdbm$(LIB_APPEND).lib $(LIBOBJS) + + +qdbm$(LIB_APPEND).lib : qdbm$(LIB_APPEND).dll + + +qdbm$(LIB_APPEND)_static.lib : $(LIBOBJS) + lib $(LIBFLAGS) /OUT:$@ $(LIBOBJS) + + +dpmgr$(EXE_APPEND).exe : $(OUTDIR)\dpmgr.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dpmgr.obj qdbm$(LIB_APPEND).lib + + +dptest$(EXE_APPEND).exe : $(OUTDIR)\dptest.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dptest.obj qdbm$(LIB_APPEND).lib + + +dptsv$(EXE_APPEND).exe : $(OUTDIR)\dptsv.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dptsv.obj qdbm$(LIB_APPEND).lib + + +crmgr$(EXE_APPEND).exe : $(OUTDIR)\crmgr.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crmgr.obj qdbm$(LIB_APPEND).lib + + +crtest$(EXE_APPEND).exe : $(OUTDIR)\crtest.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crtest.obj qdbm$(LIB_APPEND).lib + + +crtsv$(EXE_APPEND).exe : $(OUTDIR)\crtsv.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crtsv.obj qdbm$(LIB_APPEND).lib + + +rlmgr$(EXE_APPEND).exe : $(OUTDIR)\rlmgr.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\rlmgr.obj qdbm$(LIB_APPEND).lib + + +rltest$(EXE_APPEND).exe : $(OUTDIR)\rltest.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\rltest.obj qdbm$(LIB_APPEND).lib + + +hvmgr$(EXE_APPEND).exe : $(OUTDIR)\hvmgr.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\hvmgr.obj qdbm$(LIB_APPEND).lib + + +hvtest$(EXE_APPEND).exe : $(OUTDIR)\hvtest.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\hvtest.obj qdbm$(LIB_APPEND).lib + + +cbtest$(EXE_APPEND).exe : $(OUTDIR)\cbtest.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\cbtest.obj qdbm$(LIB_APPEND).lib + + +cbcodec$(EXE_APPEND).exe : $(OUTDIR)\cbcodec.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\cbcodec.obj qdbm$(LIB_APPEND).lib + + +vlmgr$(EXE_APPEND).exe : $(OUTDIR)\vlmgr.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vlmgr.obj qdbm$(LIB_APPEND).lib + + +vltest$(EXE_APPEND).exe : $(OUTDIR)\vltest.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vltest.obj qdbm$(LIB_APPEND).lib + + +vltsv$(EXE_APPEND).exe : $(OUTDIR)\vltsv.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vltsv.obj qdbm$(LIB_APPEND).lib + + +odmgr$(EXE_APPEND).exe : $(OUTDIR)\odmgr.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odmgr.obj qdbm$(LIB_APPEND).lib + + +odtest$(EXE_APPEND).exe : $(OUTDIR)\odtest.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odtest.obj qdbm$(LIB_APPEND).lib + + +odidx$(EXE_APPEND).exe : $(OUTDIR)\odidx.obj qdbm$(LIB_APPEND).lib + link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odidx.obj qdbm$(LIB_APPEND).lib + + +$(OUTDIR)\depot.obj $(OUTDIR)\dpmgr.obj $(OUTDIR)\dptest.obj $(OUTDIR)\dptsv.obj : \ + depot.h myconf.h + +$(OUTDIR)\curia.obj $(OUTDIR)\crmgr.obj $(OUTDIR)\crtest.obj $(OUTDIR)\crtsv.obj : \ + curia.h depot.h myconf.h + +$(OUTDIR)\relic.obj $(OUTDIR)\rlmgr.obj $(OUTDIR)\rltest.obj : \ + relic.h depot.h myconf.h + +$(OUTDIR)\hovel.obj $(OUTDIR)\hvmgr.obj $(OUTDIR)\hvtest.obj : \ + hovel.h depot.h curia.h myconf.h + +$(OUTDIR)\cabin.obj $(OUTDIR)\cbtest.obj $(OUTDIR)\cbcodec.obj : \ + cabin.h myconf.h + +$(OUTDIR)\villa.obj $(OUTDIR)\vlmgr.obj $(OUTDIR)\vltest.obj $(OUTDIR)\vltsv.obj : \ + villa.h depot.h cabin.h myconf.h + +$(OUTDIR)\vista.obj : vista.h villa.h depot.h curia.h cabin.h myconf.h + +$(OUTDIR)\odeum.obj $(OUTDIR)\odmgr.obj $(OUTDIR)\odtest.obj $(OUTDIR)\odidx.obj : \ + odeum.h depot.h curia.h cabin.h villa.h myconf.h + +$(OUTDIR)\myconf.obj : myconf.h + + + +# END OF FILE Deleted: box/trunk/qdbm/cabin.c =================================================================== --- box/trunk/qdbm/cabin.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/cabin.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,3529 +0,0 @@ -/************************************************************************************************* - * Implementation of Cabin - * 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. - *************************************************************************************************/ - - -#define QDBM_INTERNAL 1 - -#include "cabin.h" -#include "myconf.h" - -#define CB_GCUNIT 64 /* allocation unit size of a buffer in gc */ -#define CB_SPBUFSIZ 32 /* size of a buffer for sprintf */ -#define CB_SPMAXWIDTH 128 /* max width of a column for sprintf */ -#define CB_MAPPBNUM 251 /* bucket size of a petit map handle */ -#define CB_MAPCSUNIT 52 /* small allocation unit size of map concatenation */ -#define CB_MAPCBUNIT 252 /* big allocation unit size of map concatenation */ -#define CB_MSGBUFSIZ 256 /* size of a buffer for log message */ -#define CB_IOBUFSIZ 8192 /* size of an I/O buffer */ -#define CB_FILEMODE 00644 /* permission of a creating file */ -#define CB_NUMBUFSIZ 32 /* size of a buffer for a number */ -#define CB_ENCBUFSIZ 32 /* size of a buffer for encoding name */ -#define CB_DATEBUFSIZ 64 /* size of a buffer for date expression */ -#define CB_VNUMBUFSIZ 8 /* size of a buffer for variable length number */ - -/* set a buffer for a variable length number */ -#define CB_SETVNUMBUF(CB_len, CB_buf, CB_num) \ - do { \ - int _CB_num; \ - _CB_num = (CB_num); \ - if(_CB_num == 0){ \ - ((signed char *)(CB_buf))[0] = 0; \ - (CB_len) = 1; \ - } else { \ - (CB_len) = 0; \ - while(_CB_num > 0){ \ - int _CB_rem = _CB_num & 0x7f; \ - _CB_num >>= 7; \ - if(_CB_num > 0){ \ - ((signed char *)(CB_buf))[(CB_len)] = -_CB_rem - 1; \ - } else { \ - ((signed char *)(CB_buf))[(CB_len)] = _CB_rem; \ - } \ - (CB_len)++; \ - } \ - } \ - } while(FALSE) - -/* read a variable length buffer */ -#define CB_READVNUMBUF(CB_buf, CB_size, CB_num, CB_step) \ - do { \ - int _CB_i, _CB_base; \ - CB_num = 0; \ - _CB_base = 1; \ - if((size) < 2){ \ - CB_num = ((signed char *)(CB_buf))[0]; \ - (CB_step) = 1; \ - } else { \ - for(_CB_i = 0; _CB_i < (size); _CB_i++){ \ - if(((signed char *)(CB_buf))[_CB_i] >= 0){ \ - CB_num += ((signed char *)(CB_buf))[_CB_i] * _CB_base; \ - break; \ - } \ - CB_num += _CB_base * (((signed char *)(CB_buf))[_CB_i] + 1) * -1; \ - _CB_base *= 128; \ - } \ - (CB_step) = _CB_i + 1; \ - } \ - } while(FALSE) - -/* get the first hash value */ -#define CB_FIRSTHASH(CB_res, CB_kbuf, CB_ksiz) \ - do { \ - const unsigned char *_CB_p; \ - int _CB_ksiz; \ - _CB_p = (const unsigned char *)(CB_kbuf); \ - _CB_ksiz = CB_ksiz; \ - for((CB_res) = 19780211; _CB_ksiz--;){ \ - (CB_res) = (CB_res) * 37 + *(_CB_p)++; \ - } \ - (CB_res) &= INT_MAX; \ - } while(FALSE) - -/* get the second hash value */ -#define CB_SECONDHASH(CB_res, CB_kbuf, CB_ksiz) \ - do { \ - const unsigned char *_CB_p; \ - int _CB_ksiz; \ - _CB_p = (const unsigned char *)(CB_kbuf) + CB_ksiz - 1; \ - _CB_ksiz = CB_ksiz; \ - for((CB_res) = 0x13579bdf; _CB_ksiz--;){ \ - (CB_res) = (CB_res) * 31 + *(_CB_p)--; \ - } \ - (CB_res) &= INT_MAX; \ - } while(FALSE) - - -/* private function prototypes */ -static void cbggchandler(void); -static void cbggckeeper(void *ptr, void (*func)(void *)); -static void cbqsortsub(char *bp, int nmemb, int size, char *pswap, char *vswap, - int(*compar)(const void *, const void *)); -static int cblistelemcmp(const void *a, const void *b); -static int cbkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz); - - - -/************************************************************************************************* - * public objects - *************************************************************************************************/ - - -/* Call back function for handling a fatal error. */ -void (*cbfatalfunc)(const char *message) = NULL; - - -/* Allocate a region on memory. */ -void *cbmalloc(size_t size){ - char *p; - assert(size > 0 && size < INT_MAX); - if(!(p = malloc(size))) cbmyfatal("out of memory"); - return p; -} - - -/* Re-allocate a region on memory. */ -void *cbrealloc(void *ptr, size_t size){ - char *p; - assert(size > 0); - if(!(p = realloc(ptr, size))) cbmyfatal("out of memory"); - return p; -} - - -/* Duplicate a region on memory. */ -char *cbmemdup(const char *ptr, int size){ - char *p; - assert(ptr); - if(size < 0) size = strlen(ptr); - CB_MALLOC(p, size + 1); - memcpy(p, ptr, size); - p[size] = '\0'; - return p; -} - - -/* Free a region on memory. */ -void cbfree(void *ptr){ - free(ptr); -} - - -/* Register the pointer or handle of an object to the global garbage collector. */ -void cbglobalgc(void *ptr, void (*func)(void *)){ - assert(ptr && func); - cbggckeeper(ptr, func); -} - - -/* Exercise the global garbage collector explicitly. */ -void cbggcsweep(void){ - cbggckeeper(NULL, NULL); -} - - -/* Check availability of allocation of the virtual memory. */ -int cbvmemavail(size_t size){ - assert(size >= 0); - return _qdbm_vmemavail(size); -} - - -/* Sort an array using insert sort. */ -void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ - char *bp, *swap; - int i, j; - assert(base && nmemb >= 0 && size > 0 && compar); - bp = (char *)base; - CB_MALLOC(swap, size); - for(i = 1; i < nmemb; i++){ - if(compar(bp + (i - 1) * size, bp + i * size) > 0){ - memcpy(swap, bp + i * size, size); - for(j = i; j > 0; j--){ - if(compar(bp + (j - 1) * size, swap) < 0) break; - memcpy(bp + j * size, bp + (j - 1) * size, size); - } - memcpy(bp + j * size, swap, size); - } - } - free(swap); -} - - -/* Sort an array using shell sort. */ -void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ - char *bp, *swap; - int step, bottom, i, j; - assert(base && nmemb >= 0 && size > 0 && compar); - bp = (char *)base; - CB_MALLOC(swap, size); - for(step = (nmemb - 1) / 3; step >= 0; step = (step - 1) / 3){ - if(step < 5) step = 1; - for(bottom = 0; bottom < step; bottom++){ - for(i = bottom + step; i < nmemb; i += step){ - if(compar(bp + (i - step) * size, bp + i * size) > 0){ - memcpy(swap, bp + i * size, size); - for(j = i; j > step - 1; j -= step){ - if(compar(bp + (j - step) * size, swap) < 0) break; - memcpy(bp + j * size, bp + (j - step) * size, size); - } - memcpy(bp + j * size, swap, size); - } - } - } - if(step < 2) break; - } - free(swap); -} - - -/* Sort an array using heap sort. */ -void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ - char *bp, *swap; - int top, bottom, mybot, i; - assert(base && nmemb >= 0 && size > 0 && compar); - bp = (char *)base; - nmemb--; - bottom = nmemb / 2 + 1; - top = nmemb; - CB_MALLOC(swap, size); - while(bottom > 0){ - bottom--; - mybot = bottom; - i = 2 * mybot; - while(i <= top) { - if(i < top && compar(bp + (i + 1) * size, bp + i * size) > 0) i++; - if(compar(bp + mybot * size, bp + i * size) >= 0) break; - memcpy(swap, bp + mybot * size, size); - memcpy(bp + mybot * size, bp + i * size, size); - memcpy(bp + i * size, swap, size); - mybot = i; - i = 2 * mybot; - } - } - while(top > 0){ - memcpy(swap, bp, size); - memcpy(bp, bp + top * size, size); - memcpy(bp + top * size, swap, size); - top--; - mybot = bottom; - i = 2 * mybot; - while(i <= top){ - if(i < top && compar(bp + (i + 1) * size, bp + i * size) > 0) i++; - if(compar(bp + mybot * size, bp + i * size) >= 0) break; - memcpy(swap, bp + mybot * size, size); - memcpy(bp + mybot * size, bp + i * size, size); - memcpy(bp + i * size, swap, size); - mybot = i; - i = 2 * mybot; - } - } - free(swap); -} - - -/* Sort an array using quick sort. */ -void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ - char *pswap, *vswap; - assert(base && nmemb >= 0 && size > 0 && compar); - CB_MALLOC(pswap, size); - CB_MALLOC(vswap, size); - cbqsortsub(base, nmemb, size, pswap, vswap, compar); - free(vswap); - free(pswap); -} - - -/* Compare two strings with case insensitive evaluation. */ -int cbstricmp(const char *astr, const char *bstr){ - int ac, bc; - assert(astr && bstr); - while(*astr != '\0'){ - if(*bstr == '\0') return 1; - ac = (*astr >= 'A' && *astr <= 'Z') ? *astr + ('a' - 'A') : *(unsigned char *)astr; - bc = (*bstr >= 'A' && *bstr <= 'Z') ? *bstr + ('a' - 'A') : *(unsigned char *)bstr; - if(ac != bc) return ac - bc; - astr++; - bstr++; - } - return *bstr == '\0' ? 0 : -1; -} - - -/* Check whether a string begins with a key. */ -int cbstrfwmatch(const char *str, const char *key){ - assert(str && key); - while(*key != '\0'){ - if(*str != *key || *str == '\0') return FALSE; - key++; - str++; - } - return TRUE; -} - - -/* Check whether a string begins with a key, with case insensitive evaluation. */ -int cbstrfwimatch(const char *str, const char *key){ - int sc, kc; - assert(str && key); - while(*key != '\0'){ - if(*str == '\0') return FALSE; - sc = *str; - if(sc >= 'A' && sc <= 'Z') sc += 'a' - 'A'; - kc = *key; - if(kc >= 'A' && kc <= 'Z') kc += 'a' - 'A'; - if(sc != kc) return FALSE; - key++; - str++; - } - return TRUE; -} - - -/* Check whether a string ends with a key. */ -int cbstrbwmatch(const char *str, const char *key){ - int slen, klen, i; - assert(str && key); - slen = strlen(str); - klen = strlen(key); - for(i = 1; i <= klen; i++){ - if(i > slen || str[slen-i] != key[klen-i]) return FALSE; - } - return TRUE; -} - - -/* Check whether a string ends with a key, with case insensitive evaluation. */ -int cbstrbwimatch(const char *str, const char *key){ - int slen, klen, i, sc, kc; - assert(str && key); - slen = strlen(str); - klen = strlen(key); - for(i = 1; i <= klen; i++){ - if(i > slen) return FALSE; - sc = str[slen-i]; - if(sc >= 'A' && sc <= 'Z') sc += 'a' - 'A'; - kc = key[klen-i]; - if(kc >= 'A' && kc <= 'Z') kc += 'a' - 'A'; - if(sc != kc) return FALSE; - } - return TRUE; -} - - -/* Locate a substring in a string using KMP method. */ -char *cbstrstrkmp(const char *haystack, const char *needle){ - int i, j, hlen, nlen; - signed char tbl[0x100]; - assert(haystack && needle); - nlen = strlen(needle); - if(nlen >= 0x100) return strstr(haystack, needle); - tbl[0] = -1; - i = 0; - j = -1; - while(i < nlen){ - while((j >= 0) && (needle[i] != needle[j])){ - j = tbl[j]; - } - i++; - j++; - tbl[i] = j; - } - hlen = strlen(haystack); - i = 0; - j = 0; - while(i < hlen && j < nlen){ - while((j >= 0) && (haystack[i] != needle[j])){ - j = tbl[j]; - } - i++; - j++; - } - if(j == nlen) return (char *)(haystack + i - nlen); - return NULL; -} - - -/* Locate a substring in a string using BM method. */ -char *cbstrstrbm(const char *haystack, const char *needle){ - const unsigned char *rp; - const char *ep; - unsigned char tbl[0x100]; - int i, j, nlen, len, idx; - assert(haystack && needle); - nlen = strlen(needle); - if(nlen < 3 || nlen >= 0x100) return strstr(haystack, needle); - for(i = 0; i < 0x100; i++){ - tbl[i] = nlen; - } - len = nlen; - rp = (const unsigned char *)needle; - while(len > 0){ - tbl[*rp++] = --len; - } - nlen--; - ep = haystack + strlen(haystack) - nlen; - while(haystack < ep){ - for(i = nlen; haystack[i] == needle[i]; i--){ - if(i == 0) return (char *)haystack; - } - idx = ((unsigned char *)haystack)[i]; - j = tbl[idx] - nlen + i; - haystack += j > 0 ? j : 2; - } - return NULL; -} - - -/* Convert the letters of a string to upper case. */ -char *cbstrtoupper(char *str){ - int i; - assert(str); - for(i = 0; str[i] != '\0'; i++){ - if(str[i] >= 'a' && str[i] <= 'z') str[i] -= 'a' - 'A'; - } - return str; -} - - -/* Convert the letters of a string to lower case. */ -char *cbstrtolower(char *str){ - int i; - assert(str); - for(i = 0; str[i] != '\0'; i++){ - if(str[i] >= 'A' && str[i] <= 'Z') str[i] += 'a' - 'A'; - } - return str; -} - - -/* Cut space characters at head or tail of a string. */ -char *cbstrtrim(char *str){ - char *wp; - int i, head; - assert(str); - wp = str; - head = TRUE; - for(i = 0; str[i] != '\0'; i++){ - if((str[i] >= 0x07 && str[i] <= 0x0d) || str[i] == 0x20){ - if(!head) *(wp++) = str[i]; - } else { - *(wp++) = str[i]; - head = FALSE; - } - } - *wp = '\0'; - while(wp > str && ((wp[-1] >= 0x07 && wp[-1] <= 0x0d) || wp[-1] == 0x20)){ - *(--wp) = '\0'; - } - return str; -} - - -/* Squeeze space characters in a string and trim it. */ -char *cbstrsqzspc(char *str){ - char *wp; - int i, spc; - assert(str); - wp = str; - spc = TRUE; - for(i = 0; str[i] != '\0'; i++){ - if(str[i] > 0 && str[i] <= ' '){ - if(!spc) *(wp++) = str[i]; - spc = TRUE; - } else { - *(wp++) = str[i]; - spc = FALSE; - } - } - *wp = '\0'; - for(wp--; wp >= str; wp--){ - if(*wp > 0 && *wp <= ' '){ - *wp = '\0'; - } else { - break; - } - } - return str; -} - - -/* Count the number of characters in a string of UTF-8. */ -int cbstrcountutf(const char *str){ - const unsigned char *rp; - int cnt; - assert(str); - rp = (unsigned char *)str; - cnt = 0; - while(*rp != '\0'){ - if((*rp & 0x80) == 0x00 || (*rp & 0xe0) == 0xc0 || - (*rp & 0xf0) == 0xe0 || (*rp & 0xf8) == 0xf0) cnt++; - rp++; - } - return cnt; -} - - -/* Cut a string of UTF-8 at the specified number of characters. */ -char *cbstrcututf(char *str, int num){ - unsigned char *wp; - int cnt; - assert(str && num >= 0); - wp = (unsigned char *)str; - cnt = 0; - while(*wp != '\0'){ - if((*wp & 0x80) == 0x00 || (*wp & 0xe0) == 0xc0 || - (*wp & 0xf0) == 0xe0 || (*wp & 0xf8) == 0xf0){ - cnt++; - if(cnt > num){ - *wp = '\0'; - break; - } - } - wp++; - } - return str; -} - - -/* Get a datum handle. */ -CBDATUM *cbdatumopen(const char *ptr, int size){ - CBDATUM *datum; - CB_MALLOC(datum, sizeof(*datum)); - CB_MALLOC(datum->dptr, CB_DATUMUNIT); - datum->dptr[0] = '\0'; - datum->dsize = 0; - datum->asize = CB_DATUMUNIT; - if(ptr) CB_DATUMCAT(datum, ptr, (size >= 0 ? size : strlen(ptr))); - return datum; -} - - -/* Copy a datum. */ -CBDATUM *cbdatumdup(const CBDATUM *datum){ - assert(datum); - return cbdatumopen(datum->dptr, datum->dsize); -} - - -/* Free a datum handle. */ -void cbdatumclose(CBDATUM *datum){ - assert(datum); - free(datum->dptr); - free(datum); -} - - -/* Concatenate a datum and a region. */ -void cbdatumcat(CBDATUM *datum, const char *ptr, int size){ - assert(datum && ptr); - if(size < 0) size = strlen(ptr); - if(datum->dsize + size >= datum->asize){ - datum->asize = datum->asize * 2 + size + 1; - CB_REALLOC(datum->dptr, datum->asize); - } - memcpy(datum->dptr + datum->dsize, ptr, size); - datum->dsize += size; - datum->dptr[datum->dsize] = '\0'; -} - - -/* Get the pointer of the region of a datum. */ -const char *cbdatumptr(const CBDATUM *datum){ - assert(datum); - return datum->dptr; -} - - -/* Get the size of the region of a datum. */ -int cbdatumsize(const CBDATUM *datum){ - assert(datum); - return datum->dsize; -} - - -/* Set the size of the region of a datum. */ -void cbdatumsetsize(CBDATUM *datum, int size){ - assert(datum && size >= 0); - if(size <= datum->dsize){ - datum->dsize = size; - datum->dptr[size] = '\0'; - } else { - if(size >= datum->asize){ - datum->asize = datum->asize * 2 + size + 1; - CB_REALLOC(datum->dptr, datum->asize); - } - memset(datum->dptr + datum->dsize, 0, (size - datum->dsize) + 1); - datum->dsize = size; - } -} - - -/* Perform formatted output into a datum. */ -void cbdatumprintf(CBDATUM *datum, const char *format, ...){ - va_list ap; - char *tmp, cbuf[CB_NUMBUFSIZ], tbuf[CB_NUMBUFSIZ*2]; - unsigned char c; - int cblen, tlen; - assert(datum && format); - va_start(ap, format); - while(*format != '\0'){ - if(*format == '%'){ - cbuf[0] = '%'; - cblen = 1; - format++; - while(strchr("0123456789 .+-", *format) && *format != '\0' && cblen < CB_NUMBUFSIZ - 1){ - cbuf[cblen++] = *format; - format++; - } - cbuf[cblen++] = *format; - cbuf[cblen] = '\0'; - switch(*format){ - case 's': - tmp = va_arg(ap, char *); - if(!tmp) tmp = "(null)"; - cbdatumcat(datum, tmp, -1); - break; - case 'd': - tlen = sprintf(tbuf, cbuf, va_arg(ap, int)); - cbdatumcat(datum, tbuf, tlen); - break; - case 'o': case 'u': case 'x': case 'X': case 'c': - tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned int)); - cbdatumcat(datum, tbuf, tlen); - break; - case 'e': case 'E': case 'f': case 'g': case 'G': - tlen = sprintf(tbuf, cbuf, va_arg(ap, double)); - cbdatumcat(datum, tbuf, tlen); - break; - case '@': - tmp = va_arg(ap, char *); - if(!tmp) tmp = "(null)"; - while(*tmp){ - switch(*tmp){ - case '&': cbdatumcat(datum, "&", 5); break; - case '<': cbdatumcat(datum, "<", 4); break; - case '>': cbdatumcat(datum, ">", 4); break; - case '"': cbdatumcat(datum, """, 6); break; - default: - if(!((*tmp >= 0 && *tmp <= 0x8) || (*tmp >= 0x0e && *tmp <= 0x1f))) - cbdatumcat(datum, tmp, 1); - break; - } - tmp++; - } - break; - case '?': - tmp = va_arg(ap, char *); - if(!tmp) tmp = "(null)"; - while(*tmp){ - c = *(unsigned char *)tmp; - if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.", c))){ - cbdatumcat(datum, tmp, 1); - } else { - tlen = sprintf(tbuf, "%%%02X", c); - cbdatumcat(datum, tbuf, tlen); - } - tmp++; - } - break; - case ':': - tmp = va_arg(ap, char *); - if(!tmp) tmp = ""; - tmp = cbmimeencode(tmp, "UTF-8", TRUE); - cbdatumcat(datum, tmp, -1); - free(tmp); - break; - case '%': - cbdatumcat(datum, "%", 1); - break; - } - } else { - cbdatumcat(datum, format, 1); - } - format++; - } - va_end(ap); -} - - -/* Convert a datum to an allocated region. */ -char *cbdatumtomalloc(CBDATUM *datum, int *sp){ - char *ptr; - assert(datum); - ptr = datum->dptr; - if(sp) *sp = datum->dsize; - free(datum); - return ptr; -} - - -/* Get a list handle. */ -CBLIST *cblistopen(void){ - CBLIST *list; - CB_MALLOC(list, sizeof(*list)); - list->anum = CB_LISTUNIT; - CB_MALLOC(list->array, sizeof(list->array[0]) * list->anum); - list->start = 0; - list->num = 0; - return list; -} - - -/* Copy a list. */ -CBLIST *cblistdup(const CBLIST *list){ - CBLIST *newlist; - int i, size; - const char *val; - assert(list); - CB_LISTOPEN2(newlist, CB_LISTNUM(list)); - for(i = 0; i < CB_LISTNUM(list); i++){ - val = CB_LISTVAL2(list, i, size); - CB_LISTPUSH(newlist, val, size); - } - return newlist; -} - - -/* Close a list handle. */ -void cblistclose(CBLIST *list){ - int i, end; - assert(list); - end = list->start + list->num; - for(i = list->start; i < end; i++){ - free(list->array[i].dptr); - } - free(list->array); - free(list); -} - - -/* Get the number of elements of a list. */ -int cblistnum(const CBLIST *list){ - assert(list); - return list->num; -} - - -/* Get the pointer to the region of an element. */ -const char *cblistval(const CBLIST *list, int index, int *sp){ - assert(list && index >= 0); - if(index >= list->num) return NULL; - index += list->start; - if(sp) *sp = list->array[index].dsize; - return list->array[index].dptr; -} - - -/* Add an element at the end of a list. */ -void cblistpush(CBLIST *list, const char *ptr, int size){ - int index; - assert(list && ptr); - if(size < 0) size = strlen(ptr); - index = list->start + list->num; - if(index >= list->anum){ - list->anum *= 2; - CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); - } - CB_MALLOC(list->array[index].dptr, (size < CB_DATUMUNIT ? CB_DATUMUNIT : size) + 1); - memcpy(list->array[index].dptr, ptr, size); - list->array[index].dptr[size] = '\0'; - list->array[index].dsize = size; - list->num++; -} - - -/* Remove an element of the end of a list. */ -char *cblistpop(CBLIST *list, int *sp){ - int index; - assert(list); - if(list->num < 1) return NULL; - index = list->start + list->num - 1; - list->num--; - if(sp) *sp = list->array[index].dsize; - return list->array[index].dptr; -} - - -/* Add an element at the top of a list. */ -void cblistunshift(CBLIST *list, const char *ptr, int size){ - int index; - assert(list && ptr); - if(size < 0) size = strlen(ptr); - if(list->start < 1){ - if(list->start + list->num >= list->anum){ - list->anum *= 2; - CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); - } - list->start = list->anum - list->num; - memmove(list->array + list->start, list->array, list->num * sizeof(list->array[0])); - } - index = list->start - 1; - CB_MALLOC(list->array[index].dptr, (size < CB_DATUMUNIT ? CB_DATUMUNIT : size) + 1); - memcpy(list->array[index].dptr, ptr, size); - list->array[index].dptr[size] = '\0'; - list->array[index].dsize = size; - list->start--; - list->num++; -} - - -/* Remove an element of the top of a list. */ -char *cblistshift(CBLIST *list, int *sp){ - int index; - assert(list); - if(list->num < 1) return NULL; - index = list->start; - list->start++; - list->num--; - if(sp) *sp = list->array[index].dsize; - return list->array[index].dptr; -} - - -/* Add an element at the specified location of a list. */ -void cblistinsert(CBLIST *list, int index, const char *ptr, int size){ - assert(list && index >= 0); - if(index > list->num) return; - if(size < 0) size = strlen(ptr); - index += list->start; - if(list->start + list->num >= list->anum){ - list->anum *= 2; - CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); - } - memmove(list->array + index + 1, list->array + index, - sizeof(list->array[0]) * (list->start + list->num - index)); - CB_MEMDUP(list->array[index].dptr, ptr, size); - list->array[index].dsize = size; - list->num++; -} - - -/* Remove an element at the specified location of a list. */ -char *cblistremove(CBLIST *list, int index, int *sp){ - char *dptr; - assert(list && index >= 0); - if(index >= list->num) return NULL; - index += list->start; - dptr = list->array[index].dptr; - if(sp) *sp = list->array[index].dsize; - list->num--; - memmove(list->array + index, list->array + index + 1, - sizeof(list->array[0]) * (list->start + list->num - index)); - return dptr; -} - - -/* Overwrite an element at the specified location of a list. */ -void cblistover(CBLIST *list, int index, const char *ptr, int size){ - assert(list && index >= 0); - if(index >= list->num) return; - if(size < 0) size = strlen(ptr); - index += list->start; - if(size > list->array[index].dsize) - CB_REALLOC(list->array[index].dptr, size + 1); - memcpy(list->array[index].dptr, ptr, size); - list->array[index].dsize = size; - list->array[index].dptr[size] = '\0'; -} - - -/* Sort elements of a list in lexical order. */ -void cblistsort(CBLIST *list){ - assert(list); - qsort(list->array + list->start, list->num, sizeof(list->array[0]), cblistelemcmp); -} - - -/* Search a list for an element using liner search. */ -int cblistlsearch(const CBLIST *list, const char *ptr, int size){ - int i, end; - assert(list && ptr); - if(size < 0) size = strlen(ptr); - end = list->start + list->num; - for(i = list->start; i < end; i++){ - if(list->array[i].dsize == size && !memcmp(list->array[i].dptr, ptr, size)) - return i - list->start; - } - return -1; -} - - -/* Search a list for an element using binary search. */ -int cblistbsearch(const CBLIST *list, const char *ptr, int size){ - CBLISTDATUM key, *res; - assert(list && ptr); - if(size < 0) size = strlen(ptr); - CB_MEMDUP(key.dptr, ptr, size); - key.dsize = size; - res = bsearch(&key, list->array + list->start, list->num, sizeof(list->array[0]), cblistelemcmp); - free(key.dptr); - return res ? (res - list->array - list->start) : -1; -} - - -/* Serialize a list into a byte array. */ -char *cblistdump(const CBLIST *list, int *sp){ - char *buf, vnumbuf[CB_VNUMBUFSIZ]; - const char *vbuf; - int i, bsiz, vnumsiz, ln, vsiz; - assert(list && sp); - ln = CB_LISTNUM(list); - CB_SETVNUMBUF(vnumsiz, vnumbuf, ln); - CB_MALLOC(buf, vnumsiz + 1); - memcpy(buf, vnumbuf, vnumsiz); - bsiz = vnumsiz; - for(i = 0; i < ln; i++){ - vbuf = CB_LISTVAL2(list, i, vsiz); - CB_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); - CB_REALLOC(buf, bsiz + vnumsiz + vsiz + 1); - memcpy(buf + bsiz, vnumbuf, vnumsiz); - bsiz += vnumsiz; - memcpy(buf + bsiz, vbuf, vsiz); - bsiz += vsiz; - } - *sp = bsiz; - return buf; -} - - -/* Redintegrate a serialized list. */ -CBLIST *cblistload(const char *ptr, int size){ - CBLIST *list; - const char *rp; - int i, anum, step, ln, vsiz; - assert(ptr && size >= 0); - anum = size / (sizeof(CBLISTDATUM) + 1); - CB_LISTOPEN2(list, anum); - rp = ptr; - CB_READVNUMBUF(rp, size, ln, step); - rp += step; - size -= step; - if(ln > size) return list; - for(i = 0; i < ln; i++){ - if(size < 1) break; - CB_READVNUMBUF(rp, size, vsiz, step); - rp += step; - size -= step; - if(vsiz > size) break; - CB_LISTPUSH(list, rp, vsiz); - rp += vsiz; - } - return list; -} - - -/* Get a map handle. */ -CBMAP *cbmapopen(void){ - return cbmapopenex(CB_MAPBNUM); -} - - -/* Copy a map. */ -CBMAP *cbmapdup(CBMAP *map){ - CBMAP *newmap; - const char *kbuf, *vbuf; - int ksiz, vsiz; - assert(map); - cbmapiterinit(map); - newmap = map->rnum > CB_MAPPBNUM ? cbmapopen() : cbmapopenex(CB_MAPPBNUM); - while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ - CB_MAPITERVAL(vbuf, kbuf, vsiz); - cbmapput(newmap, kbuf, ksiz, vbuf, vsiz, FALSE); - } - cbmapiterinit(map); - return newmap; -} - - -/* Close a map handle. */ -void cbmapclose(CBMAP *map){ - CBMAPDATUM *datum, *next; - datum = map->first; - while(datum){ - next = datum->next; - free(datum); - datum = next; - } - free(map->buckets); - free(map); -} - - -/* Store a record. */ -int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over){ - CBMAPDATUM *datum, **entp, *old; - char *dbuf; - int bidx, hash, kcmp, psiz; - assert(map && kbuf && vbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if(vsiz < 0) vsiz = strlen(vbuf); - CB_FIRSTHASH(hash, kbuf, ksiz); - bidx = hash % map->bnum; - datum = map->buckets[bidx]; - entp = map->buckets + bidx; - CB_SECONDHASH(hash, kbuf, ksiz); - while(datum){ - if(hash > datum->hash){ - entp = &(datum->left); - datum = datum->left; - } else if(hash < datum->hash){ - entp = &(datum->right); - datum = datum->right; - } else { - dbuf = (char *)datum + sizeof(*datum); - kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); - if(kcmp < 0){ - entp = &(datum->left); - datum = datum->left; - } else if(kcmp > 0){ - entp = &(datum->right); - datum = datum->right; - } else { - if(!over) return FALSE; - psiz = CB_ALIGNPAD(ksiz); - if(vsiz > datum->vsiz){ - old = datum; - CB_REALLOC(datum, sizeof(*datum) + ksiz + psiz + vsiz + 1); - if(datum != old){ - if(map->first == old) map->first = datum; - if(map->last == old) map->last = datum; - if(*entp == old) *entp = datum; - if(datum->prev) datum->prev->next = datum; - if(datum->next) datum->next->prev = datum; - dbuf = (char *)datum + sizeof(*datum); - } - } - memcpy(dbuf + ksiz + psiz, vbuf, vsiz); - dbuf[ksiz+psiz+vsiz] = '\0'; - datum->vsiz = vsiz; - return TRUE; - } - } - } - psiz = CB_ALIGNPAD(ksiz); - CB_MALLOC(datum, sizeof(*datum) + ksiz + psiz + vsiz + 1); - dbuf = (char *)datum + sizeof(*datum); - memcpy(dbuf, kbuf, ksiz); - dbuf[ksiz] = '\0'; - datum->ksiz = ksiz; - memcpy(dbuf + ksiz + psiz, vbuf, vsiz); - dbuf[ksiz+psiz+vsiz] = '\0'; - datum->vsiz = vsiz; - datum->hash = hash; - datum->left = NULL; - datum->right = NULL; - datum->prev = map->last; - datum->next = NULL; - *entp = datum; - if(!map->first) map->first = datum; - if(map->last) map->last->next = datum; - map->last = datum; - map->rnum++; - return TRUE; -} - - -/* Concatenate a value at the end of the value of the existing record. */ -void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz){ - CBMAPDATUM *datum, **entp, *old; - char *dbuf; - int bidx, hash, kcmp, psiz, asiz, unit; - assert(map && kbuf && vbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if(vsiz < 0) vsiz = strlen(vbuf); - CB_FIRSTHASH(hash, kbuf, ksiz); - bidx = hash % map->bnum; - datum = map->buckets[bidx]; - entp = map->buckets + bidx; - CB_SECONDHASH(hash, kbuf, ksiz); - while(datum){ - if(hash > datum->hash){ - entp = &(datum->left); - datum = datum->left; - } else if(hash < datum->hash){ - entp = &(datum->right); - datum = datum->right; - } else { - dbuf = (char *)datum + sizeof(*datum); - kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); - if(kcmp < 0){ - entp = &(datum->left); - datum = datum->left; - } else if(kcmp > 0){ - entp = &(datum->right); - datum = datum->right; - } else { - psiz = CB_ALIGNPAD(ksiz); - asiz = sizeof(*datum) + ksiz + psiz + datum->vsiz + vsiz + 1; - unit = asiz <= CB_MAPCSUNIT ? CB_MAPCSUNIT : CB_MAPCBUNIT; - asiz = (asiz - 1) + unit - (asiz - 1) % unit; - old = datum; - CB_REALLOC(datum, asiz); - if(datum != old){ - if(map->first == old) map->first = datum; - if(map->last == old) map->last = datum; - if(*entp == old) *entp = datum; - if(datum->prev) datum->prev->next = datum; - if(datum->next) datum->next->prev = datum; - dbuf = (char *)datum + sizeof(*datum); - } - memcpy(dbuf + ksiz + psiz + datum->vsiz, vbuf, vsiz); - dbuf[ksiz+psiz+datum->vsiz+vsiz] = '\0'; - datum->vsiz += vsiz; - return; - } - } - } - psiz = CB_ALIGNPAD(ksiz); - asiz = sizeof(*datum) + ksiz + psiz + vsiz + 1; - unit = asiz <= CB_MAPCSUNIT ? CB_MAPCSUNIT : CB_MAPCBUNIT; - asiz = (asiz - 1) + unit - (asiz - 1) % unit; - CB_MALLOC(datum, asiz); - dbuf = (char *)datum + sizeof(*datum); - memcpy(dbuf, kbuf, ksiz); - dbuf[ksiz] = '\0'; - datum->ksiz = ksiz; - memcpy(dbuf + ksiz + psiz, vbuf, vsiz); - dbuf[ksiz+psiz+vsiz] = '\0'; - datum->vsiz = vsiz; - datum->hash = hash; - datum->left = NULL; - datum->right = NULL; - datum->prev = map->last; - datum->next = NULL; - *entp = datum; - if(!map->first) map->first = datum; - if(map->last) map->last->next = datum; - map->last = datum; - map->rnum++; -} - - -/* Delete a record. */ -int cbmapout(CBMAP *map, const char *kbuf, int ksiz){ - CBMAPDATUM *datum, **entp, *tmp; - char *dbuf; - int bidx, hash, kcmp; - assert(map && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - CB_FIRSTHASH(hash, kbuf, ksiz); - bidx = hash % map->bnum; - datum = map->buckets[bidx]; - entp = map->buckets + bidx; - CB_SECONDHASH(hash, kbuf, ksiz); - while(datum){ - if(hash > datum->hash){ - entp = &(datum->left); - datum = datum->left; - } else if(hash < datum->hash){ - entp = &(datum->right); - datum = datum->right; - } else { - dbuf = (char *)datum + sizeof(*datum); - kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); - if(kcmp < 0){ - entp = &(datum->left); - datum = datum->left; - } else if(kcmp > 0){ - entp = &(datum->right); - datum = datum->right; - } else { - if(datum->prev) datum->prev->next = datum->next; - if(datum->next) datum->next->prev = datum->prev; - if(datum == map->first) map->first = datum->next; - if(datum == map->last) map->last = datum->prev; - if(datum->left && !datum->right){ - *entp = datum->left; - } else if(!datum->left && datum->right){ - *entp = datum->right; - } else if(!datum->left && !datum->left){ - *entp = NULL; - } else { - *entp = datum->left; - tmp = *entp; - while(TRUE){ - if(hash > tmp->hash){ - if(tmp->left){ - tmp = tmp->left; - } else { - tmp->left = datum->right; - break; - } - } else if(hash < tmp->hash){ - if(tmp->right){ - tmp = tmp->right; - } else { - tmp->right = datum->right; - break; - } - } else { - kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); - if(kcmp < 0){ - if(tmp->left){ - tmp = tmp->left; - } else { - tmp->left = datum->right; - break; - } - } else { - if(tmp->right){ - tmp = tmp->right; - } else { - tmp->right = datum->right; - break; - } - } - } - } - } - free(datum); - map->rnum--; - return TRUE; - } - } - } - return FALSE; -} - - -/* Retrieve a record. */ -const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp){ - CBMAPDATUM *datum; - char *dbuf; - int hash, kcmp; - assert(map && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - CB_FIRSTHASH(hash, kbuf, ksiz); - datum = map->buckets[hash%map->bnum]; - CB_SECONDHASH(hash, kbuf, ksiz); - while(datum){ - if(hash > datum->hash){ - datum = datum->left; - } else if(hash < datum->hash){ - datum = datum->right; - } else { - dbuf = (char *)datum + sizeof(*datum); - kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); - if(kcmp < 0){ - datum = datum->left; - } else if(kcmp > 0){ - datum = datum->right; - } else { - if(sp) *sp = datum->vsiz; - return dbuf + datum->ksiz + CB_ALIGNPAD(datum->ksiz); - } - } - } - return NULL; -} - - -/* Move a record to the edge. */ -int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head){ - CBMAPDATUM *datum; - char *dbuf; - int hash, kcmp; - assert(map && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - CB_FIRSTHASH(hash, kbuf, ksiz); - datum = map->buckets[hash%map->bnum]; - CB_SECONDHASH(hash, kbuf, ksiz); - while(datum){ - if(hash > datum->hash){ - datum = datum->left; - } else if(hash < datum->hash){ - datum = datum->right; - } else { - dbuf = (char *)datum + sizeof(*datum); - kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); - if(kcmp < 0){ - datum = datum->left; - } else if(kcmp > 0){ - datum = datum->right; - } else { - if(head){ - if(map->first == datum) return TRUE; - if(map->last == datum) map->last = datum->prev; - if(datum->prev) datum->prev->next = datum->next; - if(datum->next) datum->next->prev = datum->prev; - datum->prev = NULL; - datum->next = map->first; - map->first->prev = datum; - map->first = datum; - } else { - if(map->last == datum) return TRUE; - if(map->first == datum) map->first = datum->next; - if(datum->prev) datum->prev->next = datum->next; - if(datum->next) datum->next->prev = datum->prev; - datum->prev = map->last; - datum->next = NULL; - map->last->next = datum; - map->last = datum; - } - return TRUE; - } - } - } - return FALSE; -} - - -/* Initialize the iterator of a map handle. */ -void cbmapiterinit(CBMAP *map){ - assert(map); - map->cur = map->first; -} - - -/* Get the next key of the iterator. */ -const char *cbmapiternext(CBMAP *map, int *sp){ - CBMAPDATUM *datum; - assert(map); - if(!map->cur) return NULL; - datum = map->cur; - map->cur = datum->next; - if(sp) *sp = datum->ksiz; - return (char *)datum + sizeof(*datum); -} - - -/* Get the value binded to the key fetched from the iterator. */ -const char *cbmapiterval(const char *kbuf, int *sp){ - CBMAPDATUM *datum; - assert(kbuf); - datum = (CBMAPDATUM *)(kbuf - sizeof(*datum)); - if(sp) *sp = datum->vsiz; - return (char *)datum + sizeof(*datum) + datum->ksiz + CB_ALIGNPAD(datum->ksiz); -} - - -/* Get the number of the records stored in a map. */ -int cbmaprnum(const CBMAP *map){ - assert(map); - return map->rnum; -} - - -/* Get the list handle contains all keys in a map. */ -CBLIST *cbmapkeys(CBMAP *map){ - CBLIST *list; - const char *kbuf; - int anum, ksiz; - assert(map); - anum = cbmaprnum(map); - CB_LISTOPEN2(list, anum); - cbmapiterinit(map); - while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ - CB_LISTPUSH(list, kbuf, ksiz); - } - return list; -} - - -/* Get the list handle contains all values in a map. */ -CBLIST *cbmapvals(CBMAP *map){ - CBLIST *list; - const char *kbuf, *vbuf; - int anum, ksiz, vsiz; - assert(map); - anum = cbmaprnum(map); - CB_LISTOPEN2(list, anum); - cbmapiterinit(map); - while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ - CB_MAPITERVAL(vbuf, kbuf, vsiz); - CB_LISTPUSH(list, vbuf, vsiz); - } - return list; -} - - -/* Serialize a map into a byte array. */ -char *cbmapdump(CBMAP *map, int *sp){ - char *buf, vnumbuf[CB_VNUMBUFSIZ]; - const char *kbuf, *vbuf; - int bsiz, vnumsiz, rn, ksiz, vsiz; - assert(map && sp); - rn = cbmaprnum(map); - CB_SETVNUMBUF(vnumsiz, vnumbuf, rn); - CB_MALLOC(buf, vnumsiz + 1); - memcpy(buf, vnumbuf, vnumsiz); - bsiz = vnumsiz; - cbmapiterinit(map); - while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ - CB_MAPITERVAL(vbuf, kbuf, vsiz); - CB_SETVNUMBUF(vnumsiz, vnumbuf, ksiz); - CB_REALLOC(buf, bsiz + vnumsiz + ksiz + 1); - memcpy(buf + bsiz, vnumbuf, vnumsiz); - bsiz += vnumsiz; - memcpy(buf + bsiz, kbuf, ksiz); - bsiz += ksiz; - CB_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); - CB_REALLOC(buf, bsiz + vnumsiz + vsiz + 1); - memcpy(buf + bsiz, vnumbuf, vnumsiz); - bsiz += vnumsiz; - memcpy(buf + bsiz, vbuf, vsiz); - bsiz += vsiz; - } - *sp = bsiz; - return buf; -} - - -/* Redintegrate a serialized map. */ -CBMAP *cbmapload(const char *ptr, int size){ - CBMAP *map; - const char *rp, *kbuf, *vbuf; - int i, step, rn, ksiz, vsiz; - assert(ptr && size >= 0); - map = cbmapopenex(CB_MAPPBNUM); - rp = ptr; - CB_READVNUMBUF(rp, size, rn, step); - rp += step; - size -= step; - if(rn > size) return map; - for(i = 0; i < rn; i++){ - if(size < 1) break; - CB_READVNUMBUF(rp, size, ksiz, step); - rp += step; - size -= step; - if(ksiz > size) break; - kbuf = rp; - rp += ksiz; - if(size < 1) break; - CB_READVNUMBUF(rp, size, vsiz, step); - rp += step; - size -= step; - if(vsiz > size) break; - vbuf = rp; - rp += vsiz; - cbmapput(map, kbuf, ksiz, vbuf, vsiz, TRUE); - } - return map; -} - - -/* Redintegrate a serialized map and get one of the records. */ -char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp){ - const char *rp, *tkbuf, *vbuf; - char *rv; - int i, step, rn, tksiz, vsiz; - assert(ptr && size >= 0 && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - rp = ptr; - CB_READVNUMBUF(rp, size, rn, step); - rp += step; - size -= step; - if(rn > size) return NULL; - for(i = 0; i < rn; i++){ - if(size < 1) break; - CB_READVNUMBUF(rp, size, tksiz, step); - rp += step; - size -= step; - if(tksiz > size) break; - tkbuf = rp; - rp += tksiz; - if(size < 1) break; - CB_READVNUMBUF(rp, size, vsiz, step); - rp += step; - size -= step; - if(vsiz > size) break; - vbuf = rp; - rp += vsiz; - if(tksiz == ksiz && !memcmp(tkbuf, kbuf, ksiz)){ - if(sp) *sp = vsiz; - CB_MEMDUP(rv, vbuf, vsiz); - return rv; - } - } - return NULL; -} - - -/* Get a heap handle. */ -CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *)){ - CBHEAP *heap; - assert(size > 0 && max >= 0 && compar); - CB_MALLOC(heap, sizeof(*heap)); - CB_MALLOC(heap->base, size * max + 1); - CB_MALLOC(heap->swap, size); - heap->size = size; - heap->num = 0; - heap->max = max; - heap->compar = compar; - return heap; -} - - -/* Copy a heap. */ -CBHEAP *cbheapdup(CBHEAP *heap){ - CBHEAP *newheap; - assert(heap); - CB_MALLOC(newheap, sizeof(*newheap)); - CB_MEMDUP(newheap->base, heap->base, heap->size * heap->max); - CB_MALLOC(newheap->swap, heap->size); - newheap->size = heap->size; - newheap->num = heap->num; - newheap->max = heap->max; - newheap->compar = heap->compar; - return newheap; -} - - -/* Close a heap handle. */ -void cbheapclose(CBHEAP *heap){ - assert(heap); - free(heap->swap); - free(heap->base); - free(heap); -} - - -/* Get the number of the records stored in a heap. */ -int cbheapnum(CBHEAP *heap){ - assert(heap); - return heap->num; -} - - -/* Insert a record into a heap. */ -int cbheapinsert(CBHEAP *heap, const void *ptr){ - char *base; - int size, pidx, cidx, bot; - assert(heap && ptr); - if(heap->max < 1) return FALSE; - base = heap->base; - size = heap->size; - if(heap->num >= heap->max){ - if(heap->compar(ptr, base) > 0) return FALSE; - memcpy(base, ptr, size); - pidx = 0; - bot = heap->num / 2; - while(pidx < bot){ - cidx = pidx * 2 + 1; - if(cidx < heap->num - 1 && heap->compar(base + cidx * size, base + (cidx + 1) * size) < 0) - cidx++; - if(heap->compar(base + pidx * size, base + cidx * size) > 0) break; - memcpy(heap->swap, base + pidx * size, size); - memcpy(base + pidx * size, base + cidx * size, size); - memcpy(base + cidx * size, heap->swap, size); - pidx = cidx; - } - } else { - memcpy(base + size * heap->num, ptr, size); - cidx = heap->num; - while(cidx > 0){ - pidx = (cidx - 1) / 2; - if(heap->compar(base + cidx * size, base + pidx * size) <= 0) break; - memcpy(heap->swap, base + cidx * size, size); - memcpy(base + cidx * size, base + pidx * size, size); - memcpy(base + pidx * size, heap->swap, size); - cidx = pidx; - } - heap->num++; - } - return TRUE; -} - - -/* Get the pointer to the region of a record in a heap. */ -const void *cbheapval(CBHEAP *heap, int index){ - assert(heap && index >= 0); - if(index >= heap->num) return NULL; - return heap->base + index * heap->size; -} - - -/* Convert a heap to an allocated region. */ -void *cbheaptomalloc(CBHEAP *heap, int *np){ - char *ptr; - assert(heap); - qsort(heap->base, heap->num, heap->size, heap->compar); - ptr = heap->base; - if(np) *np = heap->num; - free(heap->swap); - free(heap); - return ptr; -} - - -/* Allocate a formatted string on memory. */ -char *cbsprintf(const char *format, ...){ - va_list ap; - char *buf, cbuf[CB_SPBUFSIZ], *str; - int len, cblen, num, slen; - unsigned int unum; - double dnum; - va_start(ap, format); - assert(format); - CB_MALLOC(buf, 1); - len = 0; - while(*format != '\0'){ - if(*format == '%'){ - cbuf[0] = '%'; - cblen = 1; - format++; - while(strchr("0123456789 .+-", *format) && *format != '\0' && cblen < CB_SPBUFSIZ - 1){ - cbuf[cblen++] = *format; - format++; - } - cbuf[cblen] = '\0'; - if(atoi(cbuf + 1) > CB_SPMAXWIDTH - 16){ - sprintf(cbuf, "(err)"); - } else { - cbuf[cblen++] = *format; - cbuf[cblen] = '\0'; - } - switch(*format){ - case 'd': - num = va_arg(ap, int); - CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2); - len += sprintf(buf + len, cbuf, num); - break; - case 'o': case 'u': case 'x': case 'X': case 'c': - unum = va_arg(ap, unsigned int); - CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2); - len += sprintf(buf + len, cbuf, unum); - break; - case 'e': case 'E': case 'f': case 'g': case 'G': - dnum = va_arg(ap, double); - CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2); - len += sprintf(buf + len, cbuf, dnum); - break; - case 's': - str = va_arg(ap, char *); - slen = strlen(str); - CB_REALLOC(buf, len + slen + 2); - memcpy(buf + len, str, slen); - len += slen; - break; - case '%': - CB_REALLOC(buf, len + 2); - buf[len++] = '%'; - break; - default: - break; - } - } else { - CB_REALLOC(buf, len + 2); - buf[len++] = *format; - } - format++; - } - buf[len] = '\0'; - va_end(ap); - return buf; -} - - -/* Replace some patterns in a string. */ -char *cbreplace(const char *str, CBMAP *pairs){ - int i, bsiz, wi, rep, ksiz, vsiz; - char *buf; - const char *key, *val; - assert(str && pairs); - bsiz = CB_DATUMUNIT; - CB_MALLOC(buf, bsiz); - wi = 0; - while(*str != '\0'){ - rep = FALSE; - cbmapiterinit(pairs); - while((key = cbmapiternext(pairs, &ksiz)) != NULL){ - for(i = 0; i < ksiz; i++){ - if(str[i] == '\0' || str[i] != key[i]) break; - } - if(i == ksiz){ - CB_MAPITERVAL(val, key, vsiz); - if(wi + vsiz >= bsiz){ - bsiz = bsiz * 2 + vsiz; - CB_REALLOC(buf, bsiz); - } - memcpy(buf + wi, val, vsiz); - wi += vsiz; - str += ksiz; - rep = TRUE; - break; - } - } - if(!rep){ - if(wi + 1 >= bsiz){ - bsiz = bsiz * 2 + 1; - CB_REALLOC(buf, bsiz); - } - buf[wi++] = *str; - str++; - } - } - CB_REALLOC(buf, wi + 1); - buf[wi] = '\0'; - return buf; -} - - -/* Make a list by split a serial datum. */ -CBLIST *cbsplit(const char *ptr, int size, const char *delim){ - CBLIST *list; - int bi, step; - assert(ptr); - CB_LISTOPEN(list); - if(size < 0) size = strlen(ptr); - if(delim){ - for(bi = 0; bi < size; bi += step){ - step = 0; - while(bi + step < size && !strchr(delim, ptr[bi+step])){ - step++; - } - cblistpush(list, ptr + bi, step); - step++; - } - if(size > 0 && strchr(delim, ptr[size-1])) cblistpush(list, "", 0); - } else { - for(bi = 0; bi < size; bi += step){ - step = 0; - while(bi + step < size && ptr[bi+step]){ - step++; - } - cblistpush(list, ptr + bi, step); - step++; - } - if(size > 0 && ptr[size-1] == 0) cblistpush(list, "", 0); - } - return list; -} - - -/* Read whole data of a file. */ -char *cbreadfile(const char *name, int *sp){ - struct stat sbuf; - char iobuf[CB_IOBUFSIZ], *buf; - int fd, size, asiz, rv; - asiz = CB_IOBUFSIZ * 2; - if(name){ - if((fd = open(name, O_RDONLY, 0)) == -1) return NULL; - if(fstat(fd, &sbuf) != -1) asiz = sbuf.st_size + 1; - } else { - fd = 0; - } - CB_MALLOC(buf, asiz + 1); - size = 0; - while((rv = read(fd, iobuf, CB_IOBUFSIZ)) > 0){ - if(size + rv >= asiz){ - asiz = asiz * 2 + size; - CB_REALLOC(buf, asiz + 1); - } - memcpy(buf + size, iobuf, rv); - size += rv; - } - buf[size] = '\0'; - if(close(fd) == -1 || rv == -1){ - free(buf); - return NULL; - } - if(sp) *sp = size; - return buf; -} - - -/* Write data of a region into a file. */ -int cbwritefile(const char *name, const char *ptr, int size){ - int fd, err, wb; - assert(ptr); - if(size < 0) size = strlen(ptr); - if(name){ - if((fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, CB_FILEMODE)) == -1) return FALSE; - } else { - fd = 1; - } - err = FALSE; - wb = 0; - do { - wb = write(fd, ptr, size); - switch(wb){ - case -1: err = errno != EINTR ? TRUE : FALSE; break; - case 0: break; - default: - ptr += wb; - size -= wb; - break; - } - } while(size > 0); - if(close(fd) == -1) err = TRUE; - return err ? FALSE : TRUE; -} - - -/* Read every line of a file. */ -CBLIST *cbreadlines(const char *name){ - char *buf, *tmp; - int vsiz; - CBMAP *pairs; - CBLIST *list; - if(!(buf = cbreadfile(name, NULL))) return NULL; - pairs = cbmapopenex(3); - cbmapput(pairs, "\r\n", 2, "\n", 1, TRUE); - cbmapput(pairs, "\r", 1, "\n", 1, TRUE); - tmp = cbreplace(buf, pairs); - list = cbsplit(tmp, strlen(tmp), "\n"); - free(tmp); - cbmapclose(pairs); - free(buf); - if(CB_LISTNUM(list) > 0){ - cblistval(list, CB_LISTNUM(list) - 1, &vsiz); - if(vsiz < 1) CB_LISTDROP(list); - } - return list; -} - - -/* Read names of files in a directory. */ -CBLIST *cbdirlist(const char *name){ - DIR *DD; - struct dirent *dp; - CBLIST *list; - assert(name); - if(!(DD = opendir(name))) return NULL; - CB_LISTOPEN(list); - while((dp = readdir(DD)) != NULL){ - CB_LISTPUSH(list, dp->d_name, strlen(dp->d_name)); - } - if(closedir(DD) == -1){ - CB_LISTCLOSE(list); - return NULL; - } - return list; -} - - -/* Get the status of a file or a directory. */ -int cbfilestat(const char *name, int *isdirp, int *sizep, time_t *mtimep){ - struct stat sbuf; - assert(name); - if(lstat(name, &sbuf) == -1) return FALSE; - if(isdirp) *isdirp = S_ISDIR(sbuf.st_mode); - if(sizep) *sizep = (int)sbuf.st_size; - if(mtimep) *mtimep = sbuf.st_mtime; - return TRUE; -} - - -/* Remove a file or a directory and its sub ones recursively. */ -int cbremove(const char *name){ - CBLIST *list; - const char *elem; - char *path; - int i, err, tail; - struct stat sbuf; - assert(name); - if(lstat(name, &sbuf) == -1) return FALSE; - if(unlink(name) == 0) return TRUE; - if(!S_ISDIR(sbuf.st_mode) || !(list = cbdirlist(name))) return FALSE; - err = FALSE; - tail = name[0] != '\0' && name[strlen(name)-1] == MYPATHCHR; - for(i = 0; i < CB_LISTNUM(list); i++){ - elem = CB_LISTVAL(list, i); - if(!strcmp(MYCDIRSTR, elem) || !strcmp(MYPDIRSTR, elem)) continue; - if(tail){ - path = cbsprintf("%s%s", name, elem); - } else { - path = cbsprintf("%s%c%s", name, MYPATHCHR, elem); - } - if(!cbremove(path)) err = TRUE; - free(path); - } - CB_LISTCLOSE(list); - return rmdir(name) == 0 ? TRUE : FALSE; -} - - -/* Break up a URL into elements. */ -CBMAP *cburlbreak(const char *str){ - CBMAP *map; - char *tmp, *ep; - const char *rp; - int serv; - assert(str); - map = cbmapopenex(CB_MAPPBNUM); - CB_MEMDUP(tmp, str, strlen(str)); - rp = cbstrtrim(tmp); - cbmapput(map, "self", -1, rp, -1, TRUE); - serv = FALSE; - if(cbstrfwimatch(rp, "http://")){ - cbmapput(map, "scheme", -1, "http", -1, TRUE); - rp += 7; - serv = TRUE; - } else if(cbstrfwimatch(rp, "https://")){ - cbmapput(map, "scheme", -1, "https", -1, TRUE); - rp += 8; - serv = TRUE; - } else if(cbstrfwimatch(rp, "ftp://")){ - cbmapput(map, "scheme", -1, "ftp", -1, TRUE); - rp += 6; - serv = TRUE; - } else if(cbstrfwimatch(rp, "sftp://")){ - cbmapput(map, "scheme", -1, "sftp", -1, TRUE); - rp += 7; - serv = TRUE; - } else if(cbstrfwimatch(rp, "ftps://")){ - cbmapput(map, "scheme", -1, "ftps", -1, TRUE); - rp += 7; - serv = TRUE; - } else if(cbstrfwimatch(rp, "tftp://")){ - cbmapput(map, "scheme", -1, "tftp", -1, TRUE); - rp += 7; - serv = TRUE; - } else if(cbstrfwimatch(rp, "ldap://")){ - cbmapput(map, "scheme", -1, "ldap", -1, TRUE); - rp += 7; - serv = TRUE; - } else if(cbstrfwimatch(rp, "ldaps://")){ - cbmapput(map, "scheme", -1, "ldaps", -1, TRUE); - rp += 8; - serv = TRUE; - } else if(cbstrfwimatch(rp, "file://")){ - cbmapput(map, "scheme", -1, "file", -1, TRUE); - rp += 7; - serv = TRUE; - } - if((ep = strchr(rp, '#')) != NULL){ - cbmapput(map, "fragment", -1, ep + 1, -1, TRUE); - *ep = '\0'; - } - if((ep = strchr(rp, '?')) != NULL){ - cbmapput(map, "query", -1, ep + 1, -1, TRUE); - *ep = '\0'; - } - if(serv){ - if((ep = strchr(rp, '/')) != NULL){ - cbmapput(map, "path", -1, ep, -1, TRUE); - *ep = '\0'; - } else { - cbmapput(map, "path", -1, "/", -1, TRUE); - } - if((ep = strchr(rp, '@')) != NULL){ - *ep = '\0'; - if(rp[0] != '\0') cbmapput(map, "authority", -1, rp, -1, TRUE); - rp = ep + 1; - } - if((ep = strchr(rp, ':')) != NULL){ - if(ep[1] != '\0') cbmapput(map, "port", -1, ep + 1, -1, TRUE); - *ep = '\0'; - } - if(rp[0] != '\0') cbmapput(map, "host", -1, rp, -1, TRUE); - } else { - cbmapput(map, "path", -1, rp, -1, TRUE); - } - free(tmp); - if((rp = cbmapget(map, "path", -1, NULL)) != NULL){ - if((ep = strrchr(rp, '/')) != NULL){ - if(ep[1] != '\0') cbmapput(map, "file", -1, ep + 1, -1, TRUE); - } else { - cbmapput(map, "file", -1, rp, -1, TRUE); - } - } - if((rp = cbmapget(map, "file", -1, NULL)) != NULL && (!strcmp(rp, ".") || !strcmp(rp, ".."))) - cbmapout(map, "file", -1); - return map; -} - - -/* Resolve a relative URL with another absolute URL. */ -char *cburlresolve(const char *base, const char *target){ - CBMAP *telems, *belems; - CBLIST *bpaths, *opaths, *qelems; - CBDATUM *rbuf; - const char *vbuf, *path; - char *tmp, *wp, *enc, numbuf[CB_NUMBUFSIZ]; - int i, vsiz, port, num; - assert(base && target); - while(*base > '\0' && *base <= ' '){ - base++; - } - while(*target > '\0' && *target <= ' '){ - target++; - } - if(*target == '\0') target = base; - CB_DATUMOPEN(rbuf); - telems = cburlbreak(target); - port = 80; - belems = cburlbreak(cbmapget(telems, "scheme", -1, &vsiz) ? target : base); - if((vbuf = cbmapget(belems, "scheme", -1, &vsiz)) != NULL){ - CB_DATUMCAT(rbuf, vbuf, vsiz); - CB_DATUMCAT(rbuf, "://", 3); - if(!cbstricmp(vbuf, "https")){ - port = 443; - } else if(!cbstricmp(vbuf, "ftp")){ - port = 21; - } else if(!cbstricmp(vbuf, "sftp")){ - port = 115; - } else if(!cbstricmp(vbuf, "ftps")){ - port = 22; - } else if(!cbstricmp(vbuf, "tftp")){ - port = 69; - } else if(!cbstricmp(vbuf, "ldap")){ - port = 389; - } else if(!cbstricmp(vbuf, "ldaps")){ - port = 636; - } - } else { - CB_DATUMCAT(rbuf, "http://", 7); - } - if((vbuf = cbmapget(belems, "authority", -1, &vsiz)) != NULL){ - if((wp = strchr(vbuf, ':')) != NULL){ - *wp = '\0'; - tmp = cburldecode(vbuf, NULL); - enc = cburlencode(tmp, -1); - CB_DATUMCAT(rbuf, enc, strlen(enc)); - free(enc); - free(tmp); - CB_DATUMCAT(rbuf, ":", 1); - wp++; - tmp = cburldecode(wp, NULL); - enc = cburlencode(tmp, -1); - CB_DATUMCAT(rbuf, enc, strlen(enc)); - free(enc); - free(tmp); - } else { - tmp = cburldecode(vbuf, NULL); - enc = cburlencode(tmp, -1); - CB_DATUMCAT(rbuf, enc, strlen(enc)); - free(enc); - free(tmp); - } - CB_DATUMCAT(rbuf, "@", 1); - } - if((vbuf = cbmapget(belems, "host", -1, &vsiz)) != NULL){ - tmp = cburldecode(vbuf, NULL); - cbstrtolower(tmp); - enc = cburlencode(tmp, -1); - CB_DATUMCAT(rbuf, enc, strlen(enc)); - free(enc); - free(tmp); - } else { - CB_DATUMCAT(rbuf, "localhost", 9); - } - if((vbuf = cbmapget(belems, "port", -1, &vsiz)) != NULL && - (num = atoi(vbuf)) != port && num > 1){ - sprintf(numbuf, ":%d", num); - CB_DATUMCAT(rbuf, numbuf, strlen(numbuf)); - } - if(!(path = cbmapget(telems, "path", -1, NULL))) path = "/"; - if(path[0] == '\0' && (vbuf = cbmapget(belems, "path", -1, NULL)) != NULL) path = vbuf; - if(path[0] == '\0') path = "/"; - CB_LISTOPEN(bpaths); - if(path[0] != '/' && (vbuf = cbmapget(belems, "path", -1, &vsiz)) != NULL){ - opaths = cbsplit(vbuf, vsiz, "/"); - } else { - opaths = cbsplit("/", 1, "/"); - } - CB_LISTDROP(opaths); - for(i = 0; i < CB_LISTNUM(opaths); i++){ - vbuf = CB_LISTVAL2(opaths, i, vsiz); - if(vsiz < 1 || !strcmp(vbuf, ".")) continue; - if(!strcmp(vbuf, "..")){ - CB_LISTDROP(bpaths); - } else { - CB_LISTPUSH(bpaths, vbuf, vsiz); - } - } - CB_LISTCLOSE(opaths); - opaths = cbsplit(path, -1, "/"); - for(i = 0; i < CB_LISTNUM(opaths); i++){ - vbuf = CB_LISTVAL2(opaths, i, vsiz); - if(vsiz < 1 || !strcmp(vbuf, ".")) continue; - if(!strcmp(vbuf, "..")){ - CB_LISTDROP(bpaths); - } else { - CB_LISTPUSH(bpaths, vbuf, vsiz); - } - } - CB_LISTCLOSE(opaths); - for(i = 0; i < CB_LISTNUM(bpaths); i++){ - vbuf = CB_LISTVAL(bpaths, i); - if(strchr(vbuf, '%')){ - tmp = cburldecode(vbuf, NULL); - } else { - CB_MEMDUP(tmp, vbuf, strlen(vbuf)); - } - enc = cburlencode(tmp, -1); - CB_DATUMCAT(rbuf, "/", 1); - CB_DATUMCAT(rbuf, enc, strlen(enc)); - free(enc); - free(tmp); - } - if(cbstrbwmatch(path, "/")) CB_DATUMCAT(rbuf, "/", 1); - CB_LISTCLOSE(bpaths); - if((vbuf = cbmapget(telems, "query", -1, &vsiz)) != NULL){ - CB_DATUMCAT(rbuf, "?", 1); - qelems = cbsplit(vbuf, vsiz, "&;"); - for(i = 0; i < CB_LISTNUM(qelems); i++){ - vbuf = CB_LISTVAL(qelems, i); - if(i > 0) CB_DATUMCAT(rbuf, "&", 1); - if((wp = strchr(vbuf, '=')) != NULL){ - *wp = '\0'; - tmp = cburldecode(vbuf, NULL); - enc = cburlencode(tmp, -1); - CB_DATUMCAT(rbuf, enc, strlen(enc)); - free(enc); - free(tmp); - CB_DATUMCAT(rbuf, "=", 1); - wp++; - tmp = cburldecode(wp, NULL); - enc = cburlencode(tmp, -1); - CB_DATUMCAT(rbuf, enc, strlen(enc)); - free(enc); - free(tmp); - } else { - tmp = cburldecode(vbuf, NULL); - enc = cburlencode(tmp, -1); - CB_DATUMCAT(rbuf, enc, strlen(enc)); - free(enc); - free(tmp); - } - } - CB_LISTCLOSE(qelems); - } - if((vbuf = cbmapget(telems, "fragment", -1, &vsiz)) != NULL){ - tmp = cburldecode(vbuf, NULL); - enc = cburlencode(tmp, -1); - CB_DATUMCAT(rbuf, "#", 1); - CB_DATUMCAT(rbuf, enc, strlen(enc)); - free(enc); - free(tmp); - } - cbmapclose(belems); - cbmapclose(telems); - return cbdatumtomalloc(rbuf, NULL); -} - - -/* Encode a serial object with URL encoding. */ -char *cburlencode(const char *ptr, int size){ - char *buf, *wp; - int i, c; - assert(ptr); - if(size < 0) size = strlen(ptr); - CB_MALLOC(buf, size * 3 + 1); - wp = buf; - for(i = 0; i < size; i++){ - c = ((unsigned char *)ptr)[i]; - if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.!~*'()", c))){ - *(wp++) = c; - } else { - wp += sprintf(wp, "%%%02X", c); - } - } - *wp = '\0'; - return buf; -} - - -/* Decode a string encoded with URL encoding. */ -char *cburldecode(const char *str, int *sp){ - char *buf, *wp; - unsigned char c; - CB_MEMDUP(buf, str, strlen(str)); - wp = buf; - while(*str != '\0'){ - if(*str == '%'){ - str++; - if(((str[0] >= '0' && str[0] <= '9') || (str[0] >= 'A' && str[0] <= 'F') || - (str[0] >= 'a' && str[0] <= 'f')) && - ((str[1] >= '0' && str[1] <= '9') || (str[1] >= 'A' && str[1] <= 'F') || - (str[1] >= 'a' && str[1] <= 'f'))){ - c = *str; - if(c >= 'A' && c <= 'Z') c += 'a' - 'A'; - if(c >= 'a' && c <= 'z'){ - *wp = c - 'a' + 10; - } else { - *wp = c - '0'; - } - *wp *= 0x10; - str++; - c = *str; - if(c >= 'A' && c <= 'Z') c += 'a' - 'A'; - if(c >= 'a' && c <= 'z'){ - *wp += c - 'a' + 10; - } else { - *wp += c - '0'; - } - str++; - wp++; - } else { - break; - } - } else if(*str == '+'){ - *wp = ' '; - str++; - wp++; - } else { - *wp = *str; - str++; - wp++; - } - } - *wp = '\0'; - if(sp) *sp = wp - buf; - return buf; -} - - -/* Encode a serial object with Base64 encoding. */ -char *cbbaseencode(const char *ptr, int size){ - char *tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - char *buf, *wp; - const unsigned char *obj; - int i; - assert(ptr); - if(size < 0) size = strlen(ptr); - CB_MALLOC(buf, 4 * (size + 2) / 3 + 1); - obj = (const unsigned char *)ptr; - wp = buf; - for(i = 0; i < size; i += 3){ - switch(size - i){ - case 1: - *wp++ = tbl[obj[0] >> 2]; - *wp++ = tbl[(obj[0] & 3) << 4]; - *wp++ = '='; - *wp++ = '='; - break; - case 2: - *wp++ = tbl[obj[0] >> 2]; - *wp++ = tbl[((obj[0] & 3) << 4) + (obj[1] >> 4)]; - *wp++ = tbl[(obj[1] & 0xf) << 2]; - *wp++ = '='; - break; - default: - *wp++ = tbl[obj[0] >> 2]; - *wp++ = tbl[((obj[0] & 3) << 4) + (obj[1] >> 4)]; - *wp++ = tbl[((obj[1] & 0xf) << 2) + (obj[2] >> 6)]; - *wp++ = tbl[obj[2] & 0x3f]; - break; - } - obj += 3; - } - *wp = '\0'; - return buf; -} - - -/* Decode a string encoded with Base64 encoding. */ -char *cbbasedecode(const char *str, int *sp){ - unsigned char *obj, *wp; - int len, cnt, bpos, i, bits, eqcnt; - assert(str); - cnt = 0; - bpos = 0; - eqcnt = 0; - len = strlen(str); - CB_MALLOC(obj, len + 4); - wp = obj; - while(bpos < len && eqcnt == 0){ - bits = 0; - for(i = 0; bpos < len && i < 4; bpos++){ - if(str[bpos] >= 'A' && str[bpos] <= 'Z'){ - bits = (bits << 6) | (str[bpos] - 'A'); - i++; - } else if(str[bpos] >= 'a' && str[bpos] <= 'z'){ - bits = (bits << 6) | (str[bpos] - 'a' + 26); - i++; - } else if(str[bpos] >= '0' && str[bpos] <= '9'){ - bits = (bits << 6) | (str[bpos] - '0' + 52); - i++; - } else if(str[bpos] == '+'){ - bits = (bits << 6) | 62; - i++; - } else if(str[bpos] == '/'){ - bits = (bits << 6) | 63; - i++; - } else if(str[bpos] == '='){ - bits <<= 6; - i++; - eqcnt++; - } - } - if(i == 0 && bpos >= len) continue; - switch(eqcnt){ - case 0: - *wp++ = (bits >> 16) & 0xff; - *wp++ = (bits >> 8) & 0xff; - *wp++ = bits & 0xff; - cnt += 3; - break; - case 1: - *wp++ = (bits >> 16) & 0xff; - *wp++ = (bits >> 8) & 0xff; - cnt += 2; - break; - case 2: - *wp++ = (bits >> 16) & 0xff; - cnt += 1; - break; - } - } - obj[cnt] = '\0'; - if(sp) *sp = cnt; - return (char *)obj; -} - - -/* Encode a serial object with quoted-printable encoding. */ -char *cbquoteencode(const char *ptr, int size){ - const unsigned char *rp; - char *buf, *wp; - int i, cols; - assert(ptr); - if(size < 0) size = strlen(ptr); - rp = (const unsigned char *)ptr; - CB_MALLOC(buf, size * 3 + 1); - wp = buf; - cols = 0; - for(i = 0; i < size; i++){ - if(rp[i] == '=' || (rp[i] < 0x20 && rp[i] != '\r' && rp[i] != '\n' && rp[i] != '\t') || - rp[i] > 0x7e){ - wp += sprintf(wp, "=%02X", rp[i]); - cols += 3; - } else { - *(wp++) = rp[i]; - cols++; - } - } - *wp = '\0'; - return buf; -} - - -/* Decode a string encoded with quoted-printable encoding. */ -char *cbquotedecode(const char *str, int *sp){ - char *buf, *wp; - assert(str); - CB_MALLOC(buf, strlen(str) + 1); - wp = buf; - for(; *str != '\0'; str++){ - if(*str == '='){ - str++; - if(*str == '\0'){ - break; - } else if(str[0] == '\r' && str[1] == '\n'){ - str++; - } else if(str[0] != '\n' && str[0] != '\r'){ - if(*str >= 'A' && *str <= 'Z'){ - *wp = (*str - 'A' + 10) * 16; - } else if(*str >= 'a' && *str <= 'z'){ - *wp = (*str - 'a' + 10) * 16; - } else { - *wp = (*str - '0') * 16; - } - str++; - if(*str == '\0') break; - if(*str >= 'A' && *str <= 'Z'){ - *wp += *str - 'A' + 10; - } else if(*str >= 'a' && *str <= 'z'){ - *wp += *str - 'a' + 10; - } else { - *wp += *str - '0'; - } - wp++; - } - } else { - *wp = *str; - wp++; - } - } - *wp = '\0'; - if(sp) *sp = wp - buf; - return buf; -} - - -/* Split a string of MIME into headers and the body. */ -char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp){ - CBLIST *list; - const char *head, *line, *pv, *ep; - char *hbuf, *name, *rv; - int i, j, wi, hlen; - assert(ptr); - if(size < 0) size = strlen(ptr); - head = NULL; - hlen = 0; - for(i = 0; i < size; i++){ - if(i < size - 4 && ptr[i] == '\r' && ptr[i+1] == '\n' && - ptr[i+2] == '\r' && ptr[i+3] == '\n'){ - head = ptr; - hlen = i; - ptr += i + 4; - size -= i + 4; - break; - } else if(i < size - 2 && ptr[i] == '\n' && ptr[i+1] == '\n'){ - head = ptr; - hlen = i; - ptr += i + 2; - size -= i + 2; - break; - } - } - if(head && attrs){ - CB_MALLOC(hbuf, hlen + 1); - wi = 0; - for(i = 0; i < hlen; i++){ - if(head[i] == '\r') continue; - if(i < hlen - 1 && head[i] == '\n' && (head[i+1] == ' ' || head[i+1] == '\t')){ - hbuf[wi++] = ' '; - i++; - } else { - hbuf[wi++] = head[i]; - } - } - list = cbsplit(hbuf, wi, "\n"); - for(i = 0; i < CB_LISTNUM(list); i++){ - line = CB_LISTVAL(list, i); - if((pv = strchr(line, ':')) != NULL){ - CB_MEMDUP(name, line, pv - line); - for(j = 0; name[j] != '\0'; j++){ - if(name[j] >= 'A' && name[j] <= 'Z') name[j] -= 'A' - 'a'; - } - pv++; - while(*pv == ' ' || *pv == '\t'){ - pv++; - } - cbmapput(attrs, name, -1, pv, -1, TRUE); - free(name); - } - - } - CB_LISTCLOSE(list); - free(hbuf); - if((pv = cbmapget(attrs, "content-type", -1, NULL)) != NULL){ - if((ep = strchr(pv, ';')) != NULL){ - cbmapput(attrs, "TYPE", -1, pv, ep - pv, TRUE); - do { - ep++; - while(ep[0] == ' '){ - ep++; - } - if(cbstrfwimatch(ep, "charset=")){ - ep += 8; - while(*ep > '\0' && *ep <= ' '){ - ep++; - } - if(ep[0] == '"') ep++; - pv = ep; - while(ep[0] != '\0' && ep[0] != ' ' && ep[0] != '"' && ep[0] != ';'){ - ep++; - } - cbmapput(attrs, "CHARSET", -1, pv, ep - pv, TRUE); - } else if(cbstrfwimatch(ep, "boundary=")){ - ep += 9; - while(*ep > '\0' && *ep <= ' '){ - ep++; - } - if(ep[0] == '"'){ - ep++; - pv = ep; - while(ep[0] != '\0' && ep[0] != '"'){ - ep++; - } - } else { - pv = ep; - while(ep[0] != '\0' && ep[0] != ' ' && ep[0] != '"' && ep[0] != ';'){ - ep++; - } - } - cbmapput(attrs, "BOUNDARY", -1, pv, ep - pv, TRUE); - } - } while((ep = strchr(ep, ';')) != NULL); - } else { - cbmapput(attrs, "TYPE", -1, pv, -1, TRUE); - } - } - if((pv = cbmapget(attrs, "content-disposition", -1, NULL)) != NULL){ - if((ep = strchr(pv, ';')) != NULL){ - cbmapput(attrs, "DISPOSITION", -1, pv, ep - pv, TRUE); - do { - ep++; - while(ep[0] == ' '){ - ep++; - } - if(cbstrfwimatch(ep, "filename=")){ - ep += 9; - if(ep[0] == '"') ep++; - pv = ep; - while(ep[0] != '\0' && ep[0] != '"'){ - ep++; - } - cbmapput(attrs, "FILENAME", -1, pv, ep - pv, TRUE); - } else if(cbstrfwimatch(ep, "name=")){ - ep += 5; - if(ep[0] == '"') ep++; - pv = ep; - while(ep[0] != '\0' && ep[0] != '"'){ - ep++; - } - cbmapput(attrs, "NAME", -1, pv, ep - pv, TRUE); - } - } while((ep = strchr(ep, ';')) != NULL); - } else { - cbmapput(attrs, "DISPOSITION", -1, pv, -1, TRUE); - } - } - } - if(sp) *sp = size; - CB_MEMDUP(rv, ptr, size); - return rv; -} - - -/* Split multipart data in MIME into its parts. */ -CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary){ - CBLIST *list; - const char *pv, *ep; - int i, blen; - assert(ptr && boundary); - if(size < 0) size = strlen(ptr); - CB_LISTOPEN(list); - if((blen = strlen(boundary)) < 1) return list; - pv = NULL; - for(i = 0; i < size; i++){ - if(ptr[i] == '-' && ptr[i+1] == '-' && i + 2 + blen < size && - cbstrfwmatch(ptr + i + 2, boundary) && strchr("\t\n\v\f\r ", ptr[i+2+blen])){ - pv = ptr + i + 2 + blen; - if(*pv == '\r') pv++; - if(*pv == '\n') pv++; - size -= pv - ptr; - ptr = pv; - break; - } - } - if(!pv) return list; - for(i = 0; i < size; i++){ - if(ptr[i] == '-' && ptr[i+1] == '-' && i + 2 + blen < size && - cbstrfwmatch(ptr + i + 2, boundary) && strchr("\t\n\v\f\r -", ptr[i+2+blen])){ - ep = ptr + i; - if(ep > ptr && ep[-1] == '\n') ep--; - if(ep > ptr && ep[-1] == '\r') ep--; - if(ep > pv) CB_LISTPUSH(list, pv, ep - pv); - pv = ptr + i + 2 + blen; - if(*pv == '\r') pv++; - if(*pv == '\n') pv++; - } - } - return list; -} - - -/* Encode a string with MIME encoding. */ -char *cbmimeencode(const char *str, const char *encname, int base){ - char *buf, *wp, *enc; - int len; - assert(str && encname); - len = strlen(str); - CB_MALLOC(buf, len * 3 + strlen(encname) + 16); - wp = buf; - wp += sprintf(wp, "=?%s?%c?", encname, base ? 'B' : 'Q'); - enc = base ? cbbaseencode(str, len) : cbquoteencode(str, len); - wp += sprintf(wp, "%s?=", enc); - free(enc); - return buf; -} - - -/* Decode a string encoded with MIME encoding. */ -char *cbmimedecode(const char *str, char *enp){ - char *buf, *wp, *tmp, *dec; - const char *pv, *ep; - int quoted; - assert(str); - if(enp) sprintf(enp, "US-ASCII"); - CB_MALLOC(buf, strlen(str) + 1); - wp = buf; - while(*str != '\0'){ - if(cbstrfwmatch(str, "=?")){ - str += 2; - pv = str; - if(!(ep = strchr(str, '?'))) continue; - if(enp && ep - pv < CB_ENCBUFSIZ){ - memcpy(enp, pv, ep - pv); - enp[ep-pv] = '\0'; - } - pv = ep + 1; - quoted = (*pv == 'Q' || *pv == 'q'); - if(*pv != '\0') pv++; - if(*pv != '\0') pv++; - if(!(ep = strchr(pv, '?'))) continue; - CB_MEMDUP(tmp, pv, ep - pv); - dec = quoted ? cbquotedecode(tmp, NULL) : cbbasedecode(tmp, NULL); - wp += sprintf(wp, "%s", dec); - free(dec); - free(tmp); - str = ep + 1; - if(*str != '\0') str++; - } else { - *(wp++) = *str; - str++; - } - } - *wp = '\0'; - return buf; -} - - -/* Split a string of CSV into rows. */ -CBLIST *cbcsvrows(const char *str){ - CBLIST *list; - const char *pv; - int quoted; - assert(str); - CB_LISTOPEN(list); - pv = str; - quoted = FALSE; - while(TRUE){ - if(*str == '"') quoted = !quoted; - if(!quoted && (*str == '\r' || *str == '\n')){ - CB_LISTPUSH(list, pv, str - pv); - if(str[0] == '\r' && str[1] == '\n') str++; - str++; - pv = str; - } else if(*str == '\0'){ - if(str > pv) CB_LISTPUSH(list, pv, str - pv); - break; - } else { - str++; - } - } - return list; -} - - -/* Split a string of a row of CSV into cells. */ -CBLIST *cbcsvcells(const char *str){ - CBLIST *list, *uelist; - const char *pv; - char *tmp; - int i, quoted; - assert(str); - CB_LISTOPEN(list); - pv = str; - quoted = FALSE; - while(TRUE){ - if(*str == '"') quoted = !quoted; - if(!quoted && *str == ','){ - CB_LISTPUSH(list, pv, str - pv); - str++; - pv = str; - } else if(*str == '\0'){ - CB_LISTPUSH(list, pv, str - pv); - break; - } else { - str++; - } - } - CB_LISTOPEN(uelist); - for(i = 0; i < CB_LISTNUM(list); i++){ - tmp = cbcsvunescape(CB_LISTVAL(list, i)); - CB_LISTPUSH(uelist, tmp, strlen(tmp)); - free(tmp); - } - CB_LISTCLOSE(list); - return uelist; -} - - -/* Escape a string with the meta characters of CSV. */ -char *cbcsvescape(const char *str){ - char *buf, *wp; - int i; - assert(str); - CB_MALLOC(buf, strlen(str) * 2 + 3); - wp = buf; - *(wp++) = '"'; - for(i = 0; str[i] != '\0'; i++){ - if(str[i] == '"') *(wp++) = '"'; - *(wp++) = str[i]; - } - *(wp++) = '"'; - *wp = '\0'; - return buf; -} - - -/* Unescape a string with the escaped meta characters of CSV. */ -char *cbcsvunescape(const char *str){ - char *buf, *wp; - int i, len; - assert(str); - len = strlen(str); - if(str[0] == '"'){ - str++; - len--; - if(str[len-1] == '"') len--; - } - CB_MALLOC(buf, len + 1); - wp = buf; - for(i = 0; i < len; i++){ - if(str[i] == '"'){ - if(str[i+1] == '"') *(wp++) = str[i++]; - } else { - *(wp++) = str[i]; - } - } - *wp = '\0'; - return buf; -} - - -/* Split a string of XML into tags and text sections. */ -CBLIST *cbxmlbreak(const char *str, int cr){ - CBLIST *list; - CBDATUM *datum; - int i, pv, tag; - char *ep; - assert(str); - CB_LISTOPEN(list); - i = 0; - pv = 0; - tag = FALSE; - while(TRUE){ - if(str[i] == '\0'){ - if(i > pv) CB_LISTPUSH(list, str + pv, i - pv); - break; - } else if(!tag && str[i] == '<'){ - if(str[i+1] == '!' && str[i+2] == '-' && str[i+3] == '-'){ - if(i > pv) CB_LISTPUSH(list, str + pv, i - pv); - if((ep = strstr(str + i, "-->")) != NULL){ - if(!cr) CB_LISTPUSH(list, str + i, ep - str - i + 3); - i = ep - str + 2; - pv = i + 1; - } - } else if(str[i+1] == '!' && str[i+2] == '[' && cbstrfwimatch(str + i, " pv) CB_LISTPUSH(list, str + pv, i - pv); - if((ep = strstr(str + i, "]]>")) != NULL){ - i += 9; - CB_DATUMOPEN(datum); - while(str + i < ep){ - if(str[i] == '&'){ - CB_DATUMCAT(datum, "&", 5); - } else if(str[i] == '<'){ - CB_DATUMCAT(datum, "<", 4); - } else if(str[i] == '>'){ - CB_DATUMCAT(datum, ">", 4); - } else { - CB_DATUMCAT(datum, str + i, 1); - } - i++; - } - if(CB_DATUMSIZE(datum) > 0) CB_LISTPUSH(list, CB_DATUMPTR(datum), CB_DATUMSIZE(datum)); - CB_DATUMCLOSE(datum); - i = ep - str + 2; - pv = i + 1; - } - } else { - if(i > pv) CB_LISTPUSH(list, str + pv, i - pv); - tag = TRUE; - pv = i; - } - } else if(tag && str[i] == '>'){ - if(i > pv) CB_LISTPUSH(list, str + pv, i - pv + 1); - tag = FALSE; - pv = i + 1; - } - i++; - } - return list; -} - - -/* Get the map of attributes of a XML tag. */ -CBMAP *cbxmlattrs(const char *str){ - CBMAP *map; - const unsigned char *rp, *key, *val; - char *copy, *raw; - int ksiz, vsiz; - assert(str); - map = cbmapopenex(CB_MAPPBNUM); - rp = (unsigned char *)str; - while(*rp == '<' || *rp == '/' || *rp == '?' || *rp == '!' || *rp == ' '){ - rp++; - } - key = rp; - while(*rp > 0x20 && *rp != '/' && *rp != '>'){ - rp++; - } - cbmapput(map, "", -1, (char *)key, rp - key, FALSE); - while(*rp != '\0'){ - while(*rp != '\0' && (*rp <= 0x20 || *rp == '/' || *rp == '?' || *rp == '>')){ - rp++; - } - key = rp; - while(*rp > 0x20 && *rp != '/' && *rp != '>' && *rp != '='){ - rp++; - } - ksiz = rp - key; - while(*rp != '\0' && (*rp == '=' || *rp <= 0x20)){ - rp++; - } - if(*rp == '"'){ - rp++; - val = rp; - while(*rp != '\0' && *rp != '"'){ - rp++; - } - vsiz = rp - val; - } else if(*rp == '\''){ - rp++; - val = rp; - while(*rp != '\0' && *rp != '\''){ - rp++; - } - vsiz = rp - val; - } else { - val = rp; - while(*rp > 0x20 && *rp != '"' && *rp != '\'' && *rp != '>'){ - rp++; - } - vsiz = rp - val; - } - if(*rp != '\0') rp++; - if(ksiz > 0){ - CB_MEMDUP(copy, (char *)val, vsiz); - raw = cbxmlunescape(copy); - cbmapput(map, (char *)key, ksiz, raw, -1, FALSE); - free(raw); - free(copy); - } - } - return map; -} - - -/* Escape a string with the meta characters of XML. */ -char *cbxmlescape(const char *str){ - CBDATUM *datum; - assert(str); - CB_DATUMOPEN(datum); - while(*str != '\0'){ - switch(*str){ - case '&': - CB_DATUMCAT(datum, "&", 5); - break; - case '<': - CB_DATUMCAT(datum, "<", 4); - break; - case '>': - CB_DATUMCAT(datum, ">", 4); - break; - case '"': - CB_DATUMCAT(datum, """, 6); - break; - case '\'': - CB_DATUMCAT(datum, "'", 6); - break; - default: - CB_DATUMCAT(datum, str, 1); - break; - } - str++; - } - return cbdatumtomalloc(datum, NULL); -} - - -/* Unescape a string with the entity references of XML. */ -char *cbxmlunescape(const char *str){ - CBDATUM *datum; - assert(str); - CB_DATUMOPEN(datum); - while(*str != '\0'){ - if(*str == '&'){ - if(cbstrfwmatch(str, "&")){ - CB_DATUMCAT(datum, "&", 1); - str += 5; - } else if(cbstrfwmatch(str, "<")){ - CB_DATUMCAT(datum, "<", 1); - str += 4; - } else if(cbstrfwmatch(str, ">")){ - CB_DATUMCAT(datum, ">", 1); - str += 4; - } else if(cbstrfwmatch(str, """)){ - CB_DATUMCAT(datum, "\"", 1); - str += 6; - } else if(cbstrfwmatch(str, "'")){ - CB_DATUMCAT(datum, "'", 1); - str += 6; - } else { - CB_DATUMCAT(datum, str, 1); - str++; - } - } else { - CB_DATUMCAT(datum, str, 1); - str++; - } - } - return cbdatumtomalloc(datum, NULL); -} - - -/* Compress a serial object with ZLIB. */ -char *cbdeflate(const char *ptr, int size, int *sp){ - assert(ptr && sp); - if(!_qdbm_deflate) return NULL; - return _qdbm_deflate(ptr, size, sp, _QDBM_ZMZLIB); -} - - -/* Decompress a serial object compressed with ZLIB. */ -char *cbinflate(const char *ptr, int size, int *sp){ - assert(ptr && size >= 0); - if(!_qdbm_inflate) return NULL; - return _qdbm_inflate(ptr, size, sp, _QDBM_ZMZLIB); -} - - -/* Compress a serial object with GZIP. */ -char *cbgzencode(const char *ptr, int size, int *sp){ - assert(ptr && sp); - if(!_qdbm_deflate) return NULL; - return _qdbm_deflate(ptr, size, sp, _QDBM_ZMGZIP); -} - - -/* Decompress a serial object compressed with GZIP. */ -char *cbgzdecode(const char *ptr, int size, int *sp){ - assert(ptr && size >= 0); - if(!_qdbm_inflate) return NULL; - return _qdbm_inflate(ptr, size, sp, _QDBM_ZMGZIP); -} - - -/* Get the CRC32 checksum of a serial object. */ -unsigned int cbgetcrc(const char *ptr, int size){ - assert(ptr); - if(!_qdbm_inflate) return 0; - return _qdbm_getcrc(ptr, size); -} - - -/* Compress a serial object with LZO. */ -char *cblzoencode(const char *ptr, int size, int *sp){ - assert(ptr && sp); - if(!_qdbm_lzoencode) return NULL; - return _qdbm_lzoencode(ptr, size, sp); -} - - -/* Decompress a serial object compressed with LZO. */ -char *cblzodecode(const char *ptr, int size, int *sp){ - assert(ptr && size >= 0); - if(!_qdbm_lzodecode) return NULL; - return _qdbm_lzodecode(ptr, size, sp); -} - - -/* Compress a serial object with BZIP2. */ -char *cbbzencode(const char *ptr, int size, int *sp){ - assert(ptr && sp); - if(!_qdbm_bzencode) return NULL; - return _qdbm_bzencode(ptr, size, sp); -} - - -/* Decompress a serial object compressed with BZIP2. */ -char *cbbzdecode(const char *ptr, int size, int *sp){ - assert(ptr && size >= 0); - if(!_qdbm_bzdecode) return NULL; - return _qdbm_bzdecode(ptr, size, sp); -} - - -/* Convert the character encoding of a string. */ -char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp){ - char *res; - assert(ptr && icode && ocode); - if(!_qdbm_iconv) return NULL; - if((res = _qdbm_iconv(ptr, size, icode, ocode, sp, mp)) != NULL) return res; - if(!cbstricmp(icode, ocode)){ - if(sp) *sp = size; - if(mp) *mp = 0; - CB_MEMDUP(res, ptr, size < 0 ? strlen(ptr) : size); - return res; - } - return NULL; -} - - -/* Detect the encoding of a string automatically. */ -const char *cbencname(const char *ptr, int size){ - assert(ptr); - if(!_qdbm_encname) return "ISO-8859-1"; - return _qdbm_encname(ptr, size); -} - - -/* Get the jet lag of the local time in seconds. */ -int cbjetlag(void){ - struct tm ts, *tp; - time_t t, gt, lt; - if((t = time(NULL)) < 0) return 0; - if(!(tp = _qdbm_gmtime(&t, &ts))) return 0; - if((gt = mktime(tp)) < 0) return 0; - if(!(tp = _qdbm_localtime(&t, &ts))) return 0; - if((lt = mktime(tp)) < 0) return 0; - return lt - gt; -} - - -/* Get the Gregorian calendar of a time. */ -void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, - int *hourp, int *minp, int *secp){ - struct tm ts, *tp; - if(t < 0) t = time(NULL); - t += jl; - if(!(tp = _qdbm_gmtime(&t, &ts))) return; - if(yearp) *yearp = tp->tm_year + 1900; - if(monp) *monp = tp->tm_mon + 1; - if(dayp) *dayp = tp->tm_mday; - if(hourp) *hourp = tp->tm_hour; - if(minp) *minp = tp->tm_min; - if(secp) *secp = tp->tm_sec; -} - - -/* Get the day of week of a date. */ -int cbdayofweek(int year, int mon, int day){ - if(mon < 3){ - year--; - mon += 12; - } - return (day + ((8 + (13 * mon)) / 5) + (year + (year / 4) - (year / 100) + (year / 400))) % 7; -} - - -/* Get the string for a date in W3CDTF. */ -char *cbdatestrwww(time_t t, int jl){ - char date[CB_DATEBUFSIZ], tzone[CB_DATEBUFSIZ], *rv; - int year, mon, day, hour, min, sec; - cbcalendar(t, jl, &year, &mon, &day, &hour, &min, &sec); - jl /= 60; - if(jl == 0){ - sprintf(tzone, "Z"); - } else if(jl < 0){ - jl *= -1; - sprintf(tzone, "-%02d:%02d", jl / 60, jl % 60); - } else { - sprintf(tzone, "+%02d:%02d", jl / 60, jl % 60); - } - sprintf(date, "%04d-%02d-%02dT%02d:%02d:%02d%s", year, mon, day, hour, min, sec, tzone); - CB_MEMDUP(rv, date, strlen(date)); - return rv; -} - - -/* Get the string for a date in RFC 1123 format. */ -char *cbdatestrhttp(time_t t, int jl){ - char date[CB_DATEBUFSIZ], *wp, *rv; - int year, mon, day, hour, min, sec; - cbcalendar(t, jl, &year, &mon, &day, &hour, &min, &sec); - jl /= 60; - wp = date; - switch(cbdayofweek(year, mon, day)){ - case 0: wp += sprintf(wp, "Sun, "); break; - case 1: wp += sprintf(wp, "Mon, "); break; - case 2: wp += sprintf(wp, "Tue, "); break; - case 3: wp += sprintf(wp, "Wed, "); break; - case 4: wp += sprintf(wp, "Thu, "); break; - case 5: wp += sprintf(wp, "Fri, "); break; - case 6: wp += sprintf(wp, "Sat, "); break; - } - wp += sprintf(wp, "%02d ", day); - switch(mon){ - case 1: wp += sprintf(wp, "Jan "); break; - case 2: wp += sprintf(wp, "Feb "); break; - case 3: wp += sprintf(wp, "Mar "); break; - case 4: wp += sprintf(wp, "Apr "); break; - case 5: wp += sprintf(wp, "May "); break; - case 6: wp += sprintf(wp, "Jun "); break; - case 7: wp += sprintf(wp, "Jul "); break; - case 8: wp += sprintf(wp, "Aug "); break; - case 9: wp += sprintf(wp, "Sep "); break; - case 10: wp += sprintf(wp, "Oct "); break; - case 11: wp += sprintf(wp, "Nov "); break; - case 12: wp += sprintf(wp, "Dec "); break; - } - wp += sprintf(wp, "%04d %02d:%02d:%02d ", year, hour, min, sec); - if(jl == 0){ - wp += sprintf(wp, "GMT"); - } else if(jl < 0){ - jl *= -1; - wp += sprintf(wp, "-%02d%02d", jl / 60, jl % 60); - } else { - wp += sprintf(wp, "+%02d%02d", jl / 60, jl % 60); - } - CB_MEMDUP(rv, date, strlen(date)); - return rv; -} - - -/* Get the time value of a date string in decimal, W3CDTF, or RFC 1123. */ -time_t cbstrmktime(const char *str){ - const char *crp; - char *pv, *rp; - int len, clen; - time_t t; - struct tm ts; - assert(str); - while(*str > '\0' && *str <= ' '){ - str++; - } - if(*str == '\0') return -1; - if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) return (time_t)strtol(str + 2, NULL, 16); - memset(&ts, 0, sizeof(struct tm)); - ts.tm_year = 70; - ts.tm_mon = 0; - ts.tm_mday = 1; - ts.tm_hour = 0; - ts.tm_min = 0; - ts.tm_sec = 0; - ts.tm_isdst = 0; - len = strlen(str); - t = (time_t)strtol(str, &pv, 10); - if(*(signed char *)pv >= '\0' && *pv <= ' '){ - while(*pv > '\0' && *pv <= ' '){ - pv++; - } - if(*pv == '\0') return t; - } - if((pv[0] == 's' || pv[0] == 'S') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') - return t; - if((pv[0] == 'm' || pv[0] == 'M') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') - return t * 60; - if((pv[0] == 'h' || pv[0] == 'H') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') - return t * 60 * 60; - if((pv[0] == 'd' || pv[0] == 'D') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') - return t * 60 * 60 * 24; - if(len > 4 && str[4] == '-'){ - ts.tm_year = atoi(str) - 1900; - if((pv = strchr(str, '-')) != NULL && pv - str == 4){ - rp = pv + 1; - ts.tm_mon = atoi(rp) - 1; - if((pv = strchr(rp, '-')) != NULL && pv - str == 7){ - rp = pv + 1; - ts.tm_mday = atoi(rp); - if((pv = strchr(rp, 'T')) != NULL && pv - str == 10){ - rp = pv + 1; - ts.tm_hour = atoi(rp); - if((pv = strchr(rp, ':')) != NULL && pv - str == 13){ - rp = pv + 1; - ts.tm_min = atoi(rp); - } - if((pv = strchr(rp, ':')) != NULL && pv - str == 16){ - rp = pv + 1; - ts.tm_sec = atoi(rp); - } - if((pv = strchr(rp, '.')) != NULL && pv - str >= 19) rp = pv + 1; - strtol(rp, &pv, 10); - if((*pv == '+' || *pv == '-') && strlen(pv) >= 6 && pv[3] == ':') - ts.tm_sec -= (atoi(pv + 1) * 3600 + atoi(pv + 4) * 60) * (pv[0] == '+' ? 1 : -1); - } - } - } - ts.tm_sec += cbjetlag(); - return mktime(&ts); - } - if(len > 4 && str[4] == '/'){ - ts.tm_year = atoi(str) - 1900; - if((pv = strchr(str, '/')) != NULL && pv - str == 4){ - rp = pv + 1; - ts.tm_mon = atoi(rp) - 1; - if((pv = strchr(rp, '/')) != NULL && pv - str == 7){ - rp = pv + 1; - ts.tm_mday = atoi(rp); - if((pv = strchr(rp, ' ')) != NULL && pv - str == 10){ - rp = pv + 1; - ts.tm_hour = atoi(rp); - if((pv = strchr(rp, ':')) != NULL && pv - str == 13){ - rp = pv + 1; - ts.tm_min = atoi(rp); - } - if((pv = strchr(rp, ':')) != NULL && pv - str == 16){ - rp = pv + 1; - ts.tm_sec = atoi(rp); - } - if((pv = strchr(rp, '.')) != NULL && pv - str >= 19) rp = pv + 1; - strtol(rp, &pv, 10); - if((*pv == '+' || *pv == '-') && strlen(pv) >= 6 && pv[3] == ':') - ts.tm_sec -= (atoi(pv + 1) * 3600 + atoi(pv + 4) * 60) * (pv[0] == '+' ? 1 : -1); - } - } - } - ts.tm_sec += cbjetlag(); - return mktime(&ts); - } - crp = str; - if(len >= 4 && str[3] == ',') crp = str + 4; - while(*crp == ' '){ - crp++; - } - ts.tm_mday = atoi(crp); - while((*crp >= '0' && *crp <= '9') || *crp == ' '){ - crp++; - } - if(cbstrfwimatch(crp, "Jan")){ - ts.tm_mon = 0; - } else if(cbstrfwimatch(crp, "Feb")){ - ts.tm_mon = 1; - } else if(cbstrfwimatch(crp, "Mar")){ - ts.tm_mon = 2; - } else if(cbstrfwimatch(crp, "Apr")){ - ts.tm_mon = 3; - } else if(cbstrfwimatch(crp, "May")){ - ts.tm_mon = 4; - } else if(cbstrfwimatch(crp, "Jun")){ - ts.tm_mon = 5; - } else if(cbstrfwimatch(crp, "Jul")){ - ts.tm_mon = 6; - } else if(cbstrfwimatch(crp, "Aug")){ - ts.tm_mon = 7; - } else if(cbstrfwimatch(crp, "Sep")){ - ts.tm_mon = 8; - } else if(cbstrfwimatch(crp, "Oct")){ - ts.tm_mon = 9; - } else if(cbstrfwimatch(crp, "Nov")){ - ts.tm_mon = 10; - } else if(cbstrfwimatch(crp, "Dec")){ - ts.tm_mon = 11; - } else { - ts.tm_mon = -1; - } - if(ts.tm_mon >= 0) crp += 3; - while(*crp == ' '){ - crp++; - } - ts.tm_year = atoi(crp); - if(ts.tm_year >= 1969) ts.tm_year -= 1900; - while(*crp >= '0' && *crp <= '9'){ - crp++; - } - while(*crp == ' '){ - crp++; - } - if(ts.tm_mday > 0 && ts.tm_mon >= 0 && ts.tm_year >= 0){ - clen = strlen(crp); - if(clen >= 8 && crp[2] == ':' && crp[5] == ':'){ - ts.tm_hour = atoi(crp + 0); - ts.tm_min = atoi(crp + 3); - ts.tm_sec = atoi(crp + 6); - if(clen >= 14 && crp[8] == ' ' && (crp[9] == '+' || crp[9] == '-')){ - ts.tm_sec -= ((crp[10] - '0') * 36000 + (crp[11] - '0') * 3600 + - (crp[12] - '0') * 600 + (crp[13] - '0') * 60) * (crp[9] == '+' ? 1 : -1); - } else if(clen > 9){ - if(!strcmp(crp + 9, "JST")){ - ts.tm_sec -= 9 * 3600; - } else if(!strcmp(crp + 9, "CCT")){ - ts.tm_sec -= 8 * 3600; - } else if(!strcmp(crp + 9, "KST")){ - ts.tm_sec -= 9 * 3600; - } else if(!strcmp(crp + 9, "EDT")){ - ts.tm_sec -= -4 * 3600; - } else if(!strcmp(crp + 9, "EST")){ - ts.tm_sec -= -5 * 3600; - } else if(!strcmp(crp + 9, "CDT")){ - ts.tm_sec -= -5 * 3600; - } else if(!strcmp(crp + 9, "CST")){ - ts.tm_sec -= -6 * 3600; - } else if(!strcmp(crp + 9, "MDT")){ - ts.tm_sec -= -6 * 3600; - } else if(!strcmp(crp + 9, "MST")){ - ts.tm_sec -= -7 * 3600; - } else if(!strcmp(crp + 9, "PDT")){ - ts.tm_sec -= -7 * 3600; - } else if(!strcmp(crp + 9, "PST")){ - ts.tm_sec -= -8 * 3600; - } else if(!strcmp(crp + 9, "HDT")){ - ts.tm_sec -= -9 * 3600; - } else if(!strcmp(crp + 9, "HST")){ - ts.tm_sec -= -10 * 3600; - } - } - } - ts.tm_sec += cbjetlag(); - return mktime(&ts); - } - return -1; -} - - -/* Get user and system processing times. */ -void cbproctime(double *usrp, double *sysp){ - struct tms buf; - times(&buf); - if(usrp) *usrp = (double)buf.tms_utime / sysconf(_SC_CLK_TCK); - if(sysp) *sysp = (double)buf.tms_stime / sysconf(_SC_CLK_TCK); -} - - -/* Ensure that the standard I/O is binary mode. */ -void cbstdiobin(void){ - if(setmode(0, O_BINARY) == -1 || setmode(1, O_BINARY) == -1 || setmode(2, O_BINARY) == -1) - cbmyfatal("setmode failed"); -} - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Show error message on the standard error output and exit. */ -void *cbmyfatal(const char *message){ - char buf[CB_MSGBUFSIZ]; - assert(message); - if(cbfatalfunc){ - cbfatalfunc(message); - } else { - sprintf(buf, "fatal error: %s\n", message); - write(2, buf, strlen(buf)); - } - exit(1); - return NULL; -} - - -/* Create a datum handle from an allocated region. */ -CBDATUM *cbdatumopenbuf(char *ptr, int size){ - CBDATUM *datum; - assert(ptr && size >= 0); - CB_REALLOC(ptr, size + 1); - CB_MALLOC(datum, sizeof(*datum)); - datum->dptr = ptr; - datum->dptr[size] = '\0'; - datum->dsize = size; - datum->asize = size; - return datum; -} - - -/* Set a buffer to a datum handle. */ -void cbdatumsetbuf(CBDATUM *datum, char *ptr, int size){ - assert(datum && ptr && size >= 0); - free(datum->dptr); - CB_REALLOC(ptr, size + 1); - datum->dptr = ptr; - datum->dptr[size] = '\0'; - datum->dsize = size; - datum->asize = size; -} - - -/* Add an allocated element at the end of a list. */ -void cblistpushbuf(CBLIST *list, char *ptr, int size){ - int index; - assert(list && ptr && size >= 0); - index = list->start + list->num; - if(index >= list->anum){ - list->anum *= 2; - CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); - } - list->array[index].dptr = ptr; - list->array[index].dsize = size; - list->num++; -} - - -/* Get a map handle with specifying the number of buckets. */ -CBMAP *cbmapopenex(int bnum){ - CBMAP *map; - int i; - assert(bnum > 0); - CB_MALLOC(map, sizeof(*map)); - CB_MALLOC(map->buckets, sizeof(map->buckets[0]) * bnum); - for(i = 0; i < bnum; i++){ - map->buckets[i] = NULL; - } - map->first = NULL; - map->last = NULL; - map->cur = NULL; - map->bnum = bnum; - map->rnum = 0; - return map; -} - - - -/************************************************************************************************* - * private objects - *************************************************************************************************/ - - -/* Handler to invoke the global garbage collector. */ -static void cbggchandler(void){ - cbggckeeper(NULL, NULL); -} - - -/* Manage resources of the global garbage collector. - `ptr' specifies the pointer to add to the collection. If it is `NULL', all resources are - released. - `func' specifies the pointer to the function to release the resources. */ -static void cbggckeeper(void *ptr, void (*func)(void *)){ - static void **parray = NULL; - static void (**farray)(void *) = NULL; - static int onum = 0; - static int asiz = CB_GCUNIT; - int i; - if(!ptr){ - if(!parray) return; - for(i = onum - 1; i >= 0; i--){ - farray[i](parray[i]); - } - free(parray); - free(farray); - parray = NULL; - farray = NULL; - onum = 0; - asiz = CB_GCUNIT; - return; - } - if(!parray){ - CB_MALLOC(parray, sizeof(void *) * asiz); - CB_MALLOC(farray, sizeof(void *) * asiz); - if(atexit(cbggchandler) != 0) cbmyfatal("gc failed"); - } - if(onum >= asiz){ - asiz *= 2; - CB_REALLOC(parray, sizeof(void *) * asiz); - CB_REALLOC(farray, sizeof(void *) * asiz); - } - parray[onum] = ptr; - farray[onum] = func; - onum++; -} - - -/* Utility function for quick sort. - `bp' specifies the pointer to the pointer to an array. - `nmemb' specifies the number of elements of the array. - `size' specifies the size of each element. - `pswap' specifies the pointer to the swap region for a pivot. - `vswap' specifies the pointer to the swap region for elements. - `compar' specifies the pointer to comparing function. */ -static void cbqsortsub(char *bp, int nmemb, int size, char *pswap, char *vswap, - int(*compar)(const void *, const void *)){ - int top, bottom; - assert(bp && nmemb >= 0 && size > 0 && pswap && vswap && compar); - if(nmemb < 10){ - if(nmemb > 1) cbisort(bp, nmemb, size, compar); - return; - } - top = 0; - bottom = nmemb - 1; - memcpy(pswap, bp + (nmemb / 2) * size, size); - while(top - 1 < bottom){ - if(compar(bp + top * size, pswap) < 0){ - top++; - } else if(compar(bp + bottom * size, pswap) > 0){ - bottom--; - } else { - if(top != bottom){ - memcpy(vswap, bp + top * size, size); - memcpy(bp + top * size, bp + bottom * size, size); - memcpy(bp + bottom * size, vswap, size); - } - top++; - bottom--; - } - } - cbqsortsub(bp, top, size, pswap, vswap, compar); - cbqsortsub(bp + (bottom + 1) * size, nmemb - bottom - 1, size, pswap, vswap, compar); -} - - -/* Compare two list elements. - `a' specifies the pointer to one element. - `b' specifies the pointer to the other element. - The return value is positive if a is big, negative if b is big, else, it is 0. */ -static int cblistelemcmp(const void *a, const void *b){ - int i, size; - CBLISTDATUM *ap, *bp; - char *ao, *bo; - assert(a && b); - ap = (CBLISTDATUM *)a; - bp = (CBLISTDATUM *)b; - ao = ap->dptr; - bo = bp->dptr; - size = ap->dsize < bp->dsize ? ap->dsize : bp->dsize; - for(i = 0; i < size; i++){ - if(ao[i] > bo[i]) return 1; - if(ao[i] < bo[i]) return -1; - } - return ap->dsize - bp->dsize; -} - - -/* Compare two keys. - `abuf' specifies the pointer to the region of the former. - `asiz' specifies the size of the region. - `bbuf' specifies the pointer to the region of the latter. - `bsiz' specifies the size of the region. - The return value is 0 if two equals, positive if the formar is big, else, negative. */ -static int cbkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz){ - assert(abuf && asiz >= 0 && bbuf && bsiz >= 0); - if(asiz > bsiz) return 1; - if(asiz < bsiz) return -1; - return memcmp(abuf, bbuf, asiz); -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/cabin.c (from rev 2716, box/trunk/qdbm/cabin.c) =================================================================== --- box/trunk/qdbm/cabin.c (rev 0) +++ box/trunk/qdbm/cabin.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,3529 @@ +/************************************************************************************************* + * Implementation of Cabin + * 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. + *************************************************************************************************/ + + +#define QDBM_INTERNAL 1 + +#include "cabin.h" +#include "myconf.h" + +#define CB_GCUNIT 64 /* allocation unit size of a buffer in gc */ +#define CB_SPBUFSIZ 32 /* size of a buffer for sprintf */ +#define CB_SPMAXWIDTH 128 /* max width of a column for sprintf */ +#define CB_MAPPBNUM 251 /* bucket size of a petit map handle */ +#define CB_MAPCSUNIT 52 /* small allocation unit size of map concatenation */ +#define CB_MAPCBUNIT 252 /* big allocation unit size of map concatenation */ +#define CB_MSGBUFSIZ 256 /* size of a buffer for log message */ +#define CB_IOBUFSIZ 8192 /* size of an I/O buffer */ +#define CB_FILEMODE 00644 /* permission of a creating file */ +#define CB_NUMBUFSIZ 32 /* size of a buffer for a number */ +#define CB_ENCBUFSIZ 32 /* size of a buffer for encoding name */ +#define CB_DATEBUFSIZ 64 /* size of a buffer for date expression */ +#define CB_VNUMBUFSIZ 8 /* size of a buffer for variable length number */ + +/* set a buffer for a variable length number */ +#define CB_SETVNUMBUF(CB_len, CB_buf, CB_num) \ + do { \ + int _CB_num; \ + _CB_num = (CB_num); \ + if(_CB_num == 0){ \ + ((signed char *)(CB_buf))[0] = 0; \ + (CB_len) = 1; \ + } else { \ + (CB_len) = 0; \ + while(_CB_num > 0){ \ + int _CB_rem = _CB_num & 0x7f; \ + _CB_num >>= 7; \ + if(_CB_num > 0){ \ + ((signed char *)(CB_buf))[(CB_len)] = -_CB_rem - 1; \ + } else { \ + ((signed char *)(CB_buf))[(CB_len)] = _CB_rem; \ + } \ + (CB_len)++; \ + } \ + } \ + } while(FALSE) + +/* read a variable length buffer */ +#define CB_READVNUMBUF(CB_buf, CB_size, CB_num, CB_step) \ + do { \ + int _CB_i, _CB_base; \ + CB_num = 0; \ + _CB_base = 1; \ + if((size) < 2){ \ + CB_num = ((signed char *)(CB_buf))[0]; \ + (CB_step) = 1; \ + } else { \ + for(_CB_i = 0; _CB_i < (size); _CB_i++){ \ + if(((signed char *)(CB_buf))[_CB_i] >= 0){ \ + CB_num += ((signed char *)(CB_buf))[_CB_i] * _CB_base; \ + break; \ + } \ + CB_num += _CB_base * (((signed char *)(CB_buf))[_CB_i] + 1) * -1; \ + _CB_base *= 128; \ + } \ + (CB_step) = _CB_i + 1; \ + } \ + } while(FALSE) + +/* get the first hash value */ +#define CB_FIRSTHASH(CB_res, CB_kbuf, CB_ksiz) \ + do { \ + const unsigned char *_CB_p; \ + int _CB_ksiz; \ + _CB_p = (const unsigned char *)(CB_kbuf); \ + _CB_ksiz = CB_ksiz; \ + for((CB_res) = 19780211; _CB_ksiz--;){ \ + (CB_res) = (CB_res) * 37 + *(_CB_p)++; \ + } \ + (CB_res) &= INT_MAX; \ + } while(FALSE) + +/* get the second hash value */ +#define CB_SECONDHASH(CB_res, CB_kbuf, CB_ksiz) \ + do { \ + const unsigned char *_CB_p; \ + int _CB_ksiz; \ + _CB_p = (const unsigned char *)(CB_kbuf) + CB_ksiz - 1; \ + _CB_ksiz = CB_ksiz; \ + for((CB_res) = 0x13579bdf; _CB_ksiz--;){ \ + (CB_res) = (CB_res) * 31 + *(_CB_p)--; \ + } \ + (CB_res) &= INT_MAX; \ + } while(FALSE) + + +/* private function prototypes */ +static void cbggchandler(void); +static void cbggckeeper(void *ptr, void (*func)(void *)); +static void cbqsortsub(char *bp, int nmemb, int size, char *pswap, char *vswap, + int(*compar)(const void *, const void *)); +static int cblistelemcmp(const void *a, const void *b); +static int cbkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz); + + + +/************************************************************************************************* + * public objects + *************************************************************************************************/ + + +/* Call back function for handling a fatal error. */ +void (*cbfatalfunc)(const char *message) = NULL; + + +/* Allocate a region on memory. */ +void *cbmalloc(size_t size){ + char *p; + assert(size > 0 && size < INT_MAX); + if(!(p = malloc(size))) cbmyfatal("out of memory"); + return p; +} + + +/* Re-allocate a region on memory. */ +void *cbrealloc(void *ptr, size_t size){ + char *p; + assert(size > 0); + if(!(p = realloc(ptr, size))) cbmyfatal("out of memory"); + return p; +} + + +/* Duplicate a region on memory. */ +char *cbmemdup(const char *ptr, int size){ + char *p; + assert(ptr); + if(size < 0) size = strlen(ptr); + CB_MALLOC(p, size + 1); + memcpy(p, ptr, size); + p[size] = '\0'; + return p; +} + + +/* Free a region on memory. */ +void cbfree(void *ptr){ + free(ptr); +} + + +/* Register the pointer or handle of an object to the global garbage collector. */ +void cbglobalgc(void *ptr, void (*func)(void *)){ + assert(ptr && func); + cbggckeeper(ptr, func); +} + + +/* Exercise the global garbage collector explicitly. */ +void cbggcsweep(void){ + cbggckeeper(NULL, NULL); +} + + +/* Check availability of allocation of the virtual memory. */ +int cbvmemavail(size_t size){ + assert(size >= 0); + return _qdbm_vmemavail(size); +} + + +/* Sort an array using insert sort. */ +void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ + char *bp, *swap; + int i, j; + assert(base && nmemb >= 0 && size > 0 && compar); + bp = (char *)base; + CB_MALLOC(swap, size); + for(i = 1; i < nmemb; i++){ + if(compar(bp + (i - 1) * size, bp + i * size) > 0){ + memcpy(swap, bp + i * size, size); + for(j = i; j > 0; j--){ + if(compar(bp + (j - 1) * size, swap) < 0) break; + memcpy(bp + j * size, bp + (j - 1) * size, size); + } + memcpy(bp + j * size, swap, size); + } + } + free(swap); +} + + +/* Sort an array using shell sort. */ +void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ + char *bp, *swap; + int step, bottom, i, j; + assert(base && nmemb >= 0 && size > 0 && compar); + bp = (char *)base; + CB_MALLOC(swap, size); + for(step = (nmemb - 1) / 3; step >= 0; step = (step - 1) / 3){ + if(step < 5) step = 1; + for(bottom = 0; bottom < step; bottom++){ + for(i = bottom + step; i < nmemb; i += step){ + if(compar(bp + (i - step) * size, bp + i * size) > 0){ + memcpy(swap, bp + i * size, size); + for(j = i; j > step - 1; j -= step){ + if(compar(bp + (j - step) * size, swap) < 0) break; + memcpy(bp + j * size, bp + (j - step) * size, size); + } + memcpy(bp + j * size, swap, size); + } + } + } + if(step < 2) break; + } + free(swap); +} + + +/* Sort an array using heap sort. */ +void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ + char *bp, *swap; + int top, bottom, mybot, i; + assert(base && nmemb >= 0 && size > 0 && compar); + bp = (char *)base; + nmemb--; + bottom = nmemb / 2 + 1; + top = nmemb; + CB_MALLOC(swap, size); + while(bottom > 0){ + bottom--; + mybot = bottom; + i = 2 * mybot; + while(i <= top) { + if(i < top && compar(bp + (i + 1) * size, bp + i * size) > 0) i++; + if(compar(bp + mybot * size, bp + i * size) >= 0) break; + memcpy(swap, bp + mybot * size, size); + memcpy(bp + mybot * size, bp + i * size, size); + memcpy(bp + i * size, swap, size); + mybot = i; + i = 2 * mybot; + } + } + while(top > 0){ + memcpy(swap, bp, size); + memcpy(bp, bp + top * size, size); + memcpy(bp + top * size, swap, size); + top--; + mybot = bottom; + i = 2 * mybot; + while(i <= top){ + if(i < top && compar(bp + (i + 1) * size, bp + i * size) > 0) i++; + if(compar(bp + mybot * size, bp + i * size) >= 0) break; + memcpy(swap, bp + mybot * size, size); + memcpy(bp + mybot * size, bp + i * size, size); + memcpy(bp + i * size, swap, size); + mybot = i; + i = 2 * mybot; + } + } + free(swap); +} + + +/* Sort an array using quick sort. */ +void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ + char *pswap, *vswap; + assert(base && nmemb >= 0 && size > 0 && compar); + CB_MALLOC(pswap, size); + CB_MALLOC(vswap, size); + cbqsortsub(base, nmemb, size, pswap, vswap, compar); + free(vswap); + free(pswap); +} + + +/* Compare two strings with case insensitive evaluation. */ +int cbstricmp(const char *astr, const char *bstr){ + int ac, bc; + assert(astr && bstr); + while(*astr != '\0'){ + if(*bstr == '\0') return 1; + ac = (*astr >= 'A' && *astr <= 'Z') ? *astr + ('a' - 'A') : *(unsigned char *)astr; + bc = (*bstr >= 'A' && *bstr <= 'Z') ? *bstr + ('a' - 'A') : *(unsigned char *)bstr; + if(ac != bc) return ac - bc; + astr++; + bstr++; + } + return *bstr == '\0' ? 0 : -1; +} + + +/* Check whether a string begins with a key. */ +int cbstrfwmatch(const char *str, const char *key){ + assert(str && key); + while(*key != '\0'){ + if(*str != *key || *str == '\0') return FALSE; + key++; + str++; + } + return TRUE; +} + + +/* Check whether a string begins with a key, with case insensitive evaluation. */ +int cbstrfwimatch(const char *str, const char *key){ + int sc, kc; + assert(str && key); + while(*key != '\0'){ + if(*str == '\0') return FALSE; + sc = *str; + if(sc >= 'A' && sc <= 'Z') sc += 'a' - 'A'; + kc = *key; + if(kc >= 'A' && kc <= 'Z') kc += 'a' - 'A'; + if(sc != kc) return FALSE; + key++; + str++; + } + return TRUE; +} + + +/* Check whether a string ends with a key. */ +int cbstrbwmatch(const char *str, const char *key){ + int slen, klen, i; + assert(str && key); + slen = strlen(str); + klen = strlen(key); + for(i = 1; i <= klen; i++){ + if(i > slen || str[slen-i] != key[klen-i]) return FALSE; + } + return TRUE; +} + + +/* Check whether a string ends with a key, with case insensitive evaluation. */ +int cbstrbwimatch(const char *str, const char *key){ + int slen, klen, i, sc, kc; + assert(str && key); + slen = strlen(str); + klen = strlen(key); + for(i = 1; i <= klen; i++){ + if(i > slen) return FALSE; + sc = str[slen-i]; + if(sc >= 'A' && sc <= 'Z') sc += 'a' - 'A'; + kc = key[klen-i]; + if(kc >= 'A' && kc <= 'Z') kc += 'a' - 'A'; + if(sc != kc) return FALSE; + } + return TRUE; +} + + +/* Locate a substring in a string using KMP method. */ +char *cbstrstrkmp(const char *haystack, const char *needle){ + int i, j, hlen, nlen; + signed char tbl[0x100]; + assert(haystack && needle); + nlen = strlen(needle); + if(nlen >= 0x100) return strstr(haystack, needle); + tbl[0] = -1; + i = 0; + j = -1; + while(i < nlen){ + while((j >= 0) && (needle[i] != needle[j])){ + j = tbl[j]; + } + i++; + j++; + tbl[i] = j; + } + hlen = strlen(haystack); + i = 0; + j = 0; + while(i < hlen && j < nlen){ + while((j >= 0) && (haystack[i] != needle[j])){ + j = tbl[j]; + } + i++; + j++; + } + if(j == nlen) return (char *)(haystack + i - nlen); + return NULL; +} + + +/* Locate a substring in a string using BM method. */ +char *cbstrstrbm(const char *haystack, const char *needle){ + const unsigned char *rp; + const char *ep; + unsigned char tbl[0x100]; + int i, j, nlen, len, idx; + assert(haystack && needle); + nlen = strlen(needle); + if(nlen < 3 || nlen >= 0x100) return strstr(haystack, needle); + for(i = 0; i < 0x100; i++){ + tbl[i] = nlen; + } + len = nlen; + rp = (const unsigned char *)needle; + while(len > 0){ + tbl[*rp++] = --len; + } + nlen--; + ep = haystack + strlen(haystack) - nlen; + while(haystack < ep){ + for(i = nlen; haystack[i] == needle[i]; i--){ + if(i == 0) return (char *)haystack; + } + idx = ((unsigned char *)haystack)[i]; + j = tbl[idx] - nlen + i; + haystack += j > 0 ? j : 2; + } + return NULL; +} + + +/* Convert the letters of a string to upper case. */ +char *cbstrtoupper(char *str){ + int i; + assert(str); + for(i = 0; str[i] != '\0'; i++){ + if(str[i] >= 'a' && str[i] <= 'z') str[i] -= 'a' - 'A'; + } + return str; +} + + +/* Convert the letters of a string to lower case. */ +char *cbstrtolower(char *str){ + int i; + assert(str); + for(i = 0; str[i] != '\0'; i++){ + if(str[i] >= 'A' && str[i] <= 'Z') str[i] += 'a' - 'A'; + } + return str; +} + + +/* Cut space characters at head or tail of a string. */ +char *cbstrtrim(char *str){ + char *wp; + int i, head; + assert(str); + wp = str; + head = TRUE; + for(i = 0; str[i] != '\0'; i++){ + if((str[i] >= 0x07 && str[i] <= 0x0d) || str[i] == 0x20){ + if(!head) *(wp++) = str[i]; + } else { + *(wp++) = str[i]; + head = FALSE; + } + } + *wp = '\0'; + while(wp > str && ((wp[-1] >= 0x07 && wp[-1] <= 0x0d) || wp[-1] == 0x20)){ + *(--wp) = '\0'; + } + return str; +} + + +/* Squeeze space characters in a string and trim it. */ +char *cbstrsqzspc(char *str){ + char *wp; + int i, spc; + assert(str); + wp = str; + spc = TRUE; + for(i = 0; str[i] != '\0'; i++){ + if(str[i] > 0 && str[i] <= ' '){ + if(!spc) *(wp++) = str[i]; + spc = TRUE; + } else { + *(wp++) = str[i]; + spc = FALSE; + } + } + *wp = '\0'; + for(wp--; wp >= str; wp--){ + if(*wp > 0 && *wp <= ' '){ + *wp = '\0'; + } else { + break; + } + } + return str; +} + + +/* Count the number of characters in a string of UTF-8. */ +int cbstrcountutf(const char *str){ + const unsigned char *rp; + int cnt; + assert(str); + rp = (unsigned char *)str; + cnt = 0; + while(*rp != '\0'){ + if((*rp & 0x80) == 0x00 || (*rp & 0xe0) == 0xc0 || + (*rp & 0xf0) == 0xe0 || (*rp & 0xf8) == 0xf0) cnt++; + rp++; + } + return cnt; +} + + +/* Cut a string of UTF-8 at the specified number of characters. */ +char *cbstrcututf(char *str, int num){ + unsigned char *wp; + int cnt; + assert(str && num >= 0); + wp = (unsigned char *)str; + cnt = 0; + while(*wp != '\0'){ + if((*wp & 0x80) == 0x00 || (*wp & 0xe0) == 0xc0 || + (*wp & 0xf0) == 0xe0 || (*wp & 0xf8) == 0xf0){ + cnt++; + if(cnt > num){ + *wp = '\0'; + break; + } + } + wp++; + } + return str; +} + + +/* Get a datum handle. */ +CBDATUM *cbdatumopen(const char *ptr, int size){ + CBDATUM *datum; + CB_MALLOC(datum, sizeof(*datum)); + CB_MALLOC(datum->dptr, CB_DATUMUNIT); + datum->dptr[0] = '\0'; + datum->dsize = 0; + datum->asize = CB_DATUMUNIT; + if(ptr) CB_DATUMCAT(datum, ptr, (size >= 0 ? size : strlen(ptr))); + return datum; +} + + +/* Copy a datum. */ +CBDATUM *cbdatumdup(const CBDATUM *datum){ + assert(datum); + return cbdatumopen(datum->dptr, datum->dsize); +} + + +/* Free a datum handle. */ +void cbdatumclose(CBDATUM *datum){ + assert(datum); + free(datum->dptr); + free(datum); +} + + +/* Concatenate a datum and a region. */ +void cbdatumcat(CBDATUM *datum, const char *ptr, int size){ + assert(datum && ptr); + if(size < 0) size = strlen(ptr); + if(datum->dsize + size >= datum->asize){ + datum->asize = datum->asize * 2 + size + 1; + CB_REALLOC(datum->dptr, datum->asize); + } + memcpy(datum->dptr + datum->dsize, ptr, size); + datum->dsize += size; + datum->dptr[datum->dsize] = '\0'; +} + + +/* Get the pointer of the region of a datum. */ +const char *cbdatumptr(const CBDATUM *datum){ + assert(datum); + return datum->dptr; +} + + +/* Get the size of the region of a datum. */ +int cbdatumsize(const CBDATUM *datum){ + assert(datum); + return datum->dsize; +} + + +/* Set the size of the region of a datum. */ +void cbdatumsetsize(CBDATUM *datum, int size){ + assert(datum && size >= 0); + if(size <= datum->dsize){ + datum->dsize = size; + datum->dptr[size] = '\0'; + } else { + if(size >= datum->asize){ + datum->asize = datum->asize * 2 + size + 1; + CB_REALLOC(datum->dptr, datum->asize); + } + memset(datum->dptr + datum->dsize, 0, (size - datum->dsize) + 1); + datum->dsize = size; + } +} + + +/* Perform formatted output into a datum. */ +void cbdatumprintf(CBDATUM *datum, const char *format, ...){ + va_list ap; + char *tmp, cbuf[CB_NUMBUFSIZ], tbuf[CB_NUMBUFSIZ*2]; + unsigned char c; + int cblen, tlen; + assert(datum && format); + va_start(ap, format); + while(*format != '\0'){ + if(*format == '%'){ + cbuf[0] = '%'; + cblen = 1; + format++; + while(strchr("0123456789 .+-", *format) && *format != '\0' && cblen < CB_NUMBUFSIZ - 1){ + cbuf[cblen++] = *format; + format++; + } + cbuf[cblen++] = *format; + cbuf[cblen] = '\0'; + switch(*format){ + case 's': + tmp = va_arg(ap, char *); + if(!tmp) tmp = "(null)"; + cbdatumcat(datum, tmp, -1); + break; + case 'd': + tlen = sprintf(tbuf, cbuf, va_arg(ap, int)); + cbdatumcat(datum, tbuf, tlen); + break; + case 'o': case 'u': case 'x': case 'X': case 'c': + tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned int)); + cbdatumcat(datum, tbuf, tlen); + break; + case 'e': case 'E': case 'f': case 'g': case 'G': + tlen = sprintf(tbuf, cbuf, va_arg(ap, double)); + cbdatumcat(datum, tbuf, tlen); + break; + case '@': + tmp = va_arg(ap, char *); + if(!tmp) tmp = "(null)"; + while(*tmp){ + switch(*tmp){ + case '&': cbdatumcat(datum, "&", 5); break; + case '<': cbdatumcat(datum, "<", 4); break; + case '>': cbdatumcat(datum, ">", 4); break; + case '"': cbdatumcat(datum, """, 6); break; + default: + if(!((*tmp >= 0 && *tmp <= 0x8) || (*tmp >= 0x0e && *tmp <= 0x1f))) + cbdatumcat(datum, tmp, 1); + break; + } + tmp++; + } + break; + case '?': + tmp = va_arg(ap, char *); + if(!tmp) tmp = "(null)"; + while(*tmp){ + c = *(unsigned char *)tmp; + if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.", c))){ + cbdatumcat(datum, tmp, 1); + } else { + tlen = sprintf(tbuf, "%%%02X", c); + cbdatumcat(datum, tbuf, tlen); + } + tmp++; + } + break; + case ':': + tmp = va_arg(ap, char *); + if(!tmp) tmp = ""; + tmp = cbmimeencode(tmp, "UTF-8", TRUE); + cbdatumcat(datum, tmp, -1); + free(tmp); + break; + case '%': + cbdatumcat(datum, "%", 1); + break; + } + } else { + cbdatumcat(datum, format, 1); + } + format++; + } + va_end(ap); +} + + +/* Convert a datum to an allocated region. */ +char *cbdatumtomalloc(CBDATUM *datum, int *sp){ + char *ptr; + assert(datum); + ptr = datum->dptr; + if(sp) *sp = datum->dsize; + free(datum); + return ptr; +} + + +/* Get a list handle. */ +CBLIST *cblistopen(void){ + CBLIST *list; + CB_MALLOC(list, sizeof(*list)); + list->anum = CB_LISTUNIT; + CB_MALLOC(list->array, sizeof(list->array[0]) * list->anum); + list->start = 0; + list->num = 0; + return list; +} + + +/* Copy a list. */ +CBLIST *cblistdup(const CBLIST *list){ + CBLIST *newlist; + int i, size; + const char *val; + assert(list); + CB_LISTOPEN2(newlist, CB_LISTNUM(list)); + for(i = 0; i < CB_LISTNUM(list); i++){ + val = CB_LISTVAL2(list, i, size); + CB_LISTPUSH(newlist, val, size); + } + return newlist; +} + + +/* Close a list handle. */ +void cblistclose(CBLIST *list){ + int i, end; + assert(list); + end = list->start + list->num; + for(i = list->start; i < end; i++){ + free(list->array[i].dptr); + } + free(list->array); + free(list); +} + + +/* Get the number of elements of a list. */ +int cblistnum(const CBLIST *list){ + assert(list); + return list->num; +} + + +/* Get the pointer to the region of an element. */ +const char *cblistval(const CBLIST *list, int index, int *sp){ + assert(list && index >= 0); + if(index >= list->num) return NULL; + index += list->start; + if(sp) *sp = list->array[index].dsize; + return list->array[index].dptr; +} + + +/* Add an element at the end of a list. */ +void cblistpush(CBLIST *list, const char *ptr, int size){ + int index; + assert(list && ptr); + if(size < 0) size = strlen(ptr); + index = list->start + list->num; + if(index >= list->anum){ + list->anum *= 2; + CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); + } + CB_MALLOC(list->array[index].dptr, (size < CB_DATUMUNIT ? CB_DATUMUNIT : size) + 1); + memcpy(list->array[index].dptr, ptr, size); + list->array[index].dptr[size] = '\0'; + list->array[index].dsize = size; + list->num++; +} + + +/* Remove an element of the end of a list. */ +char *cblistpop(CBLIST *list, int *sp){ + int index; + assert(list); + if(list->num < 1) return NULL; + index = list->start + list->num - 1; + list->num--; + if(sp) *sp = list->array[index].dsize; + return list->array[index].dptr; +} + + +/* Add an element at the top of a list. */ +void cblistunshift(CBLIST *list, const char *ptr, int size){ + int index; + assert(list && ptr); + if(size < 0) size = strlen(ptr); + if(list->start < 1){ + if(list->start + list->num >= list->anum){ + list->anum *= 2; + CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); + } + list->start = list->anum - list->num; + memmove(list->array + list->start, list->array, list->num * sizeof(list->array[0])); + } + index = list->start - 1; + CB_MALLOC(list->array[index].dptr, (size < CB_DATUMUNIT ? CB_DATUMUNIT : size) + 1); + memcpy(list->array[index].dptr, ptr, size); + list->array[index].dptr[size] = '\0'; + list->array[index].dsize = size; + list->start--; + list->num++; +} + + +/* Remove an element of the top of a list. */ +char *cblistshift(CBLIST *list, int *sp){ + int index; + assert(list); + if(list->num < 1) return NULL; + index = list->start; + list->start++; + list->num--; + if(sp) *sp = list->array[index].dsize; + return list->array[index].dptr; +} + + +/* Add an element at the specified location of a list. */ +void cblistinsert(CBLIST *list, int index, const char *ptr, int size){ + assert(list && index >= 0); + if(index > list->num) return; + if(size < 0) size = strlen(ptr); + index += list->start; + if(list->start + list->num >= list->anum){ + list->anum *= 2; + CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); + } + memmove(list->array + index + 1, list->array + index, + sizeof(list->array[0]) * (list->start + list->num - index)); + CB_MEMDUP(list->array[index].dptr, ptr, size); + list->array[index].dsize = size; + list->num++; +} + + +/* Remove an element at the specified location of a list. */ +char *cblistremove(CBLIST *list, int index, int *sp){ + char *dptr; + assert(list && index >= 0); + if(index >= list->num) return NULL; + index += list->start; + dptr = list->array[index].dptr; + if(sp) *sp = list->array[index].dsize; + list->num--; + memmove(list->array + index, list->array + index + 1, + sizeof(list->array[0]) * (list->start + list->num - index)); + return dptr; +} + + +/* Overwrite an element at the specified location of a list. */ +void cblistover(CBLIST *list, int index, const char *ptr, int size){ + assert(list && index >= 0); + if(index >= list->num) return; + if(size < 0) size = strlen(ptr); + index += list->start; + if(size > list->array[index].dsize) + CB_REALLOC(list->array[index].dptr, size + 1); + memcpy(list->array[index].dptr, ptr, size); + list->array[index].dsize = size; + list->array[index].dptr[size] = '\0'; +} + + +/* Sort elements of a list in lexical order. */ +void cblistsort(CBLIST *list){ + assert(list); + qsort(list->array + list->start, list->num, sizeof(list->array[0]), cblistelemcmp); +} + + +/* Search a list for an element using liner search. */ +int cblistlsearch(const CBLIST *list, const char *ptr, int size){ + int i, end; + assert(list && ptr); + if(size < 0) size = strlen(ptr); + end = list->start + list->num; + for(i = list->start; i < end; i++){ + if(list->array[i].dsize == size && !memcmp(list->array[i].dptr, ptr, size)) + return i - list->start; + } + return -1; +} + + +/* Search a list for an element using binary search. */ +int cblistbsearch(const CBLIST *list, const char *ptr, int size){ + CBLISTDATUM key, *res; + assert(list && ptr); + if(size < 0) size = strlen(ptr); + CB_MEMDUP(key.dptr, ptr, size); + key.dsize = size; + res = bsearch(&key, list->array + list->start, list->num, sizeof(list->array[0]), cblistelemcmp); + free(key.dptr); + return res ? (res - list->array - list->start) : -1; +} + + +/* Serialize a list into a byte array. */ +char *cblistdump(const CBLIST *list, int *sp){ + char *buf, vnumbuf[CB_VNUMBUFSIZ]; + const char *vbuf; + int i, bsiz, vnumsiz, ln, vsiz; + assert(list && sp); + ln = CB_LISTNUM(list); + CB_SETVNUMBUF(vnumsiz, vnumbuf, ln); + CB_MALLOC(buf, vnumsiz + 1); + memcpy(buf, vnumbuf, vnumsiz); + bsiz = vnumsiz; + for(i = 0; i < ln; i++){ + vbuf = CB_LISTVAL2(list, i, vsiz); + CB_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); + CB_REALLOC(buf, bsiz + vnumsiz + vsiz + 1); + memcpy(buf + bsiz, vnumbuf, vnumsiz); + bsiz += vnumsiz; + memcpy(buf + bsiz, vbuf, vsiz); + bsiz += vsiz; + } + *sp = bsiz; + return buf; +} + + +/* Redintegrate a serialized list. */ +CBLIST *cblistload(const char *ptr, int size){ + CBLIST *list; + const char *rp; + int i, anum, step, ln, vsiz; + assert(ptr && size >= 0); + anum = size / (sizeof(CBLISTDATUM) + 1); + CB_LISTOPEN2(list, anum); + rp = ptr; + CB_READVNUMBUF(rp, size, ln, step); + rp += step; + size -= step; + if(ln > size) return list; + for(i = 0; i < ln; i++){ + if(size < 1) break; + CB_READVNUMBUF(rp, size, vsiz, step); + rp += step; + size -= step; + if(vsiz > size) break; + CB_LISTPUSH(list, rp, vsiz); + rp += vsiz; + } + return list; +} + + +/* Get a map handle. */ +CBMAP *cbmapopen(void){ + return cbmapopenex(CB_MAPBNUM); +} + + +/* Copy a map. */ +CBMAP *cbmapdup(CBMAP *map){ + CBMAP *newmap; + const char *kbuf, *vbuf; + int ksiz, vsiz; + assert(map); + cbmapiterinit(map); + newmap = map->rnum > CB_MAPPBNUM ? cbmapopen() : cbmapopenex(CB_MAPPBNUM); + while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ + CB_MAPITERVAL(vbuf, kbuf, vsiz); + cbmapput(newmap, kbuf, ksiz, vbuf, vsiz, FALSE); + } + cbmapiterinit(map); + return newmap; +} + + +/* Close a map handle. */ +void cbmapclose(CBMAP *map){ + CBMAPDATUM *datum, *next; + datum = map->first; + while(datum){ + next = datum->next; + free(datum); + datum = next; + } + free(map->buckets); + free(map); +} + + +/* Store a record. */ +int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over){ + CBMAPDATUM *datum, **entp, *old; + char *dbuf; + int bidx, hash, kcmp, psiz; + assert(map && kbuf && vbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if(vsiz < 0) vsiz = strlen(vbuf); + CB_FIRSTHASH(hash, kbuf, ksiz); + bidx = hash % map->bnum; + datum = map->buckets[bidx]; + entp = map->buckets + bidx; + CB_SECONDHASH(hash, kbuf, ksiz); + while(datum){ + if(hash > datum->hash){ + entp = &(datum->left); + datum = datum->left; + } else if(hash < datum->hash){ + entp = &(datum->right); + datum = datum->right; + } else { + dbuf = (char *)datum + sizeof(*datum); + kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); + if(kcmp < 0){ + entp = &(datum->left); + datum = datum->left; + } else if(kcmp > 0){ + entp = &(datum->right); + datum = datum->right; + } else { + if(!over) return FALSE; + psiz = CB_ALIGNPAD(ksiz); + if(vsiz > datum->vsiz){ + old = datum; + CB_REALLOC(datum, sizeof(*datum) + ksiz + psiz + vsiz + 1); + if(datum != old){ + if(map->first == old) map->first = datum; + if(map->last == old) map->last = datum; + if(*entp == old) *entp = datum; + if(datum->prev) datum->prev->next = datum; + if(datum->next) datum->next->prev = datum; + dbuf = (char *)datum + sizeof(*datum); + } + } + memcpy(dbuf + ksiz + psiz, vbuf, vsiz); + dbuf[ksiz+psiz+vsiz] = '\0'; + datum->vsiz = vsiz; + return TRUE; + } + } + } + psiz = CB_ALIGNPAD(ksiz); + CB_MALLOC(datum, sizeof(*datum) + ksiz + psiz + vsiz + 1); + dbuf = (char *)datum + sizeof(*datum); + memcpy(dbuf, kbuf, ksiz); + dbuf[ksiz] = '\0'; + datum->ksiz = ksiz; + memcpy(dbuf + ksiz + psiz, vbuf, vsiz); + dbuf[ksiz+psiz+vsiz] = '\0'; + datum->vsiz = vsiz; + datum->hash = hash; + datum->left = NULL; + datum->right = NULL; + datum->prev = map->last; + datum->next = NULL; + *entp = datum; + if(!map->first) map->first = datum; + if(map->last) map->last->next = datum; + map->last = datum; + map->rnum++; + return TRUE; +} + + +/* Concatenate a value at the end of the value of the existing record. */ +void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz){ + CBMAPDATUM *datum, **entp, *old; + char *dbuf; + int bidx, hash, kcmp, psiz, asiz, unit; + assert(map && kbuf && vbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if(vsiz < 0) vsiz = strlen(vbuf); + CB_FIRSTHASH(hash, kbuf, ksiz); + bidx = hash % map->bnum; + datum = map->buckets[bidx]; + entp = map->buckets + bidx; + CB_SECONDHASH(hash, kbuf, ksiz); + while(datum){ + if(hash > datum->hash){ + entp = &(datum->left); + datum = datum->left; + } else if(hash < datum->hash){ + entp = &(datum->right); + datum = datum->right; + } else { + dbuf = (char *)datum + sizeof(*datum); + kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); + if(kcmp < 0){ + entp = &(datum->left); + datum = datum->left; + } else if(kcmp > 0){ + entp = &(datum->right); + datum = datum->right; + } else { + psiz = CB_ALIGNPAD(ksiz); + asiz = sizeof(*datum) + ksiz + psiz + datum->vsiz + vsiz + 1; + unit = asiz <= CB_MAPCSUNIT ? CB_MAPCSUNIT : CB_MAPCBUNIT; + asiz = (asiz - 1) + unit - (asiz - 1) % unit; + old = datum; + CB_REALLOC(datum, asiz); + if(datum != old){ + if(map->first == old) map->first = datum; + if(map->last == old) map->last = datum; + if(*entp == old) *entp = datum; + if(datum->prev) datum->prev->next = datum; + if(datum->next) datum->next->prev = datum; + dbuf = (char *)datum + sizeof(*datum); + } + memcpy(dbuf + ksiz + psiz + datum->vsiz, vbuf, vsiz); + dbuf[ksiz+psiz+datum->vsiz+vsiz] = '\0'; + datum->vsiz += vsiz; + return; + } + } + } + psiz = CB_ALIGNPAD(ksiz); + asiz = sizeof(*datum) + ksiz + psiz + vsiz + 1; + unit = asiz <= CB_MAPCSUNIT ? CB_MAPCSUNIT : CB_MAPCBUNIT; + asiz = (asiz - 1) + unit - (asiz - 1) % unit; + CB_MALLOC(datum, asiz); + dbuf = (char *)datum + sizeof(*datum); + memcpy(dbuf, kbuf, ksiz); + dbuf[ksiz] = '\0'; + datum->ksiz = ksiz; + memcpy(dbuf + ksiz + psiz, vbuf, vsiz); + dbuf[ksiz+psiz+vsiz] = '\0'; + datum->vsiz = vsiz; + datum->hash = hash; + datum->left = NULL; + datum->right = NULL; + datum->prev = map->last; + datum->next = NULL; + *entp = datum; + if(!map->first) map->first = datum; + if(map->last) map->last->next = datum; + map->last = datum; + map->rnum++; +} + + +/* Delete a record. */ +int cbmapout(CBMAP *map, const char *kbuf, int ksiz){ + CBMAPDATUM *datum, **entp, *tmp; + char *dbuf; + int bidx, hash, kcmp; + assert(map && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + CB_FIRSTHASH(hash, kbuf, ksiz); + bidx = hash % map->bnum; + datum = map->buckets[bidx]; + entp = map->buckets + bidx; + CB_SECONDHASH(hash, kbuf, ksiz); + while(datum){ + if(hash > datum->hash){ + entp = &(datum->left); + datum = datum->left; + } else if(hash < datum->hash){ + entp = &(datum->right); + datum = datum->right; + } else { + dbuf = (char *)datum + sizeof(*datum); + kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); + if(kcmp < 0){ + entp = &(datum->left); + datum = datum->left; + } else if(kcmp > 0){ + entp = &(datum->right); + datum = datum->right; + } else { + if(datum->prev) datum->prev->next = datum->next; + if(datum->next) datum->next->prev = datum->prev; + if(datum == map->first) map->first = datum->next; + if(datum == map->last) map->last = datum->prev; + if(datum->left && !datum->right){ + *entp = datum->left; + } else if(!datum->left && datum->right){ + *entp = datum->right; + } else if(!datum->left && !datum->left){ + *entp = NULL; + } else { + *entp = datum->left; + tmp = *entp; + while(TRUE){ + if(hash > tmp->hash){ + if(tmp->left){ + tmp = tmp->left; + } else { + tmp->left = datum->right; + break; + } + } else if(hash < tmp->hash){ + if(tmp->right){ + tmp = tmp->right; + } else { + tmp->right = datum->right; + break; + } + } else { + kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); + if(kcmp < 0){ + if(tmp->left){ + tmp = tmp->left; + } else { + tmp->left = datum->right; + break; + } + } else { + if(tmp->right){ + tmp = tmp->right; + } else { + tmp->right = datum->right; + break; + } + } + } + } + } + free(datum); + map->rnum--; + return TRUE; + } + } + } + return FALSE; +} + + +/* Retrieve a record. */ +const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp){ + CBMAPDATUM *datum; + char *dbuf; + int hash, kcmp; + assert(map && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + CB_FIRSTHASH(hash, kbuf, ksiz); + datum = map->buckets[hash%map->bnum]; + CB_SECONDHASH(hash, kbuf, ksiz); + while(datum){ + if(hash > datum->hash){ + datum = datum->left; + } else if(hash < datum->hash){ + datum = datum->right; + } else { + dbuf = (char *)datum + sizeof(*datum); + kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); + if(kcmp < 0){ + datum = datum->left; + } else if(kcmp > 0){ + datum = datum->right; + } else { + if(sp) *sp = datum->vsiz; + return dbuf + datum->ksiz + CB_ALIGNPAD(datum->ksiz); + } + } + } + return NULL; +} + + +/* Move a record to the edge. */ +int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head){ + CBMAPDATUM *datum; + char *dbuf; + int hash, kcmp; + assert(map && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + CB_FIRSTHASH(hash, kbuf, ksiz); + datum = map->buckets[hash%map->bnum]; + CB_SECONDHASH(hash, kbuf, ksiz); + while(datum){ + if(hash > datum->hash){ + datum = datum->left; + } else if(hash < datum->hash){ + datum = datum->right; + } else { + dbuf = (char *)datum + sizeof(*datum); + kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); + if(kcmp < 0){ + datum = datum->left; + } else if(kcmp > 0){ + datum = datum->right; + } else { + if(head){ + if(map->first == datum) return TRUE; + if(map->last == datum) map->last = datum->prev; + if(datum->prev) datum->prev->next = datum->next; + if(datum->next) datum->next->prev = datum->prev; + datum->prev = NULL; + datum->next = map->first; + map->first->prev = datum; + map->first = datum; + } else { + if(map->last == datum) return TRUE; + if(map->first == datum) map->first = datum->next; + if(datum->prev) datum->prev->next = datum->next; + if(datum->next) datum->next->prev = datum->prev; + datum->prev = map->last; + datum->next = NULL; + map->last->next = datum; + map->last = datum; + } + return TRUE; + } + } + } + return FALSE; +} + + +/* Initialize the iterator of a map handle. */ +void cbmapiterinit(CBMAP *map){ + assert(map); + map->cur = map->first; +} + + +/* Get the next key of the iterator. */ +const char *cbmapiternext(CBMAP *map, int *sp){ + CBMAPDATUM *datum; + assert(map); + if(!map->cur) return NULL; + datum = map->cur; + map->cur = datum->next; + if(sp) *sp = datum->ksiz; + return (char *)datum + sizeof(*datum); +} + + +/* Get the value binded to the key fetched from the iterator. */ +const char *cbmapiterval(const char *kbuf, int *sp){ + CBMAPDATUM *datum; + assert(kbuf); + datum = (CBMAPDATUM *)(kbuf - sizeof(*datum)); + if(sp) *sp = datum->vsiz; + return (char *)datum + sizeof(*datum) + datum->ksiz + CB_ALIGNPAD(datum->ksiz); +} + + +/* Get the number of the records stored in a map. */ +int cbmaprnum(const CBMAP *map){ + assert(map); + return map->rnum; +} + + +/* Get the list handle contains all keys in a map. */ +CBLIST *cbmapkeys(CBMAP *map){ + CBLIST *list; + const char *kbuf; + int anum, ksiz; + assert(map); + anum = cbmaprnum(map); + CB_LISTOPEN2(list, anum); + cbmapiterinit(map); + while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ + CB_LISTPUSH(list, kbuf, ksiz); + } + return list; +} + + +/* Get the list handle contains all values in a map. */ +CBLIST *cbmapvals(CBMAP *map){ + CBLIST *list; + const char *kbuf, *vbuf; + int anum, ksiz, vsiz; + assert(map); + anum = cbmaprnum(map); + CB_LISTOPEN2(list, anum); + cbmapiterinit(map); + while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ + CB_MAPITERVAL(vbuf, kbuf, vsiz); + CB_LISTPUSH(list, vbuf, vsiz); + } + return list; +} + + +/* Serialize a map into a byte array. */ +char *cbmapdump(CBMAP *map, int *sp){ + char *buf, vnumbuf[CB_VNUMBUFSIZ]; + const char *kbuf, *vbuf; + int bsiz, vnumsiz, rn, ksiz, vsiz; + assert(map && sp); + rn = cbmaprnum(map); + CB_SETVNUMBUF(vnumsiz, vnumbuf, rn); + CB_MALLOC(buf, vnumsiz + 1); + memcpy(buf, vnumbuf, vnumsiz); + bsiz = vnumsiz; + cbmapiterinit(map); + while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ + CB_MAPITERVAL(vbuf, kbuf, vsiz); + CB_SETVNUMBUF(vnumsiz, vnumbuf, ksiz); + CB_REALLOC(buf, bsiz + vnumsiz + ksiz + 1); + memcpy(buf + bsiz, vnumbuf, vnumsiz); + bsiz += vnumsiz; + memcpy(buf + bsiz, kbuf, ksiz); + bsiz += ksiz; + CB_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); + CB_REALLOC(buf, bsiz + vnumsiz + vsiz + 1); + memcpy(buf + bsiz, vnumbuf, vnumsiz); + bsiz += vnumsiz; + memcpy(buf + bsiz, vbuf, vsiz); + bsiz += vsiz; + } + *sp = bsiz; + return buf; +} + + +/* Redintegrate a serialized map. */ +CBMAP *cbmapload(const char *ptr, int size){ + CBMAP *map; + const char *rp, *kbuf, *vbuf; + int i, step, rn, ksiz, vsiz; + assert(ptr && size >= 0); + map = cbmapopenex(CB_MAPPBNUM); + rp = ptr; + CB_READVNUMBUF(rp, size, rn, step); + rp += step; + size -= step; + if(rn > size) return map; + for(i = 0; i < rn; i++){ + if(size < 1) break; + CB_READVNUMBUF(rp, size, ksiz, step); + rp += step; + size -= step; + if(ksiz > size) break; + kbuf = rp; + rp += ksiz; + if(size < 1) break; + CB_READVNUMBUF(rp, size, vsiz, step); + rp += step; + size -= step; + if(vsiz > size) break; + vbuf = rp; + rp += vsiz; + cbmapput(map, kbuf, ksiz, vbuf, vsiz, TRUE); + } + return map; +} + + +/* Redintegrate a serialized map and get one of the records. */ +char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp){ + const char *rp, *tkbuf, *vbuf; + char *rv; + int i, step, rn, tksiz, vsiz; + assert(ptr && size >= 0 && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + rp = ptr; + CB_READVNUMBUF(rp, size, rn, step); + rp += step; + size -= step; + if(rn > size) return NULL; + for(i = 0; i < rn; i++){ + if(size < 1) break; + CB_READVNUMBUF(rp, size, tksiz, step); + rp += step; + size -= step; + if(tksiz > size) break; + tkbuf = rp; + rp += tksiz; + if(size < 1) break; + CB_READVNUMBUF(rp, size, vsiz, step); + rp += step; + size -= step; + if(vsiz > size) break; + vbuf = rp; + rp += vsiz; + if(tksiz == ksiz && !memcmp(tkbuf, kbuf, ksiz)){ + if(sp) *sp = vsiz; + CB_MEMDUP(rv, vbuf, vsiz); + return rv; + } + } + return NULL; +} + + +/* Get a heap handle. */ +CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *)){ + CBHEAP *heap; + assert(size > 0 && max >= 0 && compar); + CB_MALLOC(heap, sizeof(*heap)); + CB_MALLOC(heap->base, size * max + 1); + CB_MALLOC(heap->swap, size); + heap->size = size; + heap->num = 0; + heap->max = max; + heap->compar = compar; + return heap; +} + + +/* Copy a heap. */ +CBHEAP *cbheapdup(CBHEAP *heap){ + CBHEAP *newheap; + assert(heap); + CB_MALLOC(newheap, sizeof(*newheap)); + CB_MEMDUP(newheap->base, heap->base, heap->size * heap->max); + CB_MALLOC(newheap->swap, heap->size); + newheap->size = heap->size; + newheap->num = heap->num; + newheap->max = heap->max; + newheap->compar = heap->compar; + return newheap; +} + + +/* Close a heap handle. */ +void cbheapclose(CBHEAP *heap){ + assert(heap); + free(heap->swap); + free(heap->base); + free(heap); +} + + +/* Get the number of the records stored in a heap. */ +int cbheapnum(CBHEAP *heap){ + assert(heap); + return heap->num; +} + + +/* Insert a record into a heap. */ +int cbheapinsert(CBHEAP *heap, const void *ptr){ + char *base; + int size, pidx, cidx, bot; + assert(heap && ptr); + if(heap->max < 1) return FALSE; + base = heap->base; + size = heap->size; + if(heap->num >= heap->max){ + if(heap->compar(ptr, base) > 0) return FALSE; + memcpy(base, ptr, size); + pidx = 0; + bot = heap->num / 2; + while(pidx < bot){ + cidx = pidx * 2 + 1; + if(cidx < heap->num - 1 && heap->compar(base + cidx * size, base + (cidx + 1) * size) < 0) + cidx++; + if(heap->compar(base + pidx * size, base + cidx * size) > 0) break; + memcpy(heap->swap, base + pidx * size, size); + memcpy(base + pidx * size, base + cidx * size, size); + memcpy(base + cidx * size, heap->swap, size); + pidx = cidx; + } + } else { + memcpy(base + size * heap->num, ptr, size); + cidx = heap->num; + while(cidx > 0){ + pidx = (cidx - 1) / 2; + if(heap->compar(base + cidx * size, base + pidx * size) <= 0) break; + memcpy(heap->swap, base + cidx * size, size); + memcpy(base + cidx * size, base + pidx * size, size); + memcpy(base + pidx * size, heap->swap, size); + cidx = pidx; + } + heap->num++; + } + return TRUE; +} + + +/* Get the pointer to the region of a record in a heap. */ +const void *cbheapval(CBHEAP *heap, int index){ + assert(heap && index >= 0); + if(index >= heap->num) return NULL; + return heap->base + index * heap->size; +} + + +/* Convert a heap to an allocated region. */ +void *cbheaptomalloc(CBHEAP *heap, int *np){ + char *ptr; + assert(heap); + qsort(heap->base, heap->num, heap->size, heap->compar); + ptr = heap->base; + if(np) *np = heap->num; + free(heap->swap); + free(heap); + return ptr; +} + + +/* Allocate a formatted string on memory. */ +char *cbsprintf(const char *format, ...){ + va_list ap; + char *buf, cbuf[CB_SPBUFSIZ], *str; + int len, cblen, num, slen; + unsigned int unum; + double dnum; + va_start(ap, format); + assert(format); + CB_MALLOC(buf, 1); + len = 0; + while(*format != '\0'){ + if(*format == '%'){ + cbuf[0] = '%'; + cblen = 1; + format++; + while(strchr("0123456789 .+-", *format) && *format != '\0' && cblen < CB_SPBUFSIZ - 1){ + cbuf[cblen++] = *format; + format++; + } + cbuf[cblen] = '\0'; + if(atoi(cbuf + 1) > CB_SPMAXWIDTH - 16){ + sprintf(cbuf, "(err)"); + } else { + cbuf[cblen++] = *format; + cbuf[cblen] = '\0'; + } + switch(*format){ + case 'd': + num = va_arg(ap, int); + CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2); + len += sprintf(buf + len, cbuf, num); + break; + case 'o': case 'u': case 'x': case 'X': case 'c': + unum = va_arg(ap, unsigned int); + CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2); + len += sprintf(buf + len, cbuf, unum); + break; + case 'e': case 'E': case 'f': case 'g': case 'G': + dnum = va_arg(ap, double); + CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2); + len += sprintf(buf + len, cbuf, dnum); + break; + case 's': + str = va_arg(ap, char *); + slen = strlen(str); + CB_REALLOC(buf, len + slen + 2); + memcpy(buf + len, str, slen); + len += slen; + break; + case '%': + CB_REALLOC(buf, len + 2); + buf[len++] = '%'; + break; + default: + break; + } + } else { + CB_REALLOC(buf, len + 2); + buf[len++] = *format; + } + format++; + } + buf[len] = '\0'; + va_end(ap); + return buf; +} + + +/* Replace some patterns in a string. */ +char *cbreplace(const char *str, CBMAP *pairs){ + int i, bsiz, wi, rep, ksiz, vsiz; + char *buf; + const char *key, *val; + assert(str && pairs); + bsiz = CB_DATUMUNIT; + CB_MALLOC(buf, bsiz); + wi = 0; + while(*str != '\0'){ + rep = FALSE; + cbmapiterinit(pairs); + while((key = cbmapiternext(pairs, &ksiz)) != NULL){ + for(i = 0; i < ksiz; i++){ + if(str[i] == '\0' || str[i] != key[i]) break; + } + if(i == ksiz){ + CB_MAPITERVAL(val, key, vsiz); + if(wi + vsiz >= bsiz){ + bsiz = bsiz * 2 + vsiz; + CB_REALLOC(buf, bsiz); + } + memcpy(buf + wi, val, vsiz); + wi += vsiz; + str += ksiz; + rep = TRUE; + break; + } + } + if(!rep){ + if(wi + 1 >= bsiz){ + bsiz = bsiz * 2 + 1; + CB_REALLOC(buf, bsiz); + } + buf[wi++] = *str; + str++; + } + } + CB_REALLOC(buf, wi + 1); + buf[wi] = '\0'; + return buf; +} + + +/* Make a list by split a serial datum. */ +CBLIST *cbsplit(const char *ptr, int size, const char *delim){ + CBLIST *list; + int bi, step; + assert(ptr); + CB_LISTOPEN(list); + if(size < 0) size = strlen(ptr); + if(delim){ + for(bi = 0; bi < size; bi += step){ + step = 0; + while(bi + step < size && !strchr(delim, ptr[bi+step])){ + step++; + } + cblistpush(list, ptr + bi, step); + step++; + } + if(size > 0 && strchr(delim, ptr[size-1])) cblistpush(list, "", 0); + } else { + for(bi = 0; bi < size; bi += step){ + step = 0; + while(bi + step < size && ptr[bi+step]){ + step++; + } + cblistpush(list, ptr + bi, step); + step++; + } + if(size > 0 && ptr[size-1] == 0) cblistpush(list, "", 0); + } + return list; +} + + +/* Read whole data of a file. */ +char *cbreadfile(const char *name, int *sp){ + struct stat sbuf; + char iobuf[CB_IOBUFSIZ], *buf; + int fd, size, asiz, rv; + asiz = CB_IOBUFSIZ * 2; + if(name){ + if((fd = open(name, O_RDONLY, 0)) == -1) return NULL; + if(fstat(fd, &sbuf) != -1) asiz = sbuf.st_size + 1; + } else { + fd = 0; + } + CB_MALLOC(buf, asiz + 1); + size = 0; + while((rv = read(fd, iobuf, CB_IOBUFSIZ)) > 0){ + if(size + rv >= asiz){ + asiz = asiz * 2 + size; + CB_REALLOC(buf, asiz + 1); + } + memcpy(buf + size, iobuf, rv); + size += rv; + } + buf[size] = '\0'; + if(close(fd) == -1 || rv == -1){ + free(buf); + return NULL; + } + if(sp) *sp = size; + return buf; +} + + +/* Write data of a region into a file. */ +int cbwritefile(const char *name, const char *ptr, int size){ + int fd, err, wb; + assert(ptr); + if(size < 0) size = strlen(ptr); + if(name){ + if((fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, CB_FILEMODE)) == -1) return FALSE; + } else { + fd = 1; + } + err = FALSE; + wb = 0; + do { + wb = write(fd, ptr, size); + switch(wb){ + case -1: err = errno != EINTR ? TRUE : FALSE; break; + case 0: break; + default: + ptr += wb; + size -= wb; + break; + } + } while(size > 0); + if(close(fd) == -1) err = TRUE; + return err ? FALSE : TRUE; +} + + +/* Read every line of a file. */ +CBLIST *cbreadlines(const char *name){ + char *buf, *tmp; + int vsiz; + CBMAP *pairs; + CBLIST *list; + if(!(buf = cbreadfile(name, NULL))) return NULL; + pairs = cbmapopenex(3); + cbmapput(pairs, "\r\n", 2, "\n", 1, TRUE); + cbmapput(pairs, "\r", 1, "\n", 1, TRUE); + tmp = cbreplace(buf, pairs); + list = cbsplit(tmp, strlen(tmp), "\n"); + free(tmp); + cbmapclose(pairs); + free(buf); + if(CB_LISTNUM(list) > 0){ + cblistval(list, CB_LISTNUM(list) - 1, &vsiz); + if(vsiz < 1) CB_LISTDROP(list); + } + return list; +} + + +/* Read names of files in a directory. */ +CBLIST *cbdirlist(const char *name){ + DIR *DD; + struct dirent *dp; + CBLIST *list; + assert(name); + if(!(DD = opendir(name))) return NULL; + CB_LISTOPEN(list); + while((dp = readdir(DD)) != NULL){ + CB_LISTPUSH(list, dp->d_name, strlen(dp->d_name)); + } + if(closedir(DD) == -1){ + CB_LISTCLOSE(list); + return NULL; + } + return list; +} + + +/* Get the status of a file or a directory. */ +int cbfilestat(const char *name, int *isdirp, int *sizep, time_t *mtimep){ + struct stat sbuf; + assert(name); + if(lstat(name, &sbuf) == -1) return FALSE; + if(isdirp) *isdirp = S_ISDIR(sbuf.st_mode); + if(sizep) *sizep = (int)sbuf.st_size; + if(mtimep) *mtimep = sbuf.st_mtime; + return TRUE; +} + + +/* Remove a file or a directory and its sub ones recursively. */ +int cbremove(const char *name){ + CBLIST *list; + const char *elem; + char *path; + int i, err, tail; + struct stat sbuf; + assert(name); + if(lstat(name, &sbuf) == -1) return FALSE; + if(unlink(name) == 0) return TRUE; + if(!S_ISDIR(sbuf.st_mode) || !(list = cbdirlist(name))) return FALSE; + err = FALSE; + tail = name[0] != '\0' && name[strlen(name)-1] == MYPATHCHR; + for(i = 0; i < CB_LISTNUM(list); i++){ + elem = CB_LISTVAL(list, i); + if(!strcmp(MYCDIRSTR, elem) || !strcmp(MYPDIRSTR, elem)) continue; + if(tail){ + path = cbsprintf("%s%s", name, elem); + } else { + path = cbsprintf("%s%c%s", name, MYPATHCHR, elem); + } + if(!cbremove(path)) err = TRUE; + free(path); + } + CB_LISTCLOSE(list); + return rmdir(name) == 0 ? TRUE : FALSE; +} + + +/* Break up a URL into elements. */ +CBMAP *cburlbreak(const char *str){ + CBMAP *map; + char *tmp, *ep; + const char *rp; + int serv; + assert(str); + map = cbmapopenex(CB_MAPPBNUM); + CB_MEMDUP(tmp, str, strlen(str)); + rp = cbstrtrim(tmp); + cbmapput(map, "self", -1, rp, -1, TRUE); + serv = FALSE; + if(cbstrfwimatch(rp, "http://")){ + cbmapput(map, "scheme", -1, "http", -1, TRUE); + rp += 7; + serv = TRUE; + } else if(cbstrfwimatch(rp, "https://")){ + cbmapput(map, "scheme", -1, "https", -1, TRUE); + rp += 8; + serv = TRUE; + } else if(cbstrfwimatch(rp, "ftp://")){ + cbmapput(map, "scheme", -1, "ftp", -1, TRUE); + rp += 6; + serv = TRUE; + } else if(cbstrfwimatch(rp, "sftp://")){ + cbmapput(map, "scheme", -1, "sftp", -1, TRUE); + rp += 7; + serv = TRUE; + } else if(cbstrfwimatch(rp, "ftps://")){ + cbmapput(map, "scheme", -1, "ftps", -1, TRUE); + rp += 7; + serv = TRUE; + } else if(cbstrfwimatch(rp, "tftp://")){ + cbmapput(map, "scheme", -1, "tftp", -1, TRUE); + rp += 7; + serv = TRUE; + } else if(cbstrfwimatch(rp, "ldap://")){ + cbmapput(map, "scheme", -1, "ldap", -1, TRUE); + rp += 7; + serv = TRUE; + } else if(cbstrfwimatch(rp, "ldaps://")){ + cbmapput(map, "scheme", -1, "ldaps", -1, TRUE); + rp += 8; + serv = TRUE; + } else if(cbstrfwimatch(rp, "file://")){ + cbmapput(map, "scheme", -1, "file", -1, TRUE); + rp += 7; + serv = TRUE; + } + if((ep = strchr(rp, '#')) != NULL){ + cbmapput(map, "fragment", -1, ep + 1, -1, TRUE); + *ep = '\0'; + } + if((ep = strchr(rp, '?')) != NULL){ + cbmapput(map, "query", -1, ep + 1, -1, TRUE); + *ep = '\0'; + } + if(serv){ + if((ep = strchr(rp, '/')) != NULL){ + cbmapput(map, "path", -1, ep, -1, TRUE); + *ep = '\0'; + } else { + cbmapput(map, "path", -1, "/", -1, TRUE); + } + if((ep = strchr(rp, '@')) != NULL){ + *ep = '\0'; + if(rp[0] != '\0') cbmapput(map, "authority", -1, rp, -1, TRUE); + rp = ep + 1; + } + if((ep = strchr(rp, ':')) != NULL){ + if(ep[1] != '\0') cbmapput(map, "port", -1, ep + 1, -1, TRUE); + *ep = '\0'; + } + if(rp[0] != '\0') cbmapput(map, "host", -1, rp, -1, TRUE); + } else { + cbmapput(map, "path", -1, rp, -1, TRUE); + } + free(tmp); + if((rp = cbmapget(map, "path", -1, NULL)) != NULL){ + if((ep = strrchr(rp, '/')) != NULL){ + if(ep[1] != '\0') cbmapput(map, "file", -1, ep + 1, -1, TRUE); + } else { + cbmapput(map, "file", -1, rp, -1, TRUE); + } + } + if((rp = cbmapget(map, "file", -1, NULL)) != NULL && (!strcmp(rp, ".") || !strcmp(rp, ".."))) + cbmapout(map, "file", -1); + return map; +} + + +/* Resolve a relative URL with another absolute URL. */ +char *cburlresolve(const char *base, const char *target){ + CBMAP *telems, *belems; + CBLIST *bpaths, *opaths, *qelems; + CBDATUM *rbuf; + const char *vbuf, *path; + char *tmp, *wp, *enc, numbuf[CB_NUMBUFSIZ]; + int i, vsiz, port, num; + assert(base && target); + while(*base > '\0' && *base <= ' '){ + base++; + } + while(*target > '\0' && *target <= ' '){ + target++; + } + if(*target == '\0') target = base; + CB_DATUMOPEN(rbuf); + telems = cburlbreak(target); + port = 80; + belems = cburlbreak(cbmapget(telems, "scheme", -1, &vsiz) ? target : base); + if((vbuf = cbmapget(belems, "scheme", -1, &vsiz)) != NULL){ + CB_DATUMCAT(rbuf, vbuf, vsiz); + CB_DATUMCAT(rbuf, "://", 3); + if(!cbstricmp(vbuf, "https")){ + port = 443; + } else if(!cbstricmp(vbuf, "ftp")){ + port = 21; + } else if(!cbstricmp(vbuf, "sftp")){ + port = 115; + } else if(!cbstricmp(vbuf, "ftps")){ + port = 22; + } else if(!cbstricmp(vbuf, "tftp")){ + port = 69; + } else if(!cbstricmp(vbuf, "ldap")){ + port = 389; + } else if(!cbstricmp(vbuf, "ldaps")){ + port = 636; + } + } else { + CB_DATUMCAT(rbuf, "http://", 7); + } + if((vbuf = cbmapget(belems, "authority", -1, &vsiz)) != NULL){ + if((wp = strchr(vbuf, ':')) != NULL){ + *wp = '\0'; + tmp = cburldecode(vbuf, NULL); + enc = cburlencode(tmp, -1); + CB_DATUMCAT(rbuf, enc, strlen(enc)); + free(enc); + free(tmp); + CB_DATUMCAT(rbuf, ":", 1); + wp++; + tmp = cburldecode(wp, NULL); + enc = cburlencode(tmp, -1); + CB_DATUMCAT(rbuf, enc, strlen(enc)); + free(enc); + free(tmp); + } else { + tmp = cburldecode(vbuf, NULL); + enc = cburlencode(tmp, -1); + CB_DATUMCAT(rbuf, enc, strlen(enc)); + free(enc); + free(tmp); + } + CB_DATUMCAT(rbuf, "@", 1); + } + if((vbuf = cbmapget(belems, "host", -1, &vsiz)) != NULL){ + tmp = cburldecode(vbuf, NULL); + cbstrtolower(tmp); + enc = cburlencode(tmp, -1); + CB_DATUMCAT(rbuf, enc, strlen(enc)); + free(enc); + free(tmp); + } else { + CB_DATUMCAT(rbuf, "localhost", 9); + } + if((vbuf = cbmapget(belems, "port", -1, &vsiz)) != NULL && + (num = atoi(vbuf)) != port && num > 1){ + sprintf(numbuf, ":%d", num); + CB_DATUMCAT(rbuf, numbuf, strlen(numbuf)); + } + if(!(path = cbmapget(telems, "path", -1, NULL))) path = "/"; + if(path[0] == '\0' && (vbuf = cbmapget(belems, "path", -1, NULL)) != NULL) path = vbuf; + if(path[0] == '\0') path = "/"; + CB_LISTOPEN(bpaths); + if(path[0] != '/' && (vbuf = cbmapget(belems, "path", -1, &vsiz)) != NULL){ + opaths = cbsplit(vbuf, vsiz, "/"); + } else { + opaths = cbsplit("/", 1, "/"); + } + CB_LISTDROP(opaths); + for(i = 0; i < CB_LISTNUM(opaths); i++){ + vbuf = CB_LISTVAL2(opaths, i, vsiz); + if(vsiz < 1 || !strcmp(vbuf, ".")) continue; + if(!strcmp(vbuf, "..")){ + CB_LISTDROP(bpaths); + } else { + CB_LISTPUSH(bpaths, vbuf, vsiz); + } + } + CB_LISTCLOSE(opaths); + opaths = cbsplit(path, -1, "/"); + for(i = 0; i < CB_LISTNUM(opaths); i++){ + vbuf = CB_LISTVAL2(opaths, i, vsiz); + if(vsiz < 1 || !strcmp(vbuf, ".")) continue; + if(!strcmp(vbuf, "..")){ + CB_LISTDROP(bpaths); + } else { + CB_LISTPUSH(bpaths, vbuf, vsiz); + } + } + CB_LISTCLOSE(opaths); + for(i = 0; i < CB_LISTNUM(bpaths); i++){ + vbuf = CB_LISTVAL(bpaths, i); + if(strchr(vbuf, '%')){ + tmp = cburldecode(vbuf, NULL); + } else { + CB_MEMDUP(tmp, vbuf, strlen(vbuf)); + } + enc = cburlencode(tmp, -1); + CB_DATUMCAT(rbuf, "/", 1); + CB_DATUMCAT(rbuf, enc, strlen(enc)); + free(enc); + free(tmp); + } + if(cbstrbwmatch(path, "/")) CB_DATUMCAT(rbuf, "/", 1); + CB_LISTCLOSE(bpaths); + if((vbuf = cbmapget(telems, "query", -1, &vsiz)) != NULL){ + CB_DATUMCAT(rbuf, "?", 1); + qelems = cbsplit(vbuf, vsiz, "&;"); + for(i = 0; i < CB_LISTNUM(qelems); i++){ + vbuf = CB_LISTVAL(qelems, i); + if(i > 0) CB_DATUMCAT(rbuf, "&", 1); + if((wp = strchr(vbuf, '=')) != NULL){ + *wp = '\0'; + tmp = cburldecode(vbuf, NULL); + enc = cburlencode(tmp, -1); + CB_DATUMCAT(rbuf, enc, strlen(enc)); + free(enc); + free(tmp); + CB_DATUMCAT(rbuf, "=", 1); + wp++; + tmp = cburldecode(wp, NULL); + enc = cburlencode(tmp, -1); + CB_DATUMCAT(rbuf, enc, strlen(enc)); + free(enc); + free(tmp); + } else { + tmp = cburldecode(vbuf, NULL); + enc = cburlencode(tmp, -1); + CB_DATUMCAT(rbuf, enc, strlen(enc)); + free(enc); + free(tmp); + } + } + CB_LISTCLOSE(qelems); + } + if((vbuf = cbmapget(telems, "fragment", -1, &vsiz)) != NULL){ + tmp = cburldecode(vbuf, NULL); + enc = cburlencode(tmp, -1); + CB_DATUMCAT(rbuf, "#", 1); + CB_DATUMCAT(rbuf, enc, strlen(enc)); + free(enc); + free(tmp); + } + cbmapclose(belems); + cbmapclose(telems); + return cbdatumtomalloc(rbuf, NULL); +} + + +/* Encode a serial object with URL encoding. */ +char *cburlencode(const char *ptr, int size){ + char *buf, *wp; + int i, c; + assert(ptr); + if(size < 0) size = strlen(ptr); + CB_MALLOC(buf, size * 3 + 1); + wp = buf; + for(i = 0; i < size; i++){ + c = ((unsigned char *)ptr)[i]; + if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.!~*'()", c))){ + *(wp++) = c; + } else { + wp += sprintf(wp, "%%%02X", c); + } + } + *wp = '\0'; + return buf; +} + + +/* Decode a string encoded with URL encoding. */ +char *cburldecode(const char *str, int *sp){ + char *buf, *wp; + unsigned char c; + CB_MEMDUP(buf, str, strlen(str)); + wp = buf; + while(*str != '\0'){ + if(*str == '%'){ + str++; + if(((str[0] >= '0' && str[0] <= '9') || (str[0] >= 'A' && str[0] <= 'F') || + (str[0] >= 'a' && str[0] <= 'f')) && + ((str[1] >= '0' && str[1] <= '9') || (str[1] >= 'A' && str[1] <= 'F') || + (str[1] >= 'a' && str[1] <= 'f'))){ + c = *str; + if(c >= 'A' && c <= 'Z') c += 'a' - 'A'; + if(c >= 'a' && c <= 'z'){ + *wp = c - 'a' + 10; + } else { + *wp = c - '0'; + } + *wp *= 0x10; + str++; + c = *str; + if(c >= 'A' && c <= 'Z') c += 'a' - 'A'; + if(c >= 'a' && c <= 'z'){ + *wp += c - 'a' + 10; + } else { + *wp += c - '0'; + } + str++; + wp++; + } else { + break; + } + } else if(*str == '+'){ + *wp = ' '; + str++; + wp++; + } else { + *wp = *str; + str++; + wp++; + } + } + *wp = '\0'; + if(sp) *sp = wp - buf; + return buf; +} + + +/* Encode a serial object with Base64 encoding. */ +char *cbbaseencode(const char *ptr, int size){ + char *tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + char *buf, *wp; + const unsigned char *obj; + int i; + assert(ptr); + if(size < 0) size = strlen(ptr); + CB_MALLOC(buf, 4 * (size + 2) / 3 + 1); + obj = (const unsigned char *)ptr; + wp = buf; + for(i = 0; i < size; i += 3){ + switch(size - i){ + case 1: + *wp++ = tbl[obj[0] >> 2]; + *wp++ = tbl[(obj[0] & 3) << 4]; + *wp++ = '='; + *wp++ = '='; + break; + case 2: + *wp++ = tbl[obj[0] >> 2]; + *wp++ = tbl[((obj[0] & 3) << 4) + (obj[1] >> 4)]; + *wp++ = tbl[(obj[1] & 0xf) << 2]; + *wp++ = '='; + break; + default: + *wp++ = tbl[obj[0] >> 2]; + *wp++ = tbl[((obj[0] & 3) << 4) + (obj[1] >> 4)]; + *wp++ = tbl[((obj[1] & 0xf) << 2) + (obj[2] >> 6)]; + *wp++ = tbl[obj[2] & 0x3f]; + break; + } + obj += 3; + } + *wp = '\0'; + return buf; +} + + +/* Decode a string encoded with Base64 encoding. */ +char *cbbasedecode(const char *str, int *sp){ + unsigned char *obj, *wp; + int len, cnt, bpos, i, bits, eqcnt; + assert(str); + cnt = 0; + bpos = 0; + eqcnt = 0; + len = strlen(str); + CB_MALLOC(obj, len + 4); + wp = obj; + while(bpos < len && eqcnt == 0){ + bits = 0; + for(i = 0; bpos < len && i < 4; bpos++){ + if(str[bpos] >= 'A' && str[bpos] <= 'Z'){ + bits = (bits << 6) | (str[bpos] - 'A'); + i++; + } else if(str[bpos] >= 'a' && str[bpos] <= 'z'){ + bits = (bits << 6) | (str[bpos] - 'a' + 26); + i++; + } else if(str[bpos] >= '0' && str[bpos] <= '9'){ + bits = (bits << 6) | (str[bpos] - '0' + 52); + i++; + } else if(str[bpos] == '+'){ + bits = (bits << 6) | 62; + i++; + } else if(str[bpos] == '/'){ + bits = (bits << 6) | 63; + i++; + } else if(str[bpos] == '='){ + bits <<= 6; + i++; + eqcnt++; + } + } + if(i == 0 && bpos >= len) continue; + switch(eqcnt){ + case 0: + *wp++ = (bits >> 16) & 0xff; + *wp++ = (bits >> 8) & 0xff; + *wp++ = bits & 0xff; + cnt += 3; + break; + case 1: + *wp++ = (bits >> 16) & 0xff; + *wp++ = (bits >> 8) & 0xff; + cnt += 2; + break; + case 2: + *wp++ = (bits >> 16) & 0xff; + cnt += 1; + break; + } + } + obj[cnt] = '\0'; + if(sp) *sp = cnt; + return (char *)obj; +} + + +/* Encode a serial object with quoted-printable encoding. */ +char *cbquoteencode(const char *ptr, int size){ + const unsigned char *rp; + char *buf, *wp; + int i, cols; + assert(ptr); + if(size < 0) size = strlen(ptr); + rp = (const unsigned char *)ptr; + CB_MALLOC(buf, size * 3 + 1); + wp = buf; + cols = 0; + for(i = 0; i < size; i++){ + if(rp[i] == '=' || (rp[i] < 0x20 && rp[i] != '\r' && rp[i] != '\n' && rp[i] != '\t') || + rp[i] > 0x7e){ + wp += sprintf(wp, "=%02X", rp[i]); + cols += 3; + } else { + *(wp++) = rp[i]; + cols++; + } + } + *wp = '\0'; + return buf; +} + + +/* Decode a string encoded with quoted-printable encoding. */ +char *cbquotedecode(const char *str, int *sp){ + char *buf, *wp; + assert(str); + CB_MALLOC(buf, strlen(str) + 1); + wp = buf; + for(; *str != '\0'; str++){ + if(*str == '='){ + str++; + if(*str == '\0'){ + break; + } else if(str[0] == '\r' && str[1] == '\n'){ + str++; + } else if(str[0] != '\n' && str[0] != '\r'){ + if(*str >= 'A' && *str <= 'Z'){ + *wp = (*str - 'A' + 10) * 16; + } else if(*str >= 'a' && *str <= 'z'){ + *wp = (*str - 'a' + 10) * 16; + } else { + *wp = (*str - '0') * 16; + } + str++; + if(*str == '\0') break; + if(*str >= 'A' && *str <= 'Z'){ + *wp += *str - 'A' + 10; + } else if(*str >= 'a' && *str <= 'z'){ + *wp += *str - 'a' + 10; + } else { + *wp += *str - '0'; + } + wp++; + } + } else { + *wp = *str; + wp++; + } + } + *wp = '\0'; + if(sp) *sp = wp - buf; + return buf; +} + + +/* Split a string of MIME into headers and the body. */ +char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp){ + CBLIST *list; + const char *head, *line, *pv, *ep; + char *hbuf, *name, *rv; + int i, j, wi, hlen; + assert(ptr); + if(size < 0) size = strlen(ptr); + head = NULL; + hlen = 0; + for(i = 0; i < size; i++){ + if(i < size - 4 && ptr[i] == '\r' && ptr[i+1] == '\n' && + ptr[i+2] == '\r' && ptr[i+3] == '\n'){ + head = ptr; + hlen = i; + ptr += i + 4; + size -= i + 4; + break; + } else if(i < size - 2 && ptr[i] == '\n' && ptr[i+1] == '\n'){ + head = ptr; + hlen = i; + ptr += i + 2; + size -= i + 2; + break; + } + } + if(head && attrs){ + CB_MALLOC(hbuf, hlen + 1); + wi = 0; + for(i = 0; i < hlen; i++){ + if(head[i] == '\r') continue; + if(i < hlen - 1 && head[i] == '\n' && (head[i+1] == ' ' || head[i+1] == '\t')){ + hbuf[wi++] = ' '; + i++; + } else { + hbuf[wi++] = head[i]; + } + } + list = cbsplit(hbuf, wi, "\n"); + for(i = 0; i < CB_LISTNUM(list); i++){ + line = CB_LISTVAL(list, i); + if((pv = strchr(line, ':')) != NULL){ + CB_MEMDUP(name, line, pv - line); + for(j = 0; name[j] != '\0'; j++){ + if(name[j] >= 'A' && name[j] <= 'Z') name[j] -= 'A' - 'a'; + } + pv++; + while(*pv == ' ' || *pv == '\t'){ + pv++; + } + cbmapput(attrs, name, -1, pv, -1, TRUE); + free(name); + } + + } + CB_LISTCLOSE(list); + free(hbuf); + if((pv = cbmapget(attrs, "content-type", -1, NULL)) != NULL){ + if((ep = strchr(pv, ';')) != NULL){ + cbmapput(attrs, "TYPE", -1, pv, ep - pv, TRUE); + do { + ep++; + while(ep[0] == ' '){ + ep++; + } + if(cbstrfwimatch(ep, "charset=")){ + ep += 8; + while(*ep > '\0' && *ep <= ' '){ + ep++; + } + if(ep[0] == '"') ep++; + pv = ep; + while(ep[0] != '\0' && ep[0] != ' ' && ep[0] != '"' && ep[0] != ';'){ + ep++; + } + cbmapput(attrs, "CHARSET", -1, pv, ep - pv, TRUE); + } else if(cbstrfwimatch(ep, "boundary=")){ + ep += 9; + while(*ep > '\0' && *ep <= ' '){ + ep++; + } + if(ep[0] == '"'){ + ep++; + pv = ep; + while(ep[0] != '\0' && ep[0] != '"'){ + ep++; + } + } else { + pv = ep; + while(ep[0] != '\0' && ep[0] != ' ' && ep[0] != '"' && ep[0] != ';'){ + ep++; + } + } + cbmapput(attrs, "BOUNDARY", -1, pv, ep - pv, TRUE); + } + } while((ep = strchr(ep, ';')) != NULL); + } else { + cbmapput(attrs, "TYPE", -1, pv, -1, TRUE); + } + } + if((pv = cbmapget(attrs, "content-disposition", -1, NULL)) != NULL){ + if((ep = strchr(pv, ';')) != NULL){ + cbmapput(attrs, "DISPOSITION", -1, pv, ep - pv, TRUE); + do { + ep++; + while(ep[0] == ' '){ + ep++; + } + if(cbstrfwimatch(ep, "filename=")){ + ep += 9; + if(ep[0] == '"') ep++; + pv = ep; + while(ep[0] != '\0' && ep[0] != '"'){ + ep++; + } + cbmapput(attrs, "FILENAME", -1, pv, ep - pv, TRUE); + } else if(cbstrfwimatch(ep, "name=")){ + ep += 5; + if(ep[0] == '"') ep++; + pv = ep; + while(ep[0] != '\0' && ep[0] != '"'){ + ep++; + } + cbmapput(attrs, "NAME", -1, pv, ep - pv, TRUE); + } + } while((ep = strchr(ep, ';')) != NULL); + } else { + cbmapput(attrs, "DISPOSITION", -1, pv, -1, TRUE); + } + } + } + if(sp) *sp = size; + CB_MEMDUP(rv, ptr, size); + return rv; +} + + +/* Split multipart data in MIME into its parts. */ +CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary){ + CBLIST *list; + const char *pv, *ep; + int i, blen; + assert(ptr && boundary); + if(size < 0) size = strlen(ptr); + CB_LISTOPEN(list); + if((blen = strlen(boundary)) < 1) return list; + pv = NULL; + for(i = 0; i < size; i++){ + if(ptr[i] == '-' && ptr[i+1] == '-' && i + 2 + blen < size && + cbstrfwmatch(ptr + i + 2, boundary) && strchr("\t\n\v\f\r ", ptr[i+2+blen])){ + pv = ptr + i + 2 + blen; + if(*pv == '\r') pv++; + if(*pv == '\n') pv++; + size -= pv - ptr; + ptr = pv; + break; + } + } + if(!pv) return list; + for(i = 0; i < size; i++){ + if(ptr[i] == '-' && ptr[i+1] == '-' && i + 2 + blen < size && + cbstrfwmatch(ptr + i + 2, boundary) && strchr("\t\n\v\f\r -", ptr[i+2+blen])){ + ep = ptr + i; + if(ep > ptr && ep[-1] == '\n') ep--; + if(ep > ptr && ep[-1] == '\r') ep--; + if(ep > pv) CB_LISTPUSH(list, pv, ep - pv); + pv = ptr + i + 2 + blen; + if(*pv == '\r') pv++; + if(*pv == '\n') pv++; + } + } + return list; +} + + +/* Encode a string with MIME encoding. */ +char *cbmimeencode(const char *str, const char *encname, int base){ + char *buf, *wp, *enc; + int len; + assert(str && encname); + len = strlen(str); + CB_MALLOC(buf, len * 3 + strlen(encname) + 16); + wp = buf; + wp += sprintf(wp, "=?%s?%c?", encname, base ? 'B' : 'Q'); + enc = base ? cbbaseencode(str, len) : cbquoteencode(str, len); + wp += sprintf(wp, "%s?=", enc); + free(enc); + return buf; +} + + +/* Decode a string encoded with MIME encoding. */ +char *cbmimedecode(const char *str, char *enp){ + char *buf, *wp, *tmp, *dec; + const char *pv, *ep; + int quoted; + assert(str); + if(enp) sprintf(enp, "US-ASCII"); + CB_MALLOC(buf, strlen(str) + 1); + wp = buf; + while(*str != '\0'){ + if(cbstrfwmatch(str, "=?")){ + str += 2; + pv = str; + if(!(ep = strchr(str, '?'))) continue; + if(enp && ep - pv < CB_ENCBUFSIZ){ + memcpy(enp, pv, ep - pv); + enp[ep-pv] = '\0'; + } + pv = ep + 1; + quoted = (*pv == 'Q' || *pv == 'q'); + if(*pv != '\0') pv++; + if(*pv != '\0') pv++; + if(!(ep = strchr(pv, '?'))) continue; + CB_MEMDUP(tmp, pv, ep - pv); + dec = quoted ? cbquotedecode(tmp, NULL) : cbbasedecode(tmp, NULL); + wp += sprintf(wp, "%s", dec); + free(dec); + free(tmp); + str = ep + 1; + if(*str != '\0') str++; + } else { + *(wp++) = *str; + str++; + } + } + *wp = '\0'; + return buf; +} + + +/* Split a string of CSV into rows. */ +CBLIST *cbcsvrows(const char *str){ + CBLIST *list; + const char *pv; + int quoted; + assert(str); + CB_LISTOPEN(list); + pv = str; + quoted = FALSE; + while(TRUE){ + if(*str == '"') quoted = !quoted; + if(!quoted && (*str == '\r' || *str == '\n')){ + CB_LISTPUSH(list, pv, str - pv); + if(str[0] == '\r' && str[1] == '\n') str++; + str++; + pv = str; + } else if(*str == '\0'){ + if(str > pv) CB_LISTPUSH(list, pv, str - pv); + break; + } else { + str++; + } + } + return list; +} + + +/* Split a string of a row of CSV into cells. */ +CBLIST *cbcsvcells(const char *str){ + CBLIST *list, *uelist; + const char *pv; + char *tmp; + int i, quoted; + assert(str); + CB_LISTOPEN(list); + pv = str; + quoted = FALSE; + while(TRUE){ + if(*str == '"') quoted = !quoted; + if(!quoted && *str == ','){ + CB_LISTPUSH(list, pv, str - pv); + str++; + pv = str; + } else if(*str == '\0'){ + CB_LISTPUSH(list, pv, str - pv); + break; + } else { + str++; + } + } + CB_LISTOPEN(uelist); + for(i = 0; i < CB_LISTNUM(list); i++){ + tmp = cbcsvunescape(CB_LISTVAL(list, i)); + CB_LISTPUSH(uelist, tmp, strlen(tmp)); + free(tmp); + } + CB_LISTCLOSE(list); + return uelist; +} + + +/* Escape a string with the meta characters of CSV. */ +char *cbcsvescape(const char *str){ + char *buf, *wp; + int i; + assert(str); + CB_MALLOC(buf, strlen(str) * 2 + 3); + wp = buf; + *(wp++) = '"'; + for(i = 0; str[i] != '\0'; i++){ + if(str[i] == '"') *(wp++) = '"'; + *(wp++) = str[i]; + } + *(wp++) = '"'; + *wp = '\0'; + return buf; +} + + +/* Unescape a string with the escaped meta characters of CSV. */ +char *cbcsvunescape(const char *str){ + char *buf, *wp; + int i, len; + assert(str); + len = strlen(str); + if(str[0] == '"'){ + str++; + len--; + if(str[len-1] == '"') len--; + } + CB_MALLOC(buf, len + 1); + wp = buf; + for(i = 0; i < len; i++){ + if(str[i] == '"'){ + if(str[i+1] == '"') *(wp++) = str[i++]; + } else { + *(wp++) = str[i]; + } + } + *wp = '\0'; + return buf; +} + + +/* Split a string of XML into tags and text sections. */ +CBLIST *cbxmlbreak(const char *str, int cr){ + CBLIST *list; + CBDATUM *datum; + int i, pv, tag; + char *ep; + assert(str); + CB_LISTOPEN(list); + i = 0; + pv = 0; + tag = FALSE; + while(TRUE){ + if(str[i] == '\0'){ + if(i > pv) CB_LISTPUSH(list, str + pv, i - pv); + break; + } else if(!tag && str[i] == '<'){ + if(str[i+1] == '!' && str[i+2] == '-' && str[i+3] == '-'){ + if(i > pv) CB_LISTPUSH(list, str + pv, i - pv); + if((ep = strstr(str + i, "-->")) != NULL){ + if(!cr) CB_LISTPUSH(list, str + i, ep - str - i + 3); + i = ep - str + 2; + pv = i + 1; + } + } else if(str[i+1] == '!' && str[i+2] == '[' && cbstrfwimatch(str + i, " pv) CB_LISTPUSH(list, str + pv, i - pv); + if((ep = strstr(str + i, "]]>")) != NULL){ + i += 9; + CB_DATUMOPEN(datum); + while(str + i < ep){ + if(str[i] == '&'){ + CB_DATUMCAT(datum, "&", 5); + } else if(str[i] == '<'){ + CB_DATUMCAT(datum, "<", 4); + } else if(str[i] == '>'){ + CB_DATUMCAT(datum, ">", 4); + } else { + CB_DATUMCAT(datum, str + i, 1); + } + i++; + } + if(CB_DATUMSIZE(datum) > 0) CB_LISTPUSH(list, CB_DATUMPTR(datum), CB_DATUMSIZE(datum)); + CB_DATUMCLOSE(datum); + i = ep - str + 2; + pv = i + 1; + } + } else { + if(i > pv) CB_LISTPUSH(list, str + pv, i - pv); + tag = TRUE; + pv = i; + } + } else if(tag && str[i] == '>'){ + if(i > pv) CB_LISTPUSH(list, str + pv, i - pv + 1); + tag = FALSE; + pv = i + 1; + } + i++; + } + return list; +} + + +/* Get the map of attributes of a XML tag. */ +CBMAP *cbxmlattrs(const char *str){ + CBMAP *map; + const unsigned char *rp, *key, *val; + char *copy, *raw; + int ksiz, vsiz; + assert(str); + map = cbmapopenex(CB_MAPPBNUM); + rp = (unsigned char *)str; + while(*rp == '<' || *rp == '/' || *rp == '?' || *rp == '!' || *rp == ' '){ + rp++; + } + key = rp; + while(*rp > 0x20 && *rp != '/' && *rp != '>'){ + rp++; + } + cbmapput(map, "", -1, (char *)key, rp - key, FALSE); + while(*rp != '\0'){ + while(*rp != '\0' && (*rp <= 0x20 || *rp == '/' || *rp == '?' || *rp == '>')){ + rp++; + } + key = rp; + while(*rp > 0x20 && *rp != '/' && *rp != '>' && *rp != '='){ + rp++; + } + ksiz = rp - key; + while(*rp != '\0' && (*rp == '=' || *rp <= 0x20)){ + rp++; + } + if(*rp == '"'){ + rp++; + val = rp; + while(*rp != '\0' && *rp != '"'){ + rp++; + } + vsiz = rp - val; + } else if(*rp == '\''){ + rp++; + val = rp; + while(*rp != '\0' && *rp != '\''){ + rp++; + } + vsiz = rp - val; + } else { + val = rp; + while(*rp > 0x20 && *rp != '"' && *rp != '\'' && *rp != '>'){ + rp++; + } + vsiz = rp - val; + } + if(*rp != '\0') rp++; + if(ksiz > 0){ + CB_MEMDUP(copy, (char *)val, vsiz); + raw = cbxmlunescape(copy); + cbmapput(map, (char *)key, ksiz, raw, -1, FALSE); + free(raw); + free(copy); + } + } + return map; +} + + +/* Escape a string with the meta characters of XML. */ +char *cbxmlescape(const char *str){ + CBDATUM *datum; + assert(str); + CB_DATUMOPEN(datum); + while(*str != '\0'){ + switch(*str){ + case '&': + CB_DATUMCAT(datum, "&", 5); + break; + case '<': + CB_DATUMCAT(datum, "<", 4); + break; + case '>': + CB_DATUMCAT(datum, ">", 4); + break; + case '"': + CB_DATUMCAT(datum, """, 6); + break; + case '\'': + CB_DATUMCAT(datum, "'", 6); + break; + default: + CB_DATUMCAT(datum, str, 1); + break; + } + str++; + } + return cbdatumtomalloc(datum, NULL); +} + + +/* Unescape a string with the entity references of XML. */ +char *cbxmlunescape(const char *str){ + CBDATUM *datum; + assert(str); + CB_DATUMOPEN(datum); + while(*str != '\0'){ + if(*str == '&'){ + if(cbstrfwmatch(str, "&")){ + CB_DATUMCAT(datum, "&", 1); + str += 5; + } else if(cbstrfwmatch(str, "<")){ + CB_DATUMCAT(datum, "<", 1); + str += 4; + } else if(cbstrfwmatch(str, ">")){ + CB_DATUMCAT(datum, ">", 1); + str += 4; + } else if(cbstrfwmatch(str, """)){ + CB_DATUMCAT(datum, "\"", 1); + str += 6; + } else if(cbstrfwmatch(str, "'")){ + CB_DATUMCAT(datum, "'", 1); + str += 6; + } else { + CB_DATUMCAT(datum, str, 1); + str++; + } + } else { + CB_DATUMCAT(datum, str, 1); + str++; + } + } + return cbdatumtomalloc(datum, NULL); +} + + +/* Compress a serial object with ZLIB. */ +char *cbdeflate(const char *ptr, int size, int *sp){ + assert(ptr && sp); + if(!_qdbm_deflate) return NULL; + return _qdbm_deflate(ptr, size, sp, _QDBM_ZMZLIB); +} + + +/* Decompress a serial object compressed with ZLIB. */ +char *cbinflate(const char *ptr, int size, int *sp){ + assert(ptr && size >= 0); + if(!_qdbm_inflate) return NULL; + return _qdbm_inflate(ptr, size, sp, _QDBM_ZMZLIB); +} + + +/* Compress a serial object with GZIP. */ +char *cbgzencode(const char *ptr, int size, int *sp){ + assert(ptr && sp); + if(!_qdbm_deflate) return NULL; + return _qdbm_deflate(ptr, size, sp, _QDBM_ZMGZIP); +} + + +/* Decompress a serial object compressed with GZIP. */ +char *cbgzdecode(const char *ptr, int size, int *sp){ + assert(ptr && size >= 0); + if(!_qdbm_inflate) return NULL; + return _qdbm_inflate(ptr, size, sp, _QDBM_ZMGZIP); +} + + +/* Get the CRC32 checksum of a serial object. */ +unsigned int cbgetcrc(const char *ptr, int size){ + assert(ptr); + if(!_qdbm_inflate) return 0; + return _qdbm_getcrc(ptr, size); +} + + +/* Compress a serial object with LZO. */ +char *cblzoencode(const char *ptr, int size, int *sp){ + assert(ptr && sp); + if(!_qdbm_lzoencode) return NULL; + return _qdbm_lzoencode(ptr, size, sp); +} + + +/* Decompress a serial object compressed with LZO. */ +char *cblzodecode(const char *ptr, int size, int *sp){ + assert(ptr && size >= 0); + if(!_qdbm_lzodecode) return NULL; + return _qdbm_lzodecode(ptr, size, sp); +} + + +/* Compress a serial object with BZIP2. */ +char *cbbzencode(const char *ptr, int size, int *sp){ + assert(ptr && sp); + if(!_qdbm_bzencode) return NULL; + return _qdbm_bzencode(ptr, size, sp); +} + + +/* Decompress a serial object compressed with BZIP2. */ +char *cbbzdecode(const char *ptr, int size, int *sp){ + assert(ptr && size >= 0); + if(!_qdbm_bzdecode) return NULL; + return _qdbm_bzdecode(ptr, size, sp); +} + + +/* Convert the character encoding of a string. */ +char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp){ + char *res; + assert(ptr && icode && ocode); + if(!_qdbm_iconv) return NULL; + if((res = _qdbm_iconv(ptr, size, icode, ocode, sp, mp)) != NULL) return res; + if(!cbstricmp(icode, ocode)){ + if(sp) *sp = size; + if(mp) *mp = 0; + CB_MEMDUP(res, ptr, size < 0 ? strlen(ptr) : size); + return res; + } + return NULL; +} + + +/* Detect the encoding of a string automatically. */ +const char *cbencname(const char *ptr, int size){ + assert(ptr); + if(!_qdbm_encname) return "ISO-8859-1"; + return _qdbm_encname(ptr, size); +} + + +/* Get the jet lag of the local time in seconds. */ +int cbjetlag(void){ + struct tm ts, *tp; + time_t t, gt, lt; + if((t = time(NULL)) < 0) return 0; + if(!(tp = _qdbm_gmtime(&t, &ts))) return 0; + if((gt = mktime(tp)) < 0) return 0; + if(!(tp = _qdbm_localtime(&t, &ts))) return 0; + if((lt = mktime(tp)) < 0) return 0; + return lt - gt; +} + + +/* Get the Gregorian calendar of a time. */ +void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp){ + struct tm ts, *tp; + if(t < 0) t = time(NULL); + t += jl; + if(!(tp = _qdbm_gmtime(&t, &ts))) return; + if(yearp) *yearp = tp->tm_year + 1900; + if(monp) *monp = tp->tm_mon + 1; + if(dayp) *dayp = tp->tm_mday; + if(hourp) *hourp = tp->tm_hour; + if(minp) *minp = tp->tm_min; + if(secp) *secp = tp->tm_sec; +} + + +/* Get the day of week of a date. */ +int cbdayofweek(int year, int mon, int day){ + if(mon < 3){ + year--; + mon += 12; + } + return (day + ((8 + (13 * mon)) / 5) + (year + (year / 4) - (year / 100) + (year / 400))) % 7; +} + + +/* Get the string for a date in W3CDTF. */ +char *cbdatestrwww(time_t t, int jl){ + char date[CB_DATEBUFSIZ], tzone[CB_DATEBUFSIZ], *rv; + int year, mon, day, hour, min, sec; + cbcalendar(t, jl, &year, &mon, &day, &hour, &min, &sec); + jl /= 60; + if(jl == 0){ + sprintf(tzone, "Z"); + } else if(jl < 0){ + jl *= -1; + sprintf(tzone, "-%02d:%02d", jl / 60, jl % 60); + } else { + sprintf(tzone, "+%02d:%02d", jl / 60, jl % 60); + } + sprintf(date, "%04d-%02d-%02dT%02d:%02d:%02d%s", year, mon, day, hour, min, sec, tzone); + CB_MEMDUP(rv, date, strlen(date)); + return rv; +} + + +/* Get the string for a date in RFC 1123 format. */ +char *cbdatestrhttp(time_t t, int jl){ + char date[CB_DATEBUFSIZ], *wp, *rv; + int year, mon, day, hour, min, sec; + cbcalendar(t, jl, &year, &mon, &day, &hour, &min, &sec); + jl /= 60; + wp = date; + switch(cbdayofweek(year, mon, day)){ + case 0: wp += sprintf(wp, "Sun, "); break; + case 1: wp += sprintf(wp, "Mon, "); break; + case 2: wp += sprintf(wp, "Tue, "); break; + case 3: wp += sprintf(wp, "Wed, "); break; + case 4: wp += sprintf(wp, "Thu, "); break; + case 5: wp += sprintf(wp, "Fri, "); break; + case 6: wp += sprintf(wp, "Sat, "); break; + } + wp += sprintf(wp, "%02d ", day); + switch(mon){ + case 1: wp += sprintf(wp, "Jan "); break; + case 2: wp += sprintf(wp, "Feb "); break; + case 3: wp += sprintf(wp, "Mar "); break; + case 4: wp += sprintf(wp, "Apr "); break; + case 5: wp += sprintf(wp, "May "); break; + case 6: wp += sprintf(wp, "Jun "); break; + case 7: wp += sprintf(wp, "Jul "); break; + case 8: wp += sprintf(wp, "Aug "); break; + case 9: wp += sprintf(wp, "Sep "); break; + case 10: wp += sprintf(wp, "Oct "); break; + case 11: wp += sprintf(wp, "Nov "); break; + case 12: wp += sprintf(wp, "Dec "); break; + } + wp += sprintf(wp, "%04d %02d:%02d:%02d ", year, hour, min, sec); + if(jl == 0){ + wp += sprintf(wp, "GMT"); + } else if(jl < 0){ + jl *= -1; + wp += sprintf(wp, "-%02d%02d", jl / 60, jl % 60); + } else { + wp += sprintf(wp, "+%02d%02d", jl / 60, jl % 60); + } + CB_MEMDUP(rv, date, strlen(date)); + return rv; +} + + +/* Get the time value of a date string in decimal, W3CDTF, or RFC 1123. */ +time_t cbstrmktime(const char *str){ + const char *crp; + char *pv, *rp; + int len, clen; + time_t t; + struct tm ts; + assert(str); + while(*str > '\0' && *str <= ' '){ + str++; + } + if(*str == '\0') return -1; + if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) return (time_t)strtol(str + 2, NULL, 16); + memset(&ts, 0, sizeof(struct tm)); + ts.tm_year = 70; + ts.tm_mon = 0; + ts.tm_mday = 1; + ts.tm_hour = 0; + ts.tm_min = 0; + ts.tm_sec = 0; + ts.tm_isdst = 0; + len = strlen(str); + t = (time_t)strtol(str, &pv, 10); + if(*(signed char *)pv >= '\0' && *pv <= ' '){ + while(*pv > '\0' && *pv <= ' '){ + pv++; + } + if(*pv == '\0') return t; + } + if((pv[0] == 's' || pv[0] == 'S') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') + return t; + if((pv[0] == 'm' || pv[0] == 'M') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') + return t * 60; + if((pv[0] == 'h' || pv[0] == 'H') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') + return t * 60 * 60; + if((pv[0] == 'd' || pv[0] == 'D') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') + return t * 60 * 60 * 24; + if(len > 4 && str[4] == '-'){ + ts.tm_year = atoi(str) - 1900; + if((pv = strchr(str, '-')) != NULL && pv - str == 4){ + rp = pv + 1; + ts.tm_mon = atoi(rp) - 1; + if((pv = strchr(rp, '-')) != NULL && pv - str == 7){ + rp = pv + 1; + ts.tm_mday = atoi(rp); + if((pv = strchr(rp, 'T')) != NULL && pv - str == 10){ + rp = pv + 1; + ts.tm_hour = atoi(rp); + if((pv = strchr(rp, ':')) != NULL && pv - str == 13){ + rp = pv + 1; + ts.tm_min = atoi(rp); + } + if((pv = strchr(rp, ':')) != NULL && pv - str == 16){ + rp = pv + 1; + ts.tm_sec = atoi(rp); + } + if((pv = strchr(rp, '.')) != NULL && pv - str >= 19) rp = pv + 1; + strtol(rp, &pv, 10); + if((*pv == '+' || *pv == '-') && strlen(pv) >= 6 && pv[3] == ':') + ts.tm_sec -= (atoi(pv + 1) * 3600 + atoi(pv + 4) * 60) * (pv[0] == '+' ? 1 : -1); + } + } + } + ts.tm_sec += cbjetlag(); + return mktime(&ts); + } + if(len > 4 && str[4] == '/'){ + ts.tm_year = atoi(str) - 1900; + if((pv = strchr(str, '/')) != NULL && pv - str == 4){ + rp = pv + 1; + ts.tm_mon = atoi(rp) - 1; + if((pv = strchr(rp, '/')) != NULL && pv - str == 7){ + rp = pv + 1; + ts.tm_mday = atoi(rp); + if((pv = strchr(rp, ' ')) != NULL && pv - str == 10){ + rp = pv + 1; + ts.tm_hour = atoi(rp); + if((pv = strchr(rp, ':')) != NULL && pv - str == 13){ + rp = pv + 1; + ts.tm_min = atoi(rp); + } + if((pv = strchr(rp, ':')) != NULL && pv - str == 16){ + rp = pv + 1; + ts.tm_sec = atoi(rp); + } + if((pv = strchr(rp, '.')) != NULL && pv - str >= 19) rp = pv + 1; + strtol(rp, &pv, 10); + if((*pv == '+' || *pv == '-') && strlen(pv) >= 6 && pv[3] == ':') + ts.tm_sec -= (atoi(pv + 1) * 3600 + atoi(pv + 4) * 60) * (pv[0] == '+' ? 1 : -1); + } + } + } + ts.tm_sec += cbjetlag(); + return mktime(&ts); + } + crp = str; + if(len >= 4 && str[3] == ',') crp = str + 4; + while(*crp == ' '){ + crp++; + } + ts.tm_mday = atoi(crp); + while((*crp >= '0' && *crp <= '9') || *crp == ' '){ + crp++; + } + if(cbstrfwimatch(crp, "Jan")){ + ts.tm_mon = 0; + } else if(cbstrfwimatch(crp, "Feb")){ + ts.tm_mon = 1; + } else if(cbstrfwimatch(crp, "Mar")){ + ts.tm_mon = 2; + } else if(cbstrfwimatch(crp, "Apr")){ + ts.tm_mon = 3; + } else if(cbstrfwimatch(crp, "May")){ + ts.tm_mon = 4; + } else if(cbstrfwimatch(crp, "Jun")){ + ts.tm_mon = 5; + } else if(cbstrfwimatch(crp, "Jul")){ + ts.tm_mon = 6; + } else if(cbstrfwimatch(crp, "Aug")){ + ts.tm_mon = 7; + } else if(cbstrfwimatch(crp, "Sep")){ + ts.tm_mon = 8; + } else if(cbstrfwimatch(crp, "Oct")){ + ts.tm_mon = 9; + } else if(cbstrfwimatch(crp, "Nov")){ + ts.tm_mon = 10; + } else if(cbstrfwimatch(crp, "Dec")){ + ts.tm_mon = 11; + } else { + ts.tm_mon = -1; + } + if(ts.tm_mon >= 0) crp += 3; + while(*crp == ' '){ + crp++; + } + ts.tm_year = atoi(crp); + if(ts.tm_year >= 1969) ts.tm_year -= 1900; + while(*crp >= '0' && *crp <= '9'){ + crp++; + } + while(*crp == ' '){ + crp++; + } + if(ts.tm_mday > 0 && ts.tm_mon >= 0 && ts.tm_year >= 0){ + clen = strlen(crp); + if(clen >= 8 && crp[2] == ':' && crp[5] == ':'){ + ts.tm_hour = atoi(crp + 0); + ts.tm_min = atoi(crp + 3); + ts.tm_sec = atoi(crp + 6); + if(clen >= 14 && crp[8] == ' ' && (crp[9] == '+' || crp[9] == '-')){ + ts.tm_sec -= ((crp[10] - '0') * 36000 + (crp[11] - '0') * 3600 + + (crp[12] - '0') * 600 + (crp[13] - '0') * 60) * (crp[9] == '+' ? 1 : -1); + } else if(clen > 9){ + if(!strcmp(crp + 9, "JST")){ + ts.tm_sec -= 9 * 3600; + } else if(!strcmp(crp + 9, "CCT")){ + ts.tm_sec -= 8 * 3600; + } else if(!strcmp(crp + 9, "KST")){ + ts.tm_sec -= 9 * 3600; + } else if(!strcmp(crp + 9, "EDT")){ + ts.tm_sec -= -4 * 3600; + } else if(!strcmp(crp + 9, "EST")){ + ts.tm_sec -= -5 * 3600; + } else if(!strcmp(crp + 9, "CDT")){ + ts.tm_sec -= -5 * 3600; + } else if(!strcmp(crp + 9, "CST")){ + ts.tm_sec -= -6 * 3600; + } else if(!strcmp(crp + 9, "MDT")){ + ts.tm_sec -= -6 * 3600; + } else if(!strcmp(crp + 9, "MST")){ + ts.tm_sec -= -7 * 3600; + } else if(!strcmp(crp + 9, "PDT")){ + ts.tm_sec -= -7 * 3600; + } else if(!strcmp(crp + 9, "PST")){ + ts.tm_sec -= -8 * 3600; + } else if(!strcmp(crp + 9, "HDT")){ + ts.tm_sec -= -9 * 3600; + } else if(!strcmp(crp + 9, "HST")){ + ts.tm_sec -= -10 * 3600; + } + } + } + ts.tm_sec += cbjetlag(); + return mktime(&ts); + } + return -1; +} + + +/* Get user and system processing times. */ +void cbproctime(double *usrp, double *sysp){ + struct tms buf; + times(&buf); + if(usrp) *usrp = (double)buf.tms_utime / sysconf(_SC_CLK_TCK); + if(sysp) *sysp = (double)buf.tms_stime / sysconf(_SC_CLK_TCK); +} + + +/* Ensure that the standard I/O is binary mode. */ +void cbstdiobin(void){ + if(setmode(0, O_BINARY) == -1 || setmode(1, O_BINARY) == -1 || setmode(2, O_BINARY) == -1) + cbmyfatal("setmode failed"); +} + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Show error message on the standard error output and exit. */ +void *cbmyfatal(const char *message){ + char buf[CB_MSGBUFSIZ]; + assert(message); + if(cbfatalfunc){ + cbfatalfunc(message); + } else { + sprintf(buf, "fatal error: %s\n", message); + write(2, buf, strlen(buf)); + } + exit(1); + return NULL; +} + + +/* Create a datum handle from an allocated region. */ +CBDATUM *cbdatumopenbuf(char *ptr, int size){ + CBDATUM *datum; + assert(ptr && size >= 0); + CB_REALLOC(ptr, size + 1); + CB_MALLOC(datum, sizeof(*datum)); + datum->dptr = ptr; + datum->dptr[size] = '\0'; + datum->dsize = size; + datum->asize = size; + return datum; +} + + +/* Set a buffer to a datum handle. */ +void cbdatumsetbuf(CBDATUM *datum, char *ptr, int size){ + assert(datum && ptr && size >= 0); + free(datum->dptr); + CB_REALLOC(ptr, size + 1); + datum->dptr = ptr; + datum->dptr[size] = '\0'; + datum->dsize = size; + datum->asize = size; +} + + +/* Add an allocated element at the end of a list. */ +void cblistpushbuf(CBLIST *list, char *ptr, int size){ + int index; + assert(list && ptr && size >= 0); + index = list->start + list->num; + if(index >= list->anum){ + list->anum *= 2; + CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); + } + list->array[index].dptr = ptr; + list->array[index].dsize = size; + list->num++; +} + + +/* Get a map handle with specifying the number of buckets. */ +CBMAP *cbmapopenex(int bnum){ + CBMAP *map; + int i; + assert(bnum > 0); + CB_MALLOC(map, sizeof(*map)); + CB_MALLOC(map->buckets, sizeof(map->buckets[0]) * bnum); + for(i = 0; i < bnum; i++){ + map->buckets[i] = NULL; + } + map->first = NULL; + map->last = NULL; + map->cur = NULL; + map->bnum = bnum; + map->rnum = 0; + return map; +} + + + +/************************************************************************************************* + * private objects + *************************************************************************************************/ + + +/* Handler to invoke the global garbage collector. */ +static void cbggchandler(void){ + cbggckeeper(NULL, NULL); +} + + +/* Manage resources of the global garbage collector. + `ptr' specifies the pointer to add to the collection. If it is `NULL', all resources are + released. + `func' specifies the pointer to the function to release the resources. */ +static void cbggckeeper(void *ptr, void (*func)(void *)){ + static void **parray = NULL; + static void (**farray)(void *) = NULL; + static int onum = 0; + static int asiz = CB_GCUNIT; + int i; + if(!ptr){ + if(!parray) return; + for(i = onum - 1; i >= 0; i--){ + farray[i](parray[i]); + } + free(parray); + free(farray); + parray = NULL; + farray = NULL; + onum = 0; + asiz = CB_GCUNIT; + return; + } + if(!parray){ + CB_MALLOC(parray, sizeof(void *) * asiz); + CB_MALLOC(farray, sizeof(void *) * asiz); + if(atexit(cbggchandler) != 0) cbmyfatal("gc failed"); + } + if(onum >= asiz){ + asiz *= 2; + CB_REALLOC(parray, sizeof(void *) * asiz); + CB_REALLOC(farray, sizeof(void *) * asiz); + } + parray[onum] = ptr; + farray[onum] = func; + onum++; +} + + +/* Utility function for quick sort. + `bp' specifies the pointer to the pointer to an array. + `nmemb' specifies the number of elements of the array. + `size' specifies the size of each element. + `pswap' specifies the pointer to the swap region for a pivot. + `vswap' specifies the pointer to the swap region for elements. + `compar' specifies the pointer to comparing function. */ +static void cbqsortsub(char *bp, int nmemb, int size, char *pswap, char *vswap, + int(*compar)(const void *, const void *)){ + int top, bottom; + assert(bp && nmemb >= 0 && size > 0 && pswap && vswap && compar); + if(nmemb < 10){ + if(nmemb > 1) cbisort(bp, nmemb, size, compar); + return; + } + top = 0; + bottom = nmemb - 1; + memcpy(pswap, bp + (nmemb / 2) * size, size); + while(top - 1 < bottom){ + if(compar(bp + top * size, pswap) < 0){ + top++; + } else if(compar(bp + bottom * size, pswap) > 0){ + bottom--; + } else { + if(top != bottom){ + memcpy(vswap, bp + top * size, size); + memcpy(bp + top * size, bp + bottom * size, size); + memcpy(bp + bottom * size, vswap, size); + } + top++; + bottom--; + } + } + cbqsortsub(bp, top, size, pswap, vswap, compar); + cbqsortsub(bp + (bottom + 1) * size, nmemb - bottom - 1, size, pswap, vswap, compar); +} + + +/* Compare two list elements. + `a' specifies the pointer to one element. + `b' specifies the pointer to the other element. + The return value is positive if a is big, negative if b is big, else, it is 0. */ +static int cblistelemcmp(const void *a, const void *b){ + int i, size; + CBLISTDATUM *ap, *bp; + char *ao, *bo; + assert(a && b); + ap = (CBLISTDATUM *)a; + bp = (CBLISTDATUM *)b; + ao = ap->dptr; + bo = bp->dptr; + size = ap->dsize < bp->dsize ? ap->dsize : bp->dsize; + for(i = 0; i < size; i++){ + if(ao[i] > bo[i]) return 1; + if(ao[i] < bo[i]) return -1; + } + return ap->dsize - bp->dsize; +} + + +/* Compare two keys. + `abuf' specifies the pointer to the region of the former. + `asiz' specifies the size of the region. + `bbuf' specifies the pointer to the region of the latter. + `bsiz' specifies the size of the region. + The return value is 0 if two equals, positive if the formar is big, else, negative. */ +static int cbkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz){ + assert(abuf && asiz >= 0 && bbuf && bsiz >= 0); + if(asiz > bsiz) return 1; + if(asiz < bsiz) return -1; + return memcmp(abuf, bbuf, asiz); +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/cabin.h =================================================================== --- box/trunk/qdbm/cabin.h 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/cabin.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,1544 +0,0 @@ -/************************************************************************************************* - * The utitlity API of QDBM - * 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. - *************************************************************************************************/ - - -#ifndef _CABIN_H /* duplication check */ -#define _CABIN_H - -#if defined(__cplusplus) /* export for C++ */ -extern "C" { -#endif - - -#include -#include - - -#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) -#define MYEXTERN extern __declspec(dllimport) -#else -#define MYEXTERN extern -#endif - - - -/************************************************************************************************* - * API - *************************************************************************************************/ - - -#define CB_DATUMUNIT 12 /* allocation unit size of a datum handle */ -#define CB_LISTUNIT 64 /* allocation unit number of a list handle */ -#define CB_MAPBNUM 4093 /* bucket size of a map handle */ - -typedef struct { /* type of structure for a basic datum */ - char *dptr; /* pointer to the region */ - int dsize; /* size of the region */ - int asize; /* size of the allocated region */ -} CBDATUM; - -typedef struct { /* type of structure for an element of a list */ - char *dptr; /* pointer to the region */ - int dsize; /* size of the effective region */ -} CBLISTDATUM; - -typedef struct { /* type of structure for a list */ - CBLISTDATUM *array; /* array of data */ - int anum; /* number of the elements of the array */ - int start; /* start index of using elements */ - int num; /* number of using elements */ -} CBLIST; - -typedef struct _CBMAPDATUM { /* type of structure for an element of a map */ - int ksiz; /* size of the region of the key */ - int vsiz; /* size of the region of the value */ - int hash; /* second hash value */ - struct _CBMAPDATUM *left; /* pointer to the left child */ - struct _CBMAPDATUM *right; /* pointer to the right child */ - struct _CBMAPDATUM *prev; /* pointer to the previous element */ - struct _CBMAPDATUM *next; /* pointer to the next element */ -} CBMAPDATUM; - -typedef struct { /* type of structure for a map */ - CBMAPDATUM **buckets; /* bucket array */ - CBMAPDATUM *first; /* pointer to the first element */ - CBMAPDATUM *last; /* pointer to the last element */ - CBMAPDATUM *cur; /* pointer to the current element */ - int bnum; /* number of buckets */ - int rnum; /* number of records */ -} CBMAP; - -typedef struct { /* type of structure for a heap */ - char *base; /* base pointer */ - char *swap; /* region for swapping */ - int size; /* size of each record */ - int num; /* currnet number of records */ - int max; /* maximum number of records */ - int(*compar)(const void *, const void *); /* comparing function */ -} CBHEAP; - - -/* Call back function for handling a fatal error. - The argument specifies the error message. The initial value of this variable is `NULL'. - If the value is `NULL', the default function is called when a fatal error occurs. A fatal - error occurs when memory allocation is failed. */ -MYEXTERN void (*cbfatalfunc)(const char *); - - -/* Allocate a region on memory. - `size' specifies the size of the region. - The return value is the pointer to the allocated region. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -void *cbmalloc(size_t size); - - -/* Re-allocate a region on memory. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. - The return value is the pointer to the re-allocated region. - Because the region of the return value is allocated with the `realloc' call, it should be - released with the `free' call if it is no longer in use. */ -void *cbrealloc(void *ptr, size_t size); - - -/* Duplicate a region on memory. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - The return value is the pointer to the allocated region of the duplicate. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if - it is no longer in use. */ -char *cbmemdup(const char *ptr, int size); - - -/* Free a region on memory. - `ptr' specifies the pointer to a region. If it is `NULL', this function has no effect. - Although this function is just a wrapper of `free' call, this is useful in applications using - another package of the `malloc' series. */ -void cbfree(void *ptr); - - -/* Register the pointer or handle of an object to the global garbage collector. - `ptr' specifies the pointer or handle of an object. - `func' specifies the pointer to a function to release resources of the object. Its argument - is the pointer or handle of the object to release. - This function assures that resources of an object are released when the process exits - normally by returning from the `main' function or calling the `exit' function. */ -void cbglobalgc(void *ptr, void (*func)(void *)); - - -/* Exercise the global garbage collector explicitly. - Note that you should not use objects registered to the global garbage collector any longer - after calling this function. Because the global garbage collecter is initialized and you - can register new objects into it. */ -void cbggcsweep(void); - - -/* Check availability of allocation of the virtual memory. - `size' specifies the size of region to be allocated newly. - The return value is true if allocation should be success, or false if not. */ -int cbvmemavail(size_t size); - - -/* Sort an array using insert sort. - `base' spacifies the pointer to an array. - `nmemb' specifies the number of elements of the array. - `size' specifies the size of each element. - `compar' specifies the pointer to comparing function. The two arguments specify the pointers - of elements. The comparing function should returns positive if the former is big, negative - if the latter is big, 0 if both are equal. - Insert sort is useful only if most elements have been sorted already. */ -void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); - - -/* Sort an array using shell sort. - `base' spacifies the pointer to an array. - `nmemb' specifies the number of elements of the array. - `size' specifies the size of each element. - `compar' specifies the pointer to comparing function. The two arguments specify the pointers - of elements. The comparing function should returns positive if the former is big, negative - if the latter is big, 0 if both are equal. - If most elements have been sorted, shell sort may be faster than heap sort or quick sort. */ -void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); - - -/* Sort an array using heap sort. - `base' spacifies the pointer to an array. - `nmemb' specifies the number of elements of the array. - `size' specifies the size of each element. - `compar' specifies the pointer to comparing function. The two arguments specify the pointers - of elements. The comparing function should returns positive if the former is big, negative - if the latter is big, 0 if both are equal. - Although heap sort is robust against bias of input, quick sort is faster in most cases. */ -void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); - - -/* Sort an array using quick sort. - `base' spacifies the pointer to an array. - `nmemb' specifies the number of elements of the array. - `size' specifies the size of each element. - `compar' specifies the pointer to comparing function. The two arguments specify the pointers - of elements. The comparing function should returns positive if the former is big, negative - if the latter is big, 0 if both are equal. - Being sensitive to bias of input, quick sort is the fastest sorting algorithm. */ -void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); - - -/* Compare two strings with case insensitive evaluation. - `astr' specifies the pointer of one string. - `astr' specifies the pointer of the other string. - The return value is positive if the former is big, negative if the latter is big, 0 if both - are equivalent. - Upper cases and lower cases of alphabets in ASCII code are not distinguished. */ -int cbstricmp(const char *astr, const char *bstr); - - -/* Check whether a string begins with a key. - `str' specifies the pointer of a target string. - `key' specifies the pointer of a forward matching key string. - The return value is true if the target string begins with the key, else, it is false. */ -int cbstrfwmatch(const char *str, const char *key); - - -/* Check whether a string begins with a key, with case insensitive evaluation. - `str' specifies the pointer of a target string. - `key' specifies the pointer of a forward matching key string. - The return value is true if the target string begins with the key, else, it is false. - Upper cases and lower cases of alphabets in ASCII code are not distinguished. */ -int cbstrfwimatch(const char *str, const char *key); - - -/* Check whether a string ends with a key. - `str' specifies the pointer of a target string. - `key' specifies the pointer of a backward matching key string. - The return value is true if the target string ends with the key, else, it is false. */ -int cbstrbwmatch(const char *str, const char *key); - - -/* Check whether a string ends with a key, with case insensitive evaluation. - `str' specifies the pointer of a target string. - `key' specifies the pointer of a backward matching key string. - The return value is true if the target string ends with the key, else, it is false. - Upper cases and lower cases of alphabets in ASCII code are not distinguished. */ -int cbstrbwimatch(const char *str, const char *key); - - -/* Locate a substring in a string using KMP method. - `haystack' specifies the pointer of a target string. - `needle' specifies the pointer of a substring to be found. - The return value is the pointer to the beginning of the substring or `NULL' if the substring - is not found. - In most cases, `strstr' as a built-in function of the compiler is faster than this function. */ -char *cbstrstrkmp(const char *haystack, const char *needle); - - -/* Locate a substring in a string using BM method. - `haystack' specifies the pointer of a target string. - `needle' specifies the pointer of a substring to be found. - The return value is the pointer to the beginning of the substring or `NULL' if the substring - is not found. - In most cases, `strstr' as a built-in function of the compiler is faster than this function. */ -char *cbstrstrbm(const char *haystack, const char *needle); - - -/* Convert the letters of a string to upper case. - `str' specifies the pointer of a string to convert. - The return value is the pointer to the string. */ -char *cbstrtoupper(char *str); - - -/* Convert the letters of a string to lower case. - `str' specifies the pointer of a string to convert. - The return value is the pointer to the string. */ -char *cbstrtolower(char *str); - - -/* Cut space characters at head or tail of a string. - `str' specifies the pointer of a string to convert. - The return value is the pointer to the string. */ -char *cbstrtrim(char *str); - - -/* Squeeze space characters in a string and trim it. - `str' specifies the pointer of a string to convert. - The return value is the pointer to the string. */ -char *cbstrsqzspc(char *str); - - -/* Count the number of characters in a string of UTF-8. - `str' specifies the pointer of a string of UTF-8. - The return value is the number of characters in the string. */ -int cbstrcountutf(const char *str); - - -/* Cut a string of UTF-8 at the specified number of characters. - `str' specifies the pointer of a string of UTF-8. - `num' specifies the number of characters to be kept. - The return value is the pointer to the string. */ -char *cbstrcututf(char *str, int num); - - -/* Get a datum handle. - `ptr' specifies the pointer to the region of the initial content. If it is `NULL', an empty - datum is created. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - The return value is a datum handle. */ -CBDATUM *cbdatumopen(const char *ptr, int size); - - -/* Copy a datum. - `datum' specifies a datum handle. - The return value is a new datum handle. */ -CBDATUM *cbdatumdup(const CBDATUM *datum); - - -/* Free a datum handle. - `datum' specifies a datum handle. - Because the region of a closed handle is released, it becomes impossible to use the handle. */ -void cbdatumclose(CBDATUM *datum); - - -/* Concatenate a datum and a region. - `datum' specifies a datum handle. - `ptr' specifies the pointer to the region to be appended. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. */ -void cbdatumcat(CBDATUM *datum, const char *ptr, int size); - - -/* Get the pointer of the region of a datum. - `datum' specifies a datum handle. - The return value is the pointer of the region of a datum. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. */ -const char *cbdatumptr(const CBDATUM *datum); - - -/* Get the size of the region of a datum. - `datum' specifies a datum handle. - The return value is the size of the region of a datum. */ -int cbdatumsize(const CBDATUM *datum); - - -/* Change the size of the region of a datum. - `datum' specifies a datum handle. - `size' specifies the new size of the region. - If the new size is bigger than the one of old, the surplus region is filled with zero codes. */ -void cbdatumsetsize(CBDATUM *datum, int size); - - -/* Perform formatted output into a datum. - `format' specifies a printf-like format string. - The conversion character `%' can be used with such flag characters as `s', `d', `o', `u', - `x', `X', `c', `e', `E', `f', `g', `G', `@', `?', `:', `%'. `@' works as with `s' but escapes - meta characters of XML. `?' works as with `s' but escapes meta characters of URL. `:' works - as with `s' but performs MIME encoding as UTF-8. The other conversion character work as with - each original. */ -void cbdatumprintf(CBDATUM *datum, const char *format, ...); - - -/* Convert a datum to an allocated region. - `datum' specifies a datum handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer to the region of the datum. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. Because the region of the original datam is released, it should not be - released again. */ -char *cbdatumtomalloc(CBDATUM *datum, int *sp); - - -/* Get a list handle. - The return value is a list handle. */ -CBLIST *cblistopen(void); - - -/* Copy a list. - `list' specifies a list handle. - The return value is a new list handle. */ -CBLIST *cblistdup(const CBLIST *list); - - -/* Close a list handle. - `list' specifies a list handle. - Because the region of a closed handle is released, it becomes impossible to use the handle. */ -void cblistclose(CBLIST *list); - - -/* Get the number of elements of a list. - `list' specifies a list handle. - The return value is the number of elements of the list. */ -int cblistnum(const CBLIST *list); - - -/* Get the pointer to the region of an element of a list. - `list' specifies a list handle. - `index' specifies the index of an element. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer to the region of the value. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. If `index' is equal to or more than - the number of elements, the return value is `NULL'. */ -const char *cblistval(const CBLIST *list, int index, int *sp); - - -/* Add an element at the end of a list. - `list' specifies a list handle. - `ptr' specifies the pointer to the region of an element. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. */ -void cblistpush(CBLIST *list, const char *ptr, int size); - - -/* Remove an element of the end of a list. - `list' specifies a list handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer to the region of the value. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. If the list is empty, the return value is `NULL'. */ -char *cblistpop(CBLIST *list, int *sp); - - -/* Add an element at the top of a list. - `list' specifies a list handle. - `ptr' specifies the pointer to the region of an element. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. */ -void cblistunshift(CBLIST *list, const char *ptr, int size); - - -/* Remove an element of the top of a list. - `list' specifies a list handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer to the region of the value. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. If the list is empty, the return value is `NULL'. */ -char *cblistshift(CBLIST *list, int *sp); - - -/* Add an element at the specified location of a list. - `list' specifies a list handle. - `index' specifies the index of an element. - `ptr' specifies the pointer to the region of the element. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. */ -void cblistinsert(CBLIST *list, int index, const char *ptr, int size); - - -/* Remove an element at the specified location of a list. - `list' specifies a list handle. - `index' specifies the index of an element. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer to the region of the value. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. If `index' is equal to or more than the number of elements, no element - is removed and the return value is `NULL'. */ -char *cblistremove(CBLIST *list, int index, int *sp); - - -/* Overwrite an element at the specified location of a list. - `list' specifies a list handle. - `index' specifies the index of an element. - `ptr' specifies the pointer to the region of the new content. - `size' specifies the size of the new content. If it is negative, the size is assigned with - `strlen(ptr)'. - If `index' is equal to or more than the number of elements, this function has no effect. */ -void cblistover(CBLIST *list, int index, const char *ptr, int size); - - -/* Sort elements of a list in lexical order. - `list' specifies a list handle. - Quick sort is used for sorting. */ -void cblistsort(CBLIST *list); - - -/* Search a list for an element using liner search. - `list' specifies a list handle. - `ptr' specifies the pointer to the region of a key. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - The return value is the index of a corresponding element or -1 if there is no corresponding - element. If two or more elements corresponds, the former returns. */ -int cblistlsearch(const CBLIST *list, const char *ptr, int size); - - -/* Search a list for an element using binary search. - `list' specifies a list handle. It should be sorted in lexical order. - `ptr' specifies the pointer to the region of a key. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - The return value is the index of a corresponding element or -1 if there is no corresponding - element. If two or more elements corresponds, which returns is not defined. */ -int cblistbsearch(const CBLIST *list, const char *ptr, int size); - - -/* Serialize a list into a byte array. - `list' specifies a list handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. - The return value is the pointer to the region of the result serial region. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cblistdump(const CBLIST *list, int *sp); - - -/* Redintegrate a serialized list. - `ptr' specifies the pointer to a byte array. - `size' specifies the size of the region. - The return value is a new list handle. */ -CBLIST *cblistload(const char *ptr, int size); - - -/* Get a map handle. - The return value is a map handle. */ -CBMAP *cbmapopen(void); - - -/* Copy a map. - `map' specifies a map handle. - The return value is a new map handle. - The iterator of the source map is initialized. */ -CBMAP *cbmapdup(CBMAP *map); - - -/* Close a map handle. - `map' specifies a map handle. - Because the region of a closed handle is released, it becomes impossible to use the handle. */ -void cbmapclose(CBMAP *map); - - -/* Store a record into a map. - `map' specifies a map handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region of the value. If it is negative, the size is - assigned with `strlen(vbuf)'. - `over' specifies whether the value of the duplicated record is overwritten or not. - If `over' is false and the key is duplicated, the return value is false, else, it is true. */ -int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over); - - -/* Concatenate a value at the end of the value of the existing record. - `map' specifies a map handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region of the value. If it is negative, the size is - assigned with `strlen(vbuf)'. - If there is no corresponding record, a new record is created. */ -void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz); - - -/* Delete a record in a map. - `map' specifies a map handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is true. False is returned when no record corresponds to - the specified key. */ -int cbmapout(CBMAP *map, const char *kbuf, int ksiz); - - -/* Retrieve a record in a map. - `map' specifies a map handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record. `NULL' is returned when no record corresponds. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. */ -const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp); - - -/* Move a record to the edge of a map. - `map' specifies a map handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `head' specifies the destination which is head if it is true or tail if else. - If successful, the return value is true. False is returned when no record corresponds to - the specified key. */ -int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head); - - -/* Initialize the iterator of a map. - `map' specifies a map handle. - The iterator is used in order to access the key of every record stored in a map. */ -void cbmapiterinit(CBMAP *map); - - -/* Get the next key of the iterator of a map. - `map' specifies a map handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the next key, else, it is - `NULL'. `NULL' is returned when no record is to be get out of the iterator. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. The order of iteration is assured - to be the same of the one of storing. */ -const char *cbmapiternext(CBMAP *map, int *sp); - - -/* Get the value binded to the key fetched from the iterator of a map. - `kbuf' specifies the pointer to the region of a iteration key. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer to the region of the value of the corresponding record. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. */ -const char *cbmapiterval(const char *kbuf, int *sp); - - -/* Get the number of the records stored in a map. - `map' specifies a map handle. - The return value is the number of the records stored in the map. */ -int cbmaprnum(const CBMAP *map); - - -/* Get the list handle contains all keys in a map. - `map' specifies a map handle. - The return value is the list handle contains all keys in the map. - Because the handle of the return value is opened with the function `cblistopen', it should - be closed with the function `cblistclose' if it is no longer in use. */ -CBLIST *cbmapkeys(CBMAP *map); - - -/* Get the list handle contains all values in a map. - `map' specifies a map handle. - The return value is the list handle contains all values in the map. - Because the handle of the return value is opened with the function `cblistopen', it should - be closed with the function `cblistclose' if it is no longer in use. */ -CBLIST *cbmapvals(CBMAP *map); - - -/* Serialize a map into a byte array. - `map' specifies a map handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. - The return value is the pointer to the region of the result serial region. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cbmapdump(CBMAP *map, int *sp); - - -/* Redintegrate a serialized map. - `ptr' specifies the pointer to a byte array. - `size' specifies the size of the region. - The return value is a new map handle. */ -CBMAP *cbmapload(const char *ptr, int size); - - -/* Extract a record from a serialized map. - `ptr' specifies the pointer to a byte array. - `size' specifies the size of the region. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record. `NULL' is returned when no record corresponds. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. */ -char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp); - - -/* Get a heap handle. - `size' specifies the size of each record. - `max' specifies the maximum number of records in the heap. - `compar' specifies the pointer to comparing function. The two arguments specify the pointers - of records. The comparing function should returns positive if the former is big, negative - if the latter is big, 0 if both are equal. - The return value is a heap handle. */ -CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *)); - - -/* Copy a heap. - `heap' specifies a heap handle. - The return value is a new heap handle. */ -CBHEAP *cbheapdup(CBHEAP *heap); - - -/* Close a heap handle. - `heap' specifies a heap handle. - Because the region of a closed handle is released, it becomes impossible to use the handle. */ -void cbheapclose(CBHEAP *heap); - - -/* Get the number of the records stored in a heap. - `heap' specifies a heap handle. - The return value is the number of the records stored in the heap. */ -int cbheapnum(CBHEAP *heap); - - -/* Insert a record into a heap. - `heap' specifies a heap handle. - `ptr' specifies the pointer to the region of a record. - The return value is true if the record is added, else false. - If the new record is bigger than the biggest existing regord, the new record is not added. - If the new record is added and the number of records exceeds the maximum number, the biggest - existing record is removed. */ -int cbheapinsert(CBHEAP *heap, const void *ptr); - - -/* Get the pointer to the region of a record in a heap. - `heap' specifies a heap handle. - `index' specifies the index of a record. - The return value is the pointer to the region of the record. - If `index' is equal to or more than the number of records, the return value is `NULL'. Note - that records are organized by the nagative order the comparing function. */ -const void *cbheapval(CBHEAP *heap, int index); - - -/* Convert a heap to an allocated region. - `heap' specifies a heap handle. - `np' specifies the pointer to a variable to which the number of records of the return value - is assigned. If it is `NULL', it is not used. - The return value is the pointer to the region of the heap. Records are sorted. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. Because the region of the original - heap is released, it should not be released again. */ -void *cbheaptomalloc(CBHEAP *heap, int *np); - - -/* Allocate a formatted string on memory. - `format' specifies a printf-like format string. The conversion character `%' can be used - with such flag characters as `d', `o', `u', `x', `X', `e', `E', `f', `g', `G', `c', `s', and - `%'. Specifiers of the field length and the precision can be put between the conversion - characters and the flag characters. The specifiers consist of decimal characters, `.', `+', - `-', and the space character. - The other arguments are used according to the format string. - The return value is the pointer to the allocated region of the result string. Because the - region of the return value is allocated with the `malloc' call, it should be released with - the `free' call if it is no longer in use. */ -char *cbsprintf(const char *format, ...); - - -/* Replace some patterns in a string. - `str' specifies the pointer to a source string. - `pairs' specifies the handle of a map composed of pairs of replacement. The key of each pair - specifies a pattern before replacement and its value specifies the pattern after replacement. - The return value is the pointer to the allocated region of the result string. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cbreplace(const char *str, CBMAP *pairs); - - -/* Make a list by splitting a serial datum. - `ptr' specifies the pointer to the region of the source content. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - `delim' specifies a string containing delimiting characters. If it is `NULL', zero code is - used as a delimiter. - The return value is a list handle. - If two delimiters are successive, it is assumed that an empty element is between the two. - Because the handle of the return value is opened with the function `cblistopen', it should - be closed with the function `cblistclose'. */ -CBLIST *cbsplit(const char *ptr, int size, const char *delim); - - -/* Read whole data of a file. - `name' specifies the name of a file. If it is `NULL', the standard input is specified. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer to the allocated region of the read data. Because an - additional zero code is appended at the end of the region of the return value, the return - value can be treated as a character string. Because the region of the return value is - allocated with the `malloc' call, it should be released with the `free' call if it is no - longer in use. */ -char *cbreadfile(const char *name, int *sp); - - -/* Write a serial datum into a file. - `name specifies the name of a file. If it is `NULL', the standard output is specified. - `ptr' specifies the pointer to the region of the source content. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - If successful, the return value is true, else, it is false. - If the file exists, it is overwritten. Else, a new file is created. */ -int cbwritefile(const char *name, const char *ptr, int size); - - -/* Read every line of a file. - `name' specifies the name of a file. If it is `NULL', the standard input is specified. - The return value is a list handle of the lines if successful, else it is NULL. Line - separators are cut out. Because the handle of the return value is opened with the function - `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */ -CBLIST *cbreadlines(const char *name); - - -/* Read names of files in a directory. - `name' specifies the name of a directory. - The return value is a list handle of names if successful, else it is NULL. - Because the handle of the return value is opened with the function `cblistopen', it should - be closed with the function `cblistclose' if it is no longer in use. */ -CBLIST *cbdirlist(const char *name); - - -/* Get the status of a file or a directory. - `name' specifies the name of a file or a directory. - `dirp' specifies the pointer to a variable to which whether the file is a directory is - assigned. If it is `NULL', it is not used. - `sizep' specifies the pointer to a variable to which the size of the file is assigned. If it - is `NULL', it is not used. - `mtimep' specifies the pointer to a variable to which the last modified time of the file is - assigned. If it is `NULL', it is not used. - If successful, the return value is true, else, false. False is returned when the file does - not exist or the permission is denied. */ -int cbfilestat(const char *name, int *isdirp, int *sizep, time_t *mtimep); - - -/* Remove a file or a directory and its sub ones recursively. - `name' specifies the name of a file or a directory. - If successful, the return value is true, else, false. False is returned when the file does - not exist or the permission is denied. */ -int cbremove(const char *name); - - -/* Break up a URL into elements. - `str' specifies the pointer to a string of URL. - The return value is a map handle. Each key of the map is the name of an element. The key - "self" specifies the URL itself. The key "scheme" specifies the scheme. The key "host" - specifies the host of the server. The key "port" specifies the port number of the server. - The key "authority" specifies the authority information. The key "path" specifies the path - of the resource. The key "file" specifies the file name without the directory section. The - key "query" specifies the query string. The key "fragment" specifies the fragment string. - Supported schema are HTTP, HTTPS, FTP, and FILE. Absolute URL and relative URL are supported. - Because the handle of the return value is opened with the function `cbmapopen', it should - be closed with the function `cbmapclose' if it is no longer in use. */ -CBMAP *cburlbreak(const char *str); - - -/* Resolve a relative URL with another absolute URL. - `base' specifies an absolute URL of a base location. - `target' specifies a URL to be resolved. - The return value is a resolved URL. If the target URL is relative, a new URL of relative - location from the base location is returned. Else, a copy of the target URL is returned. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cburlresolve(const char *base, const char *target); - - -/* Encode a serial object with URL encoding. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - The return value is the pointer to the result string. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cburlencode(const char *ptr, int size); - - -/* Decode a string encoded with URL encoding. - `str' specifies the pointer to an encoded string. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer to the region of the result. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if - it is no longer in use. */ -char *cburldecode(const char *str, int *sp); - - -/* Encode a serial object with Base64 encoding. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - The return value is the pointer to the result string. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cbbaseencode(const char *ptr, int size); - - -/* Decode a string encoded with Base64 encoding. - `str' specifies the pointer to an encoded string. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer to the region of the result. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if - it is no longer in use. */ -char *cbbasedecode(const char *str, int *sp); - - -/* Encode a serial object with quoted-printable encoding. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - The return value is the pointer to the result string. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cbquoteencode(const char *ptr, int size); - - -/* Decode a string encoded with quoted-printable encoding. - `str' specifies the pointer to an encoded string. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer to the region of the result. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if - it is no longer in use. */ -char *cbquotedecode(const char *str, int *sp); - - -/* Split a string of MIME into headers and the body. - `ptr' specifies the pointer to the region of MIME data. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - `attrs' specifies a map handle to store attributes. If it is `NULL', it is not used. Each - key of the map is an attribute name uncapitalized. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - The return value is the pointer of the body data. - If the content type is defined, the attribute map has the key "TYPE" specifying the type. If - the character encoding is defined, the key "CHARSET" specifies the encoding name. If the - boundary string of multipart is defined, the key "BOUNDARY" specifies the string. If the - content disposition is defined, the key "DISPOSITION" specifies the direction. If the file - name is defined, the key "FILENAME" specifies the name. If the attribute name is defined, - the key "NAME" specifies the name. Because the region of the return value is allocated with - the `malloc' call, it should be released with the `free' call if it is no longer in use. */ -char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp); - - -/* Split multipart data of MIME into its parts. - `ptr' specifies the pointer to the region of multipart data of MIME. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - `boundary' specifies the pointer to the region of the boundary string. - The return value is a list handle. Each element of the list is the string of a part. - Because the handle of the return value is opened with the function `cblistopen', it should - be closed with the function `cblistclose' if it is no longer in use. */ -CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary); - - -/* Encode a string with MIME encoding. - `str' specifies the pointer to a string. - `encname' specifies a string of the name of the character encoding. - The return value is the pointer to the result string. - `base' specifies whether to use Base64 encoding. If it is false, quoted-printable is used. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cbmimeencode(const char *str, const char *encname, int base); - - -/* Decode a string encoded with MIME encoding. - `str' specifies the pointer to an encoded string. - `enp' specifies the pointer to a region into which the name of encoding is written. If it is - `NULL', it is not used. The size of the buffer should be equal to or more than 32 bytes. - The return value is the pointer to the result string. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cbmimedecode(const char *str, char *enp); - - -/* Split a string of CSV into rows. - `str' specifies the pointer to the region of an CSV string. - The return value is a list handle. Each element of the list is a string of a row. - Because the handle of the return value is opened with the function `cblistopen', it should - be closed with the function `cblistclose' if it is no longer in use. The character encoding - of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Being - compatible with MS-Excel, these functions for CSV can handle cells including such meta - characters as comma, between double quotation marks. */ -CBLIST *cbcsvrows(const char *str); - - -/* Split the string of a row of CSV into cells. - `str' specifies the pointer to the region of a row of CSV. - The return value is a list handle. Each element of the list is the unescaped string of a - cell of the row. - Because the handle of the return value is opened with the function `cblistopen', it should - be closed with the function `cblistclose' if it is no longer in use. */ -CBLIST *cbcsvcells(const char *str); - - -/* Escape a string with the meta characters of CSV. - `str' specifies the pointer to the region of a string. - The return value is the pointer to the escaped string sanitized of meta characters. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cbcsvescape(const char *str); - - -/* Unescape a string with the escaped meta characters of CSV. - `str' specifies the pointer to the region of a string with meta characters. - The return value is the pointer to the unescaped string. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cbcsvunescape(const char *str); - - -/* Split a string of XML into tags and text sections. - `str' specifies the pointer to the region of an XML string. - `cr' specifies whether to remove comments. - The return value is a list handle. Each element of the list is the string of a tag or a - text section. - Because the handle of the return value is opened with the function `cblistopen', it should - be closed with the function `cblistclose' if it is no longer in use. The character encoding - of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Because - these functions for XML are not XML parser with validation check, it can handle also HTML - and SGML. */ -CBLIST *cbxmlbreak(const char *str, int cr); - - -/* Get the map of attributes of an XML tag. - `str' specifies the pointer to the region of a tag string. - The return value is a map handle. Each key of the map is the name of an attribute. Each - value is unescaped. You can get the name of the tag with the key of an empty string. - Because the handle of the return value is opened with the function `cbmapopen', it should - be closed with the function `cbmapclose' if it is no longer in use. */ -CBMAP *cbxmlattrs(const char *str); - - -/* Escape a string with the meta characters of XML. - `str' specifies the pointer to the region of a string. - The return value is the pointer to the escaped string sanitized of meta characters. - This function converts only `&', `<', `>', and `"'. Because the region of the return value - is allocated with the `malloc' call, it should be released with the `free' call if it is no - longer in use. */ -char *cbxmlescape(const char *str); - - -/* Unescape a string with the entity references of XML. - `str' specifies the pointer to the region of a string with meta characters. - The return value is the pointer to the unescaped string. - This function restores only `&', `<', `>', and `"'. Because the region of the - return value is allocated with the `malloc' call, it should be released with the `free' call - if it is no longer in use. */ -char *cbxmlunescape(const char *str); - - -/* Compress a serial object with ZLIB. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. - If successful, the return value is the pointer to the result object, else, it is `NULL'. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. This function is available only if - QDBM was built with ZLIB enabled. */ -char *cbdeflate(const char *ptr, int size, int *sp); - - -/* Decompress a serial object compressed with ZLIB. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the result object, else, it is `NULL'. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. This function is available only if QDBM was built with ZLIB enabled. */ -char *cbinflate(const char *ptr, int size, int *sp); - - -/* Compress a serial object with GZIP. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. - If successful, the return value is the pointer to the result object, else, it is `NULL'. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. This function is available only if - QDBM was built with ZLIB enabled. */ -char *cbgzencode(const char *ptr, int size, int *sp); - - -/* Decompress a serial object compressed with GZIP. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the result object, else, it is `NULL'. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. This function is available only if QDBM was built with ZLIB enabled. */ -char *cbgzdecode(const char *ptr, int size, int *sp); - - -/* Get the CRC32 checksum of a serial object. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - The return value is the CRC32 checksum of the object. - This function is available only if QDBM was built with ZLIB enabled. */ -unsigned int cbgetcrc(const char *ptr, int size); - - -/* Compress a serial object with LZO. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. - If successful, the return value is the pointer to the result object, else, it is `NULL'. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. This function is available only if - QDBM was built with LZO enabled. */ -char *cblzoencode(const char *ptr, int size, int *sp); - - -/* Decompress a serial object compressed with LZO. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the result object, else, it is `NULL'. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. This function is available only if QDBM was built with LZO enabled. */ -char *cblzodecode(const char *ptr, int size, int *sp); - - -/* Compress a serial object with BZIP2. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. - If successful, the return value is the pointer to the result object, else, it is `NULL'. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. This function is available only if - QDBM was built with LZO enabled. */ -char *cbbzencode(const char *ptr, int size, int *sp); - - -/* Decompress a serial object compressed with BZIP2. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the result object, else, it is `NULL'. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. This function is available only if QDBM was built with LZO enabled. */ -char *cbbzdecode(const char *ptr, int size, int *sp); - - -/* Convert the character encoding of a string. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - `icode' specifies the name of encoding of the input string. - `ocode' specifies the name of encoding of the output string. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - `mp' specifies the pointer to a variable to which the number of missing characters by failure - of conversion is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the result object, else, it is `NULL'. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. This function is available only if QDBM was built with ICONV enabled. */ -char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp); - - -/* Detect the encoding of a string automatically. - `ptr' specifies the pointer to a region. - `size' specifies the size of the region. If it is negative, the size is assigned with - `strlen(ptr)'. - The return value is the string of the encoding name of the string. - As it stands, US-ASCII, ISO-2022-JP, Shift_JIS, CP932, EUC-JP, UTF-8, UTF-16, UTF-16BE, - and UTF-16LE are supported. If none of them matches, ISO-8859-1 is selected. This function - is available only if QDBM was built with ICONV enabled. */ -const char *cbencname(const char *ptr, int size); - - -/* Get the jet lag of the local time in seconds. - The return value is the jet lag of the local time in seconds. */ -int cbjetlag(void); - - -/* Get the Gregorian calendar of a time. - `t' specifies a source time. If it is negative, the current time is specified. - `jl' specifies the jet lag of a location in seconds. - `yearp' specifies the pointer to a variable to which the year is assigned. If it is `NULL', - it is not used. - `monp' specifies the pointer to a variable to which the month is assigned. If it is `NULL', - it is not used. 1 means January and 12 means December. - `dayp' specifies the pointer to a variable to which the day of the month is assigned. If it - is `NULL', it is not used. - `hourp' specifies the pointer to a variable to which the hours is assigned. If it is `NULL', - it is not used. - `minp' specifies the pointer to a variable to which the minutes is assigned. If it is `NULL', - it is not used. - `secp' specifies the pointer to a variable to which the seconds is assigned. If it is `NULL', - it is not used. */ -void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, - int *hourp, int *minp, int *secp); - - -/* Get the day of week of a date. - `year' specifies the year of a date. - `mon' specifies the month of the date. - `day' specifies the day of the date. - The return value is the day of week of the date. 0 means Sunday and 6 means Saturday. */ -int cbdayofweek(int year, int mon, int day); - - -/* Get the string for a date in W3CDTF. - `t' specifies a source time. If it is negative, the current time is specified. - `jl' specifies the jet lag of a location in seconds. - The return value is the string of the date in W3CDTF (YYYY-MM-DDThh:mm:ddTZD). - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cbdatestrwww(time_t t, int jl); - - -/* Get the string for a date in RFC 1123 format. - `t' specifies a source time. If it is negative, the current time is specified. - `jl' specifies the jet lag of a location in seconds. - The return value is the string of the date in RFC 1123 format (Wdy, DD-Mon-YYYY hh:mm:dd TZD). - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *cbdatestrhttp(time_t t, int jl); - - -/* Get the time value of a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). - `str' specifies a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). - The return value is the time value of the date or -1 if the format is invalid. - Decimal can be trailed by "s" for in seconds, "m" for in minutes, "h" for in hours, - and "d" for in days. */ -time_t cbstrmktime(const char *str); - - -/* Get user and system processing times. - `usrp' specifies the pointer to a variable to which the user processing time is assigned. - If it is `NULL', it is not used. The unit of time is seconds. - `sysp' specifies the pointer to a variable to which the system processing time is assigned. - If it is `NULL', it is not used. The unit of time is seconds. */ -void cbproctime(double *usrp, double *sysp); - - -/* Ensure that the standard I/O is binary mode. - This function is useful for applications on dosish file systems. */ -void cbstdiobin(void); - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Show error message on the standard error output and exit. - `message' specifies an error message. - This function does not return. */ -void *cbmyfatal(const char *message); - - -/* Create a datum handle from an allocated region. - `ptr' specifies the pointer to the region of an element. The region should be allocated with - malloc and it is released by the function. - `size' specifies the size of the region. */ -CBDATUM *cbdatumopenbuf(char *ptr, int size); - - -/* Set a buffer to a datum handle. - `ptr' specifies the pointer to the region of an element. The region should be allocated with - malloc and it is released by the function. - `size' specifies the size of the region. */ -void cbdatumsetbuf(CBDATUM *datum, char *ptr, int size); - - -/* Add an allocated element at the end of a list. - `list' specifies a list handle. - `ptr' specifies the pointer to the region of an element. The region should be allocated with - malloc and it is released by the function. - `size' specifies the size of the region. */ -void cblistpushbuf(CBLIST *list, char *ptr, int size); - - -/* Get a map handle with specifying the number of buckets. - `bnum' specifies the number of buckets. - The return value is a map handle. */ -CBMAP *cbmapopenex(int bnum); - - -/* Alias of `cbmalloc'. */ -#define CB_MALLOC(CB_ptr, CB_size) \ - (((CB_ptr) = malloc(CB_size)) ? (CB_ptr) : cbmyfatal("out of memory")) - - -/* Alias of `cbrealloc'. */ -#define CB_REALLOC(CB_ptr, CB_size) \ - (((CB_ptr) = realloc((CB_ptr), (CB_size))) ? (CB_ptr) : cbmyfatal("out of memory")) - - -/* Alias of `cbmemdup'. - However, `size' should not be negative. */ -#define CB_MEMDUP(CB_res, CB_ptr, CB_size) \ - do { \ - CB_MALLOC((CB_res), (CB_size) + 1); \ - memcpy((CB_res), (CB_ptr), (CB_size)); \ - (CB_res)[(CB_size)] = '\0'; \ - } while(FALSE) - - -/* Get the size of padding bytes for pointer alignment. - `hsiz' specifies the header size of the object. - The return value is the size of padding bytes. */ -#define CB_ALIGNPAD(CB_hsiz) \ - (((CB_hsiz | ~-(int)sizeof(void *)) + 1) - CB_hsiz) - - -/* Alias of `cbdatumopen'. - However, no dafault data is specified. */ -#define CB_DATUMOPEN(CB_datum) \ - do { \ - CB_MALLOC((CB_datum), sizeof(*(CB_datum))); \ - CB_MALLOC((CB_datum)->dptr, CB_DATUMUNIT); \ - (CB_datum)->dptr[0] = '\0'; \ - (CB_datum)->dsize = 0; \ - (CB_datum)->asize = CB_DATUMUNIT; \ - } while(FALSE) - - -/* Alias of `cbdatumopen'. - However, `size' should not be negative. */ -#define CB_DATUMOPEN2(CB_datum, CB_ptr, CB_size) \ - do { \ - CB_DATUMOPEN((CB_datum)); \ - CB_DATUMCAT((CB_datum), (CB_ptr), (CB_size)); \ - } while(FALSE) - - -/* Alias of `cbdatumclose'. */ -#define CB_DATUMCLOSE(CB_datum) \ - do { \ - free((CB_datum)->dptr); \ - free((CB_datum)); \ - } while(FALSE) - - -/* Alias of `cbdatumcat'. - However, `size' should not be negative. */ -#define CB_DATUMCAT(CB_datum, CB_ptr, CB_size) \ - do { \ - if((CB_datum)->dsize + (CB_size) >= (CB_datum)->asize){ \ - (CB_datum)->asize = (CB_datum)->asize * 2 + (CB_size) + 1; \ - CB_REALLOC((CB_datum)->dptr, (CB_datum)->asize); \ - } \ - memcpy((CB_datum)->dptr + (CB_datum)->dsize, (CB_ptr), (CB_size)); \ - (CB_datum)->dsize += (CB_size); \ - (CB_datum)->dptr[(CB_datum)->dsize] = '\0'; \ - } while(FALSE) - - -/* Alias of `cbdatumptr'. */ -#define CB_DATUMPTR(CB_datum) ((const char *)((CB_datum)->dptr)) - - -/* Alias of `cbdatumsize'. */ -#define CB_DATUMSIZE(CB_datum) ((int)((CB_datum)->dsize)) - - -/* Alias of `cbdatumsetsize'. */ -#define CB_DATUMSETSIZE(CB_datum, CB_size) \ - do { \ - if((CB_size) <= (CB_datum)->dsize){ \ - (CB_datum)->dsize = (CB_size); \ - (CB_datum)->dptr[(CB_size)] = '\0'; \ - } else { \ - if((CB_size) >= (CB_datum)->asize){ \ - (CB_datum)->asize = (CB_datum)->asize * 2 + (CB_size) + 1; \ - CB_REALLOC((CB_datum)->dptr, (CB_datum)->asize); \ - } \ - memset((CB_datum)->dptr + (CB_datum)->dsize, 0, ((CB_size) - (CB_datum)->dsize) + 1); \ - (CB_datum)->dsize = (CB_size); \ - } \ - } while(FALSE) - - -/* Alias of `cbdatumtomalloc'. */ -#define CB_DATUMTOMALLOC(CB_datum, CB_ptr, CB_size) \ - do { \ - (CB_ptr) = (CB_datum)->dptr; \ - (CB_size) = (CB_datum)->dsize; \ - free((CB_datum)); \ - } while(FALSE) - - -/* Alias of `cblistopen'. */ -#define CB_LISTOPEN(CB_list) \ - do { \ - CB_MALLOC((CB_list), sizeof(*(CB_list))); \ - (CB_list)->anum = CB_LISTUNIT; \ - CB_MALLOC((CB_list)->array, sizeof((CB_list)->array[0]) * (CB_list)->anum); \ - (CB_list)->start = 0; \ - (CB_list)->num = 0; \ - } while(FALSE) - - -/* Alias of `cblistopen'. - However, `anum' is specified for the number of initial allocated elements. */ -#define CB_LISTOPEN2(CB_list, CB_anum) \ - do { \ - CB_MALLOC((CB_list), sizeof(*(CB_list))); \ - (CB_list)->anum = (CB_anum) > 4 ? (CB_anum) : 4; \ - CB_MALLOC((CB_list)->array, sizeof((CB_list)->array[0]) * (CB_list)->anum); \ - (CB_list)->start = 0; \ - (CB_list)->num = 0; \ - } while(FALSE) - - -/* Alias of `cblistclose'. */ -#define CB_LISTCLOSE(CB_list) \ - do { \ - int _CB_i, _CB_end; \ - _CB_end = (CB_list)->start + (CB_list)->num; \ - for(_CB_i = (CB_list)->start; _CB_i < _CB_end; _CB_i++){ \ - free((CB_list)->array[_CB_i].dptr); \ - } \ - free((CB_list)->array); \ - free((CB_list)); \ - } while(FALSE) - - -/* Alias of `cblistnum'. */ -#define CB_LISTNUM(CB_list) \ - ((int)((CB_list)->num)) - - -/* Alias of `cblistval'. - However, `sp' is ignored. */ -#define CB_LISTVAL(CB_list, CB_index) \ - ((const char *)((CB_list)->array[(CB_list)->start+(CB_index)].dptr)) - - -/* Alias of `cblistval'. - However, `size' is used instead of `sp'. */ -#define CB_LISTVAL2(CB_list, CB_index, CB_size) \ - ((CB_size) = (CB_list)->array[(CB_list)->start+(CB_index)].dsize, \ - (const char *)((CB_list)->array[(CB_list)->start+(CB_index)].dptr)) - - -/* Alias of `cblistpush'. - However, `size' should not be negative. */ -#define CB_LISTPUSH(CB_list, CB_ptr, CB_size) \ - do { \ - int _CB_index; \ - _CB_index = (CB_list)->start + (CB_list)->num; \ - if(_CB_index >= (CB_list)->anum){ \ - (CB_list)->anum *= 2; \ - CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \ - } \ - CB_MALLOC((CB_list)->array[_CB_index].dptr, \ - ((CB_size) < CB_DATUMUNIT ? CB_DATUMUNIT : (CB_size)) + 1); \ - memcpy((CB_list)->array[_CB_index].dptr, (CB_ptr), (CB_size)); \ - (CB_list)->array[_CB_index].dptr[(CB_size)] = '\0'; \ - (CB_list)->array[_CB_index].dsize = (CB_size); \ - (CB_list)->num++; \ - } while(FALSE) - - -/* Remove and free an element of the end of a list. - `list' specifies a list handle. */ -#define CB_LISTDROP(CB_list) \ - do { \ - if((CB_list)->num > 0){ \ - free((CB_list)->array[(CB_list)->start+(CB_list)->num-1].dptr); \ - (CB_list)->num--; \ - } \ - } while(FALSE) - - -/* Alias of `cblistinsert'. - However, `index' is not checked and `size' should not be negative. */ -#define CB_LISTINSERT(CB_list, CB_index, CB_ptr, CB_size) \ - do { \ - int _CB_index = (CB_index); \ - _CB_index += (CB_list)->start; \ - if((CB_list)->start + (CB_list)->num >= (CB_list)->anum){ \ - (CB_list)->anum *= 2; \ - CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \ - } \ - memmove((CB_list)->array + _CB_index + 1, (CB_list)->array + _CB_index, \ - sizeof((CB_list)->array[0]) * ((CB_list)->start + (CB_list)->num - _CB_index)); \ - CB_MEMDUP((CB_list)->array[_CB_index].dptr, (CB_ptr), (CB_size)); \ - (CB_list)->array[_CB_index].dsize = (CB_size); \ - (CB_list)->num++; \ - } while(FALSE) - - -/* Alias of `cblistpushbuf'. */ -#define CB_LISTPUSHBUF(CB_list, CB_ptr, CB_size) \ - do{ \ - int _CB_index; \ - _CB_index = (CB_list)->start + (CB_list)->num; \ - if(_CB_index >= (CB_list)->anum){ \ - (CB_list)->anum *= 2; \ - CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \ - } \ - (CB_list)->array[_CB_index].dptr = (CB_ptr); \ - (CB_list)->array[_CB_index].dsize = (CB_size); \ - (CB_list)->num++; \ - } while(FALSE) \ - - -/* Alias of `cbmapiterval'. - However, `size' is used instead of `sp'. */ -#define CB_MAPITERVAL(CB_vbuf, CB_kbuf, CB_vsiz) \ - do { \ - CBMAPDATUM *_CB_datum; \ - _CB_datum = (CBMAPDATUM *)((CB_kbuf) - sizeof(*_CB_datum)); \ - (CB_vsiz) = _CB_datum->vsiz; \ - (CB_vbuf) = (char *)_CB_datum + sizeof(*_CB_datum) + \ - _CB_datum->ksiz + CB_ALIGNPAD(_CB_datum->ksiz); \ - } while(FALSE) - - - -#undef MYEXTERN - -#if defined(__cplusplus) /* export for C++ */ -} -#endif - -#endif /* duplication check */ - - -/* END OF FILE */ Copied: box/trunk/qdbm/cabin.h (from rev 2716, box/trunk/qdbm/cabin.h) =================================================================== --- box/trunk/qdbm/cabin.h (rev 0) +++ box/trunk/qdbm/cabin.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,1544 @@ +/************************************************************************************************* + * The utitlity API of QDBM + * 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. + *************************************************************************************************/ + + +#ifndef _CABIN_H /* duplication check */ +#define _CABIN_H + +#if defined(__cplusplus) /* export for C++ */ +extern "C" { +#endif + + +#include +#include + + +#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) +#define MYEXTERN extern __declspec(dllimport) +#else +#define MYEXTERN extern +#endif + + + +/************************************************************************************************* + * API + *************************************************************************************************/ + + +#define CB_DATUMUNIT 12 /* allocation unit size of a datum handle */ +#define CB_LISTUNIT 64 /* allocation unit number of a list handle */ +#define CB_MAPBNUM 4093 /* bucket size of a map handle */ + +typedef struct { /* type of structure for a basic datum */ + char *dptr; /* pointer to the region */ + int dsize; /* size of the region */ + int asize; /* size of the allocated region */ +} CBDATUM; + +typedef struct { /* type of structure for an element of a list */ + char *dptr; /* pointer to the region */ + int dsize; /* size of the effective region */ +} CBLISTDATUM; + +typedef struct { /* type of structure for a list */ + CBLISTDATUM *array; /* array of data */ + int anum; /* number of the elements of the array */ + int start; /* start index of using elements */ + int num; /* number of using elements */ +} CBLIST; + +typedef struct _CBMAPDATUM { /* type of structure for an element of a map */ + int ksiz; /* size of the region of the key */ + int vsiz; /* size of the region of the value */ + int hash; /* second hash value */ + struct _CBMAPDATUM *left; /* pointer to the left child */ + struct _CBMAPDATUM *right; /* pointer to the right child */ + struct _CBMAPDATUM *prev; /* pointer to the previous element */ + struct _CBMAPDATUM *next; /* pointer to the next element */ +} CBMAPDATUM; + +typedef struct { /* type of structure for a map */ + CBMAPDATUM **buckets; /* bucket array */ + CBMAPDATUM *first; /* pointer to the first element */ + CBMAPDATUM *last; /* pointer to the last element */ + CBMAPDATUM *cur; /* pointer to the current element */ + int bnum; /* number of buckets */ + int rnum; /* number of records */ +} CBMAP; + +typedef struct { /* type of structure for a heap */ + char *base; /* base pointer */ + char *swap; /* region for swapping */ + int size; /* size of each record */ + int num; /* currnet number of records */ + int max; /* maximum number of records */ + int(*compar)(const void *, const void *); /* comparing function */ +} CBHEAP; + + +/* Call back function for handling a fatal error. + The argument specifies the error message. The initial value of this variable is `NULL'. + If the value is `NULL', the default function is called when a fatal error occurs. A fatal + error occurs when memory allocation is failed. */ +MYEXTERN void (*cbfatalfunc)(const char *); + + +/* Allocate a region on memory. + `size' specifies the size of the region. + The return value is the pointer to the allocated region. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +void *cbmalloc(size_t size); + + +/* Re-allocate a region on memory. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. + The return value is the pointer to the re-allocated region. + Because the region of the return value is allocated with the `realloc' call, it should be + released with the `free' call if it is no longer in use. */ +void *cbrealloc(void *ptr, size_t size); + + +/* Duplicate a region on memory. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + The return value is the pointer to the allocated region of the duplicate. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if + it is no longer in use. */ +char *cbmemdup(const char *ptr, int size); + + +/* Free a region on memory. + `ptr' specifies the pointer to a region. If it is `NULL', this function has no effect. + Although this function is just a wrapper of `free' call, this is useful in applications using + another package of the `malloc' series. */ +void cbfree(void *ptr); + + +/* Register the pointer or handle of an object to the global garbage collector. + `ptr' specifies the pointer or handle of an object. + `func' specifies the pointer to a function to release resources of the object. Its argument + is the pointer or handle of the object to release. + This function assures that resources of an object are released when the process exits + normally by returning from the `main' function or calling the `exit' function. */ +void cbglobalgc(void *ptr, void (*func)(void *)); + + +/* Exercise the global garbage collector explicitly. + Note that you should not use objects registered to the global garbage collector any longer + after calling this function. Because the global garbage collecter is initialized and you + can register new objects into it. */ +void cbggcsweep(void); + + +/* Check availability of allocation of the virtual memory. + `size' specifies the size of region to be allocated newly. + The return value is true if allocation should be success, or false if not. */ +int cbvmemavail(size_t size); + + +/* Sort an array using insert sort. + `base' spacifies the pointer to an array. + `nmemb' specifies the number of elements of the array. + `size' specifies the size of each element. + `compar' specifies the pointer to comparing function. The two arguments specify the pointers + of elements. The comparing function should returns positive if the former is big, negative + if the latter is big, 0 if both are equal. + Insert sort is useful only if most elements have been sorted already. */ +void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); + + +/* Sort an array using shell sort. + `base' spacifies the pointer to an array. + `nmemb' specifies the number of elements of the array. + `size' specifies the size of each element. + `compar' specifies the pointer to comparing function. The two arguments specify the pointers + of elements. The comparing function should returns positive if the former is big, negative + if the latter is big, 0 if both are equal. + If most elements have been sorted, shell sort may be faster than heap sort or quick sort. */ +void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); + + +/* Sort an array using heap sort. + `base' spacifies the pointer to an array. + `nmemb' specifies the number of elements of the array. + `size' specifies the size of each element. + `compar' specifies the pointer to comparing function. The two arguments specify the pointers + of elements. The comparing function should returns positive if the former is big, negative + if the latter is big, 0 if both are equal. + Although heap sort is robust against bias of input, quick sort is faster in most cases. */ +void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); + + +/* Sort an array using quick sort. + `base' spacifies the pointer to an array. + `nmemb' specifies the number of elements of the array. + `size' specifies the size of each element. + `compar' specifies the pointer to comparing function. The two arguments specify the pointers + of elements. The comparing function should returns positive if the former is big, negative + if the latter is big, 0 if both are equal. + Being sensitive to bias of input, quick sort is the fastest sorting algorithm. */ +void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); + + +/* Compare two strings with case insensitive evaluation. + `astr' specifies the pointer of one string. + `astr' specifies the pointer of the other string. + The return value is positive if the former is big, negative if the latter is big, 0 if both + are equivalent. + Upper cases and lower cases of alphabets in ASCII code are not distinguished. */ +int cbstricmp(const char *astr, const char *bstr); + + +/* Check whether a string begins with a key. + `str' specifies the pointer of a target string. + `key' specifies the pointer of a forward matching key string. + The return value is true if the target string begins with the key, else, it is false. */ +int cbstrfwmatch(const char *str, const char *key); + + +/* Check whether a string begins with a key, with case insensitive evaluation. + `str' specifies the pointer of a target string. + `key' specifies the pointer of a forward matching key string. + The return value is true if the target string begins with the key, else, it is false. + Upper cases and lower cases of alphabets in ASCII code are not distinguished. */ +int cbstrfwimatch(const char *str, const char *key); + + +/* Check whether a string ends with a key. + `str' specifies the pointer of a target string. + `key' specifies the pointer of a backward matching key string. + The return value is true if the target string ends with the key, else, it is false. */ +int cbstrbwmatch(const char *str, const char *key); + + +/* Check whether a string ends with a key, with case insensitive evaluation. + `str' specifies the pointer of a target string. + `key' specifies the pointer of a backward matching key string. + The return value is true if the target string ends with the key, else, it is false. + Upper cases and lower cases of alphabets in ASCII code are not distinguished. */ +int cbstrbwimatch(const char *str, const char *key); + + +/* Locate a substring in a string using KMP method. + `haystack' specifies the pointer of a target string. + `needle' specifies the pointer of a substring to be found. + The return value is the pointer to the beginning of the substring or `NULL' if the substring + is not found. + In most cases, `strstr' as a built-in function of the compiler is faster than this function. */ +char *cbstrstrkmp(const char *haystack, const char *needle); + + +/* Locate a substring in a string using BM method. + `haystack' specifies the pointer of a target string. + `needle' specifies the pointer of a substring to be found. + The return value is the pointer to the beginning of the substring or `NULL' if the substring + is not found. + In most cases, `strstr' as a built-in function of the compiler is faster than this function. */ +char *cbstrstrbm(const char *haystack, const char *needle); + + +/* Convert the letters of a string to upper case. + `str' specifies the pointer of a string to convert. + The return value is the pointer to the string. */ +char *cbstrtoupper(char *str); + + +/* Convert the letters of a string to lower case. + `str' specifies the pointer of a string to convert. + The return value is the pointer to the string. */ +char *cbstrtolower(char *str); + + +/* Cut space characters at head or tail of a string. + `str' specifies the pointer of a string to convert. + The return value is the pointer to the string. */ +char *cbstrtrim(char *str); + + +/* Squeeze space characters in a string and trim it. + `str' specifies the pointer of a string to convert. + The return value is the pointer to the string. */ +char *cbstrsqzspc(char *str); + + +/* Count the number of characters in a string of UTF-8. + `str' specifies the pointer of a string of UTF-8. + The return value is the number of characters in the string. */ +int cbstrcountutf(const char *str); + + +/* Cut a string of UTF-8 at the specified number of characters. + `str' specifies the pointer of a string of UTF-8. + `num' specifies the number of characters to be kept. + The return value is the pointer to the string. */ +char *cbstrcututf(char *str, int num); + + +/* Get a datum handle. + `ptr' specifies the pointer to the region of the initial content. If it is `NULL', an empty + datum is created. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + The return value is a datum handle. */ +CBDATUM *cbdatumopen(const char *ptr, int size); + + +/* Copy a datum. + `datum' specifies a datum handle. + The return value is a new datum handle. */ +CBDATUM *cbdatumdup(const CBDATUM *datum); + + +/* Free a datum handle. + `datum' specifies a datum handle. + Because the region of a closed handle is released, it becomes impossible to use the handle. */ +void cbdatumclose(CBDATUM *datum); + + +/* Concatenate a datum and a region. + `datum' specifies a datum handle. + `ptr' specifies the pointer to the region to be appended. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. */ +void cbdatumcat(CBDATUM *datum, const char *ptr, int size); + + +/* Get the pointer of the region of a datum. + `datum' specifies a datum handle. + The return value is the pointer of the region of a datum. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. */ +const char *cbdatumptr(const CBDATUM *datum); + + +/* Get the size of the region of a datum. + `datum' specifies a datum handle. + The return value is the size of the region of a datum. */ +int cbdatumsize(const CBDATUM *datum); + + +/* Change the size of the region of a datum. + `datum' specifies a datum handle. + `size' specifies the new size of the region. + If the new size is bigger than the one of old, the surplus region is filled with zero codes. */ +void cbdatumsetsize(CBDATUM *datum, int size); + + +/* Perform formatted output into a datum. + `format' specifies a printf-like format string. + The conversion character `%' can be used with such flag characters as `s', `d', `o', `u', + `x', `X', `c', `e', `E', `f', `g', `G', `@', `?', `:', `%'. `@' works as with `s' but escapes + meta characters of XML. `?' works as with `s' but escapes meta characters of URL. `:' works + as with `s' but performs MIME encoding as UTF-8. The other conversion character work as with + each original. */ +void cbdatumprintf(CBDATUM *datum, const char *format, ...); + + +/* Convert a datum to an allocated region. + `datum' specifies a datum handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer to the region of the datum. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. Because the region of the original datam is released, it should not be + released again. */ +char *cbdatumtomalloc(CBDATUM *datum, int *sp); + + +/* Get a list handle. + The return value is a list handle. */ +CBLIST *cblistopen(void); + + +/* Copy a list. + `list' specifies a list handle. + The return value is a new list handle. */ +CBLIST *cblistdup(const CBLIST *list); + + +/* Close a list handle. + `list' specifies a list handle. + Because the region of a closed handle is released, it becomes impossible to use the handle. */ +void cblistclose(CBLIST *list); + + +/* Get the number of elements of a list. + `list' specifies a list handle. + The return value is the number of elements of the list. */ +int cblistnum(const CBLIST *list); + + +/* Get the pointer to the region of an element of a list. + `list' specifies a list handle. + `index' specifies the index of an element. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer to the region of the value. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. If `index' is equal to or more than + the number of elements, the return value is `NULL'. */ +const char *cblistval(const CBLIST *list, int index, int *sp); + + +/* Add an element at the end of a list. + `list' specifies a list handle. + `ptr' specifies the pointer to the region of an element. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. */ +void cblistpush(CBLIST *list, const char *ptr, int size); + + +/* Remove an element of the end of a list. + `list' specifies a list handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer to the region of the value. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. If the list is empty, the return value is `NULL'. */ +char *cblistpop(CBLIST *list, int *sp); + + +/* Add an element at the top of a list. + `list' specifies a list handle. + `ptr' specifies the pointer to the region of an element. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. */ +void cblistunshift(CBLIST *list, const char *ptr, int size); + + +/* Remove an element of the top of a list. + `list' specifies a list handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer to the region of the value. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. If the list is empty, the return value is `NULL'. */ +char *cblistshift(CBLIST *list, int *sp); + + +/* Add an element at the specified location of a list. + `list' specifies a list handle. + `index' specifies the index of an element. + `ptr' specifies the pointer to the region of the element. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. */ +void cblistinsert(CBLIST *list, int index, const char *ptr, int size); + + +/* Remove an element at the specified location of a list. + `list' specifies a list handle. + `index' specifies the index of an element. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer to the region of the value. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. If `index' is equal to or more than the number of elements, no element + is removed and the return value is `NULL'. */ +char *cblistremove(CBLIST *list, int index, int *sp); + + +/* Overwrite an element at the specified location of a list. + `list' specifies a list handle. + `index' specifies the index of an element. + `ptr' specifies the pointer to the region of the new content. + `size' specifies the size of the new content. If it is negative, the size is assigned with + `strlen(ptr)'. + If `index' is equal to or more than the number of elements, this function has no effect. */ +void cblistover(CBLIST *list, int index, const char *ptr, int size); + + +/* Sort elements of a list in lexical order. + `list' specifies a list handle. + Quick sort is used for sorting. */ +void cblistsort(CBLIST *list); + + +/* Search a list for an element using liner search. + `list' specifies a list handle. + `ptr' specifies the pointer to the region of a key. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + The return value is the index of a corresponding element or -1 if there is no corresponding + element. If two or more elements corresponds, the former returns. */ +int cblistlsearch(const CBLIST *list, const char *ptr, int size); + + +/* Search a list for an element using binary search. + `list' specifies a list handle. It should be sorted in lexical order. + `ptr' specifies the pointer to the region of a key. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + The return value is the index of a corresponding element or -1 if there is no corresponding + element. If two or more elements corresponds, which returns is not defined. */ +int cblistbsearch(const CBLIST *list, const char *ptr, int size); + + +/* Serialize a list into a byte array. + `list' specifies a list handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. + The return value is the pointer to the region of the result serial region. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cblistdump(const CBLIST *list, int *sp); + + +/* Redintegrate a serialized list. + `ptr' specifies the pointer to a byte array. + `size' specifies the size of the region. + The return value is a new list handle. */ +CBLIST *cblistload(const char *ptr, int size); + + +/* Get a map handle. + The return value is a map handle. */ +CBMAP *cbmapopen(void); + + +/* Copy a map. + `map' specifies a map handle. + The return value is a new map handle. + The iterator of the source map is initialized. */ +CBMAP *cbmapdup(CBMAP *map); + + +/* Close a map handle. + `map' specifies a map handle. + Because the region of a closed handle is released, it becomes impossible to use the handle. */ +void cbmapclose(CBMAP *map); + + +/* Store a record into a map. + `map' specifies a map handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region of the value. If it is negative, the size is + assigned with `strlen(vbuf)'. + `over' specifies whether the value of the duplicated record is overwritten or not. + If `over' is false and the key is duplicated, the return value is false, else, it is true. */ +int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over); + + +/* Concatenate a value at the end of the value of the existing record. + `map' specifies a map handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region of the value. If it is negative, the size is + assigned with `strlen(vbuf)'. + If there is no corresponding record, a new record is created. */ +void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz); + + +/* Delete a record in a map. + `map' specifies a map handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is true. False is returned when no record corresponds to + the specified key. */ +int cbmapout(CBMAP *map, const char *kbuf, int ksiz); + + +/* Retrieve a record in a map. + `map' specifies a map handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record. `NULL' is returned when no record corresponds. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. */ +const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp); + + +/* Move a record to the edge of a map. + `map' specifies a map handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `head' specifies the destination which is head if it is true or tail if else. + If successful, the return value is true. False is returned when no record corresponds to + the specified key. */ +int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head); + + +/* Initialize the iterator of a map. + `map' specifies a map handle. + The iterator is used in order to access the key of every record stored in a map. */ +void cbmapiterinit(CBMAP *map); + + +/* Get the next key of the iterator of a map. + `map' specifies a map handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the next key, else, it is + `NULL'. `NULL' is returned when no record is to be get out of the iterator. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. The order of iteration is assured + to be the same of the one of storing. */ +const char *cbmapiternext(CBMAP *map, int *sp); + + +/* Get the value binded to the key fetched from the iterator of a map. + `kbuf' specifies the pointer to the region of a iteration key. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer to the region of the value of the corresponding record. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. */ +const char *cbmapiterval(const char *kbuf, int *sp); + + +/* Get the number of the records stored in a map. + `map' specifies a map handle. + The return value is the number of the records stored in the map. */ +int cbmaprnum(const CBMAP *map); + + +/* Get the list handle contains all keys in a map. + `map' specifies a map handle. + The return value is the list handle contains all keys in the map. + Because the handle of the return value is opened with the function `cblistopen', it should + be closed with the function `cblistclose' if it is no longer in use. */ +CBLIST *cbmapkeys(CBMAP *map); + + +/* Get the list handle contains all values in a map. + `map' specifies a map handle. + The return value is the list handle contains all values in the map. + Because the handle of the return value is opened with the function `cblistopen', it should + be closed with the function `cblistclose' if it is no longer in use. */ +CBLIST *cbmapvals(CBMAP *map); + + +/* Serialize a map into a byte array. + `map' specifies a map handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. + The return value is the pointer to the region of the result serial region. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cbmapdump(CBMAP *map, int *sp); + + +/* Redintegrate a serialized map. + `ptr' specifies the pointer to a byte array. + `size' specifies the size of the region. + The return value is a new map handle. */ +CBMAP *cbmapload(const char *ptr, int size); + + +/* Extract a record from a serialized map. + `ptr' specifies the pointer to a byte array. + `size' specifies the size of the region. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record. `NULL' is returned when no record corresponds. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. */ +char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp); + + +/* Get a heap handle. + `size' specifies the size of each record. + `max' specifies the maximum number of records in the heap. + `compar' specifies the pointer to comparing function. The two arguments specify the pointers + of records. The comparing function should returns positive if the former is big, negative + if the latter is big, 0 if both are equal. + The return value is a heap handle. */ +CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *)); + + +/* Copy a heap. + `heap' specifies a heap handle. + The return value is a new heap handle. */ +CBHEAP *cbheapdup(CBHEAP *heap); + + +/* Close a heap handle. + `heap' specifies a heap handle. + Because the region of a closed handle is released, it becomes impossible to use the handle. */ +void cbheapclose(CBHEAP *heap); + + +/* Get the number of the records stored in a heap. + `heap' specifies a heap handle. + The return value is the number of the records stored in the heap. */ +int cbheapnum(CBHEAP *heap); + + +/* Insert a record into a heap. + `heap' specifies a heap handle. + `ptr' specifies the pointer to the region of a record. + The return value is true if the record is added, else false. + If the new record is bigger than the biggest existing regord, the new record is not added. + If the new record is added and the number of records exceeds the maximum number, the biggest + existing record is removed. */ +int cbheapinsert(CBHEAP *heap, const void *ptr); + + +/* Get the pointer to the region of a record in a heap. + `heap' specifies a heap handle. + `index' specifies the index of a record. + The return value is the pointer to the region of the record. + If `index' is equal to or more than the number of records, the return value is `NULL'. Note + that records are organized by the nagative order the comparing function. */ +const void *cbheapval(CBHEAP *heap, int index); + + +/* Convert a heap to an allocated region. + `heap' specifies a heap handle. + `np' specifies the pointer to a variable to which the number of records of the return value + is assigned. If it is `NULL', it is not used. + The return value is the pointer to the region of the heap. Records are sorted. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. Because the region of the original + heap is released, it should not be released again. */ +void *cbheaptomalloc(CBHEAP *heap, int *np); + + +/* Allocate a formatted string on memory. + `format' specifies a printf-like format string. The conversion character `%' can be used + with such flag characters as `d', `o', `u', `x', `X', `e', `E', `f', `g', `G', `c', `s', and + `%'. Specifiers of the field length and the precision can be put between the conversion + characters and the flag characters. The specifiers consist of decimal characters, `.', `+', + `-', and the space character. + The other arguments are used according to the format string. + The return value is the pointer to the allocated region of the result string. Because the + region of the return value is allocated with the `malloc' call, it should be released with + the `free' call if it is no longer in use. */ +char *cbsprintf(const char *format, ...); + + +/* Replace some patterns in a string. + `str' specifies the pointer to a source string. + `pairs' specifies the handle of a map composed of pairs of replacement. The key of each pair + specifies a pattern before replacement and its value specifies the pattern after replacement. + The return value is the pointer to the allocated region of the result string. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cbreplace(const char *str, CBMAP *pairs); + + +/* Make a list by splitting a serial datum. + `ptr' specifies the pointer to the region of the source content. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + `delim' specifies a string containing delimiting characters. If it is `NULL', zero code is + used as a delimiter. + The return value is a list handle. + If two delimiters are successive, it is assumed that an empty element is between the two. + Because the handle of the return value is opened with the function `cblistopen', it should + be closed with the function `cblistclose'. */ +CBLIST *cbsplit(const char *ptr, int size, const char *delim); + + +/* Read whole data of a file. + `name' specifies the name of a file. If it is `NULL', the standard input is specified. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer to the allocated region of the read data. Because an + additional zero code is appended at the end of the region of the return value, the return + value can be treated as a character string. Because the region of the return value is + allocated with the `malloc' call, it should be released with the `free' call if it is no + longer in use. */ +char *cbreadfile(const char *name, int *sp); + + +/* Write a serial datum into a file. + `name specifies the name of a file. If it is `NULL', the standard output is specified. + `ptr' specifies the pointer to the region of the source content. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + If successful, the return value is true, else, it is false. + If the file exists, it is overwritten. Else, a new file is created. */ +int cbwritefile(const char *name, const char *ptr, int size); + + +/* Read every line of a file. + `name' specifies the name of a file. If it is `NULL', the standard input is specified. + The return value is a list handle of the lines if successful, else it is NULL. Line + separators are cut out. Because the handle of the return value is opened with the function + `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */ +CBLIST *cbreadlines(const char *name); + + +/* Read names of files in a directory. + `name' specifies the name of a directory. + The return value is a list handle of names if successful, else it is NULL. + Because the handle of the return value is opened with the function `cblistopen', it should + be closed with the function `cblistclose' if it is no longer in use. */ +CBLIST *cbdirlist(const char *name); + + +/* Get the status of a file or a directory. + `name' specifies the name of a file or a directory. + `dirp' specifies the pointer to a variable to which whether the file is a directory is + assigned. If it is `NULL', it is not used. + `sizep' specifies the pointer to a variable to which the size of the file is assigned. If it + is `NULL', it is not used. + `mtimep' specifies the pointer to a variable to which the last modified time of the file is + assigned. If it is `NULL', it is not used. + If successful, the return value is true, else, false. False is returned when the file does + not exist or the permission is denied. */ +int cbfilestat(const char *name, int *isdirp, int *sizep, time_t *mtimep); + + +/* Remove a file or a directory and its sub ones recursively. + `name' specifies the name of a file or a directory. + If successful, the return value is true, else, false. False is returned when the file does + not exist or the permission is denied. */ +int cbremove(const char *name); + + +/* Break up a URL into elements. + `str' specifies the pointer to a string of URL. + The return value is a map handle. Each key of the map is the name of an element. The key + "self" specifies the URL itself. The key "scheme" specifies the scheme. The key "host" + specifies the host of the server. The key "port" specifies the port number of the server. + The key "authority" specifies the authority information. The key "path" specifies the path + of the resource. The key "file" specifies the file name without the directory section. The + key "query" specifies the query string. The key "fragment" specifies the fragment string. + Supported schema are HTTP, HTTPS, FTP, and FILE. Absolute URL and relative URL are supported. + Because the handle of the return value is opened with the function `cbmapopen', it should + be closed with the function `cbmapclose' if it is no longer in use. */ +CBMAP *cburlbreak(const char *str); + + +/* Resolve a relative URL with another absolute URL. + `base' specifies an absolute URL of a base location. + `target' specifies a URL to be resolved. + The return value is a resolved URL. If the target URL is relative, a new URL of relative + location from the base location is returned. Else, a copy of the target URL is returned. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cburlresolve(const char *base, const char *target); + + +/* Encode a serial object with URL encoding. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + The return value is the pointer to the result string. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cburlencode(const char *ptr, int size); + + +/* Decode a string encoded with URL encoding. + `str' specifies the pointer to an encoded string. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer to the region of the result. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if + it is no longer in use. */ +char *cburldecode(const char *str, int *sp); + + +/* Encode a serial object with Base64 encoding. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + The return value is the pointer to the result string. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cbbaseencode(const char *ptr, int size); + + +/* Decode a string encoded with Base64 encoding. + `str' specifies the pointer to an encoded string. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer to the region of the result. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if + it is no longer in use. */ +char *cbbasedecode(const char *str, int *sp); + + +/* Encode a serial object with quoted-printable encoding. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + The return value is the pointer to the result string. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cbquoteencode(const char *ptr, int size); + + +/* Decode a string encoded with quoted-printable encoding. + `str' specifies the pointer to an encoded string. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer to the region of the result. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if + it is no longer in use. */ +char *cbquotedecode(const char *str, int *sp); + + +/* Split a string of MIME into headers and the body. + `ptr' specifies the pointer to the region of MIME data. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + `attrs' specifies a map handle to store attributes. If it is `NULL', it is not used. Each + key of the map is an attribute name uncapitalized. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + The return value is the pointer of the body data. + If the content type is defined, the attribute map has the key "TYPE" specifying the type. If + the character encoding is defined, the key "CHARSET" specifies the encoding name. If the + boundary string of multipart is defined, the key "BOUNDARY" specifies the string. If the + content disposition is defined, the key "DISPOSITION" specifies the direction. If the file + name is defined, the key "FILENAME" specifies the name. If the attribute name is defined, + the key "NAME" specifies the name. Because the region of the return value is allocated with + the `malloc' call, it should be released with the `free' call if it is no longer in use. */ +char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp); + + +/* Split multipart data of MIME into its parts. + `ptr' specifies the pointer to the region of multipart data of MIME. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + `boundary' specifies the pointer to the region of the boundary string. + The return value is a list handle. Each element of the list is the string of a part. + Because the handle of the return value is opened with the function `cblistopen', it should + be closed with the function `cblistclose' if it is no longer in use. */ +CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary); + + +/* Encode a string with MIME encoding. + `str' specifies the pointer to a string. + `encname' specifies a string of the name of the character encoding. + The return value is the pointer to the result string. + `base' specifies whether to use Base64 encoding. If it is false, quoted-printable is used. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cbmimeencode(const char *str, const char *encname, int base); + + +/* Decode a string encoded with MIME encoding. + `str' specifies the pointer to an encoded string. + `enp' specifies the pointer to a region into which the name of encoding is written. If it is + `NULL', it is not used. The size of the buffer should be equal to or more than 32 bytes. + The return value is the pointer to the result string. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cbmimedecode(const char *str, char *enp); + + +/* Split a string of CSV into rows. + `str' specifies the pointer to the region of an CSV string. + The return value is a list handle. Each element of the list is a string of a row. + Because the handle of the return value is opened with the function `cblistopen', it should + be closed with the function `cblistclose' if it is no longer in use. The character encoding + of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Being + compatible with MS-Excel, these functions for CSV can handle cells including such meta + characters as comma, between double quotation marks. */ +CBLIST *cbcsvrows(const char *str); + + +/* Split the string of a row of CSV into cells. + `str' specifies the pointer to the region of a row of CSV. + The return value is a list handle. Each element of the list is the unescaped string of a + cell of the row. + Because the handle of the return value is opened with the function `cblistopen', it should + be closed with the function `cblistclose' if it is no longer in use. */ +CBLIST *cbcsvcells(const char *str); + + +/* Escape a string with the meta characters of CSV. + `str' specifies the pointer to the region of a string. + The return value is the pointer to the escaped string sanitized of meta characters. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cbcsvescape(const char *str); + + +/* Unescape a string with the escaped meta characters of CSV. + `str' specifies the pointer to the region of a string with meta characters. + The return value is the pointer to the unescaped string. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cbcsvunescape(const char *str); + + +/* Split a string of XML into tags and text sections. + `str' specifies the pointer to the region of an XML string. + `cr' specifies whether to remove comments. + The return value is a list handle. Each element of the list is the string of a tag or a + text section. + Because the handle of the return value is opened with the function `cblistopen', it should + be closed with the function `cblistclose' if it is no longer in use. The character encoding + of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Because + these functions for XML are not XML parser with validation check, it can handle also HTML + and SGML. */ +CBLIST *cbxmlbreak(const char *str, int cr); + + +/* Get the map of attributes of an XML tag. + `str' specifies the pointer to the region of a tag string. + The return value is a map handle. Each key of the map is the name of an attribute. Each + value is unescaped. You can get the name of the tag with the key of an empty string. + Because the handle of the return value is opened with the function `cbmapopen', it should + be closed with the function `cbmapclose' if it is no longer in use. */ +CBMAP *cbxmlattrs(const char *str); + + +/* Escape a string with the meta characters of XML. + `str' specifies the pointer to the region of a string. + The return value is the pointer to the escaped string sanitized of meta characters. + This function converts only `&', `<', `>', and `"'. Because the region of the return value + is allocated with the `malloc' call, it should be released with the `free' call if it is no + longer in use. */ +char *cbxmlescape(const char *str); + + +/* Unescape a string with the entity references of XML. + `str' specifies the pointer to the region of a string with meta characters. + The return value is the pointer to the unescaped string. + This function restores only `&', `<', `>', and `"'. Because the region of the + return value is allocated with the `malloc' call, it should be released with the `free' call + if it is no longer in use. */ +char *cbxmlunescape(const char *str); + + +/* Compress a serial object with ZLIB. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. + If successful, the return value is the pointer to the result object, else, it is `NULL'. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. This function is available only if + QDBM was built with ZLIB enabled. */ +char *cbdeflate(const char *ptr, int size, int *sp); + + +/* Decompress a serial object compressed with ZLIB. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the result object, else, it is `NULL'. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. This function is available only if QDBM was built with ZLIB enabled. */ +char *cbinflate(const char *ptr, int size, int *sp); + + +/* Compress a serial object with GZIP. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. + If successful, the return value is the pointer to the result object, else, it is `NULL'. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. This function is available only if + QDBM was built with ZLIB enabled. */ +char *cbgzencode(const char *ptr, int size, int *sp); + + +/* Decompress a serial object compressed with GZIP. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the result object, else, it is `NULL'. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. This function is available only if QDBM was built with ZLIB enabled. */ +char *cbgzdecode(const char *ptr, int size, int *sp); + + +/* Get the CRC32 checksum of a serial object. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + The return value is the CRC32 checksum of the object. + This function is available only if QDBM was built with ZLIB enabled. */ +unsigned int cbgetcrc(const char *ptr, int size); + + +/* Compress a serial object with LZO. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. + If successful, the return value is the pointer to the result object, else, it is `NULL'. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. This function is available only if + QDBM was built with LZO enabled. */ +char *cblzoencode(const char *ptr, int size, int *sp); + + +/* Decompress a serial object compressed with LZO. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the result object, else, it is `NULL'. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. This function is available only if QDBM was built with LZO enabled. */ +char *cblzodecode(const char *ptr, int size, int *sp); + + +/* Compress a serial object with BZIP2. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. + If successful, the return value is the pointer to the result object, else, it is `NULL'. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. This function is available only if + QDBM was built with LZO enabled. */ +char *cbbzencode(const char *ptr, int size, int *sp); + + +/* Decompress a serial object compressed with BZIP2. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the result object, else, it is `NULL'. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. This function is available only if QDBM was built with LZO enabled. */ +char *cbbzdecode(const char *ptr, int size, int *sp); + + +/* Convert the character encoding of a string. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + `icode' specifies the name of encoding of the input string. + `ocode' specifies the name of encoding of the output string. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + `mp' specifies the pointer to a variable to which the number of missing characters by failure + of conversion is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the result object, else, it is `NULL'. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. This function is available only if QDBM was built with ICONV enabled. */ +char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp); + + +/* Detect the encoding of a string automatically. + `ptr' specifies the pointer to a region. + `size' specifies the size of the region. If it is negative, the size is assigned with + `strlen(ptr)'. + The return value is the string of the encoding name of the string. + As it stands, US-ASCII, ISO-2022-JP, Shift_JIS, CP932, EUC-JP, UTF-8, UTF-16, UTF-16BE, + and UTF-16LE are supported. If none of them matches, ISO-8859-1 is selected. This function + is available only if QDBM was built with ICONV enabled. */ +const char *cbencname(const char *ptr, int size); + + +/* Get the jet lag of the local time in seconds. + The return value is the jet lag of the local time in seconds. */ +int cbjetlag(void); + + +/* Get the Gregorian calendar of a time. + `t' specifies a source time. If it is negative, the current time is specified. + `jl' specifies the jet lag of a location in seconds. + `yearp' specifies the pointer to a variable to which the year is assigned. If it is `NULL', + it is not used. + `monp' specifies the pointer to a variable to which the month is assigned. If it is `NULL', + it is not used. 1 means January and 12 means December. + `dayp' specifies the pointer to a variable to which the day of the month is assigned. If it + is `NULL', it is not used. + `hourp' specifies the pointer to a variable to which the hours is assigned. If it is `NULL', + it is not used. + `minp' specifies the pointer to a variable to which the minutes is assigned. If it is `NULL', + it is not used. + `secp' specifies the pointer to a variable to which the seconds is assigned. If it is `NULL', + it is not used. */ +void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp); + + +/* Get the day of week of a date. + `year' specifies the year of a date. + `mon' specifies the month of the date. + `day' specifies the day of the date. + The return value is the day of week of the date. 0 means Sunday and 6 means Saturday. */ +int cbdayofweek(int year, int mon, int day); + + +/* Get the string for a date in W3CDTF. + `t' specifies a source time. If it is negative, the current time is specified. + `jl' specifies the jet lag of a location in seconds. + The return value is the string of the date in W3CDTF (YYYY-MM-DDThh:mm:ddTZD). + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cbdatestrwww(time_t t, int jl); + + +/* Get the string for a date in RFC 1123 format. + `t' specifies a source time. If it is negative, the current time is specified. + `jl' specifies the jet lag of a location in seconds. + The return value is the string of the date in RFC 1123 format (Wdy, DD-Mon-YYYY hh:mm:dd TZD). + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *cbdatestrhttp(time_t t, int jl); + + +/* Get the time value of a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). + `str' specifies a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). + The return value is the time value of the date or -1 if the format is invalid. + Decimal can be trailed by "s" for in seconds, "m" for in minutes, "h" for in hours, + and "d" for in days. */ +time_t cbstrmktime(const char *str); + + +/* Get user and system processing times. + `usrp' specifies the pointer to a variable to which the user processing time is assigned. + If it is `NULL', it is not used. The unit of time is seconds. + `sysp' specifies the pointer to a variable to which the system processing time is assigned. + If it is `NULL', it is not used. The unit of time is seconds. */ +void cbproctime(double *usrp, double *sysp); + + +/* Ensure that the standard I/O is binary mode. + This function is useful for applications on dosish file systems. */ +void cbstdiobin(void); + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Show error message on the standard error output and exit. + `message' specifies an error message. + This function does not return. */ +void *cbmyfatal(const char *message); + + +/* Create a datum handle from an allocated region. + `ptr' specifies the pointer to the region of an element. The region should be allocated with + malloc and it is released by the function. + `size' specifies the size of the region. */ +CBDATUM *cbdatumopenbuf(char *ptr, int size); + + +/* Set a buffer to a datum handle. + `ptr' specifies the pointer to the region of an element. The region should be allocated with + malloc and it is released by the function. + `size' specifies the size of the region. */ +void cbdatumsetbuf(CBDATUM *datum, char *ptr, int size); + + +/* Add an allocated element at the end of a list. + `list' specifies a list handle. + `ptr' specifies the pointer to the region of an element. The region should be allocated with + malloc and it is released by the function. + `size' specifies the size of the region. */ +void cblistpushbuf(CBLIST *list, char *ptr, int size); + + +/* Get a map handle with specifying the number of buckets. + `bnum' specifies the number of buckets. + The return value is a map handle. */ +CBMAP *cbmapopenex(int bnum); + + +/* Alias of `cbmalloc'. */ +#define CB_MALLOC(CB_ptr, CB_size) \ + (((CB_ptr) = malloc(CB_size)) ? (CB_ptr) : cbmyfatal("out of memory")) + + +/* Alias of `cbrealloc'. */ +#define CB_REALLOC(CB_ptr, CB_size) \ + (((CB_ptr) = realloc((CB_ptr), (CB_size))) ? (CB_ptr) : cbmyfatal("out of memory")) + + +/* Alias of `cbmemdup'. + However, `size' should not be negative. */ +#define CB_MEMDUP(CB_res, CB_ptr, CB_size) \ + do { \ + CB_MALLOC((CB_res), (CB_size) + 1); \ + memcpy((CB_res), (CB_ptr), (CB_size)); \ + (CB_res)[(CB_size)] = '\0'; \ + } while(FALSE) + + +/* Get the size of padding bytes for pointer alignment. + `hsiz' specifies the header size of the object. + The return value is the size of padding bytes. */ +#define CB_ALIGNPAD(CB_hsiz) \ + (((CB_hsiz | ~-(int)sizeof(void *)) + 1) - CB_hsiz) + + +/* Alias of `cbdatumopen'. + However, no dafault data is specified. */ +#define CB_DATUMOPEN(CB_datum) \ + do { \ + CB_MALLOC((CB_datum), sizeof(*(CB_datum))); \ + CB_MALLOC((CB_datum)->dptr, CB_DATUMUNIT); \ + (CB_datum)->dptr[0] = '\0'; \ + (CB_datum)->dsize = 0; \ + (CB_datum)->asize = CB_DATUMUNIT; \ + } while(FALSE) + + +/* Alias of `cbdatumopen'. + However, `size' should not be negative. */ +#define CB_DATUMOPEN2(CB_datum, CB_ptr, CB_size) \ + do { \ + CB_DATUMOPEN((CB_datum)); \ + CB_DATUMCAT((CB_datum), (CB_ptr), (CB_size)); \ + } while(FALSE) + + +/* Alias of `cbdatumclose'. */ +#define CB_DATUMCLOSE(CB_datum) \ + do { \ + free((CB_datum)->dptr); \ + free((CB_datum)); \ + } while(FALSE) + + +/* Alias of `cbdatumcat'. + However, `size' should not be negative. */ +#define CB_DATUMCAT(CB_datum, CB_ptr, CB_size) \ + do { \ + if((CB_datum)->dsize + (CB_size) >= (CB_datum)->asize){ \ + (CB_datum)->asize = (CB_datum)->asize * 2 + (CB_size) + 1; \ + CB_REALLOC((CB_datum)->dptr, (CB_datum)->asize); \ + } \ + memcpy((CB_datum)->dptr + (CB_datum)->dsize, (CB_ptr), (CB_size)); \ + (CB_datum)->dsize += (CB_size); \ + (CB_datum)->dptr[(CB_datum)->dsize] = '\0'; \ + } while(FALSE) + + +/* Alias of `cbdatumptr'. */ +#define CB_DATUMPTR(CB_datum) ((const char *)((CB_datum)->dptr)) + + +/* Alias of `cbdatumsize'. */ +#define CB_DATUMSIZE(CB_datum) ((int)((CB_datum)->dsize)) + + +/* Alias of `cbdatumsetsize'. */ +#define CB_DATUMSETSIZE(CB_datum, CB_size) \ + do { \ + if((CB_size) <= (CB_datum)->dsize){ \ + (CB_datum)->dsize = (CB_size); \ + (CB_datum)->dptr[(CB_size)] = '\0'; \ + } else { \ + if((CB_size) >= (CB_datum)->asize){ \ + (CB_datum)->asize = (CB_datum)->asize * 2 + (CB_size) + 1; \ + CB_REALLOC((CB_datum)->dptr, (CB_datum)->asize); \ + } \ + memset((CB_datum)->dptr + (CB_datum)->dsize, 0, ((CB_size) - (CB_datum)->dsize) + 1); \ + (CB_datum)->dsize = (CB_size); \ + } \ + } while(FALSE) + + +/* Alias of `cbdatumtomalloc'. */ +#define CB_DATUMTOMALLOC(CB_datum, CB_ptr, CB_size) \ + do { \ + (CB_ptr) = (CB_datum)->dptr; \ + (CB_size) = (CB_datum)->dsize; \ + free((CB_datum)); \ + } while(FALSE) + + +/* Alias of `cblistopen'. */ +#define CB_LISTOPEN(CB_list) \ + do { \ + CB_MALLOC((CB_list), sizeof(*(CB_list))); \ + (CB_list)->anum = CB_LISTUNIT; \ + CB_MALLOC((CB_list)->array, sizeof((CB_list)->array[0]) * (CB_list)->anum); \ + (CB_list)->start = 0; \ + (CB_list)->num = 0; \ + } while(FALSE) + + +/* Alias of `cblistopen'. + However, `anum' is specified for the number of initial allocated elements. */ +#define CB_LISTOPEN2(CB_list, CB_anum) \ + do { \ + CB_MALLOC((CB_list), sizeof(*(CB_list))); \ + (CB_list)->anum = (CB_anum) > 4 ? (CB_anum) : 4; \ + CB_MALLOC((CB_list)->array, sizeof((CB_list)->array[0]) * (CB_list)->anum); \ + (CB_list)->start = 0; \ + (CB_list)->num = 0; \ + } while(FALSE) + + +/* Alias of `cblistclose'. */ +#define CB_LISTCLOSE(CB_list) \ + do { \ + int _CB_i, _CB_end; \ + _CB_end = (CB_list)->start + (CB_list)->num; \ + for(_CB_i = (CB_list)->start; _CB_i < _CB_end; _CB_i++){ \ + free((CB_list)->array[_CB_i].dptr); \ + } \ + free((CB_list)->array); \ + free((CB_list)); \ + } while(FALSE) + + +/* Alias of `cblistnum'. */ +#define CB_LISTNUM(CB_list) \ + ((int)((CB_list)->num)) + + +/* Alias of `cblistval'. + However, `sp' is ignored. */ +#define CB_LISTVAL(CB_list, CB_index) \ + ((const char *)((CB_list)->array[(CB_list)->start+(CB_index)].dptr)) + + +/* Alias of `cblistval'. + However, `size' is used instead of `sp'. */ +#define CB_LISTVAL2(CB_list, CB_index, CB_size) \ + ((CB_size) = (CB_list)->array[(CB_list)->start+(CB_index)].dsize, \ + (const char *)((CB_list)->array[(CB_list)->start+(CB_index)].dptr)) + + +/* Alias of `cblistpush'. + However, `size' should not be negative. */ +#define CB_LISTPUSH(CB_list, CB_ptr, CB_size) \ + do { \ + int _CB_index; \ + _CB_index = (CB_list)->start + (CB_list)->num; \ + if(_CB_index >= (CB_list)->anum){ \ + (CB_list)->anum *= 2; \ + CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \ + } \ + CB_MALLOC((CB_list)->array[_CB_index].dptr, \ + ((CB_size) < CB_DATUMUNIT ? CB_DATUMUNIT : (CB_size)) + 1); \ + memcpy((CB_list)->array[_CB_index].dptr, (CB_ptr), (CB_size)); \ + (CB_list)->array[_CB_index].dptr[(CB_size)] = '\0'; \ + (CB_list)->array[_CB_index].dsize = (CB_size); \ + (CB_list)->num++; \ + } while(FALSE) + + +/* Remove and free an element of the end of a list. + `list' specifies a list handle. */ +#define CB_LISTDROP(CB_list) \ + do { \ + if((CB_list)->num > 0){ \ + free((CB_list)->array[(CB_list)->start+(CB_list)->num-1].dptr); \ + (CB_list)->num--; \ + } \ + } while(FALSE) + + +/* Alias of `cblistinsert'. + However, `index' is not checked and `size' should not be negative. */ +#define CB_LISTINSERT(CB_list, CB_index, CB_ptr, CB_size) \ + do { \ + int _CB_index = (CB_index); \ + _CB_index += (CB_list)->start; \ + if((CB_list)->start + (CB_list)->num >= (CB_list)->anum){ \ + (CB_list)->anum *= 2; \ + CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \ + } \ + memmove((CB_list)->array + _CB_index + 1, (CB_list)->array + _CB_index, \ + sizeof((CB_list)->array[0]) * ((CB_list)->start + (CB_list)->num - _CB_index)); \ + CB_MEMDUP((CB_list)->array[_CB_index].dptr, (CB_ptr), (CB_size)); \ + (CB_list)->array[_CB_index].dsize = (CB_size); \ + (CB_list)->num++; \ + } while(FALSE) + + +/* Alias of `cblistpushbuf'. */ +#define CB_LISTPUSHBUF(CB_list, CB_ptr, CB_size) \ + do{ \ + int _CB_index; \ + _CB_index = (CB_list)->start + (CB_list)->num; \ + if(_CB_index >= (CB_list)->anum){ \ + (CB_list)->anum *= 2; \ + CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \ + } \ + (CB_list)->array[_CB_index].dptr = (CB_ptr); \ + (CB_list)->array[_CB_index].dsize = (CB_size); \ + (CB_list)->num++; \ + } while(FALSE) \ + + +/* Alias of `cbmapiterval'. + However, `size' is used instead of `sp'. */ +#define CB_MAPITERVAL(CB_vbuf, CB_kbuf, CB_vsiz) \ + do { \ + CBMAPDATUM *_CB_datum; \ + _CB_datum = (CBMAPDATUM *)((CB_kbuf) - sizeof(*_CB_datum)); \ + (CB_vsiz) = _CB_datum->vsiz; \ + (CB_vbuf) = (char *)_CB_datum + sizeof(*_CB_datum) + \ + _CB_datum->ksiz + CB_ALIGNPAD(_CB_datum->ksiz); \ + } while(FALSE) + + + +#undef MYEXTERN + +#if defined(__cplusplus) /* export for C++ */ +} +#endif + +#endif /* duplication check */ + + +/* END OF FILE */ Deleted: box/trunk/qdbm/cbcodec.c =================================================================== --- box/trunk/qdbm/cbcodec.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/cbcodec.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,1079 +0,0 @@ -/************************************************************************************************* - * Popular encoders and decoders - * 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 -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define DEFCODE "UTF-8" /* default encoding */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -char *readstdin(int *sp); -int runurl(int argc, char **argv); -int runbase(int argc, char **argv); -int runquote(int argc, char **argv); -int runmime(int argc, char **argv); -int runcsv(int argc, char **argv); -int runxml(int argc, char **argv); -int runzlib(int argc, char **argv); -int runlzo(int argc, char **argv); -int runbzip(int argc, char **argv); -int runiconv(int argc, char **argv); -int rundate(int argc, char **argv); -void shouucsmap(void); - - -/* main routine */ -int main(int argc, char **argv){ - int rv; - cbstdiobin(); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "url")){ - rv = runurl(argc, argv); - } else if(!strcmp(argv[1], "base")){ - rv = runbase(argc, argv); - } else if(!strcmp(argv[1], "quote")){ - rv = runquote(argc, argv); - } else if(!strcmp(argv[1], "mime")){ - rv = runmime(argc, argv); - } else if(!strcmp(argv[1], "csv")){ - rv = runcsv(argc, argv); - } else if(!strcmp(argv[1], "xml")){ - rv = runxml(argc, argv); - } else if(!strcmp(argv[1], "zlib")){ - rv = runzlib(argc, argv); - } else if(!strcmp(argv[1], "lzo")){ - rv = runlzo(argc, argv); - } else if(!strcmp(argv[1], "bzip")){ - rv = runbzip(argc, argv); - } else if(!strcmp(argv[1], "iconv")){ - rv = runiconv(argc, argv); - } else if(!strcmp(argv[1], "date")){ - rv = rundate(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - char *tmp; - int tsiz; - fprintf(stderr, "%s: popular encoders and decoders\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s url [-d] [-br] [-rs base target] [-l] [-e expr] [file]\n", progname); - fprintf(stderr, " %s base [-d] [-l] [-c num] [-e expr] [file]\n", progname); - fprintf(stderr, " %s quote [-d] [-l] [-c num] [-e expr] [file]\n", progname); - fprintf(stderr, " %s mime [-d] [-hd] [-bd] [-part num] [-l] [-ec code] [-qp] [-dc] [-e expr]" - " [file]\n", progname); - fprintf(stderr, " %s csv [-d] [-t] [-l] [-e expr] [-html] [file]\n", progname); - fprintf(stderr, " %s xml [-d] [-p] [-l] [-e expr] [-tsv] [file]\n", progname); - if((tmp = cbdeflate("", 0, &tsiz)) != NULL){ - fprintf(stderr, " %s zlib [-d] [-gz] [-crc] [file]\n", progname); - free(tmp); - } - if((tmp = cblzoencode("", 0, &tsiz)) != NULL){ - fprintf(stderr, " %s lzo [-d] [file]\n", progname); - free(tmp); - } - if((tmp = cbbzencode("", 0, &tsiz)) != NULL){ - fprintf(stderr, " %s bzip [-d] [file]\n", progname); - free(tmp); - } - if((tmp = cbiconv("", 0, "US-ASCII", "US-ASCII", NULL, NULL)) != NULL){ - fprintf(stderr, " %s iconv [-ic code] [-oc code] [-ol ltype] [-cn] [-wc] [-um] [file]\n", - progname); - free(tmp); - } - fprintf(stderr, " %s date [-wf] [-rf] [-utc] [str]\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* read the standard input */ -char *readstdin(int *sp){ - char *buf; - int i, blen, c; - blen = 256; - buf = cbmalloc(blen); - for(i = 0; (c = getchar()) != EOF; i++){ - if(i >= blen - 1) buf = cbrealloc(buf, blen *= 2); - buf[i] = c; - } - buf[i] = '\0'; - if(sp) *sp = i; - return buf; -} - - -/* parse arguments of url command */ -int runurl(int argc, char **argv){ - CBMAP *map; - int i, size, dec, br, line; - const char *val; - char *base, *target, *expr, *file, *buf, *res; - dec = FALSE; - br = FALSE; - line = FALSE; - base = NULL; - target = NULL; - expr = NULL; - file = NULL; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - dec = TRUE; - } else if(!strcmp(argv[i], "-br")){ - br = TRUE; - } else if(!strcmp(argv[i], "-rs")){ - if(++i >= argc) usage(); - base = argv[i]; - if(++i >= argc) usage(); - target = argv[i]; - } else if(!strcmp(argv[i], "-l")){ - line = TRUE; - } else if(!strcmp(argv[i], "-e")){ - if(++i >= argc) usage(); - expr = argv[i]; - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - buf = NULL; - if(base){ - size = strlen(base); - buf = cbmemdup(base, size); - } else if(expr){ - size = strlen(expr); - buf = cbmemdup(expr, size); - } else if(file){ - if(!(buf = cbreadfile(file, &size))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - buf = readstdin(&size); - } - if(target){ - res = cburlresolve(base, target); - printf("%s", res); - free(res); - } else if(br){ - map = cburlbreak(buf); - if((val = cbmapget(map, "self", -1, NULL))) printf("self\t%s\n", val); - if((val = cbmapget(map, "scheme", -1, NULL))) printf("scheme\t%s\n", val); - if((val = cbmapget(map, "host", -1, NULL))) printf("host\t%s\n", val); - if((val = cbmapget(map, "port", -1, NULL))) printf("port\t%s\n", val); - if((val = cbmapget(map, "authority", -1, NULL))) printf("authority\t%s\n", val); - if((val = cbmapget(map, "path", -1, NULL))) printf("path\t%s\n", val); - if((val = cbmapget(map, "file", -1, NULL))) printf("file\t%s\n", val); - if((val = cbmapget(map, "query", -1, NULL))) printf("query\t%s\n", val); - if((val = cbmapget(map, "fragment", -1, NULL))) printf("fragment\t%s\n", val); - cbmapclose(map); - } else if(dec){ - res = cburldecode(buf, &size); - for(i = 0; i < size; i++){ - putchar(res[i]); - } - free(res); - } else { - res = cburlencode(buf, size); - for(i = 0; res[i] != '\0'; i++){ - putchar(res[i]); - } - free(res); - } - if(line) putchar('\n'); - free(buf); - return 0; -} - - -/* parse arguments of base command */ -int runbase(int argc, char **argv){ - int i, ci, size, dec, line, cols; - char *expr, *file, *buf, *res; - dec = FALSE; - line = FALSE; - cols = -1; - expr = NULL; - file = NULL; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - dec = TRUE; - } else if(!strcmp(argv[i], "-l")){ - line = TRUE; - } else if(!strcmp(argv[i], "-c")){ - if(++i >= argc) usage(); - cols = atoi(argv[i]); - } else if(!strcmp(argv[i], "-e")){ - if(++i >= argc) usage(); - expr = argv[i]; - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - buf = NULL; - if(expr){ - size = strlen(expr); - buf = cbmemdup(expr, size); - } else if(file){ - if(!(buf = cbreadfile(file, &size))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - buf = readstdin(&size); - } - if(dec){ - res = cbbasedecode(buf, &size); - for(i = 0; i < size; i++){ - putchar(res[i]); - } - free(res); - } else { - res = cbbaseencode(buf, size); - ci = 0; - for(i = 0; res[i] != '\0'; i++){ - if(cols > 0 && ci >= cols){ - putchar('\n'); - ci = 0; - } - putchar(res[i]); - ci++; - } - free(res); - } - if(line) putchar('\n'); - free(buf); - return 0; -} - - -/* parse arguments of quote command */ -int runquote(int argc, char **argv){ - int i, ci, size, dec, line, cols; - char *expr, *file, *buf, *res; - dec = FALSE; - line = FALSE; - cols = -1; - expr = NULL; - file = NULL; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - dec = TRUE; - } else if(!strcmp(argv[i], "-l")){ - line = TRUE; - } else if(!strcmp(argv[i], "-c")){ - if(++i >= argc) usage(); - cols = atoi(argv[i]); - } else if(!strcmp(argv[i], "-e")){ - if(++i >= argc) usage(); - expr = argv[i]; - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - buf = NULL; - if(expr){ - size = strlen(expr); - buf = cbmemdup(expr, size); - } else if(file){ - if(!(buf = cbreadfile(file, &size))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - buf = readstdin(&size); - } - if(dec){ - res = cbquotedecode(buf, &size); - for(i = 0; i < size; i++){ - putchar(res[i]); - } - free(res); - } else { - res = cbquoteencode(buf, size); - ci = 0; - for(i = 0; res[i] != '\0'; i++){ - if(cols > 0 && (ci >= cols || (ci >= cols - 2 && res[i] == '='))){ - printf("=\n"); - ci = 0; - } - if(res[i] == '\r' || res[i] == '\n') ci = 0; - putchar(res[i]); - ci++; - } - free(res); - } - if(line) putchar('\n'); - free(buf); - return 0; -} - - -/* parse arguments of mime command */ -int runmime(int argc, char **argv){ - CBMAP *attrs; - CBLIST *parts; - int i, size, dec, line, qp, dc, hd, bd, pnum, rsiz, bsiz; - const char *key, *body; - char *code, *expr, *file, *buf, *res, renc[64]; - dec = FALSE; - hd = FALSE; - bd = FALSE; - pnum = 0; - line = FALSE; - dc = FALSE; - qp = FALSE; - code = NULL; - expr = NULL; - file = NULL; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - dec = TRUE; - } else if(!strcmp(argv[i], "-hd")){ - hd = TRUE; - } else if(!strcmp(argv[i], "-bd")){ - bd = TRUE; - } else if(!strcmp(argv[i], "-part")){ - if(++i >= argc) usage(); - pnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-l")){ - line = TRUE; - } else if(!strcmp(argv[i], "-ec")){ - if(++i >= argc) usage(); - code = argv[i]; - } else if(!strcmp(argv[i], "-qp")){ - qp = TRUE; - } else if(!strcmp(argv[i], "-dc")){ - dc = TRUE; - } else if(!strcmp(argv[i], "-e")){ - if(++i >= argc) usage(); - expr = argv[i]; - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - buf = NULL; - if(expr){ - size = strlen(expr); - buf = cbmemdup(expr, size); - } else if(file){ - if(!(buf = cbreadfile(file, &size))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - buf = readstdin(&size); - } - if(hd || bd || pnum > 0){ - attrs = cbmapopen(); - res = cbmimebreak(buf, size, attrs, &rsiz); - if(pnum > 0){ - parts = NULL; - if(!(key = cbmapget(attrs, "TYPE", -1, NULL)) || !cbstrfwimatch(key, "multipart/") || - !(key = cbmapget(attrs, "BOUNDARY", -1, NULL)) || - !(parts = cbmimeparts(res, rsiz, key)) || cblistnum(parts) < pnum){ - fprintf(stderr, "%s: not multipart or no such part\n", progname); - if(parts) cblistclose(parts); - free(res); - cbmapclose(attrs); - free(buf); - return 1; - } - body = cblistval(parts, pnum - 1, &bsiz); - for(i = 0; i < bsiz; i++){ - putchar(body[i]); - } - cblistclose(parts); - } else if(hd){ - cbmapiterinit(attrs); - while((key = cbmapiternext(attrs, NULL)) != NULL){ - printf("%s\t%s\n", key, cbmapget(attrs, key, -1, NULL)); - } - } else { - for(i = 0; i < rsiz; i++){ - putchar(res[i]); - } - } - free(res); - cbmapclose(attrs); - } else if(dec){ - res = cbmimedecode(buf, renc); - printf("%s", dc ? renc : res); - free(res); - } else { - res = cbmimeencode(buf, code ? code : DEFCODE, !qp); - printf("%s", res); - free(res); - } - if(line) putchar('\n'); - free(buf); - return 0; -} - - -/* parse arguments of csv command */ -int runcsv(int argc, char **argv){ - CBLIST *rows, *cells; - int i, j, k, dec, tb, line, html; - const char *row, *cell; - char *expr, *file, *buf, *res; - dec = FALSE; - tb = FALSE; - line = FALSE; - html = FALSE; - expr = NULL; - file = NULL; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - dec = TRUE; - } else if(!strcmp(argv[i], "-t")){ - tb = TRUE; - } else if(!strcmp(argv[i], "-l")){ - line = TRUE; - } else if(!strcmp(argv[i], "-e")){ - if(++i >= argc) usage(); - expr = argv[i]; - } else if(!strcmp(argv[i], "-html")){ - html = TRUE; - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - buf = NULL; - if(expr){ - buf = cbmemdup(expr, -1); - } else if(file){ - if(!(buf = cbreadfile(file, NULL))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - buf = readstdin(NULL); - } - if(tb || html){ - if(html) printf("\n"); - rows = cbcsvrows(buf); - for(i = 0; i < cblistnum(rows); i++){ - if(html) printf(""); - row = cblistval(rows, i, NULL); - cells = cbcsvcells(row); - for(j = 0; j < cblistnum(cells); j++){ - cell = cblistval(cells, j, NULL); - if(html){ - printf(""); - } else { - if(j > 0) putchar('\t'); - for(k = 0; cell[k] != '\0'; k++){ - if(((unsigned char *)cell)[k] >= 0x20) putchar(cell[k]); - } - } - } - cblistclose(cells); - if(html) printf(""); - putchar('\n'); - } - cblistclose(rows); - if(html) printf("
"); - for(k = 0; cell[k] != '\0'; k++){ - if(cell[k] == '\r' || cell[k] == '\n'){ - printf("
"); - if(cell[k] == '\r' && cell[k] == '\n') k++; - } else { - switch(cell[k]){ - case '&': printf("&"); break; - case '<': printf("<"); break; - case '>': printf(">"); break; - default: putchar(cell[k]); break; - } - } - } - printf("
\n"); - } else if(dec){ - res = cbcsvunescape(buf); - for(i = 0; res[i] != '\0'; i++){ - putchar(res[i]); - } - free(res); - } else { - res = cbcsvescape(buf); - for(i = 0; res[i] != '\0'; i++){ - putchar(res[i]); - } - free(res); - } - if(line) putchar('\n'); - free(buf); - return 0; -} - - -/* parse arguments of xml command */ -int runxml(int argc, char **argv){ - CBLIST *elems; - CBMAP *attrs; - int i, j, dec, pb, line, tsv, div; - const char *elem, *attr; - char *expr, *file, *buf, *res; - dec = FALSE; - pb = FALSE; - line = FALSE; - tsv = FALSE; - expr = NULL; - file = NULL; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - dec = TRUE; - } else if(!strcmp(argv[i], "-p")){ - pb = TRUE; - } else if(!strcmp(argv[i], "-l")){ - line = TRUE; - } else if(!strcmp(argv[i], "-e")){ - if(++i >= argc) usage(); - expr = argv[i]; - } else if(!strcmp(argv[i], "-tsv")){ - tsv = TRUE; - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - buf = NULL; - if(expr){ - buf = cbmemdup(expr, -1); - } else if(file){ - if(!(buf = cbreadfile(file, NULL))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - buf = readstdin(NULL); - } - if(pb || tsv){ - elems = cbxmlbreak(buf, FALSE); - for(i = 0; i < cblistnum(elems); i++){ - elem = cblistval(elems, i, NULL); - div = FALSE; - if(elem[0] == '<'){ - if(cbstrfwimatch(elem, "")){ - printf("EMPTAG"); - div = TRUE; - } else { - printf("BEGTAG"); - div = TRUE; - } - } else { - printf("TEXT"); - } - putchar('\t'); - if(tsv){ - if(div){ - attrs = cbxmlattrs(elem); - cbmapiterinit(attrs); - for(j = 0; (attr = cbmapiternext(attrs, NULL)) != NULL; j++){ - if(j < 1){ - printf("%s", cbmapget(attrs, attr, -1, NULL)); - } else { - printf("\t%s\t%s", attr, cbmapget(attrs, attr, -1, NULL)); - } - } - cbmapclose(attrs); - } else { - res = cbxmlunescape(elem); - for(j = 0; elem[j] != '\0'; j++){ - if(((unsigned char *)elem)[j] < 0x20 || elem[j] == '%'){ - printf("%%%02X", elem[j]); - } else { - putchar(elem[j]); - } - } - free(res); - } - } else { - printf("%s", elem); - } - putchar('\n'); - } - cblistclose(elems); - } else if(dec){ - res = cbxmlunescape(buf); - for(i = 0; res[i] != '\0'; i++){ - putchar(res[i]); - } - free(res); - } else { - res = cbxmlescape(buf); - for(i = 0; res[i] != '\0'; i++){ - putchar(res[i]); - } - free(res); - } - if(line) putchar('\n'); - free(buf); - return 0; -} - - -/* parse arguments of zlib command */ -int runzlib(int argc, char **argv){ - unsigned int sum; - int i, bsiz, rsiz, dec, gz, crc; - char *file, *buf, *res; - dec = FALSE; - gz = FALSE; - crc = FALSE; - file = NULL; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - dec = TRUE; - } else if(!strcmp(argv[i], "-gz")){ - gz = TRUE; - } else if(!strcmp(argv[i], "-crc")){ - crc = TRUE; - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - buf = NULL; - if(file){ - if(!(buf = cbreadfile(file, &bsiz))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - buf = readstdin(&bsiz); - } - if(crc){ - sum = cbgetcrc(buf, bsiz); - for(i = 0; i < sizeof(int); i++){ - printf("%02x", sum / 0x1000000); - sum <<= 8; - } - putchar('\n'); - } else if(dec){ - if(!(res = gz ? cbgzdecode(buf, bsiz, &rsiz) : cbinflate(buf, bsiz, &rsiz))){ - fprintf(stderr, "%s: inflate failed\n", progname); - free(buf); - return 1; - } - for(i = 0; i < rsiz; i++){ - putchar(res[i]); - } - free(res); - } else { - if(!(res = gz ? cbgzencode(buf, bsiz, &rsiz) : cbdeflate(buf, bsiz, &rsiz))){ - fprintf(stderr, "%s: deflate failed\n", progname); - free(buf); - return 1; - } - for(i = 0; i < rsiz; i++){ - putchar(res[i]); - } - free(res); - } - free(buf); - return 0; -} - - -/* parse arguments of lzo command */ -int runlzo(int argc, char **argv){ - int i, bsiz, rsiz, dec; - char *file, *buf, *res; - dec = FALSE; - file = NULL; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - dec = TRUE; - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - buf = NULL; - if(file){ - if(!(buf = cbreadfile(file, &bsiz))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - buf = readstdin(&bsiz); - } - if(dec){ - if(!(res = cblzodecode(buf, bsiz, &rsiz))){ - fprintf(stderr, "%s: decode failed\n", progname); - free(buf); - return 1; - } - for(i = 0; i < rsiz; i++){ - putchar(res[i]); - } - free(res); - } else { - if(!(res = cblzoencode(buf, bsiz, &rsiz))){ - fprintf(stderr, "%s: encode failed\n", progname); - free(buf); - return 1; - } - for(i = 0; i < rsiz; i++){ - putchar(res[i]); - } - free(res); - } - free(buf); - return 0; -} - - -/* parse arguments of bzip command */ -int runbzip(int argc, char **argv){ - int i, bsiz, rsiz, dec; - char *file, *buf, *res; - dec = FALSE; - file = NULL; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - dec = TRUE; - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - buf = NULL; - if(file){ - if(!(buf = cbreadfile(file, &bsiz))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - buf = readstdin(&bsiz); - } - if(dec){ - if(!(res = cbbzdecode(buf, bsiz, &rsiz))){ - fprintf(stderr, "%s: decode failed\n", progname); - free(buf); - return 1; - } - for(i = 0; i < rsiz; i++){ - putchar(res[i]); - } - free(res); - } else { - if(!(res = cbbzencode(buf, bsiz, &rsiz))){ - fprintf(stderr, "%s: encode failed\n", progname); - free(buf); - return 1; - } - for(i = 0; i < rsiz; i++){ - putchar(res[i]); - } - free(res); - } - free(buf); - return 0; -} - - -/* parse arguments of iconv command */ -int runiconv(int argc, char **argv){ - CBDATUM *datum; - const char *rcode; - char *icode, *ocode, *ltype, *file, *buf, *res, *norm, *orig; - int i, cn, wc, bsiz, rsiz, nsiz, osiz, miss; - icode = NULL; - ocode = NULL; - ltype = NULL; - file = NULL; - cn = FALSE; - wc = FALSE; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-ic")){ - if(++i >= argc) usage(); - icode = argv[i]; - } else if(!strcmp(argv[i], "-oc")){ - if(++i >= argc) usage(); - ocode = argv[i]; - } else if(!strcmp(argv[i], "-ol")){ - if(++i >= argc) usage(); - ltype = argv[i]; - } else if(!strcmp(argv[i], "-cn")){ - cn = TRUE; - } else if(!strcmp(argv[i], "-wc")){ - wc = TRUE; - } else if(!strcmp(argv[i], "-um")){ - shouucsmap(); - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - buf = NULL; - if(file){ - if(!(buf = cbreadfile(file, &bsiz))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - buf = readstdin(&bsiz); - } - miss = 0; - if(cn){ - printf("%s\n", cbencname(buf, bsiz)); - } else if(wc){ - printf("%d\n", cbstrcountutf(buf)); - } else { - rcode = icode ? icode : cbencname(buf, bsiz); - if(!(res = cbiconv(buf, bsiz, rcode, ocode ? ocode : DEFCODE, - &rsiz, &miss))){ - fprintf(stderr, "%s: iconv failed\n", progname); - free(buf); - return 1; - } - if(miss > 0) fprintf(stderr, "%s: missing %d characters\n", progname, miss); - if(ltype && (!cbstricmp(ltype, "u") || !cbstricmp(ltype, "unix") || - !cbstricmp(ltype, "lf"))){ - ltype = "\n"; - } else if(ltype && (!cbstricmp(ltype, "d") || !cbstricmp(ltype, "dos") || - !cbstricmp(ltype, "crlf"))){ - ltype = "\r\n"; - } else if(ltype && (!cbstricmp(ltype, "m") || !cbstricmp(ltype, "mac") || - !cbstricmp(ltype, "cr"))){ - ltype = "\r"; - } else { - ltype = NULL; - } - if(ltype){ - if(!(norm = cbiconv(res, rsiz, ocode, "UTF-8", &nsiz, NULL))){ - fprintf(stderr, "%s: iconv failed\n", progname); - free(res); - free(buf); - return 1; - } - datum = cbdatumopen(NULL, -1); - for(i = 0; i < nsiz; i++){ - if(norm[i] == '\r'){ - if(norm[i+1] == '\n') i++; - cbdatumcat(datum, ltype, -1); - } else if(norm[i] == '\n'){ - cbdatumcat(datum, ltype, -1); - } else { - cbdatumcat(datum, norm + i, 1); - } - } - if(!(orig = cbiconv(cbdatumptr(datum), cbdatumsize(datum), "UTF-8", ocode, &osiz, NULL))){ - fprintf(stderr, "%s: iconv failed\n", progname); - cbdatumclose(datum); - free(norm); - free(res); - free(buf); - return 1; - } - for(i = 0; i < osiz; i++){ - putchar(orig[i]); - } - free(orig); - cbdatumclose(datum); - free(norm); - } else { - for(i = 0; i < rsiz; i++){ - putchar(res[i]); - } - } - free(res); - } - free(buf); - return miss > 0 ? 1 : 0; -} - - -/* parse arguments of date command */ -int rundate(int argc, char **argv){ - int i, wb, rb, utc, jl; - char *date, *res; - time_t t; - wb = FALSE; - rb = FALSE; - utc = FALSE; - date = NULL; - for(i = 2; i < argc; i++){ - if(!date && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-wf")){ - wb = TRUE; - } else if(!strcmp(argv[i], "-rf")){ - rb = TRUE; - } else if(!strcmp(argv[i], "-utc")){ - utc = TRUE; - } else { - usage(); - } - } else if(!date){ - date = argv[i]; - } else { - usage(); - } - } - jl = utc ? 0 : cbjetlag(); - if(date){ - t = cbstrmktime(date); - } else { - t = time(NULL); - } - if(wb){ - res = cbdatestrwww(t, jl); - } else if(rb){ - res = cbdatestrhttp(t, jl); - } else { - res = cbsprintf("%d", (int)t); - } - if(t >= 0){ - printf("%s\n", res); - } else { - if(date){ - fprintf(stderr, "%s: %s: invalid date format\n", progname, date); - } else { - fprintf(stderr, "%s: invalid time setting\n", progname); - } - } - free(res); - return 0; -} - - -/* show mapping of UCS-2 and exit. */ -void shouucsmap(void){ - unsigned char buf[2], *tmp; - int i, j, tsiz; - for(i = 0; i < 65536; i++){ - buf[0] = i / 256; - buf[1] = i % 256; - printf("%d\t", i); - printf("U+%02X%02X\t", buf[0], buf[1]); - printf("\"\\x%x\\x%x\"\t", buf[0], buf[1]); - if((tmp = (unsigned char *)cbiconv((char *)buf, 2, "UTF-16BE", "UTF-8", - &tsiz, NULL)) != NULL){ - if(tsiz > 0){ - printf("\""); - for(j = 0; j < tsiz; j++){ - printf("\\x%x", tmp[j]); - } - printf("\""); - } else { - printf("NULL"); - } - free(tmp); - } - printf("\n"); - } - exit(0); -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/cbcodec.c (from rev 2716, box/trunk/qdbm/cbcodec.c) =================================================================== --- box/trunk/qdbm/cbcodec.c (rev 0) +++ box/trunk/qdbm/cbcodec.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,1079 @@ +/************************************************************************************************* + * Popular encoders and decoders + * 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 +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define DEFCODE "UTF-8" /* default encoding */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +char *readstdin(int *sp); +int runurl(int argc, char **argv); +int runbase(int argc, char **argv); +int runquote(int argc, char **argv); +int runmime(int argc, char **argv); +int runcsv(int argc, char **argv); +int runxml(int argc, char **argv); +int runzlib(int argc, char **argv); +int runlzo(int argc, char **argv); +int runbzip(int argc, char **argv); +int runiconv(int argc, char **argv); +int rundate(int argc, char **argv); +void shouucsmap(void); + + +/* main routine */ +int main(int argc, char **argv){ + int rv; + cbstdiobin(); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "url")){ + rv = runurl(argc, argv); + } else if(!strcmp(argv[1], "base")){ + rv = runbase(argc, argv); + } else if(!strcmp(argv[1], "quote")){ + rv = runquote(argc, argv); + } else if(!strcmp(argv[1], "mime")){ + rv = runmime(argc, argv); + } else if(!strcmp(argv[1], "csv")){ + rv = runcsv(argc, argv); + } else if(!strcmp(argv[1], "xml")){ + rv = runxml(argc, argv); + } else if(!strcmp(argv[1], "zlib")){ + rv = runzlib(argc, argv); + } else if(!strcmp(argv[1], "lzo")){ + rv = runlzo(argc, argv); + } else if(!strcmp(argv[1], "bzip")){ + rv = runbzip(argc, argv); + } else if(!strcmp(argv[1], "iconv")){ + rv = runiconv(argc, argv); + } else if(!strcmp(argv[1], "date")){ + rv = rundate(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + char *tmp; + int tsiz; + fprintf(stderr, "%s: popular encoders and decoders\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s url [-d] [-br] [-rs base target] [-l] [-e expr] [file]\n", progname); + fprintf(stderr, " %s base [-d] [-l] [-c num] [-e expr] [file]\n", progname); + fprintf(stderr, " %s quote [-d] [-l] [-c num] [-e expr] [file]\n", progname); + fprintf(stderr, " %s mime [-d] [-hd] [-bd] [-part num] [-l] [-ec code] [-qp] [-dc] [-e expr]" + " [file]\n", progname); + fprintf(stderr, " %s csv [-d] [-t] [-l] [-e expr] [-html] [file]\n", progname); + fprintf(stderr, " %s xml [-d] [-p] [-l] [-e expr] [-tsv] [file]\n", progname); + if((tmp = cbdeflate("", 0, &tsiz)) != NULL){ + fprintf(stderr, " %s zlib [-d] [-gz] [-crc] [file]\n", progname); + free(tmp); + } + if((tmp = cblzoencode("", 0, &tsiz)) != NULL){ + fprintf(stderr, " %s lzo [-d] [file]\n", progname); + free(tmp); + } + if((tmp = cbbzencode("", 0, &tsiz)) != NULL){ + fprintf(stderr, " %s bzip [-d] [file]\n", progname); + free(tmp); + } + if((tmp = cbiconv("", 0, "US-ASCII", "US-ASCII", NULL, NULL)) != NULL){ + fprintf(stderr, " %s iconv [-ic code] [-oc code] [-ol ltype] [-cn] [-wc] [-um] [file]\n", + progname); + free(tmp); + } + fprintf(stderr, " %s date [-wf] [-rf] [-utc] [str]\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* read the standard input */ +char *readstdin(int *sp){ + char *buf; + int i, blen, c; + blen = 256; + buf = cbmalloc(blen); + for(i = 0; (c = getchar()) != EOF; i++){ + if(i >= blen - 1) buf = cbrealloc(buf, blen *= 2); + buf[i] = c; + } + buf[i] = '\0'; + if(sp) *sp = i; + return buf; +} + + +/* parse arguments of url command */ +int runurl(int argc, char **argv){ + CBMAP *map; + int i, size, dec, br, line; + const char *val; + char *base, *target, *expr, *file, *buf, *res; + dec = FALSE; + br = FALSE; + line = FALSE; + base = NULL; + target = NULL; + expr = NULL; + file = NULL; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + dec = TRUE; + } else if(!strcmp(argv[i], "-br")){ + br = TRUE; + } else if(!strcmp(argv[i], "-rs")){ + if(++i >= argc) usage(); + base = argv[i]; + if(++i >= argc) usage(); + target = argv[i]; + } else if(!strcmp(argv[i], "-l")){ + line = TRUE; + } else if(!strcmp(argv[i], "-e")){ + if(++i >= argc) usage(); + expr = argv[i]; + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + buf = NULL; + if(base){ + size = strlen(base); + buf = cbmemdup(base, size); + } else if(expr){ + size = strlen(expr); + buf = cbmemdup(expr, size); + } else if(file){ + if(!(buf = cbreadfile(file, &size))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + buf = readstdin(&size); + } + if(target){ + res = cburlresolve(base, target); + printf("%s", res); + free(res); + } else if(br){ + map = cburlbreak(buf); + if((val = cbmapget(map, "self", -1, NULL))) printf("self\t%s\n", val); + if((val = cbmapget(map, "scheme", -1, NULL))) printf("scheme\t%s\n", val); + if((val = cbmapget(map, "host", -1, NULL))) printf("host\t%s\n", val); + if((val = cbmapget(map, "port", -1, NULL))) printf("port\t%s\n", val); + if((val = cbmapget(map, "authority", -1, NULL))) printf("authority\t%s\n", val); + if((val = cbmapget(map, "path", -1, NULL))) printf("path\t%s\n", val); + if((val = cbmapget(map, "file", -1, NULL))) printf("file\t%s\n", val); + if((val = cbmapget(map, "query", -1, NULL))) printf("query\t%s\n", val); + if((val = cbmapget(map, "fragment", -1, NULL))) printf("fragment\t%s\n", val); + cbmapclose(map); + } else if(dec){ + res = cburldecode(buf, &size); + for(i = 0; i < size; i++){ + putchar(res[i]); + } + free(res); + } else { + res = cburlencode(buf, size); + for(i = 0; res[i] != '\0'; i++){ + putchar(res[i]); + } + free(res); + } + if(line) putchar('\n'); + free(buf); + return 0; +} + + +/* parse arguments of base command */ +int runbase(int argc, char **argv){ + int i, ci, size, dec, line, cols; + char *expr, *file, *buf, *res; + dec = FALSE; + line = FALSE; + cols = -1; + expr = NULL; + file = NULL; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + dec = TRUE; + } else if(!strcmp(argv[i], "-l")){ + line = TRUE; + } else if(!strcmp(argv[i], "-c")){ + if(++i >= argc) usage(); + cols = atoi(argv[i]); + } else if(!strcmp(argv[i], "-e")){ + if(++i >= argc) usage(); + expr = argv[i]; + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + buf = NULL; + if(expr){ + size = strlen(expr); + buf = cbmemdup(expr, size); + } else if(file){ + if(!(buf = cbreadfile(file, &size))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + buf = readstdin(&size); + } + if(dec){ + res = cbbasedecode(buf, &size); + for(i = 0; i < size; i++){ + putchar(res[i]); + } + free(res); + } else { + res = cbbaseencode(buf, size); + ci = 0; + for(i = 0; res[i] != '\0'; i++){ + if(cols > 0 && ci >= cols){ + putchar('\n'); + ci = 0; + } + putchar(res[i]); + ci++; + } + free(res); + } + if(line) putchar('\n'); + free(buf); + return 0; +} + + +/* parse arguments of quote command */ +int runquote(int argc, char **argv){ + int i, ci, size, dec, line, cols; + char *expr, *file, *buf, *res; + dec = FALSE; + line = FALSE; + cols = -1; + expr = NULL; + file = NULL; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + dec = TRUE; + } else if(!strcmp(argv[i], "-l")){ + line = TRUE; + } else if(!strcmp(argv[i], "-c")){ + if(++i >= argc) usage(); + cols = atoi(argv[i]); + } else if(!strcmp(argv[i], "-e")){ + if(++i >= argc) usage(); + expr = argv[i]; + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + buf = NULL; + if(expr){ + size = strlen(expr); + buf = cbmemdup(expr, size); + } else if(file){ + if(!(buf = cbreadfile(file, &size))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + buf = readstdin(&size); + } + if(dec){ + res = cbquotedecode(buf, &size); + for(i = 0; i < size; i++){ + putchar(res[i]); + } + free(res); + } else { + res = cbquoteencode(buf, size); + ci = 0; + for(i = 0; res[i] != '\0'; i++){ + if(cols > 0 && (ci >= cols || (ci >= cols - 2 && res[i] == '='))){ + printf("=\n"); + ci = 0; + } + if(res[i] == '\r' || res[i] == '\n') ci = 0; + putchar(res[i]); + ci++; + } + free(res); + } + if(line) putchar('\n'); + free(buf); + return 0; +} + + +/* parse arguments of mime command */ +int runmime(int argc, char **argv){ + CBMAP *attrs; + CBLIST *parts; + int i, size, dec, line, qp, dc, hd, bd, pnum, rsiz, bsiz; + const char *key, *body; + char *code, *expr, *file, *buf, *res, renc[64]; + dec = FALSE; + hd = FALSE; + bd = FALSE; + pnum = 0; + line = FALSE; + dc = FALSE; + qp = FALSE; + code = NULL; + expr = NULL; + file = NULL; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + dec = TRUE; + } else if(!strcmp(argv[i], "-hd")){ + hd = TRUE; + } else if(!strcmp(argv[i], "-bd")){ + bd = TRUE; + } else if(!strcmp(argv[i], "-part")){ + if(++i >= argc) usage(); + pnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-l")){ + line = TRUE; + } else if(!strcmp(argv[i], "-ec")){ + if(++i >= argc) usage(); + code = argv[i]; + } else if(!strcmp(argv[i], "-qp")){ + qp = TRUE; + } else if(!strcmp(argv[i], "-dc")){ + dc = TRUE; + } else if(!strcmp(argv[i], "-e")){ + if(++i >= argc) usage(); + expr = argv[i]; + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + buf = NULL; + if(expr){ + size = strlen(expr); + buf = cbmemdup(expr, size); + } else if(file){ + if(!(buf = cbreadfile(file, &size))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + buf = readstdin(&size); + } + if(hd || bd || pnum > 0){ + attrs = cbmapopen(); + res = cbmimebreak(buf, size, attrs, &rsiz); + if(pnum > 0){ + parts = NULL; + if(!(key = cbmapget(attrs, "TYPE", -1, NULL)) || !cbstrfwimatch(key, "multipart/") || + !(key = cbmapget(attrs, "BOUNDARY", -1, NULL)) || + !(parts = cbmimeparts(res, rsiz, key)) || cblistnum(parts) < pnum){ + fprintf(stderr, "%s: not multipart or no such part\n", progname); + if(parts) cblistclose(parts); + free(res); + cbmapclose(attrs); + free(buf); + return 1; + } + body = cblistval(parts, pnum - 1, &bsiz); + for(i = 0; i < bsiz; i++){ + putchar(body[i]); + } + cblistclose(parts); + } else if(hd){ + cbmapiterinit(attrs); + while((key = cbmapiternext(attrs, NULL)) != NULL){ + printf("%s\t%s\n", key, cbmapget(attrs, key, -1, NULL)); + } + } else { + for(i = 0; i < rsiz; i++){ + putchar(res[i]); + } + } + free(res); + cbmapclose(attrs); + } else if(dec){ + res = cbmimedecode(buf, renc); + printf("%s", dc ? renc : res); + free(res); + } else { + res = cbmimeencode(buf, code ? code : DEFCODE, !qp); + printf("%s", res); + free(res); + } + if(line) putchar('\n'); + free(buf); + return 0; +} + + +/* parse arguments of csv command */ +int runcsv(int argc, char **argv){ + CBLIST *rows, *cells; + int i, j, k, dec, tb, line, html; + const char *row, *cell; + char *expr, *file, *buf, *res; + dec = FALSE; + tb = FALSE; + line = FALSE; + html = FALSE; + expr = NULL; + file = NULL; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + dec = TRUE; + } else if(!strcmp(argv[i], "-t")){ + tb = TRUE; + } else if(!strcmp(argv[i], "-l")){ + line = TRUE; + } else if(!strcmp(argv[i], "-e")){ + if(++i >= argc) usage(); + expr = argv[i]; + } else if(!strcmp(argv[i], "-html")){ + html = TRUE; + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + buf = NULL; + if(expr){ + buf = cbmemdup(expr, -1); + } else if(file){ + if(!(buf = cbreadfile(file, NULL))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + buf = readstdin(NULL); + } + if(tb || html){ + if(html) printf("\n"); + rows = cbcsvrows(buf); + for(i = 0; i < cblistnum(rows); i++){ + if(html) printf(""); + row = cblistval(rows, i, NULL); + cells = cbcsvcells(row); + for(j = 0; j < cblistnum(cells); j++){ + cell = cblistval(cells, j, NULL); + if(html){ + printf(""); + } else { + if(j > 0) putchar('\t'); + for(k = 0; cell[k] != '\0'; k++){ + if(((unsigned char *)cell)[k] >= 0x20) putchar(cell[k]); + } + } + } + cblistclose(cells); + if(html) printf(""); + putchar('\n'); + } + cblistclose(rows); + if(html) printf("
"); + for(k = 0; cell[k] != '\0'; k++){ + if(cell[k] == '\r' || cell[k] == '\n'){ + printf("
"); + if(cell[k] == '\r' && cell[k] == '\n') k++; + } else { + switch(cell[k]){ + case '&': printf("&"); break; + case '<': printf("<"); break; + case '>': printf(">"); break; + default: putchar(cell[k]); break; + } + } + } + printf("
\n"); + } else if(dec){ + res = cbcsvunescape(buf); + for(i = 0; res[i] != '\0'; i++){ + putchar(res[i]); + } + free(res); + } else { + res = cbcsvescape(buf); + for(i = 0; res[i] != '\0'; i++){ + putchar(res[i]); + } + free(res); + } + if(line) putchar('\n'); + free(buf); + return 0; +} + + +/* parse arguments of xml command */ +int runxml(int argc, char **argv){ + CBLIST *elems; + CBMAP *attrs; + int i, j, dec, pb, line, tsv, div; + const char *elem, *attr; + char *expr, *file, *buf, *res; + dec = FALSE; + pb = FALSE; + line = FALSE; + tsv = FALSE; + expr = NULL; + file = NULL; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + dec = TRUE; + } else if(!strcmp(argv[i], "-p")){ + pb = TRUE; + } else if(!strcmp(argv[i], "-l")){ + line = TRUE; + } else if(!strcmp(argv[i], "-e")){ + if(++i >= argc) usage(); + expr = argv[i]; + } else if(!strcmp(argv[i], "-tsv")){ + tsv = TRUE; + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + buf = NULL; + if(expr){ + buf = cbmemdup(expr, -1); + } else if(file){ + if(!(buf = cbreadfile(file, NULL))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + buf = readstdin(NULL); + } + if(pb || tsv){ + elems = cbxmlbreak(buf, FALSE); + for(i = 0; i < cblistnum(elems); i++){ + elem = cblistval(elems, i, NULL); + div = FALSE; + if(elem[0] == '<'){ + if(cbstrfwimatch(elem, "")){ + printf("EMPTAG"); + div = TRUE; + } else { + printf("BEGTAG"); + div = TRUE; + } + } else { + printf("TEXT"); + } + putchar('\t'); + if(tsv){ + if(div){ + attrs = cbxmlattrs(elem); + cbmapiterinit(attrs); + for(j = 0; (attr = cbmapiternext(attrs, NULL)) != NULL; j++){ + if(j < 1){ + printf("%s", cbmapget(attrs, attr, -1, NULL)); + } else { + printf("\t%s\t%s", attr, cbmapget(attrs, attr, -1, NULL)); + } + } + cbmapclose(attrs); + } else { + res = cbxmlunescape(elem); + for(j = 0; elem[j] != '\0'; j++){ + if(((unsigned char *)elem)[j] < 0x20 || elem[j] == '%'){ + printf("%%%02X", elem[j]); + } else { + putchar(elem[j]); + } + } + free(res); + } + } else { + printf("%s", elem); + } + putchar('\n'); + } + cblistclose(elems); + } else if(dec){ + res = cbxmlunescape(buf); + for(i = 0; res[i] != '\0'; i++){ + putchar(res[i]); + } + free(res); + } else { + res = cbxmlescape(buf); + for(i = 0; res[i] != '\0'; i++){ + putchar(res[i]); + } + free(res); + } + if(line) putchar('\n'); + free(buf); + return 0; +} + + +/* parse arguments of zlib command */ +int runzlib(int argc, char **argv){ + unsigned int sum; + int i, bsiz, rsiz, dec, gz, crc; + char *file, *buf, *res; + dec = FALSE; + gz = FALSE; + crc = FALSE; + file = NULL; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + dec = TRUE; + } else if(!strcmp(argv[i], "-gz")){ + gz = TRUE; + } else if(!strcmp(argv[i], "-crc")){ + crc = TRUE; + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + buf = NULL; + if(file){ + if(!(buf = cbreadfile(file, &bsiz))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + buf = readstdin(&bsiz); + } + if(crc){ + sum = cbgetcrc(buf, bsiz); + for(i = 0; i < sizeof(int); i++){ + printf("%02x", sum / 0x1000000); + sum <<= 8; + } + putchar('\n'); + } else if(dec){ + if(!(res = gz ? cbgzdecode(buf, bsiz, &rsiz) : cbinflate(buf, bsiz, &rsiz))){ + fprintf(stderr, "%s: inflate failed\n", progname); + free(buf); + return 1; + } + for(i = 0; i < rsiz; i++){ + putchar(res[i]); + } + free(res); + } else { + if(!(res = gz ? cbgzencode(buf, bsiz, &rsiz) : cbdeflate(buf, bsiz, &rsiz))){ + fprintf(stderr, "%s: deflate failed\n", progname); + free(buf); + return 1; + } + for(i = 0; i < rsiz; i++){ + putchar(res[i]); + } + free(res); + } + free(buf); + return 0; +} + + +/* parse arguments of lzo command */ +int runlzo(int argc, char **argv){ + int i, bsiz, rsiz, dec; + char *file, *buf, *res; + dec = FALSE; + file = NULL; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + dec = TRUE; + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + buf = NULL; + if(file){ + if(!(buf = cbreadfile(file, &bsiz))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + buf = readstdin(&bsiz); + } + if(dec){ + if(!(res = cblzodecode(buf, bsiz, &rsiz))){ + fprintf(stderr, "%s: decode failed\n", progname); + free(buf); + return 1; + } + for(i = 0; i < rsiz; i++){ + putchar(res[i]); + } + free(res); + } else { + if(!(res = cblzoencode(buf, bsiz, &rsiz))){ + fprintf(stderr, "%s: encode failed\n", progname); + free(buf); + return 1; + } + for(i = 0; i < rsiz; i++){ + putchar(res[i]); + } + free(res); + } + free(buf); + return 0; +} + + +/* parse arguments of bzip command */ +int runbzip(int argc, char **argv){ + int i, bsiz, rsiz, dec; + char *file, *buf, *res; + dec = FALSE; + file = NULL; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + dec = TRUE; + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + buf = NULL; + if(file){ + if(!(buf = cbreadfile(file, &bsiz))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + buf = readstdin(&bsiz); + } + if(dec){ + if(!(res = cbbzdecode(buf, bsiz, &rsiz))){ + fprintf(stderr, "%s: decode failed\n", progname); + free(buf); + return 1; + } + for(i = 0; i < rsiz; i++){ + putchar(res[i]); + } + free(res); + } else { + if(!(res = cbbzencode(buf, bsiz, &rsiz))){ + fprintf(stderr, "%s: encode failed\n", progname); + free(buf); + return 1; + } + for(i = 0; i < rsiz; i++){ + putchar(res[i]); + } + free(res); + } + free(buf); + return 0; +} + + +/* parse arguments of iconv command */ +int runiconv(int argc, char **argv){ + CBDATUM *datum; + const char *rcode; + char *icode, *ocode, *ltype, *file, *buf, *res, *norm, *orig; + int i, cn, wc, bsiz, rsiz, nsiz, osiz, miss; + icode = NULL; + ocode = NULL; + ltype = NULL; + file = NULL; + cn = FALSE; + wc = FALSE; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-ic")){ + if(++i >= argc) usage(); + icode = argv[i]; + } else if(!strcmp(argv[i], "-oc")){ + if(++i >= argc) usage(); + ocode = argv[i]; + } else if(!strcmp(argv[i], "-ol")){ + if(++i >= argc) usage(); + ltype = argv[i]; + } else if(!strcmp(argv[i], "-cn")){ + cn = TRUE; + } else if(!strcmp(argv[i], "-wc")){ + wc = TRUE; + } else if(!strcmp(argv[i], "-um")){ + shouucsmap(); + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + buf = NULL; + if(file){ + if(!(buf = cbreadfile(file, &bsiz))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + buf = readstdin(&bsiz); + } + miss = 0; + if(cn){ + printf("%s\n", cbencname(buf, bsiz)); + } else if(wc){ + printf("%d\n", cbstrcountutf(buf)); + } else { + rcode = icode ? icode : cbencname(buf, bsiz); + if(!(res = cbiconv(buf, bsiz, rcode, ocode ? ocode : DEFCODE, + &rsiz, &miss))){ + fprintf(stderr, "%s: iconv failed\n", progname); + free(buf); + return 1; + } + if(miss > 0) fprintf(stderr, "%s: missing %d characters\n", progname, miss); + if(ltype && (!cbstricmp(ltype, "u") || !cbstricmp(ltype, "unix") || + !cbstricmp(ltype, "lf"))){ + ltype = "\n"; + } else if(ltype && (!cbstricmp(ltype, "d") || !cbstricmp(ltype, "dos") || + !cbstricmp(ltype, "crlf"))){ + ltype = "\r\n"; + } else if(ltype && (!cbstricmp(ltype, "m") || !cbstricmp(ltype, "mac") || + !cbstricmp(ltype, "cr"))){ + ltype = "\r"; + } else { + ltype = NULL; + } + if(ltype){ + if(!(norm = cbiconv(res, rsiz, ocode, "UTF-8", &nsiz, NULL))){ + fprintf(stderr, "%s: iconv failed\n", progname); + free(res); + free(buf); + return 1; + } + datum = cbdatumopen(NULL, -1); + for(i = 0; i < nsiz; i++){ + if(norm[i] == '\r'){ + if(norm[i+1] == '\n') i++; + cbdatumcat(datum, ltype, -1); + } else if(norm[i] == '\n'){ + cbdatumcat(datum, ltype, -1); + } else { + cbdatumcat(datum, norm + i, 1); + } + } + if(!(orig = cbiconv(cbdatumptr(datum), cbdatumsize(datum), "UTF-8", ocode, &osiz, NULL))){ + fprintf(stderr, "%s: iconv failed\n", progname); + cbdatumclose(datum); + free(norm); + free(res); + free(buf); + return 1; + } + for(i = 0; i < osiz; i++){ + putchar(orig[i]); + } + free(orig); + cbdatumclose(datum); + free(norm); + } else { + for(i = 0; i < rsiz; i++){ + putchar(res[i]); + } + } + free(res); + } + free(buf); + return miss > 0 ? 1 : 0; +} + + +/* parse arguments of date command */ +int rundate(int argc, char **argv){ + int i, wb, rb, utc, jl; + char *date, *res; + time_t t; + wb = FALSE; + rb = FALSE; + utc = FALSE; + date = NULL; + for(i = 2; i < argc; i++){ + if(!date && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-wf")){ + wb = TRUE; + } else if(!strcmp(argv[i], "-rf")){ + rb = TRUE; + } else if(!strcmp(argv[i], "-utc")){ + utc = TRUE; + } else { + usage(); + } + } else if(!date){ + date = argv[i]; + } else { + usage(); + } + } + jl = utc ? 0 : cbjetlag(); + if(date){ + t = cbstrmktime(date); + } else { + t = time(NULL); + } + if(wb){ + res = cbdatestrwww(t, jl); + } else if(rb){ + res = cbdatestrhttp(t, jl); + } else { + res = cbsprintf("%d", (int)t); + } + if(t >= 0){ + printf("%s\n", res); + } else { + if(date){ + fprintf(stderr, "%s: %s: invalid date format\n", progname, date); + } else { + fprintf(stderr, "%s: invalid time setting\n", progname); + } + } + free(res); + return 0; +} + + +/* show mapping of UCS-2 and exit. */ +void shouucsmap(void){ + unsigned char buf[2], *tmp; + int i, j, tsiz; + for(i = 0; i < 65536; i++){ + buf[0] = i / 256; + buf[1] = i % 256; + printf("%d\t", i); + printf("U+%02X%02X\t", buf[0], buf[1]); + printf("\"\\x%x\\x%x\"\t", buf[0], buf[1]); + if((tmp = (unsigned char *)cbiconv((char *)buf, 2, "UTF-16BE", "UTF-8", + &tsiz, NULL)) != NULL){ + if(tsiz > 0){ + printf("\""); + for(j = 0; j < tsiz; j++){ + printf("\\x%x", tmp[j]); + } + printf("\""); + } else { + printf("NULL"); + } + free(tmp); + } + printf("\n"); + } + exit(0); +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/cbtest.c =================================================================== --- box/trunk/qdbm/cbtest.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/cbtest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,924 +0,0 @@ -/************************************************************************************************* - * Test cases of Cabin - * 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 -#include -#include -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define RECBUFSIZ 32 /* buffer for records */ -#define TEXTBUFSIZ 262144 /* buffer for text */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -int runsort(int argc, char **argv); -int runstrstr(int argc, char **argv); -int runlist(int argc, char **argv); -int runmap(int argc, char **argv); -int runheap(int argc, char **argv); -int runwicked(int argc, char **argv); -int runmisc(int argc, char **argv); -int printfflush(const char *format, ...); -int strpcmp(const void *ap, const void *bp); -int intpcmp(const void *ap, const void *bp); -int myrand(void); -int dosort(int rnum, int disp); -int dostrstr(int rnum, int disp); -int dolist(int rnum, int disp); -int domap(int rnum, int bnum, int disp); -int doheap(int rnum, int max, int disp); -int dowicked(int rnum); -int domisc(void); - - -/* main routine */ -int main(int argc, char **argv){ - int rv; - cbstdiobin(); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "sort")){ - rv = runsort(argc, argv); - } else if(!strcmp(argv[1], "strstr")){ - rv = runstrstr(argc, argv); - } else if(!strcmp(argv[1], "list")){ - rv = runlist(argc, argv); - } else if(!strcmp(argv[1], "map")){ - rv = runmap(argc, argv); - } else if(!strcmp(argv[1], "heap")){ - rv = runheap(argc, argv); - } else if(!strcmp(argv[1], "wicked")){ - rv = runwicked(argc, argv); - } else if(!strcmp(argv[1], "misc")){ - rv = runmisc(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: test cases for Cabin\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s sort [-d] rnum\n", progname); - fprintf(stderr, " %s strstr [-d] rnum\n", progname); - fprintf(stderr, " %s list [-d] rnum\n", progname); - fprintf(stderr, " %s map [-d] rnum [bnum]\n", progname); - fprintf(stderr, " %s heap [-d] rnum [top]\n", progname); - fprintf(stderr, " %s wicked rnum\n", progname); - fprintf(stderr, " %s misc\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of sort command */ -int runsort(int argc, char **argv){ - int i, rnum, disp, rv; - char *rstr; - rstr = NULL; - rnum = 0; - disp = FALSE; - for(i = 2; i < argc; i++){ - if(argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - disp = TRUE; - } else { - usage(); - } - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = dosort(rnum, disp); - return rv; -} - - -/* parse arguments of strstr command */ -int runstrstr(int argc, char **argv){ - int i, rnum, disp, rv; - char *rstr; - rstr = NULL; - rnum = 0; - disp = FALSE; - for(i = 2; i < argc; i++){ - if(argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - disp = TRUE; - } else { - usage(); - } - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = dostrstr(rnum, disp); - return rv; -} - - -/* parse arguments of list command */ -int runlist(int argc, char **argv){ - int i, rnum, disp, rv; - char *rstr; - rstr = NULL; - rnum = 0; - disp = FALSE; - for(i = 2; i < argc; i++){ - if(argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - disp = TRUE; - } else { - usage(); - } - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = dolist(rnum, disp); - return rv; -} - - -/* parse arguments of map command */ -int runmap(int argc, char **argv){ - int i, rnum, bnum, disp, rv; - char *rstr, *bstr; - rstr = NULL; - bstr = NULL; - rnum = 0; - bnum = -1; - disp = FALSE; - for(i = 2; i < argc; i++){ - if(argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - disp = TRUE; - } else { - usage(); - } - } else if(!rstr){ - rstr = argv[i]; - } else if(!bstr){ - bstr = argv[i]; - } else { - usage(); - } - } - if(!rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - if(bstr) bnum = atoi(bstr); - rv = domap(rnum, bnum, disp); - return rv; -} - - -/* parse arguments of heap command */ -int runheap(int argc, char **argv){ - int i, rnum, max, disp, rv; - char *rstr, *mstr; - rstr = NULL; - mstr = NULL; - rnum = 0; - max = -1; - disp = FALSE; - for(i = 2; i < argc; i++){ - if(argv[i][0] == '-'){ - if(!strcmp(argv[i], "-d")){ - disp = TRUE; - } else { - usage(); - } - } else if(!rstr){ - rstr = argv[i]; - } else if(!mstr){ - mstr = argv[i]; - } else { - usage(); - } - } - if(!rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - if(mstr) max = atoi(mstr); - if(max < 0) max = rnum; - rv = doheap(rnum, max, disp); - rv = 0; - return rv; -} - - -/* parse arguments of wicked command */ -int runwicked(int argc, char **argv){ - int i, rnum, rv; - char *rstr; - rstr = NULL; - rnum = 0; - for(i = 2; i < argc; i++){ - if(argv[i][0] == '-'){ - usage(); - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = dowicked(rnum); - return rv; -} - - -/* parse arguments of misc command */ -int runmisc(int argc, char **argv){ - int rv; - rv = domisc(); - return rv; -} - - -/* print formatted string and flush the buffer */ -int printfflush(const char *format, ...){ - va_list ap; - int rv; - va_start(ap, format); - rv = vprintf(format, ap); - if(fflush(stdout) == EOF) rv = -1; - va_end(ap); - return rv; -} - - -/* comparing function for strings */ -int strpcmp(const void *ap, const void *bp){ - return strcmp(*(char **)ap, *(char **)bp); -} - - -/* comparing function for integers */ -int intpcmp(const void *ap, const void *bp){ - return *(int *)ap - *(int *)bp; -} - - -/* pseudo random number generator */ -int myrand(void){ - static int cnt = 0; - if(cnt == 0) srand(time(NULL)); - return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; -} - - -/* perform sort command */ -int dosort(int rnum, int disp){ - char **ivector1, **ivector2, **ivector3, **ivector4, **ivector5; - char buf[RECBUFSIZ]; - int i, len, err; - if(!disp) printfflush("\n rnum=%d\n\n", rnum); - ivector1 = cbmalloc(rnum * sizeof(ivector1[0])); - ivector2 = cbmalloc(rnum * sizeof(ivector2[0])); - ivector3 = cbmalloc(rnum * sizeof(ivector3[0])); - ivector4 = cbmalloc(rnum * sizeof(ivector4[0])); - ivector5 = cbmalloc(rnum * sizeof(ivector5[0])); - err = FALSE; - for(i = 0; i < rnum; i++){ - len = sprintf(buf, "%08d", myrand() % rnum + 1); - ivector1[i] = cbmemdup(buf, len); - ivector2[i] = cbmemdup(buf, len); - ivector3[i] = cbmemdup(buf, len); - ivector4[i] = cbmemdup(buf, len); - ivector5[i] = cbmemdup(buf, len); - } - if(!disp) printfflush("Sorting with insert sort ... "); - cbisort(ivector1, rnum, sizeof(ivector1[0]), strpcmp); - if(!disp) printfflush("ok\n"); - if(!disp) printfflush("Sorting with shell sort ... "); - cbssort(ivector2, rnum, sizeof(ivector2[0]), strpcmp); - if(!disp) printfflush("ok\n"); - if(!disp) printfflush("Sorting with heap sort ... "); - cbhsort(ivector3, rnum, sizeof(ivector3[0]), strpcmp); - if(!disp) printfflush("ok\n"); - if(!disp) printfflush("Sorting with quick sort ... "); - cbqsort(ivector4, rnum, sizeof(ivector4[0]), strpcmp); - if(!disp) printfflush("ok\n"); - for(i = 0; i < rnum; i++){ - if(disp) printfflush("%s\t%s\t%s\t%s\t[%s]\n", - ivector1[i], ivector2[i], ivector3[i], ivector4[i], ivector5[i]); - if(strcmp(ivector1[i], ivector2[i])) err = TRUE; - if(strcmp(ivector1[i], ivector3[i])) err = TRUE; - if(strcmp(ivector1[i], ivector4[i])) err = TRUE; - free(ivector1[i]); - free(ivector2[i]); - free(ivector3[i]); - free(ivector4[i]); - free(ivector5[i]); - } - free(ivector1); - free(ivector2); - free(ivector3); - free(ivector4); - free(ivector5); - if(err) fprintf(stderr, "%s: sorting failed\n", progname); - if(!disp && !err) printfflush("all ok\n\n"); - return err ? 1 : 0; -} - - -/* perform strstr command */ -int dostrstr(int rnum, int disp){ - char *text, buf[RECBUFSIZ], *std, *kmp, *bm; - int i, j, len, err; - text = cbmalloc(TEXTBUFSIZ); - for(i = 0; i < TEXTBUFSIZ - 1; i++){ - text[i] = 'a' + myrand() % ('z' - 'a'); - } - text[i] = '\0'; - err = FALSE; - if(!disp) printfflush("Locating substrings ... "); - for(i = 0; i < rnum; i++){ - len = myrand() % (RECBUFSIZ - 1); - for(j = 0; j < len; j++){ - buf[j] = 'a' + myrand() % ('z' - 'a'); - } - buf[j] = 0; - std = strstr(text, buf); - kmp = cbstrstrkmp(text, buf); - bm = cbstrstrbm(text, buf); - if(kmp != std || bm != std){ - err = TRUE; - break; - } - if(disp && std) printf("%s\n", buf); - } - if(err) fprintf(stderr, "%s: string scanning failed\n", progname); - if(!disp && !err){ - printfflush("ok\n"); - printfflush("all ok\n\n"); - } - free(text); - return err ? 1 : 0; -} - - -/* perform list command */ -int dolist(int rnum, int disp){ - CBLIST *list; - const char *vbuf; - char buf[RECBUFSIZ], *tmp; - int i, err, len, vsiz; - if(!disp) printfflush("\n rnum=%d\n\n", rnum); - list = cblistopen(); - err = FALSE; - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", i); - cblistpush(list, buf, len); - if(!disp && rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - if(disp){ - for(i = 0; i < cblistnum(list); i++){ - if((vbuf = cblistval(list, i, &vsiz)) != NULL){ - printfflush("%s:%d\n", vbuf, vsiz); - } else { - fprintf(stderr, "%s: val error\n", progname); - err = TRUE; - break; - } - } - printfflush("\n"); - while((tmp = cblistpop(list, &vsiz)) != NULL){ - printfflush("%s:%d\n", tmp, vsiz); - free(tmp); - } - } - cblistclose(list); - if(!disp && !err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform list command */ -int domap(int rnum, int bnum, int disp){ - CBMAP *map; - const char *kbuf, *vbuf; - char buf[RECBUFSIZ]; - int i, err, len, ksiz, vsiz; - if(!disp) printfflush("\n rnum=%d bnum=%d\n\n", rnum, bnum); - map = bnum > 0 ? cbmapopenex(bnum) : cbmapopen(); - err = FALSE; - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", i); - if(!cbmapput(map, buf, len, buf, len, FALSE)){ - fprintf(stderr, "%s: put error\n", progname); - err = TRUE; - break; - } - if(!disp && rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - if(disp){ - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", i); - if((vbuf = cbmapget(map, buf, len, &vsiz)) != NULL){ - printfflush("%s:%d\t%s:%d\n", buf, len, vbuf, vsiz); - } else { - fprintf(stderr, "%s: get error\n", progname); - } - } - printfflush("\n"); - cbmapiterinit(map); - while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ - vbuf = cbmapiterval(kbuf, &vsiz); - printfflush("%s:%d\t%s:%d\n", kbuf, ksiz, vbuf, vsiz); - } - } - cbmapclose(map); - if(!disp && !err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform heap command */ -int doheap(int rnum, int max, int disp){ - CBHEAP *heap; - int *orig, *ary; - int i, err, num, anum; - if(!disp) printfflush("\n rnum=%d max=%d\n\n", rnum, max); - orig = disp ? cbmalloc(rnum * sizeof(int) + 1) : NULL; - heap = cbheapopen(sizeof(int), max, intpcmp); - err = FALSE; - for(i = 1; i <= rnum; i++){ - num = myrand() % rnum + 1; - if(orig) orig[i-1] = num; - cbheapinsert(heap, &num); - if(!disp && rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - if(disp){ - for(i = 0; i < cbheapnum(heap); i++){ - printf("%d\n", *(int *)cbheapval(heap, i)); - } - printf("\n"); - qsort(orig, rnum, sizeof(int), intpcmp); - ary = (int *)cbheaptomalloc(heap, &anum); - if(anum != rnum && anum != max) err = TRUE; - for(i = 0; i < anum; i++){ - printf("%d\t%d\n", ary[i], orig[i]); - if(ary[i] != orig[i]) err = TRUE; - } - free(ary); - } else { - cbheapclose(heap); - } - free(orig); - if(!disp && !err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform wicked command */ -int dowicked(int rnum){ - CBLIST *list; - CBMAP *map; - int i, len; - char buf[RECBUFSIZ], *tmp; - printfflush("\n rnum=%d\n\n", rnum); - list = cblistopen(); - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%d", myrand() % rnum + 1); - switch(myrand() % 16){ - case 0: - free(cblistpop(list, NULL)); - putchar('O'); - break; - case 1: - cblistunshift(list, buf, len); - putchar('U'); - break; - case 2: - free(cblistshift(list, NULL)); - putchar('S'); - break; - case 3: - cblistinsert(list, myrand() % (cblistnum(list) + 1), buf, len); - putchar('I'); - break; - case 4: - free(cblistremove(list, myrand() % (cblistnum(list) + 1), NULL)); - putchar('R'); - break; - case 5: - cblistover(list, myrand() % (cblistnum(list) + 1), buf, len); - putchar('V'); - break; - case 6: - tmp = cbmemdup(buf, len); - cblistpushbuf(list, tmp, len); - putchar('B'); - break; - default: - cblistpush(list, buf, len); - putchar('P'); - break; - } - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - cblistclose(list); - map = cbmapopen(); - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%d", myrand() % rnum + 1); - switch(myrand() % 16){ - case 0: - cbmapput(map, buf, len, buf, len, FALSE); - putchar('I'); - break; - case 1: - cbmapputcat(map, buf, len, buf, len); - putchar('C'); - break; - case 2: - cbmapget(map, buf, len, NULL); - putchar('V'); - break; - case 3: - cbmapout(map, buf, len); - putchar('D'); - break; - case 4: - cbmapmove(map, buf, len, myrand() % 2); - putchar('M'); - break; - default: - cbmapput(map, buf, len, buf, len, TRUE); - putchar('O'); - break; - } - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - cbmapclose(map); - printfflush("ok\n\n"); - return 0; -} - - -/* perform misc command */ -int domisc(void){ - CBDATUM *odatum, *ndatum; - CBLIST *olist, *nlist, *elems, *glist; - CBMAP *omap, *nmap, *pairs, *gmap; - int i, j, ssiz, osiz, tsiz, jl; - char kbuf[RECBUFSIZ], vbuf[RECBUFSIZ], *sbuf, spbuf[1024], *tmp, *orig, renc[64]; - const char *op, *np; - time_t t; - printfflush("\n\n"); - printfflush("Checking memory allocation ... "); - tmp = cbmalloc(1024); - for(i = 1; i <= 65536; i *= 2){ - tmp = cbrealloc(tmp, i); - } - cbfree(tmp); - printfflush("ok\n"); - printfflush("Checking basic datum ... "); - odatum = cbdatumopen("x", -1); - for(i = 0; i < 1000; i++){ - cbdatumcat(odatum, "x", 1); - } - cbdatumclose(odatum); - tmp = cbmalloc(3); - memcpy(tmp, "abc", 3); - odatum = cbdatumopenbuf(tmp, 3); - for(i = 0; i < 1000; i++){ - cbdatumcat(odatum, ".", 1); - } - ndatum = cbdatumdup(odatum); - for(i = 0; i < 1000; i++){ - cbdatumcat(ndatum, "*", 1); - } - for(i = 0; i < 1000; i++){ - tmp = cbmalloc(3); - memcpy(tmp, "123", 3); - cbdatumsetbuf(ndatum, tmp, 3); - } - cbdatumprintf(ndatum, "[%s\t%08d\t%08o\t%08x\t%08.1f\t%@\t%?\t%:]", - "mikio", 1978, 1978, 1978, 1978.0211, "<>&#!+-*/%", "<>&#!+-*/%", "<>&#!+-*/%"); - cbdatumclose(ndatum); - cbdatumclose(odatum); - printfflush("ok\n"); - printfflush("Checking serialization of list ... "); - olist = cblistopen(); - for(i = 1; i <= 1000; i++){ - sprintf(vbuf, "%d", i); - cblistpush(olist, vbuf, -1); - } - sbuf = cblistdump(olist, &ssiz); - nlist = cblistload(sbuf, ssiz); - free(sbuf); - for(i = 0; i < cblistnum(olist); i++){ - op = cblistval(olist, i, NULL); - np = cblistval(nlist, i, NULL); - if(!op || !np || strcmp(op, np)){ - cblistclose(nlist); - cblistclose(olist); - fprintf(stderr, "%s: validation failed\n", progname); - return 1; - } - } - cblistclose(nlist); - cblistclose(olist); - printfflush("ok\n"); - printfflush("Checking serialization of map ... "); - omap = cbmapopen(); - for(i = 1; i <= 1000; i++){ - sprintf(kbuf, "%X", i); - sprintf(vbuf, "[%d]", i); - cbmapput(omap, kbuf, -1, vbuf, -1, TRUE); - } - sbuf = cbmapdump(omap, &ssiz); - nmap = cbmapload(sbuf, ssiz); - free(cbmaploadone(sbuf, ssiz, "1", 2, &tsiz)); - free(cbmaploadone(sbuf, ssiz, "33", 2, &tsiz)); - free(sbuf); - cbmapiterinit(omap); - while((op = cbmapiternext(omap, NULL)) != NULL){ - if(!(np = cbmapget(nmap, op, -1, NULL))){ - cbmapclose(nmap); - cbmapclose(omap); - fprintf(stderr, "%s: validation failed\n", progname); - return 1; - } - } - cbmapclose(nmap); - cbmapclose(omap); - printfflush("ok\n"); - printfflush("Checking string utilities ... "); - sprintf(spbuf, "[%08d/%08o/%08u/%08x/%08X/%08.3e/%08.3E/%08.3f/%08.3g/%08.3G/%c/%s/%%]", - 123456, 123456, 123456, 123456, 123456, - 123456.789, 123456.789, 123456.789, 123456.789, 123456.789, - 'A', "hoge"); - tmp = cbsprintf("[%08d/%08o/%08u/%08x/%08X/%08.3e/%08.3E/%08.3f/%08.3g/%08.3G/%c/%s/%%]", - 123456, 123456, 123456, 123456, 123456, - 123456.789, 123456.789, 123456.789, 123456.789, 123456.789, - 'A', "hoge"); - while(strcmp(spbuf, tmp)){ - free(tmp); - fprintf(stderr, "%s: cbsprintf is invalid\n", progname); - return 1; - } - free(tmp); - pairs = cbmapopen(); - cbmapput(pairs, "aa", -1, "AAA", -1, TRUE); - cbmapput(pairs, "bb", -1, "BBB", -1, TRUE); - cbmapput(pairs, "cc", -1, "CCC", -1, TRUE); - cbmapput(pairs, "ZZZ", -1, "z", -1, TRUE); - tmp = cbreplace("[aaaaabbbbbcccccdddddZZZZ]", pairs); - if(strcmp(tmp, "[AAAAAAaBBBBBBbCCCCCCcdddddzZ]")){ - free(tmp); - cbmapclose(pairs); - fprintf(stderr, "%s: cbreplace is invalid\n", progname); - return 1; - } - free(tmp); - cbmapclose(pairs); - elems = cbsplit("aa bb,ccc-dd,", -1, " ,-"); - if(cblistnum(elems) != 5 || strcmp(cblistval(elems, 0, NULL), "aa") || - strcmp(cblistval(elems, 1, NULL), "bb") || strcmp(cblistval(elems, 2, NULL), "ccc") || - strcmp(cblistval(elems, 3, NULL), "dd") || strcmp(cblistval(elems, 4, NULL), "")){ - cblistclose(elems); - fprintf(stderr, "%s: cbsplit is invalid\n", progname); - return 1; - } - cblistclose(elems); - if(cbstricmp("abc", "ABC") || !cbstricmp("abc", "abcd")){ - fprintf(stderr, "%s: cbstricmp is invalid\n", progname); - return 1; - } - if(!cbstrfwmatch("abcd", "abc") || cbstrfwmatch("abc", "abcd")){ - fprintf(stderr, "%s: cbstrfwmatch is invalid\n", progname); - return 1; - } - if(!cbstrfwimatch("abcd", "ABC") || cbstrfwmatch("abc", "ABCD")){ - fprintf(stderr, "%s: cbstrfwimatch is invalid\n", progname); - return 1; - } - if(!cbstrbwmatch("dcba", "cba") || cbstrbwmatch("cba", "dcba")){ - fprintf(stderr, "%s: cbstrbwmatch is invalid\n", progname); - return 1; - } - if(!cbstrbwimatch("dcba", "CBA") || cbstrbwimatch("cba", "DCBA")){ - fprintf(stderr, "%s: cbstrbwimatch is invalid\n", progname); - return 1; - } - tmp = cbmemdup(" \r\n[Quick Database Manager]\r\n ", -1); - if(cbstrtoupper(tmp) != tmp || strcmp(tmp, " \r\n[QUICK DATABASE MANAGER]\r\n ")){ - free(tmp); - fprintf(stderr, "%s: cbstrtoupper is invalid\n", progname); - return 1; - } - if(cbstrtolower(tmp) != tmp || strcmp(tmp, " \r\n[quick database manager]\r\n ")){ - free(tmp); - fprintf(stderr, "%s: cbstrtolower is invalid\n", progname); - return 1; - } - if(cbstrtrim(tmp) != tmp || strcmp(tmp, "[quick database manager]")){ - free(tmp); - fprintf(stderr, "%s: cbstrtrim is invalid\n", progname); - return 1; - } - if(cbstrsqzspc(tmp) != tmp || strcmp(tmp, "[quick database manager]")){ - free(tmp); - fprintf(stderr, "%s: cbstrsqzspc is invalid\n", progname); - return 1; - } - cbstrcututf(tmp, 5); - if(cbstrcountutf(tmp) != 5){ - free(tmp); - fprintf(stderr, "%s: cbstrcututf or cbstrcountutf is invalid\n", progname); - return 1; - } - free(tmp); - printfflush("ok\n"); - printfflush("Checking encoding utilities ... "); - strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n\n"); - tmp = cbbaseencode(spbuf, -1); - orig = cbbasedecode(tmp, &osiz); - if(osiz != strlen(spbuf) || strcmp(orig, spbuf)){ - free(orig); - free(tmp); - fprintf(stderr, "%s: Base64 encoding is invalid\n", progname); - return 1; - } - free(orig); - free(tmp); - strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n\n"); - tmp = cbquoteencode(spbuf, -1); - orig = cbquotedecode(tmp, &osiz); - if(osiz != strlen(spbuf) || strcmp(orig, spbuf)){ - free(orig); - free(tmp); - fprintf(stderr, "%s: quoted-printable encoding is invalid\n", progname); - return 1; - } - free(orig); - free(tmp); - strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n\n"); - tmp = cbmimeencode(spbuf, "ISO-8859-1", TRUE); - orig = cbmimedecode(tmp, renc); - if(osiz != strlen(spbuf) || strcmp(orig, spbuf) || strcmp(renc, "ISO-8859-1")){ - free(orig); - free(tmp); - fprintf(stderr, "%s: MIME encoding is invalid\n", progname); - return 1; - } - free(orig); - free(tmp); - strcpy(spbuf, "\"He says...\r\n\"\"What PROGRAM are they watching?\"\"\""); - tmp = cbcsvunescape(spbuf); - orig = cbcsvescape(tmp); - if(strcmp(orig, spbuf)){ - free(orig); - free(tmp); - fprintf(stderr, "%s: CSV escaping is invalid\n", progname); - return 1; - } - free(orig); - free(tmp); - strcpy(spbuf, "<Nuts&Milk> is "very" surfin'!"); - tmp = cbxmlunescape(spbuf); - orig = cbxmlescape(tmp); - if(strcmp(orig, spbuf)){ - free(orig); - free(tmp); - fprintf(stderr, "%s: XML escaping is invalid\n", progname); - return 1; - } - free(orig); - free(tmp); - printfflush("ok\n"); - printfflush("Checking date utilities ... "); - for(i = 0; i < 200; i++){ - jl = (myrand() % 23) * 1800; - if(myrand() % 2 == 0) jl *= -1; - t = myrand() % (INT_MAX - 3600 * 24 * 365 * 6) + 3600 * 24 * 365 * 5; - tmp = cbdatestrwww(t, jl); - t = cbstrmktime(tmp); - orig = cbdatestrwww(t, jl); - if(strcmp(orig, tmp)){ - free(orig); - free(tmp); - fprintf(stderr, "%s: W3CDTF formatter is invalid\n", progname); - return 1; - } - free(orig); - free(tmp); - tmp = cbdatestrhttp(t, jl); - t = cbstrmktime(tmp); - orig = cbdatestrhttp(t, jl); - if(strcmp(orig, tmp)){ - free(orig); - free(tmp); - fprintf(stderr, "%s: RFC 822 date formatter is invalid\n", progname); - return 1; - } - free(orig); - free(tmp); - } - printfflush("ok\n"); - printfflush("Checking the global garbage collector ... "); - for(i = 0; i < 512; i++){ - glist = cblistopen(); - cbglobalgc(glist, (void (*)(void *))cblistclose); - for(j = 0; j < 10; j++){ - sprintf(kbuf, "%08d", j); - cblistpush(glist, kbuf, -1); - } - gmap = cbmapopen(); - cbglobalgc(gmap, (void (*)(void *))cbmapclose); - for(j = 0; j < 10; j++){ - sprintf(kbuf, "%08d", j); - cbmapput(gmap, kbuf, -1, kbuf, -1, TRUE); - } - if(myrand() % 64 == 0){ - cbvmemavail(100); - cbggcsweep(); - } - } - printfflush("ok\n"); - printfflush("all ok\n\n"); - return 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/cbtest.c (from rev 2716, box/trunk/qdbm/cbtest.c) =================================================================== --- box/trunk/qdbm/cbtest.c (rev 0) +++ box/trunk/qdbm/cbtest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,924 @@ +/************************************************************************************************* + * Test cases of Cabin + * 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 +#include +#include +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define RECBUFSIZ 32 /* buffer for records */ +#define TEXTBUFSIZ 262144 /* buffer for text */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +int runsort(int argc, char **argv); +int runstrstr(int argc, char **argv); +int runlist(int argc, char **argv); +int runmap(int argc, char **argv); +int runheap(int argc, char **argv); +int runwicked(int argc, char **argv); +int runmisc(int argc, char **argv); +int printfflush(const char *format, ...); +int strpcmp(const void *ap, const void *bp); +int intpcmp(const void *ap, const void *bp); +int myrand(void); +int dosort(int rnum, int disp); +int dostrstr(int rnum, int disp); +int dolist(int rnum, int disp); +int domap(int rnum, int bnum, int disp); +int doheap(int rnum, int max, int disp); +int dowicked(int rnum); +int domisc(void); + + +/* main routine */ +int main(int argc, char **argv){ + int rv; + cbstdiobin(); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "sort")){ + rv = runsort(argc, argv); + } else if(!strcmp(argv[1], "strstr")){ + rv = runstrstr(argc, argv); + } else if(!strcmp(argv[1], "list")){ + rv = runlist(argc, argv); + } else if(!strcmp(argv[1], "map")){ + rv = runmap(argc, argv); + } else if(!strcmp(argv[1], "heap")){ + rv = runheap(argc, argv); + } else if(!strcmp(argv[1], "wicked")){ + rv = runwicked(argc, argv); + } else if(!strcmp(argv[1], "misc")){ + rv = runmisc(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: test cases for Cabin\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s sort [-d] rnum\n", progname); + fprintf(stderr, " %s strstr [-d] rnum\n", progname); + fprintf(stderr, " %s list [-d] rnum\n", progname); + fprintf(stderr, " %s map [-d] rnum [bnum]\n", progname); + fprintf(stderr, " %s heap [-d] rnum [top]\n", progname); + fprintf(stderr, " %s wicked rnum\n", progname); + fprintf(stderr, " %s misc\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of sort command */ +int runsort(int argc, char **argv){ + int i, rnum, disp, rv; + char *rstr; + rstr = NULL; + rnum = 0; + disp = FALSE; + for(i = 2; i < argc; i++){ + if(argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + disp = TRUE; + } else { + usage(); + } + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = dosort(rnum, disp); + return rv; +} + + +/* parse arguments of strstr command */ +int runstrstr(int argc, char **argv){ + int i, rnum, disp, rv; + char *rstr; + rstr = NULL; + rnum = 0; + disp = FALSE; + for(i = 2; i < argc; i++){ + if(argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + disp = TRUE; + } else { + usage(); + } + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = dostrstr(rnum, disp); + return rv; +} + + +/* parse arguments of list command */ +int runlist(int argc, char **argv){ + int i, rnum, disp, rv; + char *rstr; + rstr = NULL; + rnum = 0; + disp = FALSE; + for(i = 2; i < argc; i++){ + if(argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + disp = TRUE; + } else { + usage(); + } + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = dolist(rnum, disp); + return rv; +} + + +/* parse arguments of map command */ +int runmap(int argc, char **argv){ + int i, rnum, bnum, disp, rv; + char *rstr, *bstr; + rstr = NULL; + bstr = NULL; + rnum = 0; + bnum = -1; + disp = FALSE; + for(i = 2; i < argc; i++){ + if(argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + disp = TRUE; + } else { + usage(); + } + } else if(!rstr){ + rstr = argv[i]; + } else if(!bstr){ + bstr = argv[i]; + } else { + usage(); + } + } + if(!rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + if(bstr) bnum = atoi(bstr); + rv = domap(rnum, bnum, disp); + return rv; +} + + +/* parse arguments of heap command */ +int runheap(int argc, char **argv){ + int i, rnum, max, disp, rv; + char *rstr, *mstr; + rstr = NULL; + mstr = NULL; + rnum = 0; + max = -1; + disp = FALSE; + for(i = 2; i < argc; i++){ + if(argv[i][0] == '-'){ + if(!strcmp(argv[i], "-d")){ + disp = TRUE; + } else { + usage(); + } + } else if(!rstr){ + rstr = argv[i]; + } else if(!mstr){ + mstr = argv[i]; + } else { + usage(); + } + } + if(!rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + if(mstr) max = atoi(mstr); + if(max < 0) max = rnum; + rv = doheap(rnum, max, disp); + rv = 0; + return rv; +} + + +/* parse arguments of wicked command */ +int runwicked(int argc, char **argv){ + int i, rnum, rv; + char *rstr; + rstr = NULL; + rnum = 0; + for(i = 2; i < argc; i++){ + if(argv[i][0] == '-'){ + usage(); + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = dowicked(rnum); + return rv; +} + + +/* parse arguments of misc command */ +int runmisc(int argc, char **argv){ + int rv; + rv = domisc(); + return rv; +} + + +/* print formatted string and flush the buffer */ +int printfflush(const char *format, ...){ + va_list ap; + int rv; + va_start(ap, format); + rv = vprintf(format, ap); + if(fflush(stdout) == EOF) rv = -1; + va_end(ap); + return rv; +} + + +/* comparing function for strings */ +int strpcmp(const void *ap, const void *bp){ + return strcmp(*(char **)ap, *(char **)bp); +} + + +/* comparing function for integers */ +int intpcmp(const void *ap, const void *bp){ + return *(int *)ap - *(int *)bp; +} + + +/* pseudo random number generator */ +int myrand(void){ + static int cnt = 0; + if(cnt == 0) srand(time(NULL)); + return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; +} + + +/* perform sort command */ +int dosort(int rnum, int disp){ + char **ivector1, **ivector2, **ivector3, **ivector4, **ivector5; + char buf[RECBUFSIZ]; + int i, len, err; + if(!disp) printfflush("\n rnum=%d\n\n", rnum); + ivector1 = cbmalloc(rnum * sizeof(ivector1[0])); + ivector2 = cbmalloc(rnum * sizeof(ivector2[0])); + ivector3 = cbmalloc(rnum * sizeof(ivector3[0])); + ivector4 = cbmalloc(rnum * sizeof(ivector4[0])); + ivector5 = cbmalloc(rnum * sizeof(ivector5[0])); + err = FALSE; + for(i = 0; i < rnum; i++){ + len = sprintf(buf, "%08d", myrand() % rnum + 1); + ivector1[i] = cbmemdup(buf, len); + ivector2[i] = cbmemdup(buf, len); + ivector3[i] = cbmemdup(buf, len); + ivector4[i] = cbmemdup(buf, len); + ivector5[i] = cbmemdup(buf, len); + } + if(!disp) printfflush("Sorting with insert sort ... "); + cbisort(ivector1, rnum, sizeof(ivector1[0]), strpcmp); + if(!disp) printfflush("ok\n"); + if(!disp) printfflush("Sorting with shell sort ... "); + cbssort(ivector2, rnum, sizeof(ivector2[0]), strpcmp); + if(!disp) printfflush("ok\n"); + if(!disp) printfflush("Sorting with heap sort ... "); + cbhsort(ivector3, rnum, sizeof(ivector3[0]), strpcmp); + if(!disp) printfflush("ok\n"); + if(!disp) printfflush("Sorting with quick sort ... "); + cbqsort(ivector4, rnum, sizeof(ivector4[0]), strpcmp); + if(!disp) printfflush("ok\n"); + for(i = 0; i < rnum; i++){ + if(disp) printfflush("%s\t%s\t%s\t%s\t[%s]\n", + ivector1[i], ivector2[i], ivector3[i], ivector4[i], ivector5[i]); + if(strcmp(ivector1[i], ivector2[i])) err = TRUE; + if(strcmp(ivector1[i], ivector3[i])) err = TRUE; + if(strcmp(ivector1[i], ivector4[i])) err = TRUE; + free(ivector1[i]); + free(ivector2[i]); + free(ivector3[i]); + free(ivector4[i]); + free(ivector5[i]); + } + free(ivector1); + free(ivector2); + free(ivector3); + free(ivector4); + free(ivector5); + if(err) fprintf(stderr, "%s: sorting failed\n", progname); + if(!disp && !err) printfflush("all ok\n\n"); + return err ? 1 : 0; +} + + +/* perform strstr command */ +int dostrstr(int rnum, int disp){ + char *text, buf[RECBUFSIZ], *std, *kmp, *bm; + int i, j, len, err; + text = cbmalloc(TEXTBUFSIZ); + for(i = 0; i < TEXTBUFSIZ - 1; i++){ + text[i] = 'a' + myrand() % ('z' - 'a'); + } + text[i] = '\0'; + err = FALSE; + if(!disp) printfflush("Locating substrings ... "); + for(i = 0; i < rnum; i++){ + len = myrand() % (RECBUFSIZ - 1); + for(j = 0; j < len; j++){ + buf[j] = 'a' + myrand() % ('z' - 'a'); + } + buf[j] = 0; + std = strstr(text, buf); + kmp = cbstrstrkmp(text, buf); + bm = cbstrstrbm(text, buf); + if(kmp != std || bm != std){ + err = TRUE; + break; + } + if(disp && std) printf("%s\n", buf); + } + if(err) fprintf(stderr, "%s: string scanning failed\n", progname); + if(!disp && !err){ + printfflush("ok\n"); + printfflush("all ok\n\n"); + } + free(text); + return err ? 1 : 0; +} + + +/* perform list command */ +int dolist(int rnum, int disp){ + CBLIST *list; + const char *vbuf; + char buf[RECBUFSIZ], *tmp; + int i, err, len, vsiz; + if(!disp) printfflush("\n rnum=%d\n\n", rnum); + list = cblistopen(); + err = FALSE; + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", i); + cblistpush(list, buf, len); + if(!disp && rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + if(disp){ + for(i = 0; i < cblistnum(list); i++){ + if((vbuf = cblistval(list, i, &vsiz)) != NULL){ + printfflush("%s:%d\n", vbuf, vsiz); + } else { + fprintf(stderr, "%s: val error\n", progname); + err = TRUE; + break; + } + } + printfflush("\n"); + while((tmp = cblistpop(list, &vsiz)) != NULL){ + printfflush("%s:%d\n", tmp, vsiz); + free(tmp); + } + } + cblistclose(list); + if(!disp && !err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform list command */ +int domap(int rnum, int bnum, int disp){ + CBMAP *map; + const char *kbuf, *vbuf; + char buf[RECBUFSIZ]; + int i, err, len, ksiz, vsiz; + if(!disp) printfflush("\n rnum=%d bnum=%d\n\n", rnum, bnum); + map = bnum > 0 ? cbmapopenex(bnum) : cbmapopen(); + err = FALSE; + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", i); + if(!cbmapput(map, buf, len, buf, len, FALSE)){ + fprintf(stderr, "%s: put error\n", progname); + err = TRUE; + break; + } + if(!disp && rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + if(disp){ + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", i); + if((vbuf = cbmapget(map, buf, len, &vsiz)) != NULL){ + printfflush("%s:%d\t%s:%d\n", buf, len, vbuf, vsiz); + } else { + fprintf(stderr, "%s: get error\n", progname); + } + } + printfflush("\n"); + cbmapiterinit(map); + while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ + vbuf = cbmapiterval(kbuf, &vsiz); + printfflush("%s:%d\t%s:%d\n", kbuf, ksiz, vbuf, vsiz); + } + } + cbmapclose(map); + if(!disp && !err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform heap command */ +int doheap(int rnum, int max, int disp){ + CBHEAP *heap; + int *orig, *ary; + int i, err, num, anum; + if(!disp) printfflush("\n rnum=%d max=%d\n\n", rnum, max); + orig = disp ? cbmalloc(rnum * sizeof(int) + 1) : NULL; + heap = cbheapopen(sizeof(int), max, intpcmp); + err = FALSE; + for(i = 1; i <= rnum; i++){ + num = myrand() % rnum + 1; + if(orig) orig[i-1] = num; + cbheapinsert(heap, &num); + if(!disp && rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + if(disp){ + for(i = 0; i < cbheapnum(heap); i++){ + printf("%d\n", *(int *)cbheapval(heap, i)); + } + printf("\n"); + qsort(orig, rnum, sizeof(int), intpcmp); + ary = (int *)cbheaptomalloc(heap, &anum); + if(anum != rnum && anum != max) err = TRUE; + for(i = 0; i < anum; i++){ + printf("%d\t%d\n", ary[i], orig[i]); + if(ary[i] != orig[i]) err = TRUE; + } + free(ary); + } else { + cbheapclose(heap); + } + free(orig); + if(!disp && !err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform wicked command */ +int dowicked(int rnum){ + CBLIST *list; + CBMAP *map; + int i, len; + char buf[RECBUFSIZ], *tmp; + printfflush("\n rnum=%d\n\n", rnum); + list = cblistopen(); + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%d", myrand() % rnum + 1); + switch(myrand() % 16){ + case 0: + free(cblistpop(list, NULL)); + putchar('O'); + break; + case 1: + cblistunshift(list, buf, len); + putchar('U'); + break; + case 2: + free(cblistshift(list, NULL)); + putchar('S'); + break; + case 3: + cblistinsert(list, myrand() % (cblistnum(list) + 1), buf, len); + putchar('I'); + break; + case 4: + free(cblistremove(list, myrand() % (cblistnum(list) + 1), NULL)); + putchar('R'); + break; + case 5: + cblistover(list, myrand() % (cblistnum(list) + 1), buf, len); + putchar('V'); + break; + case 6: + tmp = cbmemdup(buf, len); + cblistpushbuf(list, tmp, len); + putchar('B'); + break; + default: + cblistpush(list, buf, len); + putchar('P'); + break; + } + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + cblistclose(list); + map = cbmapopen(); + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%d", myrand() % rnum + 1); + switch(myrand() % 16){ + case 0: + cbmapput(map, buf, len, buf, len, FALSE); + putchar('I'); + break; + case 1: + cbmapputcat(map, buf, len, buf, len); + putchar('C'); + break; + case 2: + cbmapget(map, buf, len, NULL); + putchar('V'); + break; + case 3: + cbmapout(map, buf, len); + putchar('D'); + break; + case 4: + cbmapmove(map, buf, len, myrand() % 2); + putchar('M'); + break; + default: + cbmapput(map, buf, len, buf, len, TRUE); + putchar('O'); + break; + } + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + cbmapclose(map); + printfflush("ok\n\n"); + return 0; +} + + +/* perform misc command */ +int domisc(void){ + CBDATUM *odatum, *ndatum; + CBLIST *olist, *nlist, *elems, *glist; + CBMAP *omap, *nmap, *pairs, *gmap; + int i, j, ssiz, osiz, tsiz, jl; + char kbuf[RECBUFSIZ], vbuf[RECBUFSIZ], *sbuf, spbuf[1024], *tmp, *orig, renc[64]; + const char *op, *np; + time_t t; + printfflush("\n\n"); + printfflush("Checking memory allocation ... "); + tmp = cbmalloc(1024); + for(i = 1; i <= 65536; i *= 2){ + tmp = cbrealloc(tmp, i); + } + cbfree(tmp); + printfflush("ok\n"); + printfflush("Checking basic datum ... "); + odatum = cbdatumopen("x", -1); + for(i = 0; i < 1000; i++){ + cbdatumcat(odatum, "x", 1); + } + cbdatumclose(odatum); + tmp = cbmalloc(3); + memcpy(tmp, "abc", 3); + odatum = cbdatumopenbuf(tmp, 3); + for(i = 0; i < 1000; i++){ + cbdatumcat(odatum, ".", 1); + } + ndatum = cbdatumdup(odatum); + for(i = 0; i < 1000; i++){ + cbdatumcat(ndatum, "*", 1); + } + for(i = 0; i < 1000; i++){ + tmp = cbmalloc(3); + memcpy(tmp, "123", 3); + cbdatumsetbuf(ndatum, tmp, 3); + } + cbdatumprintf(ndatum, "[%s\t%08d\t%08o\t%08x\t%08.1f\t%@\t%?\t%:]", + "mikio", 1978, 1978, 1978, 1978.0211, "<>&#!+-*/%", "<>&#!+-*/%", "<>&#!+-*/%"); + cbdatumclose(ndatum); + cbdatumclose(odatum); + printfflush("ok\n"); + printfflush("Checking serialization of list ... "); + olist = cblistopen(); + for(i = 1; i <= 1000; i++){ + sprintf(vbuf, "%d", i); + cblistpush(olist, vbuf, -1); + } + sbuf = cblistdump(olist, &ssiz); + nlist = cblistload(sbuf, ssiz); + free(sbuf); + for(i = 0; i < cblistnum(olist); i++){ + op = cblistval(olist, i, NULL); + np = cblistval(nlist, i, NULL); + if(!op || !np || strcmp(op, np)){ + cblistclose(nlist); + cblistclose(olist); + fprintf(stderr, "%s: validation failed\n", progname); + return 1; + } + } + cblistclose(nlist); + cblistclose(olist); + printfflush("ok\n"); + printfflush("Checking serialization of map ... "); + omap = cbmapopen(); + for(i = 1; i <= 1000; i++){ + sprintf(kbuf, "%X", i); + sprintf(vbuf, "[%d]", i); + cbmapput(omap, kbuf, -1, vbuf, -1, TRUE); + } + sbuf = cbmapdump(omap, &ssiz); + nmap = cbmapload(sbuf, ssiz); + free(cbmaploadone(sbuf, ssiz, "1", 2, &tsiz)); + free(cbmaploadone(sbuf, ssiz, "33", 2, &tsiz)); + free(sbuf); + cbmapiterinit(omap); + while((op = cbmapiternext(omap, NULL)) != NULL){ + if(!(np = cbmapget(nmap, op, -1, NULL))){ + cbmapclose(nmap); + cbmapclose(omap); + fprintf(stderr, "%s: validation failed\n", progname); + return 1; + } + } + cbmapclose(nmap); + cbmapclose(omap); + printfflush("ok\n"); + printfflush("Checking string utilities ... "); + sprintf(spbuf, "[%08d/%08o/%08u/%08x/%08X/%08.3e/%08.3E/%08.3f/%08.3g/%08.3G/%c/%s/%%]", + 123456, 123456, 123456, 123456, 123456, + 123456.789, 123456.789, 123456.789, 123456.789, 123456.789, + 'A', "hoge"); + tmp = cbsprintf("[%08d/%08o/%08u/%08x/%08X/%08.3e/%08.3E/%08.3f/%08.3g/%08.3G/%c/%s/%%]", + 123456, 123456, 123456, 123456, 123456, + 123456.789, 123456.789, 123456.789, 123456.789, 123456.789, + 'A', "hoge"); + while(strcmp(spbuf, tmp)){ + free(tmp); + fprintf(stderr, "%s: cbsprintf is invalid\n", progname); + return 1; + } + free(tmp); + pairs = cbmapopen(); + cbmapput(pairs, "aa", -1, "AAA", -1, TRUE); + cbmapput(pairs, "bb", -1, "BBB", -1, TRUE); + cbmapput(pairs, "cc", -1, "CCC", -1, TRUE); + cbmapput(pairs, "ZZZ", -1, "z", -1, TRUE); + tmp = cbreplace("[aaaaabbbbbcccccdddddZZZZ]", pairs); + if(strcmp(tmp, "[AAAAAAaBBBBBBbCCCCCCcdddddzZ]")){ + free(tmp); + cbmapclose(pairs); + fprintf(stderr, "%s: cbreplace is invalid\n", progname); + return 1; + } + free(tmp); + cbmapclose(pairs); + elems = cbsplit("aa bb,ccc-dd,", -1, " ,-"); + if(cblistnum(elems) != 5 || strcmp(cblistval(elems, 0, NULL), "aa") || + strcmp(cblistval(elems, 1, NULL), "bb") || strcmp(cblistval(elems, 2, NULL), "ccc") || + strcmp(cblistval(elems, 3, NULL), "dd") || strcmp(cblistval(elems, 4, NULL), "")){ + cblistclose(elems); + fprintf(stderr, "%s: cbsplit is invalid\n", progname); + return 1; + } + cblistclose(elems); + if(cbstricmp("abc", "ABC") || !cbstricmp("abc", "abcd")){ + fprintf(stderr, "%s: cbstricmp is invalid\n", progname); + return 1; + } + if(!cbstrfwmatch("abcd", "abc") || cbstrfwmatch("abc", "abcd")){ + fprintf(stderr, "%s: cbstrfwmatch is invalid\n", progname); + return 1; + } + if(!cbstrfwimatch("abcd", "ABC") || cbstrfwmatch("abc", "ABCD")){ + fprintf(stderr, "%s: cbstrfwimatch is invalid\n", progname); + return 1; + } + if(!cbstrbwmatch("dcba", "cba") || cbstrbwmatch("cba", "dcba")){ + fprintf(stderr, "%s: cbstrbwmatch is invalid\n", progname); + return 1; + } + if(!cbstrbwimatch("dcba", "CBA") || cbstrbwimatch("cba", "DCBA")){ + fprintf(stderr, "%s: cbstrbwimatch is invalid\n", progname); + return 1; + } + tmp = cbmemdup(" \r\n[Quick Database Manager]\r\n ", -1); + if(cbstrtoupper(tmp) != tmp || strcmp(tmp, " \r\n[QUICK DATABASE MANAGER]\r\n ")){ + free(tmp); + fprintf(stderr, "%s: cbstrtoupper is invalid\n", progname); + return 1; + } + if(cbstrtolower(tmp) != tmp || strcmp(tmp, " \r\n[quick database manager]\r\n ")){ + free(tmp); + fprintf(stderr, "%s: cbstrtolower is invalid\n", progname); + return 1; + } + if(cbstrtrim(tmp) != tmp || strcmp(tmp, "[quick database manager]")){ + free(tmp); + fprintf(stderr, "%s: cbstrtrim is invalid\n", progname); + return 1; + } + if(cbstrsqzspc(tmp) != tmp || strcmp(tmp, "[quick database manager]")){ + free(tmp); + fprintf(stderr, "%s: cbstrsqzspc is invalid\n", progname); + return 1; + } + cbstrcututf(tmp, 5); + if(cbstrcountutf(tmp) != 5){ + free(tmp); + fprintf(stderr, "%s: cbstrcututf or cbstrcountutf is invalid\n", progname); + return 1; + } + free(tmp); + printfflush("ok\n"); + printfflush("Checking encoding utilities ... "); + strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n\n"); + tmp = cbbaseencode(spbuf, -1); + orig = cbbasedecode(tmp, &osiz); + if(osiz != strlen(spbuf) || strcmp(orig, spbuf)){ + free(orig); + free(tmp); + fprintf(stderr, "%s: Base64 encoding is invalid\n", progname); + return 1; + } + free(orig); + free(tmp); + strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n\n"); + tmp = cbquoteencode(spbuf, -1); + orig = cbquotedecode(tmp, &osiz); + if(osiz != strlen(spbuf) || strcmp(orig, spbuf)){ + free(orig); + free(tmp); + fprintf(stderr, "%s: quoted-printable encoding is invalid\n", progname); + return 1; + } + free(orig); + free(tmp); + strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n\n"); + tmp = cbmimeencode(spbuf, "ISO-8859-1", TRUE); + orig = cbmimedecode(tmp, renc); + if(osiz != strlen(spbuf) || strcmp(orig, spbuf) || strcmp(renc, "ISO-8859-1")){ + free(orig); + free(tmp); + fprintf(stderr, "%s: MIME encoding is invalid\n", progname); + return 1; + } + free(orig); + free(tmp); + strcpy(spbuf, "\"He says...\r\n\"\"What PROGRAM are they watching?\"\"\""); + tmp = cbcsvunescape(spbuf); + orig = cbcsvescape(tmp); + if(strcmp(orig, spbuf)){ + free(orig); + free(tmp); + fprintf(stderr, "%s: CSV escaping is invalid\n", progname); + return 1; + } + free(orig); + free(tmp); + strcpy(spbuf, "<Nuts&Milk> is "very" surfin'!"); + tmp = cbxmlunescape(spbuf); + orig = cbxmlescape(tmp); + if(strcmp(orig, spbuf)){ + free(orig); + free(tmp); + fprintf(stderr, "%s: XML escaping is invalid\n", progname); + return 1; + } + free(orig); + free(tmp); + printfflush("ok\n"); + printfflush("Checking date utilities ... "); + for(i = 0; i < 200; i++){ + jl = (myrand() % 23) * 1800; + if(myrand() % 2 == 0) jl *= -1; + t = myrand() % (INT_MAX - 3600 * 24 * 365 * 6) + 3600 * 24 * 365 * 5; + tmp = cbdatestrwww(t, jl); + t = cbstrmktime(tmp); + orig = cbdatestrwww(t, jl); + if(strcmp(orig, tmp)){ + free(orig); + free(tmp); + fprintf(stderr, "%s: W3CDTF formatter is invalid\n", progname); + return 1; + } + free(orig); + free(tmp); + tmp = cbdatestrhttp(t, jl); + t = cbstrmktime(tmp); + orig = cbdatestrhttp(t, jl); + if(strcmp(orig, tmp)){ + free(orig); + free(tmp); + fprintf(stderr, "%s: RFC 822 date formatter is invalid\n", progname); + return 1; + } + free(orig); + free(tmp); + } + printfflush("ok\n"); + printfflush("Checking the global garbage collector ... "); + for(i = 0; i < 512; i++){ + glist = cblistopen(); + cbglobalgc(glist, (void (*)(void *))cblistclose); + for(j = 0; j < 10; j++){ + sprintf(kbuf, "%08d", j); + cblistpush(glist, kbuf, -1); + } + gmap = cbmapopen(); + cbglobalgc(gmap, (void (*)(void *))cbmapclose); + for(j = 0; j < 10; j++){ + sprintf(kbuf, "%08d", j); + cbmapput(gmap, kbuf, -1, kbuf, -1, TRUE); + } + if(myrand() % 64 == 0){ + cbvmemavail(100); + cbggcsweep(); + } + } + printfflush("ok\n"); + printfflush("all ok\n\n"); + return 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/configure =================================================================== --- box/trunk/qdbm/configure 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/configure 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,3913 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.59 for qdbm 1.8.77. -# -# Copyright (C) 2003 Free Software Foundation, Inc. -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi -DUALCASE=1; export DUALCASE # for MKS sh - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - - -# PATH needs CR, and LINENO needs CR and PATH. -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; -esac - -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else - as_ln_s='ln -s' - fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.file - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_executable_p="test -f" - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - - -# Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -exec 6>&1 - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_config_libobj_dir=. -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} - -# Maximum number of lines to put in a shell here document. -# This variable seems obsolete. It should probably be removed, and -# only ac_max_sed_lines should be used. -: ${ac_max_here_lines=38} - -# Identity of this package. -PACKAGE_NAME='qdbm' -PACKAGE_TARNAME='qdbm' -PACKAGE_VERSION='1.8.77' -PACKAGE_STRING='qdbm 1.8.77' -PACKAGE_BUGREPORT='' - -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LIBVER LIBREV TARGETS MYDEFS MYOPTS MGWLIBS LD AR LIBOBJS LTLIBOBJS' -ac_subst_files='' - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' -includedir='${prefix}/include' -oldincludedir='/usr/include' -infodir='${prefix}/info' -mandir='${prefix}/man' - -ac_prev= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" - ac_prev= - continue - fi - - ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_option in - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - eval "enable_$ac_feature=no" ;; - - -enable-* | --enable-*) - ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; - esac - eval "enable_$ac_feature='$ac_optarg'" ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package| sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; - esac - eval "with_$ac_package='$ac_optarg'" ;; - - -without-* | --without-*) - ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/-/_/g'` - eval "with_$ac_package=no" ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) { echo "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } - ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` - eval "$ac_envvar='$ac_optarg'" - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } -fi - -# Be sure to have absolute paths. -for ac_var in exec_prefix prefix -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* | NONE | '' ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; - esac -done - -# Be sure to have absolute paths. -for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ - localstatedir libdir includedir oldincludedir infodir mandir -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; - esac -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then its parent. - ac_confdir=`(dirname "$0") 2>/dev/null || -$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$0" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r $srcdir/$ac_unique_file; then - if test "$ac_srcdir_defaulted" = yes; then - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 - { (exit 1); exit 1; }; } - else - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } - fi -fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || - { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 - { (exit 1); exit 1; }; } -srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` -ac_env_build_alias_set=${build_alias+set} -ac_env_build_alias_value=$build_alias -ac_cv_env_build_alias_set=${build_alias+set} -ac_cv_env_build_alias_value=$build_alias -ac_env_host_alias_set=${host_alias+set} -ac_env_host_alias_value=$host_alias -ac_cv_env_host_alias_set=${host_alias+set} -ac_cv_env_host_alias_value=$host_alias -ac_env_target_alias_set=${target_alias+set} -ac_env_target_alias_value=$target_alias -ac_cv_env_target_alias_set=${target_alias+set} -ac_cv_env_target_alias_value=$target_alias -ac_env_CC_set=${CC+set} -ac_env_CC_value=$CC -ac_cv_env_CC_set=${CC+set} -ac_cv_env_CC_value=$CC -ac_env_CFLAGS_set=${CFLAGS+set} -ac_env_CFLAGS_value=$CFLAGS -ac_cv_env_CFLAGS_set=${CFLAGS+set} -ac_cv_env_CFLAGS_value=$CFLAGS -ac_env_LDFLAGS_set=${LDFLAGS+set} -ac_env_LDFLAGS_value=$LDFLAGS -ac_cv_env_LDFLAGS_set=${LDFLAGS+set} -ac_cv_env_LDFLAGS_value=$LDFLAGS -ac_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_env_CPPFLAGS_value=$CPPFLAGS -ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_cv_env_CPPFLAGS_value=$CPPFLAGS - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures qdbm 1.8.77 to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -_ACEOF - - cat <<_ACEOF -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data [PREFIX/share] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --infodir=DIR info documentation [PREFIX/info] - --mandir=DIR man documentation [PREFIX/man] -_ACEOF - - cat <<\_ACEOF -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of qdbm 1.8.77:";; - esac - cat <<\_ACEOF - -Optional Features: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-debug build for debugging - --enable-devel build for development - --enable-stable build for stable release - --enable-pthread use POSIX thread and make APIs thread-safe - --disable-lock build for environments without file locking - --disable-mmap build for environments without memory mapping - --enable-zlib feature ZLIB for B+ tree and inverted index - --enable-lzo feature LZO for B+ tree and inverted index - --enable-bzip feature BZIP2 for B+ tree and inverted index - --enable-iconv feature ICONV utilities - --disable-warn hide warnings in the configuration - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have - headers in a nonstandard directory - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -_ACEOF -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - ac_popdir=`pwd` - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d $ac_dir || continue - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - cd $ac_dir - # Check for guested configure; otherwise get Cygnus style configure. - if test -f $ac_srcdir/configure.gnu; then - echo - $SHELL $ac_srcdir/configure.gnu --help=recursive - elif test -f $ac_srcdir/configure; then - echo - $SHELL $ac_srcdir/configure --help=recursive - elif test -f $ac_srcdir/configure.ac || - test -f $ac_srcdir/configure.in; then - echo - $ac_configure --help - else - echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi - cd $ac_popdir - done -fi - -test -n "$ac_init_help" && exit 0 -if $ac_init_version; then - cat <<\_ACEOF -qdbm configure 1.8.77 -generated by GNU Autoconf 2.59 - -Copyright (C) 2003 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit 0 -fi -exec 5>config.log -cat >&5 <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by qdbm $as_me 1.8.77, which was -generated by GNU Autoconf 2.59. Invocation command line was - - $ $0 $@ - -_ACEOF -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -hostinfo = `(hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - echo "PATH: $as_dir" -done - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_sep= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; - 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" - # Get rid of the leading space. - ac_sep=" " - ;; - esac - done -done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Be sure not to use single quotes in there, as some shells, -# such as our DU 5.0 friend, will then `close' the trap. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - cat <<\_ASBOX -## ---------------- ## -## Cache variables. ## -## ---------------- ## -_ASBOX - echo - # The following way of writing the cache mishandles newlines in values, -{ - (set) 2>&1 | - case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in - *ac_space=\ *) - sed -n \ - "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" - ;; - *) - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} - echo - - cat <<\_ASBOX -## ----------------- ## -## Output variables. ## -## ----------------- ## -_ASBOX - echo - for ac_var in $ac_subst_vars - do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" - done | sort - echo - - if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------- ## -## Output files. ## -## ------------- ## -_ASBOX - echo - for ac_var in $ac_subst_files - do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" - done | sort - echo - fi - - if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## -## confdefs.h. ## -## ----------- ## -_ASBOX - echo - sed "/^$/d" confdefs.h | sort - echo - fi - test "$ac_signal" != 0 && - echo "$as_me: caught signal $ac_signal" - echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core && - rm -rf conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status - ' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo >confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer explicitly selected file to automatically selected ones. -if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi -fi -for ac_site_file in $CONFIG_SITE; do - if test -r "$ac_site_file"; then - { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 -echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . $cache_file;; - *) . ./$cache_file;; - esac - fi -else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in `(set) 2>&1 | - sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val="\$ac_cv_env_${ac_var}_value" - eval ac_new_val="\$ac_env_${ac_var}_value" - case $ac_old_set,$ac_new_set in - set,) - { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 -echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 -echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 -echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 -echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Export variables -LIBVER=14 -LIBREV=13 -TARGETS="all" -MYDEFS="" -MYOPTS="" -MGWLIBS="" -LD="ld" -AR="ar" - -# Building paths -pathtmp="$PATH" -PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" -PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" -LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" -LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" -CPATH="$HOME/include:/usr/local/include:$CPATH" -export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH - - - -#================================================================ -# Options -#================================================================ - - -# Internal variables -enables="" -ispthread="" -iszlib="" -isiconv="" -isnowarn="" - -# Debug mode -# Check whether --enable-debug or --disable-debug was given. -if test "${enable_debug+set}" = set; then - enableval="$enable_debug" - -fi; -if test "$enable_debug" = "yes" -then - TARGETS="debug" - enables="$enables (debug)" -fi - -# Developping mode -# Check whether --enable-devel or --disable-devel was given. -if test "${enable_devel+set}" = set; then - enableval="$enable_devel" - -fi; -if test "$enable_devel" = "yes" -then - TARGETS="devel" - enables="$enables (devel)" -fi - -# Stable mode -# Check whether --enable-stable or --disable-stable was given. -if test "${enable_stable+set}" = set; then - enableval="$enable_stable" - -fi; -if test "$enable_stable" = "yes" -then - TARGETS="stable" - enables="$enables (stable)" -fi - -# Enable POSIX thread -# Check whether --enable-pthread or --disable-pthread was given. -if test "${enable_pthread+set}" = set; then - enableval="$enable_pthread" - -fi; -if test "$enable_pthread" = "yes" -then - MYDEFS="$MYDEFS -DMYPTHREAD" - enables="$enables (pthread)" - ispthread="yes" -fi - -# Disable file locking -# Check whether --enable-lock or --disable-lock was given. -if test "${enable_lock+set}" = set; then - enableval="$enable_lock" - -fi; -if test "$enable_lock" = "no" -then - MYDEFS="$MYDEFS -DMYNOLOCK" - enables="$enables (no-lock)" -fi - -# Disable memory mapping -# Check whether --enable-mmap or --disable-mmap was given. -if test "${enable_mmap+set}" = set; then - enableval="$enable_mmap" - -fi; -if test "$enable_mmap" = "no" -then - MYDEFS="$MYDEFS -DMYNOMMAP" - enables="$enables (no-mmap)" -fi - -# Enable ZLIB compression -# Check whether --enable-zlib or --disable-zlib was given. -if test "${enable_zlib+set}" = set; then - enableval="$enable_zlib" - -fi; -if test "$enable_zlib" = "yes" -then - MYDEFS="$MYDEFS -DMYZLIB" - MGWLIBS="-lz $MGWLIBS" - enables="$enables (zlib)" - iszlib="yes" -fi - -# Enable LZO compression -# Check whether --enable-lzo or --disable-lzo was given. -if test "${enable_lzo+set}" = set; then - enableval="$enable_lzo" - -fi; -if test "$enable_lzo" = "yes" -then - MYDEFS="$MYDEFS -DMYLZO" - MGWLIBS="-llzo2 $MGWLIBS" - enables="$enables (lzo)" - islzo="yes" -fi - -# Enable BZIP2 compression -# Check whether --enable-bzip or --disable-bzip was given. -if test "${enable_bzip+set}" = set; then - enableval="$enable_bzip" - -fi; -if test "$enable_bzip" = "yes" -then - MYDEFS="$MYDEFS -DMYBZIP" - MGWLIBS="-lbz2 $MGWLIBS" - enables="$enables (bzip)" - isbzip="yes" -fi - -# Enable ICONV utilities -# Check whether --enable-iconv or --disable-iconv was given. -if test "${enable_iconv+set}" = set; then - enableval="$enable_iconv" - -fi; -if test "$enable_iconv" = "yes" -then - MYDEFS="$MYDEFS -DMYICONV" - MGWLIBS="-liconv $MGWLIBS" - enables="$enables (iconv)" - isiconv="yes" -fi - -# No warning configuration -# Check whether --enable-warn or --disable-warn was given. -if test "${enable_warn+set}" = set; then - enableval="$enable_warn" - -fi; -if test "$enable_warn" = "no" -then - isnowarn="yes" -fi - -# Messages -printf '#================================================================\n' -printf '# Configuring QDBM version %s%s.\n' "$PACKAGE_VERSION" "$enables" -printf '#================================================================\n' - - - -#================================================================ -# Checking Commands to Build with -#================================================================ - - -# C compiler -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_CC" && break -done - - CC=$ac_ct_CC -fi - -fi - - -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - -# Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 - (eval $ac_compiler --version &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 - (eval $ac_compiler -v &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 - (eval $ac_compiler -V &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 -echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 - (eval $ac_link_default) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Find the output, starting from the most likely. This scheme is -# not robust to junk in `.', hence go to wildcards (a.*) only as a last -# resort. - -# Be careful to initialize this variable, since it used to be cached. -# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. -ac_cv_exeext= -# b.out is created by i960 compilers. -for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) - ;; - conftest.$ac_ext ) - # This is the source file. - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool, - # but it would be cool to find out if it's true. Does anybody - # maintain Libtool? --akim. - export ac_cv_exeext - break;; - * ) - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } -fi - -ac_exeext=$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6 - -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - -rm -f a.out a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6 - -echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - export ac_cv_exeext - break;; - * ) break;; - esac -done -else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6 - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6 -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 -GCC=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -CFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_cc_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 -echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_prog_cc_stdc=no -ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std1 is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std1. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -# Don't try gcc -ansi; that turns off useful extensions and -# breaks some systems' header files. -# AIX -qlanglvl=ansi -# Ultrix and OSF/1 -std1 -# HP-UX 10.20 and later -Ae -# HP-UX older versions -Aa -D_HPUX_SOURCE -# SVR4 -Xc -D__EXTENSIONS__ -for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_stdc=$ac_arg -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext -done -rm -f conftest.$ac_ext conftest.$ac_objext -CC=$ac_save_CC - -fi - -case "x$ac_cv_prog_cc_stdc" in - x|xno) - echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6 ;; - *) - echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 - CC="$CC $ac_cv_prog_cc_stdc" ;; -esac - -# Some people use a C++ compiler to compile C. Since we use `exit', -# in C++ we need to declare it. In case someone uses the same compiler -# for both compiling C and C++ we need to have the C++ compiler decide -# the declaration of exit, since it's the most demanding environment. -cat >conftest.$ac_ext <<_ACEOF -#ifndef __cplusplus - choke me -#endif -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -#include -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h -fi - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -if test "$GCC" != "yes" -then - if test "$isnowarn" != "yes" - then - printf '#================================================================\n' 1>&2 - printf '# WARNING: GCC is required to build this package.\n' 1>&2 - printf '#================================================================\n' 1>&2 - fi -fi -if uname | egrep -i 'Linux' > /dev/null 2>&1 && - uname -m | egrep '(x|i)(3|4|5|6|7|8|9)?86' > /dev/null 2>&1 -then - MYOPTS="-minline-all-stringops" -fi -if uname | egrep -i 'SunOS' > /dev/null 2>&1 -then - MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" -fi -if uname | egrep -i 'BSD' > /dev/null 2>&1 -then - MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" -fi -if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1 -then - MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" -fi - -# Linker -printf 'checking for ld... ' -if which ld | grep '/ld$' > /dev/null 2>&1 -then - LD=`which ld` - printf '%s\n' "$LD" -else - printf 'no\n' - if test "$isnowarn" != "yes" - then - printf '#================================================================\n' 1>&2 - printf '# WARNING: ld is not found in PATH.\n' 1>&2 - printf '#================================================================\n' 1>&2 - fi -fi - -# Archiver -printf 'checking for ar... ' -if which ar | grep '/ar$' > /dev/null 2>&1 -then - AR=`which ar` - printf '%s\n' "$AR" -else - printf 'no\n' - if test "$isnowarn" != "yes" - then - printf '#================================================================\n' 1>&2 - printf '# WARNING: ar is not found in PATH.\n' 1>&2 - printf '#================================================================\n' 1>&2 - fi -fi - - - -#================================================================ -# Checking Libraries -#================================================================ - - -# Underlying libraries - - -echo "$as_me:$LINENO: checking for main in -lc" >&5 -echo $ECHO_N "checking for main in -lc... $ECHO_C" >&6 -if test "${ac_cv_lib_c_main+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lc $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - - -int -main () -{ -main (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_c_main=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_c_main=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_c_main" >&5 -echo "${ECHO_T}$ac_cv_lib_c_main" >&6 -if test $ac_cv_lib_c_main = yes; then - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBC 1 -_ACEOF - - LIBS="-lc $LIBS" - -fi - - -# for pthread -if test "$ispthread" = "yes" -then - -echo "$as_me:$LINENO: checking for main in -lpthread" >&5 -echo $ECHO_N "checking for main in -lpthread... $ECHO_C" >&6 -if test "${ac_cv_lib_pthread_main+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpthread $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - - -int -main () -{ -main (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_pthread_main=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_pthread_main=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_main" >&5 -echo "${ECHO_T}$ac_cv_lib_pthread_main" >&6 -if test $ac_cv_lib_pthread_main = yes; then - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBPTHREAD 1 -_ACEOF - - LIBS="-lpthread $LIBS" - -fi - -fi - -# for zlib -if test "$iszlib" = "yes" -then - -echo "$as_me:$LINENO: checking for main in -lz" >&5 -echo $ECHO_N "checking for main in -lz... $ECHO_C" >&6 -if test "${ac_cv_lib_z_main+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lz $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - - -int -main () -{ -main (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_z_main=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_z_main=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_z_main" >&5 -echo "${ECHO_T}$ac_cv_lib_z_main" >&6 -if test $ac_cv_lib_z_main = yes; then - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBZ 1 -_ACEOF - - LIBS="-lz $LIBS" - -fi - -fi - -# for lzo -if test "$islzo" = "yes" -then - -echo "$as_me:$LINENO: checking for main in -llzo2" >&5 -echo $ECHO_N "checking for main in -llzo2... $ECHO_C" >&6 -if test "${ac_cv_lib_lzo2_main+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-llzo2 $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - - -int -main () -{ -main (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_lzo2_main=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_lzo2_main=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_lzo2_main" >&5 -echo "${ECHO_T}$ac_cv_lib_lzo2_main" >&6 -if test $ac_cv_lib_lzo2_main = yes; then - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBLZO2 1 -_ACEOF - - LIBS="-llzo2 $LIBS" - -fi - -fi - -# for bzip -if test "$isbzip" = "yes" -then - -echo "$as_me:$LINENO: checking for main in -lbz2" >&5 -echo $ECHO_N "checking for main in -lbz2... $ECHO_C" >&6 -if test "${ac_cv_lib_bz2_main+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lbz2 $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - - -int -main () -{ -main (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_bz2_main=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_bz2_main=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_bz2_main" >&5 -echo "${ECHO_T}$ac_cv_lib_bz2_main" >&6 -if test $ac_cv_lib_bz2_main = yes; then - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBBZ2 1 -_ACEOF - - LIBS="-lbz2 $LIBS" - -fi - -fi - -# for iconv -if test "$isiconv" = "yes" -then - -echo "$as_me:$LINENO: checking for main in -liconv" >&5 -echo $ECHO_N "checking for main in -liconv... $ECHO_C" >&6 -if test "${ac_cv_lib_iconv_main+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-liconv $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - - -int -main () -{ -main (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_iconv_main=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_iconv_main=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_iconv_main" >&5 -echo "${ECHO_T}$ac_cv_lib_iconv_main" >&6 -if test $ac_cv_lib_iconv_main = yes; then - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBICONV 1 -_ACEOF - - LIBS="-liconv $LIBS" - -fi - -fi - -# For old BSDs -if test "$ispthread" = "yes" && uname -a | grep BSD > /dev/null && - test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a -then - LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'` -fi - -# Duplication of QDBM for C -echo "$as_me:$LINENO: checking for main in -lqdbm" >&5 -echo $ECHO_N "checking for main in -lqdbm... $ECHO_C" >&6 -if test "${ac_cv_lib_qdbm_main+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lqdbm $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - - -int -main () -{ -main (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_qdbm_main=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_qdbm_main=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_qdbm_main" >&5 -echo "${ECHO_T}$ac_cv_lib_qdbm_main" >&6 -if test $ac_cv_lib_qdbm_main = yes; then - if test "$isnowarn" != "yes" - then - printf '#================================================================\n' 1>&2 - printf '# WARNING: The existing library was detected.\n' 1>&2 - printf '#================================================================\n' 1>&2 - fi - -fi - - - - -#================================================================ -# Generic Settings -#================================================================ - - -# Export variables - - - - - - - - - - - -# Targets - ac_config_files="$ac_config_files Makefile LTmakefile qdbm.spec qdbm.pc" -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -{ - (set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} | - sed ' - t clear - : clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - : end' >>confcache -if diff $cache_file confcache >/dev/null 2>&1; then :; else - if test -w $cache_file; then - test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" - cat confcache >$cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/; -s/:*\${srcdir}:*/:/; -s/:*@srcdir@:*/:/; -s/^\([^=]*=[ ]*\):*/\1/; -s/:*$//; -s/^[^=]*=[ ]*$//; -}' -fi - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then we branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -cat >confdef2opt.sed <<\_ACEOF -t clear -: clear -s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g -t quote -s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g -t quote -d -: quote -s,[ `~#$^&*(){}\\|;'"<>?],\\&,g -s,\[,\\&,g -s,\],\\&,g -s,\$,$$,g -p -_ACEOF -# We use echo to avoid assuming a particular line-breaking character. -# The extra dot is to prevent the shell from consuming trailing -# line-breaks from the sub-command output. A line-break within -# single-quotes doesn't work because, if this script is created in a -# platform that uses two characters for line-breaks (e.g., DOS), tr -# would break. -ac_LF_and_DOT=`echo; echo .` -DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` -rm -f confdef2opt.sed - - -ac_libobjs= -ac_ltlibobjs= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_i=`echo "$ac_i" | - sed 's/\$U\././;s/\.o$//;s/\.obj$//'` - # 2. Add them. - ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: ${CONFIG_STATUS=./config.status} -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 -echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi -DUALCASE=1; export DUALCASE # for MKS sh - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - - -# PATH needs CR, and LINENO needs CR and PATH. -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 -echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 -echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; -esac - -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else - as_ln_s='ln -s' - fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.file - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_executable_p="test -f" - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - -exec 6>&1 - -# Open the log real soon, to keep \$[0] and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. Logging --version etc. is OK. -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX -} >&5 -cat >&5 <<_CSEOF - -This file was extended by qdbm $as_me 1.8.77, which was -generated by GNU Autoconf 2.59. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -_CSEOF -echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 -echo >&5 -_ACEOF - -# Files that config.status was made for. -if test -n "$ac_config_files"; then - echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_headers"; then - echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_links"; then - echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_commands"; then - echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS -fi - -cat >>$CONFIG_STATUS <<\_ACEOF - -ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. - -Usage: $0 [OPTIONS] [FILE]... - - -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Report bugs to ." -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF -ac_cs_version="\\ -qdbm config.status 1.8.77 -configured by $0, generated by GNU Autoconf 2.59, - with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" - -Copyright (C) 2003 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." -srcdir=$srcdir -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If no file are specified by the user, then we need to provide default -# value. By we need to know if files were specified by the user. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=*) - ac_option=`expr "x$1" : 'x\([^=]*\)='` - ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` - ac_shift=: - ;; - -*) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - *) # This is not an option, so the user has probably given explicit - # arguments. - ac_option=$1 - ac_need_defaults=false;; - esac - - case $ac_option in - # Handling of the options. -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --vers* | -V ) - echo "$ac_cs_version"; exit 0 ;; - --he | --h) - # Conflict between --help and --header - { { echo "$as_me:$LINENO: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; };; - --help | --hel | -h ) - echo "$ac_cs_usage"; exit 0 ;; - --debug | --d* | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - CONFIG_FILES="$CONFIG_FILES $ac_optarg" - ac_need_defaults=false;; - --header | --heade | --head | --hea ) - $ac_shift - CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" - ac_need_defaults=false;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; } ;; - - *) ac_config_targets="$ac_config_targets $1" ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -if \$ac_cs_recheck; then - echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 - exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion -fi - -_ACEOF - - - - - -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_config_target in $ac_config_targets -do - case "$ac_config_target" in - # Handling of arguments. - "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "LTmakefile" ) CONFIG_FILES="$CONFIG_FILES LTmakefile" ;; - "qdbm.spec" ) CONFIG_FILES="$CONFIG_FILES qdbm.spec" ;; - "qdbm.pc" ) CONFIG_FILES="$CONFIG_FILES qdbm.pc" ;; - *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; - esac -done - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason to put it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Create a temporary directory, and hook for its removal unless debugging. -$debug || -{ - trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 -} - -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=./confstat$$-$RANDOM - (umask 077 && mkdir $tmp) -} || -{ - echo "$me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } -} - -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF - -# -# CONFIG_FILES section. -# - -# No need to generate the scripts if there are no CONFIG_FILES. -# This happens for instance when ./config.status config.h -if test -n "\$CONFIG_FILES"; then - # Protect against being on the right side of a sed subst in config.status. - sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; - s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF -s, at SHELL@,$SHELL,;t t -s, at PATH_SEPARATOR@,$PATH_SEPARATOR,;t t -s, at PACKAGE_NAME@,$PACKAGE_NAME,;t t -s, at PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t -s, at PACKAGE_VERSION@,$PACKAGE_VERSION,;t t -s, at PACKAGE_STRING@,$PACKAGE_STRING,;t t -s, at PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t -s, at exec_prefix@,$exec_prefix,;t t -s, at prefix@,$prefix,;t t -s, at program_transform_name@,$program_transform_name,;t t -s, at bindir@,$bindir,;t t -s, at sbindir@,$sbindir,;t t -s, at libexecdir@,$libexecdir,;t t -s, at datadir@,$datadir,;t t -s, at sysconfdir@,$sysconfdir,;t t -s, at sharedstatedir@,$sharedstatedir,;t t -s, at localstatedir@,$localstatedir,;t t -s, at libdir@,$libdir,;t t -s, at includedir@,$includedir,;t t -s, at oldincludedir@,$oldincludedir,;t t -s, at infodir@,$infodir,;t t -s, at mandir@,$mandir,;t t -s, at build_alias@,$build_alias,;t t -s, at host_alias@,$host_alias,;t t -s, at target_alias@,$target_alias,;t t -s, at DEFS@,$DEFS,;t t -s, at ECHO_C@,$ECHO_C,;t t -s, at ECHO_N@,$ECHO_N,;t t -s, at ECHO_T@,$ECHO_T,;t t -s, at LIBS@,$LIBS,;t t -s, at CC@,$CC,;t t -s, at CFLAGS@,$CFLAGS,;t t -s, at LDFLAGS@,$LDFLAGS,;t t -s, at CPPFLAGS@,$CPPFLAGS,;t t -s, at ac_ct_CC@,$ac_ct_CC,;t t -s, at EXEEXT@,$EXEEXT,;t t -s, at OBJEXT@,$OBJEXT,;t t -s, at LIBVER@,$LIBVER,;t t -s, at LIBREV@,$LIBREV,;t t -s, at TARGETS@,$TARGETS,;t t -s, at MYDEFS@,$MYDEFS,;t t -s, at MYOPTS@,$MYOPTS,;t t -s, at MGWLIBS@,$MGWLIBS,;t t -s, at LD@,$LD,;t t -s, at AR@,$AR,;t t -s, at LIBOBJS@,$LIBOBJS,;t t -s, at LTLIBOBJS@,$LTLIBOBJS,;t t -CEOF - -_ACEOF - - cat >>$CONFIG_STATUS <<\_ACEOF - # Split the substitutions into bite-sized pieces for seds with - # small command number limits, like on Digital OSF/1 and HP-UX. - ac_max_sed_lines=48 - ac_sed_frag=1 # Number of current file. - ac_beg=1 # First line for current file. - ac_end=$ac_max_sed_lines # Line after last line for current file. - ac_more_lines=: - ac_sed_cmds= - while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - else - sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - fi - if test ! -s $tmp/subs.frag; then - ac_more_lines=false - else - # The purpose of the label and of the branching condition is to - # speed up the sed processing (if there are no `@' at all, there - # is no need to browse any of the substitutions). - # These are the two extra sed commands mentioned above. - (echo ':t - /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" - else - ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" - fi - ac_sed_frag=`expr $ac_sed_frag + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_lines` - fi - done - if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat - fi -fi # test -n "$CONFIG_FILES" - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; - esac - - # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. - ac_dir=`(dirname "$ac_file") 2>/dev/null || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - - - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - configure_input= - else - configure_input="$ac_file. " - fi - configure_input=$configure_input"Generated from `echo $ac_file_in | - sed 's,.*/,,'` by configure." - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - sed "$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s, at configure_input@,$configure_input,;t t -s, at srcdir@,$ac_srcdir,;t t -s, at abs_srcdir@,$ac_abs_srcdir,;t t -s, at top_srcdir@,$ac_top_srcdir,;t t -s, at abs_top_srcdir@,$ac_abs_top_srcdir,;t t -s, at builddir@,$ac_builddir,;t t -s, at abs_builddir@,$ac_abs_builddir,;t t -s, at top_builddir@,$ac_top_builddir,;t t -s, at abs_top_builddir@,$ac_abs_top_builddir,;t t -" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out - rm -f $tmp/stdin - if test x"$ac_file" != x-; then - mv $tmp/out $ac_file - else - cat $tmp/out - rm -f $tmp/out - fi - -done -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF - -{ (exit 0); exit 0; } -_ACEOF -chmod +x $CONFIG_STATUS -ac_clean_files=$ac_clean_files_save - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } -fi - - -# Messages -printf '#================================================================\n' -printf '# Ready to make.\n' -printf '#================================================================\n' - - - -# END OF FILE Copied: box/trunk/qdbm/configure (from rev 2716, box/trunk/qdbm/configure) =================================================================== --- box/trunk/qdbm/configure (rev 0) +++ box/trunk/qdbm/configure 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,3913 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59 for qdbm 1.8.77. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='qdbm' +PACKAGE_TARNAME='qdbm' +PACKAGE_VERSION='1.8.77' +PACKAGE_STRING='qdbm 1.8.77' +PACKAGE_BUGREPORT='' + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LIBVER LIBREV TARGETS MYDEFS MYOPTS MGWLIBS LD AR LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures qdbm 1.8.77 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of qdbm 1.8.77:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-debug build for debugging + --enable-devel build for development + --enable-stable build for stable release + --enable-pthread use POSIX thread and make APIs thread-safe + --disable-lock build for environments without file locking + --disable-mmap build for environments without memory mapping + --enable-zlib feature ZLIB for B+ tree and inverted index + --enable-lzo feature LZO for B+ tree and inverted index + --enable-bzip feature BZIP2 for B+ tree and inverted index + --enable-iconv feature ICONV utilities + --disable-warn hide warnings in the configuration + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +qdbm configure 1.8.77 +generated by GNU Autoconf 2.59 + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by qdbm $as_me 1.8.77, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Export variables +LIBVER=14 +LIBREV=13 +TARGETS="all" +MYDEFS="" +MYOPTS="" +MGWLIBS="" +LD="ld" +AR="ar" + +# Building paths +pathtmp="$PATH" +PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" +PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" +LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" +LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" +CPATH="$HOME/include:/usr/local/include:$CPATH" +export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH + + + +#================================================================ +# Options +#================================================================ + + +# Internal variables +enables="" +ispthread="" +iszlib="" +isiconv="" +isnowarn="" + +# Debug mode +# Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + +fi; +if test "$enable_debug" = "yes" +then + TARGETS="debug" + enables="$enables (debug)" +fi + +# Developping mode +# Check whether --enable-devel or --disable-devel was given. +if test "${enable_devel+set}" = set; then + enableval="$enable_devel" + +fi; +if test "$enable_devel" = "yes" +then + TARGETS="devel" + enables="$enables (devel)" +fi + +# Stable mode +# Check whether --enable-stable or --disable-stable was given. +if test "${enable_stable+set}" = set; then + enableval="$enable_stable" + +fi; +if test "$enable_stable" = "yes" +then + TARGETS="stable" + enables="$enables (stable)" +fi + +# Enable POSIX thread +# Check whether --enable-pthread or --disable-pthread was given. +if test "${enable_pthread+set}" = set; then + enableval="$enable_pthread" + +fi; +if test "$enable_pthread" = "yes" +then + MYDEFS="$MYDEFS -DMYPTHREAD" + enables="$enables (pthread)" + ispthread="yes" +fi + +# Disable file locking +# Check whether --enable-lock or --disable-lock was given. +if test "${enable_lock+set}" = set; then + enableval="$enable_lock" + +fi; +if test "$enable_lock" = "no" +then + MYDEFS="$MYDEFS -DMYNOLOCK" + enables="$enables (no-lock)" +fi + +# Disable memory mapping +# Check whether --enable-mmap or --disable-mmap was given. +if test "${enable_mmap+set}" = set; then + enableval="$enable_mmap" + +fi; +if test "$enable_mmap" = "no" +then + MYDEFS="$MYDEFS -DMYNOMMAP" + enables="$enables (no-mmap)" +fi + +# Enable ZLIB compression +# Check whether --enable-zlib or --disable-zlib was given. +if test "${enable_zlib+set}" = set; then + enableval="$enable_zlib" + +fi; +if test "$enable_zlib" = "yes" +then + MYDEFS="$MYDEFS -DMYZLIB" + MGWLIBS="-lz $MGWLIBS" + enables="$enables (zlib)" + iszlib="yes" +fi + +# Enable LZO compression +# Check whether --enable-lzo or --disable-lzo was given. +if test "${enable_lzo+set}" = set; then + enableval="$enable_lzo" + +fi; +if test "$enable_lzo" = "yes" +then + MYDEFS="$MYDEFS -DMYLZO" + MGWLIBS="-llzo2 $MGWLIBS" + enables="$enables (lzo)" + islzo="yes" +fi + +# Enable BZIP2 compression +# Check whether --enable-bzip or --disable-bzip was given. +if test "${enable_bzip+set}" = set; then + enableval="$enable_bzip" + +fi; +if test "$enable_bzip" = "yes" +then + MYDEFS="$MYDEFS -DMYBZIP" + MGWLIBS="-lbz2 $MGWLIBS" + enables="$enables (bzip)" + isbzip="yes" +fi + +# Enable ICONV utilities +# Check whether --enable-iconv or --disable-iconv was given. +if test "${enable_iconv+set}" = set; then + enableval="$enable_iconv" + +fi; +if test "$enable_iconv" = "yes" +then + MYDEFS="$MYDEFS -DMYICONV" + MGWLIBS="-liconv $MGWLIBS" + enables="$enables (iconv)" + isiconv="yes" +fi + +# No warning configuration +# Check whether --enable-warn or --disable-warn was given. +if test "${enable_warn+set}" = set; then + enableval="$enable_warn" + +fi; +if test "$enable_warn" = "no" +then + isnowarn="yes" +fi + +# Messages +printf '#================================================================\n' +printf '# Configuring QDBM version %s%s.\n' "$PACKAGE_VERSION" "$enables" +printf '#================================================================\n' + + + +#================================================================ +# Checking Commands to Build with +#================================================================ + + +# C compiler +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +if test "$GCC" != "yes" +then + if test "$isnowarn" != "yes" + then + printf '#================================================================\n' 1>&2 + printf '# WARNING: GCC is required to build this package.\n' 1>&2 + printf '#================================================================\n' 1>&2 + fi +fi +if uname | egrep -i 'Linux' > /dev/null 2>&1 && + uname -m | egrep '(x|i)(3|4|5|6|7|8|9)?86' > /dev/null 2>&1 +then + MYOPTS="-minline-all-stringops" +fi +if uname | egrep -i 'SunOS' > /dev/null 2>&1 +then + MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" +fi +if uname | egrep -i 'BSD' > /dev/null 2>&1 +then + MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" +fi +if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1 +then + MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" +fi + +# Linker +printf 'checking for ld... ' +if which ld | grep '/ld$' > /dev/null 2>&1 +then + LD=`which ld` + printf '%s\n' "$LD" +else + printf 'no\n' + if test "$isnowarn" != "yes" + then + printf '#================================================================\n' 1>&2 + printf '# WARNING: ld is not found in PATH.\n' 1>&2 + printf '#================================================================\n' 1>&2 + fi +fi + +# Archiver +printf 'checking for ar... ' +if which ar | grep '/ar$' > /dev/null 2>&1 +then + AR=`which ar` + printf '%s\n' "$AR" +else + printf 'no\n' + if test "$isnowarn" != "yes" + then + printf '#================================================================\n' 1>&2 + printf '# WARNING: ar is not found in PATH.\n' 1>&2 + printf '#================================================================\n' 1>&2 + fi +fi + + + +#================================================================ +# Checking Libraries +#================================================================ + + +# Underlying libraries + + +echo "$as_me:$LINENO: checking for main in -lc" >&5 +echo $ECHO_N "checking for main in -lc... $ECHO_C" >&6 +if test "${ac_cv_lib_c_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_c_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_c_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_c_main" >&5 +echo "${ECHO_T}$ac_cv_lib_c_main" >&6 +if test $ac_cv_lib_c_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBC 1 +_ACEOF + + LIBS="-lc $LIBS" + +fi + + +# for pthread +if test "$ispthread" = "yes" +then + +echo "$as_me:$LINENO: checking for main in -lpthread" >&5 +echo $ECHO_N "checking for main in -lpthread... $ECHO_C" >&6 +if test "${ac_cv_lib_pthread_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthread_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_main" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread_main" >&6 +if test $ac_cv_lib_pthread_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +fi + +fi + +# for zlib +if test "$iszlib" = "yes" +then + +echo "$as_me:$LINENO: checking for main in -lz" >&5 +echo $ECHO_N "checking for main in -lz... $ECHO_C" >&6 +if test "${ac_cv_lib_z_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_z_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_z_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_z_main" >&5 +echo "${ECHO_T}$ac_cv_lib_z_main" >&6 +if test $ac_cv_lib_z_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +fi + +fi + +# for lzo +if test "$islzo" = "yes" +then + +echo "$as_me:$LINENO: checking for main in -llzo2" >&5 +echo $ECHO_N "checking for main in -llzo2... $ECHO_C" >&6 +if test "${ac_cv_lib_lzo2_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzo2 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_lzo2_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_lzo2_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_lzo2_main" >&5 +echo "${ECHO_T}$ac_cv_lib_lzo2_main" >&6 +if test $ac_cv_lib_lzo2_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLZO2 1 +_ACEOF + + LIBS="-llzo2 $LIBS" + +fi + +fi + +# for bzip +if test "$isbzip" = "yes" +then + +echo "$as_me:$LINENO: checking for main in -lbz2" >&5 +echo $ECHO_N "checking for main in -lbz2... $ECHO_C" >&6 +if test "${ac_cv_lib_bz2_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbz2 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_bz2_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_bz2_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_bz2_main" >&5 +echo "${ECHO_T}$ac_cv_lib_bz2_main" >&6 +if test $ac_cv_lib_bz2_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBBZ2 1 +_ACEOF + + LIBS="-lbz2 $LIBS" + +fi + +fi + +# for iconv +if test "$isiconv" = "yes" +then + +echo "$as_me:$LINENO: checking for main in -liconv" >&5 +echo $ECHO_N "checking for main in -liconv... $ECHO_C" >&6 +if test "${ac_cv_lib_iconv_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-liconv $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_iconv_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_iconv_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_iconv_main" >&5 +echo "${ECHO_T}$ac_cv_lib_iconv_main" >&6 +if test $ac_cv_lib_iconv_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBICONV 1 +_ACEOF + + LIBS="-liconv $LIBS" + +fi + +fi + +# For old BSDs +if test "$ispthread" = "yes" && uname -a | grep BSD > /dev/null && + test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a +then + LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'` +fi + +# Duplication of QDBM for C +echo "$as_me:$LINENO: checking for main in -lqdbm" >&5 +echo $ECHO_N "checking for main in -lqdbm... $ECHO_C" >&6 +if test "${ac_cv_lib_qdbm_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lqdbm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_qdbm_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_qdbm_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_qdbm_main" >&5 +echo "${ECHO_T}$ac_cv_lib_qdbm_main" >&6 +if test $ac_cv_lib_qdbm_main = yes; then + if test "$isnowarn" != "yes" + then + printf '#================================================================\n' 1>&2 + printf '# WARNING: The existing library was detected.\n' 1>&2 + printf '#================================================================\n' 1>&2 + fi + +fi + + + + +#================================================================ +# Generic Settings +#================================================================ + + +# Export variables + + + + + + + + + + + +# Targets + ac_config_files="$ac_config_files Makefile LTmakefile qdbm.spec qdbm.pc" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by qdbm $as_me 1.8.77, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +qdbm config.status 1.8.77 +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "LTmakefile" ) CONFIG_FILES="$CONFIG_FILES LTmakefile" ;; + "qdbm.spec" ) CONFIG_FILES="$CONFIG_FILES qdbm.spec" ;; + "qdbm.pc" ) CONFIG_FILES="$CONFIG_FILES qdbm.pc" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s, at SHELL@,$SHELL,;t t +s, at PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s, at PACKAGE_NAME@,$PACKAGE_NAME,;t t +s, at PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s, at PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s, at PACKAGE_STRING@,$PACKAGE_STRING,;t t +s, at PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s, at exec_prefix@,$exec_prefix,;t t +s, at prefix@,$prefix,;t t +s, at program_transform_name@,$program_transform_name,;t t +s, at bindir@,$bindir,;t t +s, at sbindir@,$sbindir,;t t +s, at libexecdir@,$libexecdir,;t t +s, at datadir@,$datadir,;t t +s, at sysconfdir@,$sysconfdir,;t t +s, at sharedstatedir@,$sharedstatedir,;t t +s, at localstatedir@,$localstatedir,;t t +s, at libdir@,$libdir,;t t +s, at includedir@,$includedir,;t t +s, at oldincludedir@,$oldincludedir,;t t +s, at infodir@,$infodir,;t t +s, at mandir@,$mandir,;t t +s, at build_alias@,$build_alias,;t t +s, at host_alias@,$host_alias,;t t +s, at target_alias@,$target_alias,;t t +s, at DEFS@,$DEFS,;t t +s, at ECHO_C@,$ECHO_C,;t t +s, at ECHO_N@,$ECHO_N,;t t +s, at ECHO_T@,$ECHO_T,;t t +s, at LIBS@,$LIBS,;t t +s, at CC@,$CC,;t t +s, at CFLAGS@,$CFLAGS,;t t +s, at LDFLAGS@,$LDFLAGS,;t t +s, at CPPFLAGS@,$CPPFLAGS,;t t +s, at ac_ct_CC@,$ac_ct_CC,;t t +s, at EXEEXT@,$EXEEXT,;t t +s, at OBJEXT@,$OBJEXT,;t t +s, at LIBVER@,$LIBVER,;t t +s, at LIBREV@,$LIBREV,;t t +s, at TARGETS@,$TARGETS,;t t +s, at MYDEFS@,$MYDEFS,;t t +s, at MYOPTS@,$MYOPTS,;t t +s, at MGWLIBS@,$MGWLIBS,;t t +s, at LD@,$LD,;t t +s, at AR@,$AR,;t t +s, at LIBOBJS@,$LIBOBJS,;t t +s, at LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s, at configure_input@,$configure_input,;t t +s, at srcdir@,$ac_srcdir,;t t +s, at abs_srcdir@,$ac_abs_srcdir,;t t +s, at top_srcdir@,$ac_top_srcdir,;t t +s, at abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s, at builddir@,$ac_builddir,;t t +s, at abs_builddir@,$ac_abs_builddir,;t t +s, at top_builddir@,$ac_top_builddir,;t t +s, at abs_top_builddir@,$ac_abs_top_builddir,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + +# Messages +printf '#================================================================\n' +printf '# Ready to make.\n' +printf '#================================================================\n' + + + +# END OF FILE Deleted: box/trunk/qdbm/configure.in =================================================================== --- box/trunk/qdbm/configure.in 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/configure.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,312 +0,0 @@ -# Source of configuration for QDBM - - - -#================================================================ -# Generic Settings -#================================================================ - - -# Targets -AC_INIT(qdbm, 1.8.77) - -# Export variables -LIBVER=14 -LIBREV=13 -TARGETS="all" -MYDEFS="" -MYOPTS="" -MGWLIBS="" -LD="ld" -AR="ar" - -# Building paths -pathtmp="$PATH" -PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" -PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" -LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" -LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" -CPATH="$HOME/include:/usr/local/include:$CPATH" -export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH - - - -#================================================================ -# Options -#================================================================ - - -# Internal variables -enables="" -ispthread="" -iszlib="" -isiconv="" -isnowarn="" - -# Debug mode -AC_ARG_ENABLE(debug, - AC_HELP_STRING([--enable-debug], [build for debugging])) -if test "$enable_debug" = "yes" -then - TARGETS="debug" - enables="$enables (debug)" -fi - -# Developping mode -AC_ARG_ENABLE(devel, - AC_HELP_STRING([--enable-devel], [build for development])) -if test "$enable_devel" = "yes" -then - TARGETS="devel" - enables="$enables (devel)" -fi - -# Stable mode -AC_ARG_ENABLE(stable, - AC_HELP_STRING([--enable-stable], [build for stable release])) -if test "$enable_stable" = "yes" -then - TARGETS="stable" - enables="$enables (stable)" -fi - -# Enable POSIX thread -AC_ARG_ENABLE(pthread, - AC_HELP_STRING([--enable-pthread], [use POSIX thread and make APIs thread-safe])) -if test "$enable_pthread" = "yes" -then - MYDEFS="$MYDEFS -DMYPTHREAD" - enables="$enables (pthread)" - ispthread="yes" -fi - -# Disable file locking -AC_ARG_ENABLE(lock, - AC_HELP_STRING([--disable-lock], [build for environments without file locking])) -if test "$enable_lock" = "no" -then - MYDEFS="$MYDEFS -DMYNOLOCK" - enables="$enables (no-lock)" -fi - -# Disable memory mapping -AC_ARG_ENABLE(mmap, - AC_HELP_STRING([--disable-mmap], [build for environments without memory mapping])) -if test "$enable_mmap" = "no" -then - MYDEFS="$MYDEFS -DMYNOMMAP" - enables="$enables (no-mmap)" -fi - -# Enable ZLIB compression -AC_ARG_ENABLE(zlib, - AC_HELP_STRING([--enable-zlib], [feature ZLIB for B+ tree and inverted index])) -if test "$enable_zlib" = "yes" -then - MYDEFS="$MYDEFS -DMYZLIB" - MGWLIBS="-lz $MGWLIBS" - enables="$enables (zlib)" - iszlib="yes" -fi - -# Enable LZO compression -AC_ARG_ENABLE(lzo, - AC_HELP_STRING([--enable-lzo], [feature LZO for B+ tree and inverted index])) -if test "$enable_lzo" = "yes" -then - MYDEFS="$MYDEFS -DMYLZO" - MGWLIBS="-llzo2 $MGWLIBS" - enables="$enables (lzo)" - islzo="yes" -fi - -# Enable BZIP2 compression -AC_ARG_ENABLE(bzip, - AC_HELP_STRING([--enable-bzip], [feature BZIP2 for B+ tree and inverted index])) -if test "$enable_bzip" = "yes" -then - MYDEFS="$MYDEFS -DMYBZIP" - MGWLIBS="-lbz2 $MGWLIBS" - enables="$enables (bzip)" - isbzip="yes" -fi - -# Enable ICONV utilities -AC_ARG_ENABLE(iconv, - AC_HELP_STRING([--enable-iconv], [feature ICONV utilities])) -if test "$enable_iconv" = "yes" -then - MYDEFS="$MYDEFS -DMYICONV" - MGWLIBS="-liconv $MGWLIBS" - enables="$enables (iconv)" - isiconv="yes" -fi - -# No warning configuration -AC_ARG_ENABLE(warn, - AC_HELP_STRING([--disable-warn], [hide warnings in the configuration])) -if test "$enable_warn" = "no" -then - isnowarn="yes" -fi - -# Messages -printf '#================================================================\n' -printf '# Configuring QDBM version %s%s.\n' "$PACKAGE_VERSION" "$enables" -printf '#================================================================\n' - - - -#================================================================ -# Checking Commands to Build with -#================================================================ - - -# C compiler -AC_PROG_CC -if test "$GCC" != "yes" -then - if test "$isnowarn" != "yes" - then - printf '#================================================================\n' 1>&2 - printf '# WARNING: GCC is required to build this package.\n' 1>&2 - printf '#================================================================\n' 1>&2 - fi -fi -if uname | egrep -i 'Linux' > /dev/null 2>&1 && - uname -m | egrep '(x|i)(3|4|5|6|7|8|9)?86' > /dev/null 2>&1 -then - MYOPTS="-minline-all-stringops" -fi -if uname | egrep -i 'SunOS' > /dev/null 2>&1 -then - MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" -fi -if uname | egrep -i 'BSD' > /dev/null 2>&1 -then - MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" -fi -if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1 -then - MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" -fi - -# Linker -printf 'checking for ld... ' -if which ld | grep '/ld$' > /dev/null 2>&1 -then - LD=`which ld` - printf '%s\n' "$LD" -else - printf 'no\n' - if test "$isnowarn" != "yes" - then - printf '#================================================================\n' 1>&2 - printf '# WARNING: ld is not found in PATH.\n' 1>&2 - printf '#================================================================\n' 1>&2 - fi -fi - -# Archiver -printf 'checking for ar... ' -if which ar | grep '/ar$' > /dev/null 2>&1 -then - AR=`which ar` - printf '%s\n' "$AR" -else - printf 'no\n' - if test "$isnowarn" != "yes" - then - printf '#================================================================\n' 1>&2 - printf '# WARNING: ar is not found in PATH.\n' 1>&2 - printf '#================================================================\n' 1>&2 - fi -fi - - - -#================================================================ -# Checking Libraries -#================================================================ - - -# Underlying libraries -AC_CHECK_LIB(c, main) - -# for pthread -if test "$ispthread" = "yes" -then - AC_CHECK_LIB(pthread, main) -fi - -# for zlib -if test "$iszlib" = "yes" -then - AC_CHECK_LIB(z, main) -fi - -# for lzo -if test "$islzo" = "yes" -then - AC_CHECK_LIB(lzo2, main) -fi - -# for bzip -if test "$isbzip" = "yes" -then - AC_CHECK_LIB(bz2, main) -fi - -# for iconv -if test "$isiconv" = "yes" -then - AC_CHECK_LIB(iconv, main) -fi - -# For old BSDs -if test "$ispthread" = "yes" && uname -a | grep BSD > /dev/null && - test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a -then - LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'` -fi - -# Duplication of QDBM for C -AC_CHECK_LIB(qdbm, main, - if test "$isnowarn" != "yes" - then - printf '#================================================================\n' 1>&2 - printf '# WARNING: The existing library was detected.\n' 1>&2 - printf '#================================================================\n' 1>&2 - fi -) - - - -#================================================================ -# Generic Settings -#================================================================ - - -# Export variables -AC_SUBST(LIBVER) -AC_SUBST(LIBREV) -AC_SUBST(TARGETS) -AC_SUBST(MYDEFS) -AC_SUBST(MYOPTS) -AC_SUBST(MGWLIBS) -AC_SUBST(LD) -AC_SUBST(AR) -AC_SUBST(CPPFLAGS) -AC_SUBST(LDFLAGS) - -# Targets -AC_OUTPUT(Makefile LTmakefile qdbm.spec qdbm.pc) - -# Messages -printf '#================================================================\n' -printf '# Ready to make.\n' -printf '#================================================================\n' - - - -# END OF FILE Copied: box/trunk/qdbm/configure.in (from rev 2716, box/trunk/qdbm/configure.in) =================================================================== --- box/trunk/qdbm/configure.in (rev 0) +++ box/trunk/qdbm/configure.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,312 @@ +# Source of configuration for QDBM + + + +#================================================================ +# Generic Settings +#================================================================ + + +# Targets +AC_INIT(qdbm, 1.8.77) + +# Export variables +LIBVER=14 +LIBREV=13 +TARGETS="all" +MYDEFS="" +MYOPTS="" +MGWLIBS="" +LD="ld" +AR="ar" + +# Building paths +pathtmp="$PATH" +PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" +PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" +LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" +LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" +CPATH="$HOME/include:/usr/local/include:$CPATH" +export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH + + + +#================================================================ +# Options +#================================================================ + + +# Internal variables +enables="" +ispthread="" +iszlib="" +isiconv="" +isnowarn="" + +# Debug mode +AC_ARG_ENABLE(debug, + AC_HELP_STRING([--enable-debug], [build for debugging])) +if test "$enable_debug" = "yes" +then + TARGETS="debug" + enables="$enables (debug)" +fi + +# Developping mode +AC_ARG_ENABLE(devel, + AC_HELP_STRING([--enable-devel], [build for development])) +if test "$enable_devel" = "yes" +then + TARGETS="devel" + enables="$enables (devel)" +fi + +# Stable mode +AC_ARG_ENABLE(stable, + AC_HELP_STRING([--enable-stable], [build for stable release])) +if test "$enable_stable" = "yes" +then + TARGETS="stable" + enables="$enables (stable)" +fi + +# Enable POSIX thread +AC_ARG_ENABLE(pthread, + AC_HELP_STRING([--enable-pthread], [use POSIX thread and make APIs thread-safe])) +if test "$enable_pthread" = "yes" +then + MYDEFS="$MYDEFS -DMYPTHREAD" + enables="$enables (pthread)" + ispthread="yes" +fi + +# Disable file locking +AC_ARG_ENABLE(lock, + AC_HELP_STRING([--disable-lock], [build for environments without file locking])) +if test "$enable_lock" = "no" +then + MYDEFS="$MYDEFS -DMYNOLOCK" + enables="$enables (no-lock)" +fi + +# Disable memory mapping +AC_ARG_ENABLE(mmap, + AC_HELP_STRING([--disable-mmap], [build for environments without memory mapping])) +if test "$enable_mmap" = "no" +then + MYDEFS="$MYDEFS -DMYNOMMAP" + enables="$enables (no-mmap)" +fi + +# Enable ZLIB compression +AC_ARG_ENABLE(zlib, + AC_HELP_STRING([--enable-zlib], [feature ZLIB for B+ tree and inverted index])) +if test "$enable_zlib" = "yes" +then + MYDEFS="$MYDEFS -DMYZLIB" + MGWLIBS="-lz $MGWLIBS" + enables="$enables (zlib)" + iszlib="yes" +fi + +# Enable LZO compression +AC_ARG_ENABLE(lzo, + AC_HELP_STRING([--enable-lzo], [feature LZO for B+ tree and inverted index])) +if test "$enable_lzo" = "yes" +then + MYDEFS="$MYDEFS -DMYLZO" + MGWLIBS="-llzo2 $MGWLIBS" + enables="$enables (lzo)" + islzo="yes" +fi + +# Enable BZIP2 compression +AC_ARG_ENABLE(bzip, + AC_HELP_STRING([--enable-bzip], [feature BZIP2 for B+ tree and inverted index])) +if test "$enable_bzip" = "yes" +then + MYDEFS="$MYDEFS -DMYBZIP" + MGWLIBS="-lbz2 $MGWLIBS" + enables="$enables (bzip)" + isbzip="yes" +fi + +# Enable ICONV utilities +AC_ARG_ENABLE(iconv, + AC_HELP_STRING([--enable-iconv], [feature ICONV utilities])) +if test "$enable_iconv" = "yes" +then + MYDEFS="$MYDEFS -DMYICONV" + MGWLIBS="-liconv $MGWLIBS" + enables="$enables (iconv)" + isiconv="yes" +fi + +# No warning configuration +AC_ARG_ENABLE(warn, + AC_HELP_STRING([--disable-warn], [hide warnings in the configuration])) +if test "$enable_warn" = "no" +then + isnowarn="yes" +fi + +# Messages +printf '#================================================================\n' +printf '# Configuring QDBM version %s%s.\n' "$PACKAGE_VERSION" "$enables" +printf '#================================================================\n' + + + +#================================================================ +# Checking Commands to Build with +#================================================================ + + +# C compiler +AC_PROG_CC +if test "$GCC" != "yes" +then + if test "$isnowarn" != "yes" + then + printf '#================================================================\n' 1>&2 + printf '# WARNING: GCC is required to build this package.\n' 1>&2 + printf '#================================================================\n' 1>&2 + fi +fi +if uname | egrep -i 'Linux' > /dev/null 2>&1 && + uname -m | egrep '(x|i)(3|4|5|6|7|8|9)?86' > /dev/null 2>&1 +then + MYOPTS="-minline-all-stringops" +fi +if uname | egrep -i 'SunOS' > /dev/null 2>&1 +then + MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" +fi +if uname | egrep -i 'BSD' > /dev/null 2>&1 +then + MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" +fi +if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1 +then + MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" +fi + +# Linker +printf 'checking for ld... ' +if which ld | grep '/ld$' > /dev/null 2>&1 +then + LD=`which ld` + printf '%s\n' "$LD" +else + printf 'no\n' + if test "$isnowarn" != "yes" + then + printf '#================================================================\n' 1>&2 + printf '# WARNING: ld is not found in PATH.\n' 1>&2 + printf '#================================================================\n' 1>&2 + fi +fi + +# Archiver +printf 'checking for ar... ' +if which ar | grep '/ar$' > /dev/null 2>&1 +then + AR=`which ar` + printf '%s\n' "$AR" +else + printf 'no\n' + if test "$isnowarn" != "yes" + then + printf '#================================================================\n' 1>&2 + printf '# WARNING: ar is not found in PATH.\n' 1>&2 + printf '#================================================================\n' 1>&2 + fi +fi + + + +#================================================================ +# Checking Libraries +#================================================================ + + +# Underlying libraries +AC_CHECK_LIB(c, main) + +# for pthread +if test "$ispthread" = "yes" +then + AC_CHECK_LIB(pthread, main) +fi + +# for zlib +if test "$iszlib" = "yes" +then + AC_CHECK_LIB(z, main) +fi + +# for lzo +if test "$islzo" = "yes" +then + AC_CHECK_LIB(lzo2, main) +fi + +# for bzip +if test "$isbzip" = "yes" +then + AC_CHECK_LIB(bz2, main) +fi + +# for iconv +if test "$isiconv" = "yes" +then + AC_CHECK_LIB(iconv, main) +fi + +# For old BSDs +if test "$ispthread" = "yes" && uname -a | grep BSD > /dev/null && + test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a +then + LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'` +fi + +# Duplication of QDBM for C +AC_CHECK_LIB(qdbm, main, + if test "$isnowarn" != "yes" + then + printf '#================================================================\n' 1>&2 + printf '# WARNING: The existing library was detected.\n' 1>&2 + printf '#================================================================\n' 1>&2 + fi +) + + + +#================================================================ +# Generic Settings +#================================================================ + + +# Export variables +AC_SUBST(LIBVER) +AC_SUBST(LIBREV) +AC_SUBST(TARGETS) +AC_SUBST(MYDEFS) +AC_SUBST(MYOPTS) +AC_SUBST(MGWLIBS) +AC_SUBST(LD) +AC_SUBST(AR) +AC_SUBST(CPPFLAGS) +AC_SUBST(LDFLAGS) + +# Targets +AC_OUTPUT(Makefile LTmakefile qdbm.spec qdbm.pc) + +# Messages +printf '#================================================================\n' +printf '# Ready to make.\n' +printf '#================================================================\n' + + + +# END OF FILE Deleted: box/trunk/qdbm/crmgr.c =================================================================== --- box/trunk/qdbm/crmgr.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/crmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,956 +0,0 @@ -/************************************************************************************************* - * Utility for debugging Curia and its applications - * 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 -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define ALIGNSIZ 32 /* basic size of alignment */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -char *hextoobj(const char *str, int *sp); -char *dectoiobj(const char *str, int *sp); -int runcreate(int argc, char **argv); -int runput(int argc, char **argv); -int runout(int argc, char **argv); -int runget(int argc, char **argv); -int runlist(int argc, char **argv); -int runoptimize(int argc, char **argv); -int runinform(int argc, char **argv); -int runremove(int argc, char **argv); -int runrepair(int argc, char **argv); -int runexportdb(int argc, char **argv); -int runimportdb(int argc, char **argv); -int runsnaffle(int argc, char **argv); -void pdperror(const char *name); -void printobj(const char *obj, int size); -void printobjhex(const char *obj, int size); -int docreate(const char *name, int bnum, int dnum, int sparse); -int doput(const char *name, const char *kbuf, int ksiz, - const char *vbuf, int vsiz, int dmode, int lob, int align); -int doout(const char *name, const char *kbuf, int ksiz, int lob); -int doget(const char *name, int opts, const char *kbuf, int ksiz, - int start, int max, int ox, int lob, int nb); -int dolist(const char *name, int opts, int kb, int vb, int ox); -int dooptimize(const char *name, int bnum, int align); -int doinform(const char *name, int opts); -int doremove(const char *name); -int dorepair(const char *name); -int doexportdb(const char *name, const char *dir); -int doimportdb(const char *name, const char *dir, int bnum, int dnum); -int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb); - - -/* main routine */ -int main(int argc, char **argv){ - char *env; - int rv; - cbstdiobin(); - progname = argv[0]; - if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "create")){ - rv = runcreate(argc, argv); - } else if(!strcmp(argv[1], "put")){ - rv = runput(argc, argv); - } else if(!strcmp(argv[1], "out")){ - rv = runout(argc, argv); - } else if(!strcmp(argv[1], "get")){ - rv = runget(argc, argv); - } else if(!strcmp(argv[1], "list")){ - rv = runlist(argc, argv); - } else if(!strcmp(argv[1], "optimize")){ - rv = runoptimize(argc, argv); - } else if(!strcmp(argv[1], "inform")){ - rv = runinform(argc, argv); - } else if(!strcmp(argv[1], "remove")){ - rv = runremove(argc, argv); - } else if(!strcmp(argv[1], "repair")){ - rv = runrepair(argc, argv); - } else if(!strcmp(argv[1], "exportdb")){ - rv = runexportdb(argc, argv); - } else if(!strcmp(argv[1], "importdb")){ - rv = runimportdb(argc, argv); - } else if(!strcmp(argv[1], "snaffle")){ - rv = runsnaffle(argc, argv); - } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ - printf("Powered by QDBM version %s on %s%s\n", - dpversion, dpsysname, dpisreentrant ? " (reentrant)" : ""); - printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); - rv = 0; - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: administration utility for Curia\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s create [-s] [-bnum num] [-dnum num] name\n", progname); - fprintf(stderr, " %s put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] " - "name key val\n", progname); - fprintf(stderr, " %s out [-kx|-ki] [-lob] name key\n", progname); - fprintf(stderr, " %s get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-lob] [-n] name key\n", - progname); - fprintf(stderr, " %s list [-nl] [-k|-v] [-ox] name\n", progname); - fprintf(stderr, " %s optimize [-bnum num] [-na] name\n", progname); - fprintf(stderr, " %s inform [-nl] name\n", progname); - fprintf(stderr, " %s remove name\n", progname); - fprintf(stderr, " %s repair name\n", progname); - fprintf(stderr, " %s exportdb name dir\n", progname); - fprintf(stderr, " %s importdb [-bnum num] [-dnum num] name dir\n", progname); - fprintf(stderr, " %s snaffle [-kx|-ki] [-ox] [-n] name key\n", progname); - fprintf(stderr, " %s version\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* create a binary object from a hexadecimal string */ -char *hextoobj(const char *str, int *sp){ - char *buf, mbuf[3]; - int len, i, j; - len = strlen(str); - if(!(buf = malloc(len + 1))) return NULL; - j = 0; - for(i = 0; i < len; i += 2){ - while(strchr(" \n\r\t\f\v", str[i])){ - i++; - } - if((mbuf[0] = str[i]) == '\0') break; - if((mbuf[1] = str[i+1]) == '\0') break; - mbuf[2] = '\0'; - buf[j++] = (char)strtol(mbuf, NULL, 16); - } - buf[j] = '\0'; - *sp = j; - return buf; -} - - -/* create a integer object from a decimal string */ -char *dectoiobj(const char *str, int *sp){ - char *buf; - int num; - num = atoi(str); - if(!(buf = malloc(sizeof(int)))) return NULL; - *(int *)buf = num; - *sp = sizeof(int); - return buf; -} - - -/* parse arguments of create command */ -int runcreate(int argc, char **argv){ - char *name; - int i, sb, bnum, dnum, rv; - name = NULL; - sb = FALSE; - bnum = -1; - dnum = -1; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-s")){ - sb = TRUE; - } else if(!strcmp(argv[i], "-bnum")){ - if(++i >= argc) usage(); - bnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-dnum")){ - if(++i >= argc) usage(); - dnum = atoi(argv[i]); - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = docreate(name, bnum, dnum, sb); - return rv; -} - - -/* parse arguments of put command */ -int runput(int argc, char **argv){ - char *name, *key, *val, *kbuf, *vbuf; - int i, kx, ki, vx, vi, vf, lob, ksiz, vsiz, align, rv; - int dmode; - name = NULL; - kx = FALSE; - ki = FALSE; - vx = FALSE; - vi = FALSE; - vf = FALSE; - lob = FALSE; - align = ALIGNSIZ; - key = NULL; - val = NULL; - dmode = CR_DOVER; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else if(!strcmp(argv[i], "-vx")){ - vx = TRUE; - } else if(!strcmp(argv[i], "-vi")){ - vi = TRUE; - } else if(!strcmp(argv[i], "-vf")){ - vf = TRUE; - } else if(!strcmp(argv[i], "-keep")){ - dmode = CR_DKEEP; - } else if(!strcmp(argv[i], "-cat")){ - dmode = CR_DCAT; - } else if(!strcmp(argv[i], "-lob")){ - lob = TRUE; - } else if(!strcmp(argv[i], "-na")){ - align = 0; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else if(!val){ - val = argv[i]; - } else { - usage(); - } - } - if(!name || !key || !val) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(vx){ - vbuf = hextoobj(val, &vsiz); - } else if(vi){ - vbuf = dectoiobj(val, &vsiz); - } else if(vf){ - vbuf = cbreadfile(val, &vsiz); - } else { - vbuf = cbmemdup(val, -1); - vsiz = -1; - } - if(kbuf && vbuf){ - rv = doput(name, kbuf, ksiz, vbuf, vsiz, dmode, lob, align); - } else { - if(vf){ - fprintf(stderr, "%s: %s: cannot read\n", progname, val); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - } - rv = 1; - } - free(kbuf); - free(vbuf); - return rv; -} - - -/* parse arguments of out command */ -int runout(int argc, char **argv){ - char *name, *key, *kbuf; - int i, kx, ki, lob, ksiz, rv; - name = NULL; - kx = FALSE; - ki = FALSE; - lob = FALSE; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else if(!strcmp(argv[i], "-lob")){ - lob = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(kbuf){ - rv = doout(name, kbuf, ksiz, lob); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* parse arguments of get command */ -int runget(int argc, char **argv){ - char *name, *key, *kbuf; - int i, opts, kx, ki, ox, lob, nb, start, max, ksiz, rv; - name = NULL; - opts = 0; - kx = FALSE; - ki = FALSE; - ox = FALSE; - lob = FALSE; - nb = FALSE; - start = 0; - max = -1; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-nl")){ - opts |= CR_ONOLCK; - } else if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else if(!strcmp(argv[i], "-lob")){ - lob = TRUE; - } else if(!strcmp(argv[i], "-n")){ - nb = TRUE; - } else if(!strcmp(argv[i], "-start")){ - if(++i >= argc) usage(); - start = atoi(argv[i]); - } else if(!strcmp(argv[i], "-max")){ - if(++i >= argc) usage(); - max = atoi(argv[i]); - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key || start < 0) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(kbuf){ - rv = doget(name, opts, kbuf, ksiz, start, max, ox, lob, nb); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* parse arguments of list command */ -int runlist(int argc, char **argv){ - char *name; - int i, opts, kb, vb, ox, rv; - name = NULL; - opts = 0; - kb = FALSE; - vb = FALSE; - ox = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-nl")){ - opts |= CR_ONOLCK; - } else if(!strcmp(argv[i], "-k")){ - kb = TRUE; - } else if(!strcmp(argv[i], "-v")){ - vb = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dolist(name, opts, kb, vb, ox); - return rv; -} - - -/* parse arguments of optimize command */ -int runoptimize(int argc, char **argv){ - char *name; - int i, bnum, align, rv; - name = NULL; - bnum = -1; - align = ALIGNSIZ; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-bnum")){ - if(++i >= argc) usage(); - bnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-na")){ - align = 0; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dooptimize(name, bnum, align); - return rv; -} - - -/* parse arguments of inform command */ -int runinform(int argc, char **argv){ - char *name; - int i, opts, rv; - name = NULL; - opts = 0; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-nl")){ - opts |= CR_ONOLCK; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doinform(name, opts); - return rv; -} - - -/* parse arguments of remove command */ -int runremove(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doremove(name); - return rv; -} - - -/* parse arguments of repair command */ -int runrepair(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dorepair(name); - return rv; -} - - -/* parse arguments of exportdb command */ -int runexportdb(int argc, char **argv){ - char *name, *dir; - int i, rv; - name = NULL; - dir = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else if(!dir){ - dir = argv[i]; - } else { - usage(); - } - } - if(!name || !dir) usage(); - rv = doexportdb(name, dir); - return rv; -} - - -/* parse arguments of importdb command */ -int runimportdb(int argc, char **argv){ - char *name, *dir; - int i, bnum, dnum, rv; - name = NULL; - dir = NULL; - bnum = -1; - dnum = -1; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-bnum")){ - if(++i >= argc) usage(); - bnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-dnum")){ - if(++i >= argc) usage(); - dnum = atoi(argv[i]); - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!dir){ - dir = argv[i]; - } else { - usage(); - } - } - if(!name || !dir) usage(); - rv = doimportdb(name, dir, bnum, dnum); - return rv; -} - - -/* parse arguments of snaffle command */ -int runsnaffle(int argc, char **argv){ - char *name, *key, *kbuf; - int i, kx, ki, ox, nb, start, max, ksiz, rv; - name = NULL; - kx = FALSE; - ki = FALSE; - ox = FALSE; - nb = FALSE; - start = 0; - max = -1; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else if(!strcmp(argv[i], "-n")){ - nb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key || start < 0) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(kbuf){ - rv = dosnaffle(name, kbuf, ksiz, ox, nb); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* print an object */ -void printobj(const char *obj, int size){ - int i; - for(i = 0; i < size; i++){ - putchar(obj[i]); - } -} - - -/* print an object as a hexadecimal string */ -void printobjhex(const char *obj, int size){ - int i; - for(i = 0; i < size; i++){ - printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); - } -} - - -/* perform create command */ -int docreate(const char *name, int bnum, int dnum, int sparse){ - CURIA *curia; - int omode; - omode = CR_OWRITER | CR_OCREAT | CR_OTRUNC | (sparse ? CR_OSPARSE : 0); - if(!(curia = cropen(name, omode, bnum, dnum))){ - pdperror(name); - return 1; - } - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform put command */ -int doput(const char *name, const char *kbuf, int ksiz, - const char *vbuf, int vsiz, int dmode, int lob, int align){ - CURIA *curia; - if(!(curia = cropen(name, CR_OWRITER, -1, -1))){ - pdperror(name); - return 1; - } - if(align > 0 && !crsetalign(curia, ALIGNSIZ)){ - pdperror(name); - crclose(curia); - return 1; - } - if(lob){ - if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, dmode)){ - pdperror(name); - crclose(curia); - return 1; - } - } else { - if(!crput(curia, kbuf, ksiz, vbuf, vsiz, dmode)){ - pdperror(name); - crclose(curia); - return 1; - } - } - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform out command */ -int doout(const char *name, const char *kbuf, int ksiz, int lob){ - CURIA *curia; - if(!(curia = cropen(name, CR_OWRITER, -1, -1))){ - pdperror(name); - return 1; - } - if(lob){ - if(!croutlob(curia, kbuf, ksiz)){ - pdperror(name); - crclose(curia); - return 1; - } - } else { - if(!crout(curia, kbuf, ksiz)){ - pdperror(name); - crclose(curia); - return 1; - } - } - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform get command */ -int doget(const char *name, int opts, const char *kbuf, int ksiz, - int start, int max, int ox, int lob, int nb){ - CURIA *curia; - char *vbuf; - int vsiz; - if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){ - pdperror(name); - return 1; - } - if(lob){ - if(!(vbuf = crgetlob(curia, kbuf, ksiz, start, max, &vsiz))){ - pdperror(name); - crclose(curia); - return 1; - } - } else { - if(!(vbuf = crget(curia, kbuf, ksiz, start, max, &vsiz))){ - pdperror(name); - crclose(curia); - return 1; - } - } - if(ox){ - printobjhex(vbuf, vsiz); - } else { - printobj(vbuf, vsiz); - } - free(vbuf); - if(!nb) putchar('\n'); - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform list command */ -int dolist(const char *name, int opts, int kb, int vb, int ox){ - CURIA *curia; - char *kbuf, *vbuf; - int ksiz, vsiz; - if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){ - pdperror(name); - return 1; - } - criterinit(curia); - while((kbuf = criternext(curia, &ksiz)) != NULL){ - if(!(vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz))){ - pdperror(name); - free(kbuf); - break; - } - if(ox){ - if(!vb) printobjhex(kbuf, ksiz); - if(!kb && !vb) putchar('\t'); - if(!kb) printobjhex(vbuf, vsiz); - } else { - if(!vb) printobj(kbuf, ksiz); - if(!kb && !vb) putchar('\t'); - if(!kb) printobj(vbuf, vsiz); - } - putchar('\n'); - free(vbuf); - free(kbuf); - } - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform optimize command */ -int dooptimize(const char *name, int bnum, int align){ - CURIA *curia; - if(!(curia = cropen(name, CR_OWRITER, -1, -1))){ - pdperror(name); - return 1; - } - if(align > 0 && !crsetalign(curia, ALIGNSIZ)){ - pdperror(name); - crclose(curia); - return 1; - } - if(!croptimize(curia, bnum)){ - pdperror(name); - crclose(curia); - return 1; - } - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform inform command */ -int doinform(const char *name, int opts){ - CURIA *curia; - if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){ - pdperror(name); - return 1; - } - printf("name: %s\n", crname(curia)); - printf("file size: %.0f\n", crfsizd(curia)); - printf("all buckets: %d\n", crbnum(curia)); - printf("used buckets: %d\n", crbusenum(curia)); - printf("records: %d\n", crrnum(curia)); - printf("inode number: %d\n", crinode(curia)); - printf("modified time: %.0f\n", (double)crmtime(curia)); - printf("LOB records: %d\n", crrnumlob(curia)); - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform remove command */ -int doremove(const char *name){ - if(!crremove(name)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform repair command */ -int dorepair(const char *name){ - if(!crrepair(name)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform exportdb command */ -int doexportdb(const char *name, const char *dir){ - CURIA *curia; - if(!(curia = cropen(name, CR_OREADER, -1, -1))){ - pdperror(name); - return 1; - } - if(!crexportdb(curia, dir)){ - pdperror(name); - crclose(curia); - return 1; - } - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform importdb command */ -int doimportdb(const char *name, const char *dir, int bnum, int dnum){ - CURIA *curia; - if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum))){ - pdperror(name); - return 1; - } - if(!crimportdb(curia, dir)){ - pdperror(name); - crclose(curia); - return 1; - } - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform snaffle command */ -int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb){ - char *vbuf; - int vsiz; - if(!(vbuf = crsnaffle(name, kbuf, ksiz, &vsiz))){ - pdperror(name); - return 1; - } - if(ox){ - printobjhex(vbuf, vsiz); - } else { - printobj(vbuf, vsiz); - } - free(vbuf); - if(!nb) putchar('\n'); - return 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/crmgr.c (from rev 2716, box/trunk/qdbm/crmgr.c) =================================================================== --- box/trunk/qdbm/crmgr.c (rev 0) +++ box/trunk/qdbm/crmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,956 @@ +/************************************************************************************************* + * Utility for debugging Curia and its applications + * 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 +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define ALIGNSIZ 32 /* basic size of alignment */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +char *hextoobj(const char *str, int *sp); +char *dectoiobj(const char *str, int *sp); +int runcreate(int argc, char **argv); +int runput(int argc, char **argv); +int runout(int argc, char **argv); +int runget(int argc, char **argv); +int runlist(int argc, char **argv); +int runoptimize(int argc, char **argv); +int runinform(int argc, char **argv); +int runremove(int argc, char **argv); +int runrepair(int argc, char **argv); +int runexportdb(int argc, char **argv); +int runimportdb(int argc, char **argv); +int runsnaffle(int argc, char **argv); +void pdperror(const char *name); +void printobj(const char *obj, int size); +void printobjhex(const char *obj, int size); +int docreate(const char *name, int bnum, int dnum, int sparse); +int doput(const char *name, const char *kbuf, int ksiz, + const char *vbuf, int vsiz, int dmode, int lob, int align); +int doout(const char *name, const char *kbuf, int ksiz, int lob); +int doget(const char *name, int opts, const char *kbuf, int ksiz, + int start, int max, int ox, int lob, int nb); +int dolist(const char *name, int opts, int kb, int vb, int ox); +int dooptimize(const char *name, int bnum, int align); +int doinform(const char *name, int opts); +int doremove(const char *name); +int dorepair(const char *name); +int doexportdb(const char *name, const char *dir); +int doimportdb(const char *name, const char *dir, int bnum, int dnum); +int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb); + + +/* main routine */ +int main(int argc, char **argv){ + char *env; + int rv; + cbstdiobin(); + progname = argv[0]; + if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "create")){ + rv = runcreate(argc, argv); + } else if(!strcmp(argv[1], "put")){ + rv = runput(argc, argv); + } else if(!strcmp(argv[1], "out")){ + rv = runout(argc, argv); + } else if(!strcmp(argv[1], "get")){ + rv = runget(argc, argv); + } else if(!strcmp(argv[1], "list")){ + rv = runlist(argc, argv); + } else if(!strcmp(argv[1], "optimize")){ + rv = runoptimize(argc, argv); + } else if(!strcmp(argv[1], "inform")){ + rv = runinform(argc, argv); + } else if(!strcmp(argv[1], "remove")){ + rv = runremove(argc, argv); + } else if(!strcmp(argv[1], "repair")){ + rv = runrepair(argc, argv); + } else if(!strcmp(argv[1], "exportdb")){ + rv = runexportdb(argc, argv); + } else if(!strcmp(argv[1], "importdb")){ + rv = runimportdb(argc, argv); + } else if(!strcmp(argv[1], "snaffle")){ + rv = runsnaffle(argc, argv); + } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ + printf("Powered by QDBM version %s on %s%s\n", + dpversion, dpsysname, dpisreentrant ? " (reentrant)" : ""); + printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); + rv = 0; + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: administration utility for Curia\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s create [-s] [-bnum num] [-dnum num] name\n", progname); + fprintf(stderr, " %s put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] " + "name key val\n", progname); + fprintf(stderr, " %s out [-kx|-ki] [-lob] name key\n", progname); + fprintf(stderr, " %s get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-lob] [-n] name key\n", + progname); + fprintf(stderr, " %s list [-nl] [-k|-v] [-ox] name\n", progname); + fprintf(stderr, " %s optimize [-bnum num] [-na] name\n", progname); + fprintf(stderr, " %s inform [-nl] name\n", progname); + fprintf(stderr, " %s remove name\n", progname); + fprintf(stderr, " %s repair name\n", progname); + fprintf(stderr, " %s exportdb name dir\n", progname); + fprintf(stderr, " %s importdb [-bnum num] [-dnum num] name dir\n", progname); + fprintf(stderr, " %s snaffle [-kx|-ki] [-ox] [-n] name key\n", progname); + fprintf(stderr, " %s version\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* create a binary object from a hexadecimal string */ +char *hextoobj(const char *str, int *sp){ + char *buf, mbuf[3]; + int len, i, j; + len = strlen(str); + if(!(buf = malloc(len + 1))) return NULL; + j = 0; + for(i = 0; i < len; i += 2){ + while(strchr(" \n\r\t\f\v", str[i])){ + i++; + } + if((mbuf[0] = str[i]) == '\0') break; + if((mbuf[1] = str[i+1]) == '\0') break; + mbuf[2] = '\0'; + buf[j++] = (char)strtol(mbuf, NULL, 16); + } + buf[j] = '\0'; + *sp = j; + return buf; +} + + +/* create a integer object from a decimal string */ +char *dectoiobj(const char *str, int *sp){ + char *buf; + int num; + num = atoi(str); + if(!(buf = malloc(sizeof(int)))) return NULL; + *(int *)buf = num; + *sp = sizeof(int); + return buf; +} + + +/* parse arguments of create command */ +int runcreate(int argc, char **argv){ + char *name; + int i, sb, bnum, dnum, rv; + name = NULL; + sb = FALSE; + bnum = -1; + dnum = -1; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-s")){ + sb = TRUE; + } else if(!strcmp(argv[i], "-bnum")){ + if(++i >= argc) usage(); + bnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-dnum")){ + if(++i >= argc) usage(); + dnum = atoi(argv[i]); + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = docreate(name, bnum, dnum, sb); + return rv; +} + + +/* parse arguments of put command */ +int runput(int argc, char **argv){ + char *name, *key, *val, *kbuf, *vbuf; + int i, kx, ki, vx, vi, vf, lob, ksiz, vsiz, align, rv; + int dmode; + name = NULL; + kx = FALSE; + ki = FALSE; + vx = FALSE; + vi = FALSE; + vf = FALSE; + lob = FALSE; + align = ALIGNSIZ; + key = NULL; + val = NULL; + dmode = CR_DOVER; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else if(!strcmp(argv[i], "-vx")){ + vx = TRUE; + } else if(!strcmp(argv[i], "-vi")){ + vi = TRUE; + } else if(!strcmp(argv[i], "-vf")){ + vf = TRUE; + } else if(!strcmp(argv[i], "-keep")){ + dmode = CR_DKEEP; + } else if(!strcmp(argv[i], "-cat")){ + dmode = CR_DCAT; + } else if(!strcmp(argv[i], "-lob")){ + lob = TRUE; + } else if(!strcmp(argv[i], "-na")){ + align = 0; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else if(!val){ + val = argv[i]; + } else { + usage(); + } + } + if(!name || !key || !val) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(vx){ + vbuf = hextoobj(val, &vsiz); + } else if(vi){ + vbuf = dectoiobj(val, &vsiz); + } else if(vf){ + vbuf = cbreadfile(val, &vsiz); + } else { + vbuf = cbmemdup(val, -1); + vsiz = -1; + } + if(kbuf && vbuf){ + rv = doput(name, kbuf, ksiz, vbuf, vsiz, dmode, lob, align); + } else { + if(vf){ + fprintf(stderr, "%s: %s: cannot read\n", progname, val); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + } + rv = 1; + } + free(kbuf); + free(vbuf); + return rv; +} + + +/* parse arguments of out command */ +int runout(int argc, char **argv){ + char *name, *key, *kbuf; + int i, kx, ki, lob, ksiz, rv; + name = NULL; + kx = FALSE; + ki = FALSE; + lob = FALSE; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else if(!strcmp(argv[i], "-lob")){ + lob = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(kbuf){ + rv = doout(name, kbuf, ksiz, lob); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* parse arguments of get command */ +int runget(int argc, char **argv){ + char *name, *key, *kbuf; + int i, opts, kx, ki, ox, lob, nb, start, max, ksiz, rv; + name = NULL; + opts = 0; + kx = FALSE; + ki = FALSE; + ox = FALSE; + lob = FALSE; + nb = FALSE; + start = 0; + max = -1; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-nl")){ + opts |= CR_ONOLCK; + } else if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else if(!strcmp(argv[i], "-lob")){ + lob = TRUE; + } else if(!strcmp(argv[i], "-n")){ + nb = TRUE; + } else if(!strcmp(argv[i], "-start")){ + if(++i >= argc) usage(); + start = atoi(argv[i]); + } else if(!strcmp(argv[i], "-max")){ + if(++i >= argc) usage(); + max = atoi(argv[i]); + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key || start < 0) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(kbuf){ + rv = doget(name, opts, kbuf, ksiz, start, max, ox, lob, nb); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* parse arguments of list command */ +int runlist(int argc, char **argv){ + char *name; + int i, opts, kb, vb, ox, rv; + name = NULL; + opts = 0; + kb = FALSE; + vb = FALSE; + ox = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-nl")){ + opts |= CR_ONOLCK; + } else if(!strcmp(argv[i], "-k")){ + kb = TRUE; + } else if(!strcmp(argv[i], "-v")){ + vb = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dolist(name, opts, kb, vb, ox); + return rv; +} + + +/* parse arguments of optimize command */ +int runoptimize(int argc, char **argv){ + char *name; + int i, bnum, align, rv; + name = NULL; + bnum = -1; + align = ALIGNSIZ; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-bnum")){ + if(++i >= argc) usage(); + bnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-na")){ + align = 0; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dooptimize(name, bnum, align); + return rv; +} + + +/* parse arguments of inform command */ +int runinform(int argc, char **argv){ + char *name; + int i, opts, rv; + name = NULL; + opts = 0; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-nl")){ + opts |= CR_ONOLCK; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doinform(name, opts); + return rv; +} + + +/* parse arguments of remove command */ +int runremove(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doremove(name); + return rv; +} + + +/* parse arguments of repair command */ +int runrepair(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dorepair(name); + return rv; +} + + +/* parse arguments of exportdb command */ +int runexportdb(int argc, char **argv){ + char *name, *dir; + int i, rv; + name = NULL; + dir = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else if(!dir){ + dir = argv[i]; + } else { + usage(); + } + } + if(!name || !dir) usage(); + rv = doexportdb(name, dir); + return rv; +} + + +/* parse arguments of importdb command */ +int runimportdb(int argc, char **argv){ + char *name, *dir; + int i, bnum, dnum, rv; + name = NULL; + dir = NULL; + bnum = -1; + dnum = -1; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-bnum")){ + if(++i >= argc) usage(); + bnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-dnum")){ + if(++i >= argc) usage(); + dnum = atoi(argv[i]); + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!dir){ + dir = argv[i]; + } else { + usage(); + } + } + if(!name || !dir) usage(); + rv = doimportdb(name, dir, bnum, dnum); + return rv; +} + + +/* parse arguments of snaffle command */ +int runsnaffle(int argc, char **argv){ + char *name, *key, *kbuf; + int i, kx, ki, ox, nb, start, max, ksiz, rv; + name = NULL; + kx = FALSE; + ki = FALSE; + ox = FALSE; + nb = FALSE; + start = 0; + max = -1; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else if(!strcmp(argv[i], "-n")){ + nb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key || start < 0) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(kbuf){ + rv = dosnaffle(name, kbuf, ksiz, ox, nb); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* print an object */ +void printobj(const char *obj, int size){ + int i; + for(i = 0; i < size; i++){ + putchar(obj[i]); + } +} + + +/* print an object as a hexadecimal string */ +void printobjhex(const char *obj, int size){ + int i; + for(i = 0; i < size; i++){ + printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); + } +} + + +/* perform create command */ +int docreate(const char *name, int bnum, int dnum, int sparse){ + CURIA *curia; + int omode; + omode = CR_OWRITER | CR_OCREAT | CR_OTRUNC | (sparse ? CR_OSPARSE : 0); + if(!(curia = cropen(name, omode, bnum, dnum))){ + pdperror(name); + return 1; + } + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform put command */ +int doput(const char *name, const char *kbuf, int ksiz, + const char *vbuf, int vsiz, int dmode, int lob, int align){ + CURIA *curia; + if(!(curia = cropen(name, CR_OWRITER, -1, -1))){ + pdperror(name); + return 1; + } + if(align > 0 && !crsetalign(curia, ALIGNSIZ)){ + pdperror(name); + crclose(curia); + return 1; + } + if(lob){ + if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, dmode)){ + pdperror(name); + crclose(curia); + return 1; + } + } else { + if(!crput(curia, kbuf, ksiz, vbuf, vsiz, dmode)){ + pdperror(name); + crclose(curia); + return 1; + } + } + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform out command */ +int doout(const char *name, const char *kbuf, int ksiz, int lob){ + CURIA *curia; + if(!(curia = cropen(name, CR_OWRITER, -1, -1))){ + pdperror(name); + return 1; + } + if(lob){ + if(!croutlob(curia, kbuf, ksiz)){ + pdperror(name); + crclose(curia); + return 1; + } + } else { + if(!crout(curia, kbuf, ksiz)){ + pdperror(name); + crclose(curia); + return 1; + } + } + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform get command */ +int doget(const char *name, int opts, const char *kbuf, int ksiz, + int start, int max, int ox, int lob, int nb){ + CURIA *curia; + char *vbuf; + int vsiz; + if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){ + pdperror(name); + return 1; + } + if(lob){ + if(!(vbuf = crgetlob(curia, kbuf, ksiz, start, max, &vsiz))){ + pdperror(name); + crclose(curia); + return 1; + } + } else { + if(!(vbuf = crget(curia, kbuf, ksiz, start, max, &vsiz))){ + pdperror(name); + crclose(curia); + return 1; + } + } + if(ox){ + printobjhex(vbuf, vsiz); + } else { + printobj(vbuf, vsiz); + } + free(vbuf); + if(!nb) putchar('\n'); + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform list command */ +int dolist(const char *name, int opts, int kb, int vb, int ox){ + CURIA *curia; + char *kbuf, *vbuf; + int ksiz, vsiz; + if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){ + pdperror(name); + return 1; + } + criterinit(curia); + while((kbuf = criternext(curia, &ksiz)) != NULL){ + if(!(vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz))){ + pdperror(name); + free(kbuf); + break; + } + if(ox){ + if(!vb) printobjhex(kbuf, ksiz); + if(!kb && !vb) putchar('\t'); + if(!kb) printobjhex(vbuf, vsiz); + } else { + if(!vb) printobj(kbuf, ksiz); + if(!kb && !vb) putchar('\t'); + if(!kb) printobj(vbuf, vsiz); + } + putchar('\n'); + free(vbuf); + free(kbuf); + } + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform optimize command */ +int dooptimize(const char *name, int bnum, int align){ + CURIA *curia; + if(!(curia = cropen(name, CR_OWRITER, -1, -1))){ + pdperror(name); + return 1; + } + if(align > 0 && !crsetalign(curia, ALIGNSIZ)){ + pdperror(name); + crclose(curia); + return 1; + } + if(!croptimize(curia, bnum)){ + pdperror(name); + crclose(curia); + return 1; + } + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform inform command */ +int doinform(const char *name, int opts){ + CURIA *curia; + if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){ + pdperror(name); + return 1; + } + printf("name: %s\n", crname(curia)); + printf("file size: %.0f\n", crfsizd(curia)); + printf("all buckets: %d\n", crbnum(curia)); + printf("used buckets: %d\n", crbusenum(curia)); + printf("records: %d\n", crrnum(curia)); + printf("inode number: %d\n", crinode(curia)); + printf("modified time: %.0f\n", (double)crmtime(curia)); + printf("LOB records: %d\n", crrnumlob(curia)); + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform remove command */ +int doremove(const char *name){ + if(!crremove(name)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform repair command */ +int dorepair(const char *name){ + if(!crrepair(name)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform exportdb command */ +int doexportdb(const char *name, const char *dir){ + CURIA *curia; + if(!(curia = cropen(name, CR_OREADER, -1, -1))){ + pdperror(name); + return 1; + } + if(!crexportdb(curia, dir)){ + pdperror(name); + crclose(curia); + return 1; + } + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform importdb command */ +int doimportdb(const char *name, const char *dir, int bnum, int dnum){ + CURIA *curia; + if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum))){ + pdperror(name); + return 1; + } + if(!crimportdb(curia, dir)){ + pdperror(name); + crclose(curia); + return 1; + } + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform snaffle command */ +int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb){ + char *vbuf; + int vsiz; + if(!(vbuf = crsnaffle(name, kbuf, ksiz, &vsiz))){ + pdperror(name); + return 1; + } + if(ox){ + printobjhex(vbuf, vsiz); + } else { + printobj(vbuf, vsiz); + } + free(vbuf); + if(!nb) putchar('\n'); + return 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/crtest.c =================================================================== --- box/trunk/qdbm/crtest.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/crtest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,873 +0,0 @@ -/************************************************************************************************* - * Test cases of Curia - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define RECBUFSIZ 32 /* buffer for records */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -int runwrite(int argc, char **argv); -int runread(int argc, char **argv); -int runrcat(int argc, char **argv); -int runcombo(int argc, char **argv); -int runwicked(int argc, char **argv); -int printfflush(const char *format, ...); -void pdperror(const char *name); -int myrand(void); -int dowrite(const char *name, int rnum, int bnum, int dnum, int sparse, int lob); -int doread(const char *name, int wb, int lob); -int dorcat(const char *name, int rnum, int bnum, int dnum, int pnum, - int align, int fbpsiz, int cb); -int docombo(const char *name); -int dowicked(const char *name, int rnum, int cb); - - -/* main routine */ -int main(int argc, char **argv){ - char *env; - int rv; - cbstdiobin(); - if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "write")){ - rv = runwrite(argc, argv); - } else if(!strcmp(argv[1], "read")){ - rv = runread(argc, argv); - } else if(!strcmp(argv[1], "rcat")){ - rv = runrcat(argc, argv); - } else if(!strcmp(argv[1], "combo")){ - rv = runcombo(argc, argv); - } else if(!strcmp(argv[1], "wicked")){ - rv = runwicked(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: test cases for Curia\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s write [-s] [-lob] name rnum bnum dnum\n", progname); - fprintf(stderr, " %s read [-wb] [-lob] name\n", progname); - fprintf(stderr, " %s rcat [-c] name rnum bnum dnum pnum align fbpsiz\n", progname); - fprintf(stderr, " %s combo name\n", progname); - fprintf(stderr, " %s wicked [-c] name rnum\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of write command */ -int runwrite(int argc, char **argv){ - char *name, *rstr, *bstr, *dstr; - int i, rnum, bnum, dnum, sb, lob, rv; - name = NULL; - rstr = NULL; - bstr = NULL; - dstr = NULL; - rnum = 0; - bnum = 0; - dnum = 0; - sb = FALSE; - lob = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-s")){ - sb = TRUE; - } else if(!strcmp(argv[i], "-lob")){ - lob = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else if(!bstr){ - bstr = argv[i]; - } else if(!dstr){ - dstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr || !bstr || !dstr) usage(); - rnum = atoi(rstr); - bnum = atoi(bstr); - dnum = atoi(dstr); - if(rnum < 1 || bnum < 1 || dnum < 1) usage(); - rv = dowrite(name, rnum, bnum, dnum, sb, lob); - return rv; -} - - -/* parse arguments of read command */ -int runread(int argc, char **argv){ - char *name; - int i, wb, lob, rv; - name = NULL; - wb = FALSE; - lob = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-wb")){ - wb = TRUE; - } else if(!strcmp(argv[i], "-lob")){ - lob = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doread(name, wb, lob); - return rv; -} - - -/* parse arguments of rcat command */ -int runrcat(int argc, char **argv){ - char *name, *rstr, *bstr, *dstr, *pstr, *astr, *fstr; - int i, rnum, bnum, dnum, pnum, align, fbpsiz, cb, rv; - name = NULL; - rstr = NULL; - bstr = NULL; - dstr = NULL; - pstr = NULL; - astr = NULL; - fstr = NULL; - rnum = 0; - bnum = 0; - pnum = 0; - align = 0; - fbpsiz = 0; - cb = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-c")){ - cb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else if(!bstr){ - bstr = argv[i]; - } else if(!dstr){ - dstr = argv[i]; - } else if(!pstr){ - pstr = argv[i]; - } else if(!astr){ - astr = argv[i]; - } else if(!fstr){ - fstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr || !bstr || !dstr || !pstr || !astr || !fstr) usage(); - rnum = atoi(rstr); - bnum = atoi(bstr); - dnum = atoi(dstr); - pnum = atoi(pstr); - align = atoi(astr); - fbpsiz = atoi(fstr); - if(rnum < 1 || bnum < 1 || dnum < 1 || pnum < 1 || fbpsiz < 0) usage(); - rv = dorcat(name, rnum, bnum, dnum, pnum, align, fbpsiz, cb); - return rv; -} - - -/* parse arguments of combo command */ -int runcombo(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = docombo(name); - return rv; -} - - -/* parse arguments of wicked command */ -int runwicked(int argc, char **argv){ - char *name, *rstr; - int i, rnum, cb, rv; - name = NULL; - rstr = NULL; - rnum = 0; - cb = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-c")){ - cb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = dowicked(name, rnum, cb); - return rv; -} - - -/* print formatted string and flush the buffer */ -int printfflush(const char *format, ...){ - va_list ap; - int rv; - va_start(ap, format); - rv = vprintf(format, ap); - if(fflush(stdout) == EOF) rv = -1; - va_end(ap); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* pseudo random number generator */ -int myrand(void){ - static int cnt = 0; - if(cnt == 0) srand(time(NULL)); - return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; -} - - -/* perform write command */ -int dowrite(const char *name, int rnum, int bnum, int dnum, int sparse, int lob){ - CURIA *curia; - int i, omode, err, len; - char buf[RECBUFSIZ]; - printfflush("\n name=%s rnum=%d bnum=%d dnum=%d s=%d lob=%d\n\n", - name, rnum, bnum, dnum, sparse, lob); - /* open a database */ - omode = CR_OWRITER | CR_OCREAT | CR_OTRUNC | (sparse ? CR_OSPARSE : 0); - if(!(curia = cropen(name, omode, bnum, dnum))){ - pdperror(name); - return 1; - } - err = FALSE; - /* loop for each record */ - for(i = 1; i <= rnum; i++){ - /* store a record */ - len = sprintf(buf, "%08d", i); - if(lob){ - if(!crputlob(curia, buf, len, buf, len, CR_DOVER)){ - pdperror(name); - err = TRUE; - break; - } - } else { - if(!crput(curia, buf, len, buf, len, CR_DOVER)){ - pdperror(name); - err = TRUE; - break; - } - } - /* print progression */ - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - if(!crclose(curia)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform read command */ -int doread(const char *name, int wb, int lob){ - CURIA *curia; - int i, rnum, err, len; - char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; - printfflush("\n name=%s wb=%d lob=%d\n\n", name, wb, lob); - /* open a database */ - if(!(curia = cropen(name, CR_OREADER, -1, -1))){ - pdperror(name); - return 1; - } - /* get the number of records */ - if(lob){ - rnum = crrnumlob(curia); - } else { - rnum = crrnum(curia); - } - err = FALSE; - /* loop for each record */ - for(i = 1; i <= rnum; i++){ - /* retrieve a record */ - len = sprintf(buf, "%08d", i); - if(lob){ - if(!(val = crgetlob(curia, buf, len, 0, -1, NULL))){ - pdperror(name); - err = TRUE; - break; - } - free(val); - } else if(wb){ - if(crgetwb(curia, buf, len, 0, RECBUFSIZ, vbuf) == -1){ - pdperror(name); - err = TRUE; - break; - } - } else { - if(!(val = crget(curia, buf, len, 0, -1, NULL))){ - pdperror(name); - err = TRUE; - break; - } - free(val); - } - /* print progression */ - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - if(!crclose(curia)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform rcat command */ -int dorcat(const char *name, int rnum, int bnum, int dnum, int pnum, - int align, int fbpsiz, int cb){ - CURIA *curia; - CBMAP *map; - int i, err, len, ksiz, vsiz, rsiz; - const char *kbuf, *vbuf; - char buf[RECBUFSIZ], *rbuf; - printfflush("\n name=%s rnum=%d bnum=%d dnum=%d pnum=%d" - " align=%d fbpsiz=%d c=%d\n\n", name, rnum, bnum, dnum, pnum, align, fbpsiz, cb); - if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum))){ - pdperror(name); - return 1; - } - if(!crsetalign(curia, align) || !crsetfbpsiz(curia, fbpsiz)){ - pdperror(name); - crclose(curia); - return 1; - } - map = NULL; - if(cb) map = cbmapopen(); - err = FALSE; - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", myrand() % pnum + 1); - if(!crput(curia, buf, len, buf, len, CR_DCAT)){ - pdperror(name); - err = TRUE; - break; - } - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d: fsiz=%d rnum=%d)\n", i, crfsiz(curia), crrnum(curia)); - } - } - } - if(map){ - printfflush("Matching records ... "); - cbmapiterinit(map); - while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ - vbuf = cbmapget(map, kbuf, ksiz, &vsiz); - if(!(rbuf = crget(curia, kbuf, ksiz, 0, -1, &rsiz))){ - pdperror(name); - err = TRUE; - break; - } - if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){ - fprintf(stderr, "%s: %s: unmatched record\n", progname, name); - free(rbuf); - err = TRUE; - break; - } - free(rbuf); - } - cbmapclose(map); - if(!err) printfflush("ok\n"); - } - if(!crclose(curia)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform combo command */ -int docombo(const char *name){ - CURIA *curia; - char buf[RECBUFSIZ], wbuf[RECBUFSIZ], *vbuf; - int i, len, wlen, vsiz; - printfflush("\n name=%s\n\n", name); - printfflush("Creating a database with bnum 3 ... "); - if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, 3, 3))){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Setting alignment as 16 ... "); - if(!crsetalign(curia, 16)){ - pdperror(name); - crclose(curia); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 20 records ... "); - for(i = 1; i <= 20; i++){ - len = sprintf(buf, "%08d", i); - if(!crput(curia, buf, len, buf, len, CR_DOVER)){ - pdperror(name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking records ... "); - for(i = 1; i <= 20; i++){ - len = sprintf(buf, "%08d", i); - if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ - pdperror(name); - crclose(curia); - return 1; - } - free(vbuf); - if(vsiz != crvsiz(curia, buf, len)){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Overwriting top 10 records without moving rooms ... "); - for(i = 1; i <= 10; i++){ - len = sprintf(buf, "%08d", i); - if(!crput(curia, buf, len, buf, len, CR_DOVER)){ - pdperror(name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Overwriting top 5 records with moving rooms ... "); - for(i = 1; i <= 5; i++){ - len = sprintf(buf, "%08d", i); - wlen = sprintf(wbuf, "%024d", i); - if(!crput(curia, buf, len, wbuf, wlen, CR_DOVER)){ - pdperror(name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); - for(i = 1; i <= 15; i++){ - len = sprintf(buf, "%08d", i); - wlen = sprintf(wbuf, "========================"); - if(!crput(curia, buf, len, wbuf, wlen, CR_DCAT)){ - pdperror(name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking records ... "); - for(i = 1; i <= 20; i++){ - len = sprintf(buf, "%08d", i); - if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ - pdperror(name); - crclose(curia); - return 1; - } - free(vbuf); - if(vsiz != crvsiz(curia, buf, len)){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Deleting top 10 records ... "); - for(i = 1; i <= 10; i++){ - len = sprintf(buf, "%08d", i); - if(!crout(curia, buf, len)){ - pdperror(name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking deleted records ... "); - for(i = 1; i <= 10; i++){ - len = sprintf(buf, "%08d", i); - vbuf = crget(curia, buf, len, 0, -1, &vsiz); - free(vbuf); - if(vbuf || dpecode != DP_ENOITEM){ - fprintf(stderr, "%s: %s: deleting failed\n", progname, name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); - for(i = 1; i <= 15; i++){ - len = sprintf(buf, "%08d", i); - wlen = sprintf(wbuf, "========================"); - if(!crput(curia, buf, len, wbuf, wlen, CR_DCAT)){ - pdperror(name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking records ... "); - for(i = 1; i <= 20; i++){ - len = sprintf(buf, "%08d", i); - if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ - pdperror(name); - crclose(curia); - return 1; - } - free(vbuf); - if(vsiz != crvsiz(curia, buf, len)){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Optimizing the database ... "); - if(!croptimize(curia, -1)){ - pdperror(name); - crclose(curia); - return 1; - } - printfflush("ok\n"); - printfflush("Checking records ... "); - for(i = 1; i <= 20; i++){ - len = sprintf(buf, "%08d", i); - if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ - pdperror(name); - crclose(curia); - return 1; - } - free(vbuf); - if(vsiz != crvsiz(curia, buf, len)){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Closing database ... "); - if(!crclose(curia)){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Creating a database with bnum 1000000 ... "); - if(!(curia = cropen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 1000000, -1))){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 1000 records ... "); - for(i = 1; i <= 1000; i++){ - len = sprintf(buf, "%08d", i); - if(!crput(curia, buf, len, buf, len, DP_DOVER)){ - pdperror(name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Adding 64 records ... "); - for(i = 1; i <= 64; i++){ - len = sprintf(buf, "%o", i); - if(!crput(curia, buf, len, buf, len, DP_DOVER)){ - pdperror(name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Syncing the database ... "); - if(!crsync(curia)){ - pdperror(name); - crclose(curia); - return 1; - } - printfflush("ok\n"); - printfflush("Retrieving records directly ... "); - for(i = 1; i <= 64; i++){ - len = sprintf(buf, "%o", i); - if(!(vbuf = crsnaffle(name, buf, len, &vsiz))){ - pdperror(name); - crclose(curia); - return 1; - } - if(strcmp(vbuf, buf)){ - fprintf(stderr, "%s: %s: invalid content\n", progname, name); - free(vbuf); - crclose(curia); - return 1; - } - free(vbuf); - if(vsiz != crvsiz(curia, buf, len)){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - crclose(curia); - return 1; - } - } - printfflush("ok\n"); - printfflush("Optimizing the database ... "); - if(!croptimize(curia, -1)){ - pdperror(name); - crclose(curia); - return 1; - } - printfflush("ok\n"); - printfflush("Closing the database ... "); - if(!crclose(curia)){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("all ok\n\n"); - return 0; -} - - -/* perform wicked command */ -int dowicked(const char *name, int rnum, int cb){ - CURIA *curia; - CBMAP *map; - int i, len, err, align, mksiz, mvsiz, rsiz; - const char *mkbuf, *mvbuf; - char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; - printfflush("\n name=%s rnum=%d\n\n", name, rnum); - err = FALSE; - if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, rnum / 10, 5))){ - pdperror(name); - return 1; - } - if(!crsetalign(curia, 16) || !crsetfbpsiz(curia, 256)){ - pdperror(name); - err = TRUE; - } - map = NULL; - if(cb) map = cbmapopen(); - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", myrand() % rnum + 1); - switch(myrand() % 16){ - case 0: - putchar('O'); - if(!crput(curia, buf, len, buf, len, CR_DOVER)) err = TRUE; - if(map) cbmapput(map, buf, len, buf, len, TRUE); - break; - case 1: - putchar('K'); - if(!crput(curia, buf, len, buf, len, CR_DKEEP) && dpecode != DP_EKEEP) err = TRUE; - if(map) cbmapput(map, buf, len, buf, len, FALSE); - break; - case 2: - putchar('D'); - if(!crout(curia, buf, len) && dpecode != DP_ENOITEM) err = TRUE; - if(map) cbmapout(map, buf, len); - break; - case 3: - putchar('G'); - if(crgetwb(curia, buf, len, 2, RECBUFSIZ, vbuf) == -1 && dpecode != DP_ENOITEM) err = TRUE; - break; - case 4: - putchar('V'); - if(crvsiz(curia, buf, len) == -1 && dpecode != DP_ENOITEM) err = TRUE; - break; - default: - putchar('C'); - if(!crput(curia, buf, len, buf, len, CR_DCAT)) err = TRUE; - if(map) cbmapputcat(map, buf, len, buf, len); - break; - } - if(i % 50 == 0) printfflush(" (%08d)\n", i); - if(!err && rnum > 100 && myrand() % (rnum / 100) == 0){ - if(myrand() % 10 == 0){ - align = (myrand() % 4 + 1) * -1; - } else { - align = myrand() % 32; - } - if(!crsetalign(curia, align)) err = TRUE; - } - if(err){ - pdperror(name); - break; - } - } - if(!croptimize(curia, -1)){ - pdperror(name); - err = TRUE; - } - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", i); - if(!crput(curia, buf, len, ":", -1, CR_DCAT)){ - pdperror(name); - err = TRUE; - break; - } - if(map) cbmapputcat(map, buf, len, ":", -1); - putchar(':'); - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - if(!croptimize(curia, -1)){ - pdperror(name); - err = TRUE; - } - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", i); - if(!(val = crget(curia, buf, len, 0, -1, NULL))){ - pdperror(name); - err = TRUE; - break; - } - free(val); - putchar('='); - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - if(!criterinit(curia)){ - pdperror(name); - err = TRUE; - } - for(i = 1; i <= rnum; i++){ - if(!(val = criternext(curia, NULL))){ - pdperror(name); - err = TRUE; - break; - } - free(val); - putchar('@'); - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - if(map){ - printfflush("Matching records ... "); - cbmapiterinit(map); - while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){ - mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz); - if(!(val = crget(curia, mkbuf, mksiz, 0, -1, &rsiz))){ - pdperror(name); - err = TRUE; - break; - } - if(rsiz != mvsiz || memcmp(val, mvbuf, rsiz)){ - fprintf(stderr, "%s: %s: unmatched record\n", progname, name); - free(val); - err = TRUE; - break; - } - free(val); - } - cbmapclose(map); - if(!err) printfflush("ok\n"); - } - if(!crclose(curia)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/crtest.c (from rev 2716, box/trunk/qdbm/crtest.c) =================================================================== --- box/trunk/qdbm/crtest.c (rev 0) +++ box/trunk/qdbm/crtest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,873 @@ +/************************************************************************************************* + * Test cases of Curia + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define RECBUFSIZ 32 /* buffer for records */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +int runwrite(int argc, char **argv); +int runread(int argc, char **argv); +int runrcat(int argc, char **argv); +int runcombo(int argc, char **argv); +int runwicked(int argc, char **argv); +int printfflush(const char *format, ...); +void pdperror(const char *name); +int myrand(void); +int dowrite(const char *name, int rnum, int bnum, int dnum, int sparse, int lob); +int doread(const char *name, int wb, int lob); +int dorcat(const char *name, int rnum, int bnum, int dnum, int pnum, + int align, int fbpsiz, int cb); +int docombo(const char *name); +int dowicked(const char *name, int rnum, int cb); + + +/* main routine */ +int main(int argc, char **argv){ + char *env; + int rv; + cbstdiobin(); + if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "write")){ + rv = runwrite(argc, argv); + } else if(!strcmp(argv[1], "read")){ + rv = runread(argc, argv); + } else if(!strcmp(argv[1], "rcat")){ + rv = runrcat(argc, argv); + } else if(!strcmp(argv[1], "combo")){ + rv = runcombo(argc, argv); + } else if(!strcmp(argv[1], "wicked")){ + rv = runwicked(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: test cases for Curia\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s write [-s] [-lob] name rnum bnum dnum\n", progname); + fprintf(stderr, " %s read [-wb] [-lob] name\n", progname); + fprintf(stderr, " %s rcat [-c] name rnum bnum dnum pnum align fbpsiz\n", progname); + fprintf(stderr, " %s combo name\n", progname); + fprintf(stderr, " %s wicked [-c] name rnum\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of write command */ +int runwrite(int argc, char **argv){ + char *name, *rstr, *bstr, *dstr; + int i, rnum, bnum, dnum, sb, lob, rv; + name = NULL; + rstr = NULL; + bstr = NULL; + dstr = NULL; + rnum = 0; + bnum = 0; + dnum = 0; + sb = FALSE; + lob = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-s")){ + sb = TRUE; + } else if(!strcmp(argv[i], "-lob")){ + lob = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else if(!bstr){ + bstr = argv[i]; + } else if(!dstr){ + dstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr || !bstr || !dstr) usage(); + rnum = atoi(rstr); + bnum = atoi(bstr); + dnum = atoi(dstr); + if(rnum < 1 || bnum < 1 || dnum < 1) usage(); + rv = dowrite(name, rnum, bnum, dnum, sb, lob); + return rv; +} + + +/* parse arguments of read command */ +int runread(int argc, char **argv){ + char *name; + int i, wb, lob, rv; + name = NULL; + wb = FALSE; + lob = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-wb")){ + wb = TRUE; + } else if(!strcmp(argv[i], "-lob")){ + lob = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doread(name, wb, lob); + return rv; +} + + +/* parse arguments of rcat command */ +int runrcat(int argc, char **argv){ + char *name, *rstr, *bstr, *dstr, *pstr, *astr, *fstr; + int i, rnum, bnum, dnum, pnum, align, fbpsiz, cb, rv; + name = NULL; + rstr = NULL; + bstr = NULL; + dstr = NULL; + pstr = NULL; + astr = NULL; + fstr = NULL; + rnum = 0; + bnum = 0; + pnum = 0; + align = 0; + fbpsiz = 0; + cb = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-c")){ + cb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else if(!bstr){ + bstr = argv[i]; + } else if(!dstr){ + dstr = argv[i]; + } else if(!pstr){ + pstr = argv[i]; + } else if(!astr){ + astr = argv[i]; + } else if(!fstr){ + fstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr || !bstr || !dstr || !pstr || !astr || !fstr) usage(); + rnum = atoi(rstr); + bnum = atoi(bstr); + dnum = atoi(dstr); + pnum = atoi(pstr); + align = atoi(astr); + fbpsiz = atoi(fstr); + if(rnum < 1 || bnum < 1 || dnum < 1 || pnum < 1 || fbpsiz < 0) usage(); + rv = dorcat(name, rnum, bnum, dnum, pnum, align, fbpsiz, cb); + return rv; +} + + +/* parse arguments of combo command */ +int runcombo(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = docombo(name); + return rv; +} + + +/* parse arguments of wicked command */ +int runwicked(int argc, char **argv){ + char *name, *rstr; + int i, rnum, cb, rv; + name = NULL; + rstr = NULL; + rnum = 0; + cb = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-c")){ + cb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = dowicked(name, rnum, cb); + return rv; +} + + +/* print formatted string and flush the buffer */ +int printfflush(const char *format, ...){ + va_list ap; + int rv; + va_start(ap, format); + rv = vprintf(format, ap); + if(fflush(stdout) == EOF) rv = -1; + va_end(ap); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* pseudo random number generator */ +int myrand(void){ + static int cnt = 0; + if(cnt == 0) srand(time(NULL)); + return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; +} + + +/* perform write command */ +int dowrite(const char *name, int rnum, int bnum, int dnum, int sparse, int lob){ + CURIA *curia; + int i, omode, err, len; + char buf[RECBUFSIZ]; + printfflush("\n name=%s rnum=%d bnum=%d dnum=%d s=%d lob=%d\n\n", + name, rnum, bnum, dnum, sparse, lob); + /* open a database */ + omode = CR_OWRITER | CR_OCREAT | CR_OTRUNC | (sparse ? CR_OSPARSE : 0); + if(!(curia = cropen(name, omode, bnum, dnum))){ + pdperror(name); + return 1; + } + err = FALSE; + /* loop for each record */ + for(i = 1; i <= rnum; i++){ + /* store a record */ + len = sprintf(buf, "%08d", i); + if(lob){ + if(!crputlob(curia, buf, len, buf, len, CR_DOVER)){ + pdperror(name); + err = TRUE; + break; + } + } else { + if(!crput(curia, buf, len, buf, len, CR_DOVER)){ + pdperror(name); + err = TRUE; + break; + } + } + /* print progression */ + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + if(!crclose(curia)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform read command */ +int doread(const char *name, int wb, int lob){ + CURIA *curia; + int i, rnum, err, len; + char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; + printfflush("\n name=%s wb=%d lob=%d\n\n", name, wb, lob); + /* open a database */ + if(!(curia = cropen(name, CR_OREADER, -1, -1))){ + pdperror(name); + return 1; + } + /* get the number of records */ + if(lob){ + rnum = crrnumlob(curia); + } else { + rnum = crrnum(curia); + } + err = FALSE; + /* loop for each record */ + for(i = 1; i <= rnum; i++){ + /* retrieve a record */ + len = sprintf(buf, "%08d", i); + if(lob){ + if(!(val = crgetlob(curia, buf, len, 0, -1, NULL))){ + pdperror(name); + err = TRUE; + break; + } + free(val); + } else if(wb){ + if(crgetwb(curia, buf, len, 0, RECBUFSIZ, vbuf) == -1){ + pdperror(name); + err = TRUE; + break; + } + } else { + if(!(val = crget(curia, buf, len, 0, -1, NULL))){ + pdperror(name); + err = TRUE; + break; + } + free(val); + } + /* print progression */ + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + if(!crclose(curia)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform rcat command */ +int dorcat(const char *name, int rnum, int bnum, int dnum, int pnum, + int align, int fbpsiz, int cb){ + CURIA *curia; + CBMAP *map; + int i, err, len, ksiz, vsiz, rsiz; + const char *kbuf, *vbuf; + char buf[RECBUFSIZ], *rbuf; + printfflush("\n name=%s rnum=%d bnum=%d dnum=%d pnum=%d" + " align=%d fbpsiz=%d c=%d\n\n", name, rnum, bnum, dnum, pnum, align, fbpsiz, cb); + if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum))){ + pdperror(name); + return 1; + } + if(!crsetalign(curia, align) || !crsetfbpsiz(curia, fbpsiz)){ + pdperror(name); + crclose(curia); + return 1; + } + map = NULL; + if(cb) map = cbmapopen(); + err = FALSE; + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", myrand() % pnum + 1); + if(!crput(curia, buf, len, buf, len, CR_DCAT)){ + pdperror(name); + err = TRUE; + break; + } + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d: fsiz=%d rnum=%d)\n", i, crfsiz(curia), crrnum(curia)); + } + } + } + if(map){ + printfflush("Matching records ... "); + cbmapiterinit(map); + while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ + vbuf = cbmapget(map, kbuf, ksiz, &vsiz); + if(!(rbuf = crget(curia, kbuf, ksiz, 0, -1, &rsiz))){ + pdperror(name); + err = TRUE; + break; + } + if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){ + fprintf(stderr, "%s: %s: unmatched record\n", progname, name); + free(rbuf); + err = TRUE; + break; + } + free(rbuf); + } + cbmapclose(map); + if(!err) printfflush("ok\n"); + } + if(!crclose(curia)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform combo command */ +int docombo(const char *name){ + CURIA *curia; + char buf[RECBUFSIZ], wbuf[RECBUFSIZ], *vbuf; + int i, len, wlen, vsiz; + printfflush("\n name=%s\n\n", name); + printfflush("Creating a database with bnum 3 ... "); + if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, 3, 3))){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Setting alignment as 16 ... "); + if(!crsetalign(curia, 16)){ + pdperror(name); + crclose(curia); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 20 records ... "); + for(i = 1; i <= 20; i++){ + len = sprintf(buf, "%08d", i); + if(!crput(curia, buf, len, buf, len, CR_DOVER)){ + pdperror(name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking records ... "); + for(i = 1; i <= 20; i++){ + len = sprintf(buf, "%08d", i); + if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ + pdperror(name); + crclose(curia); + return 1; + } + free(vbuf); + if(vsiz != crvsiz(curia, buf, len)){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Overwriting top 10 records without moving rooms ... "); + for(i = 1; i <= 10; i++){ + len = sprintf(buf, "%08d", i); + if(!crput(curia, buf, len, buf, len, CR_DOVER)){ + pdperror(name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Overwriting top 5 records with moving rooms ... "); + for(i = 1; i <= 5; i++){ + len = sprintf(buf, "%08d", i); + wlen = sprintf(wbuf, "%024d", i); + if(!crput(curia, buf, len, wbuf, wlen, CR_DOVER)){ + pdperror(name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); + for(i = 1; i <= 15; i++){ + len = sprintf(buf, "%08d", i); + wlen = sprintf(wbuf, "========================"); + if(!crput(curia, buf, len, wbuf, wlen, CR_DCAT)){ + pdperror(name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking records ... "); + for(i = 1; i <= 20; i++){ + len = sprintf(buf, "%08d", i); + if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ + pdperror(name); + crclose(curia); + return 1; + } + free(vbuf); + if(vsiz != crvsiz(curia, buf, len)){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Deleting top 10 records ... "); + for(i = 1; i <= 10; i++){ + len = sprintf(buf, "%08d", i); + if(!crout(curia, buf, len)){ + pdperror(name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking deleted records ... "); + for(i = 1; i <= 10; i++){ + len = sprintf(buf, "%08d", i); + vbuf = crget(curia, buf, len, 0, -1, &vsiz); + free(vbuf); + if(vbuf || dpecode != DP_ENOITEM){ + fprintf(stderr, "%s: %s: deleting failed\n", progname, name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); + for(i = 1; i <= 15; i++){ + len = sprintf(buf, "%08d", i); + wlen = sprintf(wbuf, "========================"); + if(!crput(curia, buf, len, wbuf, wlen, CR_DCAT)){ + pdperror(name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking records ... "); + for(i = 1; i <= 20; i++){ + len = sprintf(buf, "%08d", i); + if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ + pdperror(name); + crclose(curia); + return 1; + } + free(vbuf); + if(vsiz != crvsiz(curia, buf, len)){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Optimizing the database ... "); + if(!croptimize(curia, -1)){ + pdperror(name); + crclose(curia); + return 1; + } + printfflush("ok\n"); + printfflush("Checking records ... "); + for(i = 1; i <= 20; i++){ + len = sprintf(buf, "%08d", i); + if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ + pdperror(name); + crclose(curia); + return 1; + } + free(vbuf); + if(vsiz != crvsiz(curia, buf, len)){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Closing database ... "); + if(!crclose(curia)){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Creating a database with bnum 1000000 ... "); + if(!(curia = cropen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 1000000, -1))){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 1000 records ... "); + for(i = 1; i <= 1000; i++){ + len = sprintf(buf, "%08d", i); + if(!crput(curia, buf, len, buf, len, DP_DOVER)){ + pdperror(name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Adding 64 records ... "); + for(i = 1; i <= 64; i++){ + len = sprintf(buf, "%o", i); + if(!crput(curia, buf, len, buf, len, DP_DOVER)){ + pdperror(name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Syncing the database ... "); + if(!crsync(curia)){ + pdperror(name); + crclose(curia); + return 1; + } + printfflush("ok\n"); + printfflush("Retrieving records directly ... "); + for(i = 1; i <= 64; i++){ + len = sprintf(buf, "%o", i); + if(!(vbuf = crsnaffle(name, buf, len, &vsiz))){ + pdperror(name); + crclose(curia); + return 1; + } + if(strcmp(vbuf, buf)){ + fprintf(stderr, "%s: %s: invalid content\n", progname, name); + free(vbuf); + crclose(curia); + return 1; + } + free(vbuf); + if(vsiz != crvsiz(curia, buf, len)){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + crclose(curia); + return 1; + } + } + printfflush("ok\n"); + printfflush("Optimizing the database ... "); + if(!croptimize(curia, -1)){ + pdperror(name); + crclose(curia); + return 1; + } + printfflush("ok\n"); + printfflush("Closing the database ... "); + if(!crclose(curia)){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("all ok\n\n"); + return 0; +} + + +/* perform wicked command */ +int dowicked(const char *name, int rnum, int cb){ + CURIA *curia; + CBMAP *map; + int i, len, err, align, mksiz, mvsiz, rsiz; + const char *mkbuf, *mvbuf; + char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; + printfflush("\n name=%s rnum=%d\n\n", name, rnum); + err = FALSE; + if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, rnum / 10, 5))){ + pdperror(name); + return 1; + } + if(!crsetalign(curia, 16) || !crsetfbpsiz(curia, 256)){ + pdperror(name); + err = TRUE; + } + map = NULL; + if(cb) map = cbmapopen(); + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", myrand() % rnum + 1); + switch(myrand() % 16){ + case 0: + putchar('O'); + if(!crput(curia, buf, len, buf, len, CR_DOVER)) err = TRUE; + if(map) cbmapput(map, buf, len, buf, len, TRUE); + break; + case 1: + putchar('K'); + if(!crput(curia, buf, len, buf, len, CR_DKEEP) && dpecode != DP_EKEEP) err = TRUE; + if(map) cbmapput(map, buf, len, buf, len, FALSE); + break; + case 2: + putchar('D'); + if(!crout(curia, buf, len) && dpecode != DP_ENOITEM) err = TRUE; + if(map) cbmapout(map, buf, len); + break; + case 3: + putchar('G'); + if(crgetwb(curia, buf, len, 2, RECBUFSIZ, vbuf) == -1 && dpecode != DP_ENOITEM) err = TRUE; + break; + case 4: + putchar('V'); + if(crvsiz(curia, buf, len) == -1 && dpecode != DP_ENOITEM) err = TRUE; + break; + default: + putchar('C'); + if(!crput(curia, buf, len, buf, len, CR_DCAT)) err = TRUE; + if(map) cbmapputcat(map, buf, len, buf, len); + break; + } + if(i % 50 == 0) printfflush(" (%08d)\n", i); + if(!err && rnum > 100 && myrand() % (rnum / 100) == 0){ + if(myrand() % 10 == 0){ + align = (myrand() % 4 + 1) * -1; + } else { + align = myrand() % 32; + } + if(!crsetalign(curia, align)) err = TRUE; + } + if(err){ + pdperror(name); + break; + } + } + if(!croptimize(curia, -1)){ + pdperror(name); + err = TRUE; + } + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", i); + if(!crput(curia, buf, len, ":", -1, CR_DCAT)){ + pdperror(name); + err = TRUE; + break; + } + if(map) cbmapputcat(map, buf, len, ":", -1); + putchar(':'); + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + if(!croptimize(curia, -1)){ + pdperror(name); + err = TRUE; + } + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", i); + if(!(val = crget(curia, buf, len, 0, -1, NULL))){ + pdperror(name); + err = TRUE; + break; + } + free(val); + putchar('='); + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + if(!criterinit(curia)){ + pdperror(name); + err = TRUE; + } + for(i = 1; i <= rnum; i++){ + if(!(val = criternext(curia, NULL))){ + pdperror(name); + err = TRUE; + break; + } + free(val); + putchar('@'); + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + if(map){ + printfflush("Matching records ... "); + cbmapiterinit(map); + while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){ + mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz); + if(!(val = crget(curia, mkbuf, mksiz, 0, -1, &rsiz))){ + pdperror(name); + err = TRUE; + break; + } + if(rsiz != mvsiz || memcmp(val, mvbuf, rsiz)){ + fprintf(stderr, "%s: %s: unmatched record\n", progname, name); + free(val); + err = TRUE; + break; + } + free(val); + } + cbmapclose(map); + if(!err) printfflush("ok\n"); + } + if(!crclose(curia)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/crtsv.c =================================================================== --- box/trunk/qdbm/crtsv.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/crtsv.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,266 +0,0 @@ -/************************************************************************************************* - * Mutual converter between a database of Curia and a TSV text - * 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 -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -int runimport(int argc, char **argv); -int runexport(int argc, char **argv); -void pdperror(const char *name); -char *getl(void); -int doimport(const char *name, int bnum, int dnum, int bin); -int doexport(const char *name, int bin); - - -/* main routine */ -int main(int argc, char **argv){ - int rv; - cbstdiobin(); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "import")){ - rv = runimport(argc, argv); - } else if(!strcmp(argv[1], "export")){ - rv = runexport(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: mutual converter between TSV and Curia database\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s import [-bnum num] [-dnum num] [-bin] name\n", progname); - fprintf(stderr, " %s export [-bin] name\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of import command */ -int runimport(int argc, char **argv){ - char *name; - int i, bnum, dnum, bin, rv; - name = NULL; - bnum = -1; - dnum = -1; - bin = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-bnum")){ - if(++i >= argc) usage(); - bnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-dnum")){ - if(++i >= argc) usage(); - dnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-bin")){ - bin = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doimport(name, bnum, dnum, bin); - return rv; -} - - -/* parse arguments of export command */ -int runexport(int argc, char **argv){ - char *name; - int i, bin, rv; - name = NULL; - bin = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-bin")){ - bin = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doexport(name, bin); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* read a line */ -char *getl(void){ - char *buf; - int c, len, blen; - buf = NULL; - len = 0; - blen = 256; - while((c = getchar()) != EOF){ - if(blen <= len) blen *= 2; - buf = cbrealloc(buf, blen + 1); - if(c == '\n') c = '\0'; - buf[len++] = c; - if(c == '\0') break; - } - if(!buf) return NULL; - buf[len] = '\0'; - return buf; -} - - -/* perform import command */ -int doimport(const char *name, int bnum, int dnum, int bin){ - CURIA *curia; - char *buf, *kbuf, *vbuf, *ktmp, *vtmp; - int i, err, ktsiz, vtsiz; - /* open a database */ - if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT, bnum, dnum))){ - pdperror(name); - return 1; - } - /* loop for each line */ - err = FALSE; - for(i = 1; (buf = getl()) != NULL; i++){ - kbuf = buf; - if((vbuf = strchr(buf, '\t')) != NULL){ - *vbuf = '\0'; - vbuf++; - /* store a record */ - if(bin){ - ktmp = cbbasedecode(kbuf, &ktsiz); - vtmp = cbbasedecode(vbuf, &vtsiz); - if(!crput(curia, ktmp, ktsiz, vtmp, vtsiz, CR_DOVER)){ - pdperror(name); - err = TRUE; - } - free(vtmp); - free(ktmp); - } else { - if(!crput(curia, kbuf, -1, vbuf, -1, CR_DOVER)){ - pdperror(name); - err = TRUE; - } - } - } else { - fprintf(stderr, "%s: %s: invalid format in line %d\n", progname, name, i); - } - free(buf); - if(err) break; - } - /* close the database */ - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return err ? 1 : 0; -} - - -/* perform export command */ -int doexport(const char *name, int bin){ - CURIA *curia; - char *kbuf, *vbuf, *tmp; - int err, ksiz, vsiz; - /* open a database */ - if(!(curia = cropen(name, CR_OREADER, -1, -1))){ - pdperror(name); - return 1; - } - /* initialize the iterator */ - criterinit(curia); - /* loop for each key */ - err = FALSE; - while((kbuf = criternext(curia, &ksiz)) != NULL){ - /* retrieve a value with a key */ - if(!(vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz))){ - pdperror(name); - free(kbuf); - err = TRUE; - break; - } - /* output data */ - if(bin){ - tmp = cbbaseencode(kbuf, ksiz); - printf("%s\t", tmp); - free(tmp); - tmp = cbbaseencode(vbuf, vsiz); - printf("%s\n", tmp); - free(tmp); - } else { - printf("%s\t%s\n", kbuf, vbuf); - } - /* free resources */ - free(vbuf); - free(kbuf); - } - /* check whether all records were retrieved */ - if(dpecode != DP_ENOITEM){ - pdperror(name); - err = TRUE; - } - /* close the database */ - if(!crclose(curia)){ - pdperror(name); - return 1; - } - return err ? 1 : 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/crtsv.c (from rev 2716, box/trunk/qdbm/crtsv.c) =================================================================== --- box/trunk/qdbm/crtsv.c (rev 0) +++ box/trunk/qdbm/crtsv.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,266 @@ +/************************************************************************************************* + * Mutual converter between a database of Curia and a TSV text + * 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 +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +int runimport(int argc, char **argv); +int runexport(int argc, char **argv); +void pdperror(const char *name); +char *getl(void); +int doimport(const char *name, int bnum, int dnum, int bin); +int doexport(const char *name, int bin); + + +/* main routine */ +int main(int argc, char **argv){ + int rv; + cbstdiobin(); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "import")){ + rv = runimport(argc, argv); + } else if(!strcmp(argv[1], "export")){ + rv = runexport(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: mutual converter between TSV and Curia database\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s import [-bnum num] [-dnum num] [-bin] name\n", progname); + fprintf(stderr, " %s export [-bin] name\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of import command */ +int runimport(int argc, char **argv){ + char *name; + int i, bnum, dnum, bin, rv; + name = NULL; + bnum = -1; + dnum = -1; + bin = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-bnum")){ + if(++i >= argc) usage(); + bnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-dnum")){ + if(++i >= argc) usage(); + dnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-bin")){ + bin = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doimport(name, bnum, dnum, bin); + return rv; +} + + +/* parse arguments of export command */ +int runexport(int argc, char **argv){ + char *name; + int i, bin, rv; + name = NULL; + bin = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-bin")){ + bin = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doexport(name, bin); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* read a line */ +char *getl(void){ + char *buf; + int c, len, blen; + buf = NULL; + len = 0; + blen = 256; + while((c = getchar()) != EOF){ + if(blen <= len) blen *= 2; + buf = cbrealloc(buf, blen + 1); + if(c == '\n') c = '\0'; + buf[len++] = c; + if(c == '\0') break; + } + if(!buf) return NULL; + buf[len] = '\0'; + return buf; +} + + +/* perform import command */ +int doimport(const char *name, int bnum, int dnum, int bin){ + CURIA *curia; + char *buf, *kbuf, *vbuf, *ktmp, *vtmp; + int i, err, ktsiz, vtsiz; + /* open a database */ + if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT, bnum, dnum))){ + pdperror(name); + return 1; + } + /* loop for each line */ + err = FALSE; + for(i = 1; (buf = getl()) != NULL; i++){ + kbuf = buf; + if((vbuf = strchr(buf, '\t')) != NULL){ + *vbuf = '\0'; + vbuf++; + /* store a record */ + if(bin){ + ktmp = cbbasedecode(kbuf, &ktsiz); + vtmp = cbbasedecode(vbuf, &vtsiz); + if(!crput(curia, ktmp, ktsiz, vtmp, vtsiz, CR_DOVER)){ + pdperror(name); + err = TRUE; + } + free(vtmp); + free(ktmp); + } else { + if(!crput(curia, kbuf, -1, vbuf, -1, CR_DOVER)){ + pdperror(name); + err = TRUE; + } + } + } else { + fprintf(stderr, "%s: %s: invalid format in line %d\n", progname, name, i); + } + free(buf); + if(err) break; + } + /* close the database */ + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return err ? 1 : 0; +} + + +/* perform export command */ +int doexport(const char *name, int bin){ + CURIA *curia; + char *kbuf, *vbuf, *tmp; + int err, ksiz, vsiz; + /* open a database */ + if(!(curia = cropen(name, CR_OREADER, -1, -1))){ + pdperror(name); + return 1; + } + /* initialize the iterator */ + criterinit(curia); + /* loop for each key */ + err = FALSE; + while((kbuf = criternext(curia, &ksiz)) != NULL){ + /* retrieve a value with a key */ + if(!(vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz))){ + pdperror(name); + free(kbuf); + err = TRUE; + break; + } + /* output data */ + if(bin){ + tmp = cbbaseencode(kbuf, ksiz); + printf("%s\t", tmp); + free(tmp); + tmp = cbbaseencode(vbuf, vsiz); + printf("%s\n", tmp); + free(tmp); + } else { + printf("%s\t%s\n", kbuf, vbuf); + } + /* free resources */ + free(vbuf); + free(kbuf); + } + /* check whether all records were retrieved */ + if(dpecode != DP_ENOITEM){ + pdperror(name); + err = TRUE; + } + /* close the database */ + if(!crclose(curia)){ + pdperror(name); + return 1; + } + return err ? 1 : 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/curia.c =================================================================== --- box/trunk/qdbm/curia.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/curia.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,1192 +0,0 @@ -/************************************************************************************************* - * Implementation of Curia - * 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. - *************************************************************************************************/ - - -#define QDBM_INTERNAL 1 - -#include "curia.h" -#include "myconf.h" - -#define CR_NAMEMAX 512 /* max size of a database name */ -#define CR_DPMAX 512 /* max number of division of a database */ -#define CR_DIRMODE 00755 /* permission of a creating directory */ -#define CR_FILEMODE 00644 /* permission of a creating file */ -#define CR_PATHBUFSIZ 1024 /* size of a path buffer */ -#define CR_DEFDNUM 5 /* default number of division of a database */ -#define CR_ATTRBNUM 16 /* bucket number of attrubute database */ -#define CR_DPNAME "depot" /* name of each sub database */ -#define CR_KEYDNUM "dnum" /* key of division number */ -#define CR_KEYLRNUM "lrnum" /* key of the number of large objects */ -#define CR_TMPFSUF MYEXTSTR "crtmp" /* suffix of a temporary directory */ -#define CR_LOBDIR "lob" /* name of the directory of large objects */ -#define CR_LOBDDEPTH 2 /* depth of the directories of large objects */ -#define CR_NUMBUFSIZ 32 /* size of a buffer for a number */ -#define CR_IOBUFSIZ 8192 /* size of an I/O buffer */ - - -/* private function prototypes */ -static char *crstrdup(const char *str); -static int crdpgetnum(DEPOT *depot, const char *kbuf, int ksiz); -static char *crgetlobpath(CURIA *curia, const char *kbuf, int ksiz); -static int crmklobdir(const char *path); -static int crrmlobdir(const char *path); -static int crcplobdir(CURIA *curia, const char *path); -static int crwrite(int fd, const void *buf, int size); -static int crread(int fd, void *buf, int size); - - - -/************************************************************************************************* - * public objects - *************************************************************************************************/ - - -/* Get a database handle. */ -CURIA *cropen(const char *name, int omode, int bnum, int dnum){ - DEPOT *attr, **depots; - char path[CR_PATHBUFSIZ], *tname; - int i, j, dpomode, inode, lrnum; - struct stat sbuf; - CURIA *curia; - assert(name); - if(dnum < 1) dnum = CR_DEFDNUM; - if(dnum > CR_DPMAX) dnum = CR_DPMAX; - if(strlen(name) > CR_NAMEMAX){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return NULL; - } - dpomode = DP_OREADER; - if(omode & CR_OWRITER){ - dpomode = DP_OWRITER; - if(omode & CR_OCREAT) dpomode |= DP_OCREAT; - if(omode & CR_OTRUNC) dpomode |= DP_OTRUNC; - if(omode & CR_OSPARSE) dpomode |= DP_OSPARSE; - } - if(omode & CR_ONOLCK) dpomode |= DP_ONOLCK; - if(omode & CR_OLCKNB) dpomode |= DP_OLCKNB; - attr = NULL; - lrnum = 0; - if((omode & CR_OWRITER) && (omode & CR_OCREAT)){ - if(mkdir(name, CR_DIRMODE) == -1 && errno != EEXIST){ - dpecodeset(DP_EMKDIR, __FILE__, __LINE__); - return NULL; - } - sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); - if(!(attr = dpopen(path, dpomode, CR_ATTRBNUM))) return NULL; - if(dprnum(attr) > 0){ - if((dnum = crdpgetnum(attr, CR_KEYDNUM, -1)) < 1 || - (lrnum = crdpgetnum(attr, CR_KEYLRNUM, -1)) < 0){ - dpclose(attr); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - } else { - if(!dpput(attr, CR_KEYDNUM, -1, (char *)&dnum, sizeof(int), DP_DOVER) || - !dpput(attr, CR_KEYLRNUM, -1, (char *)&lrnum, sizeof(int), DP_DOVER)){ - dpclose(attr); - return NULL; - } - for(i = 0; i < dnum; i++){ - sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1); - if(mkdir(path, CR_DIRMODE) == -1 && errno != EEXIST){ - dpclose(attr); - dpecodeset(DP_EMKDIR, __FILE__, __LINE__); - return NULL; - } - } - } - } - if(!attr){ - sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); - if(!(attr = dpopen(path, dpomode, 1))) return NULL; - if(!(omode & CR_OTRUNC)){ - if((dnum = crdpgetnum(attr, CR_KEYDNUM, -1)) < 1 || - (lrnum = crdpgetnum(attr, CR_KEYLRNUM, -1)) < 0){ - dpclose(attr); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - } - } - if(omode & CR_OTRUNC){ - for(i = 0; i < CR_DPMAX; i++){ - sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_DPNAME); - if(unlink(path) == -1 && errno != ENOENT){ - dpclose(attr); - dpecodeset(DP_EUNLINK, __FILE__, __LINE__); - return NULL; - } - sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_LOBDIR); - if(!crrmlobdir(path)){ - dpclose(attr); - return NULL; - } - if(i >= dnum){ - sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1); - if(rmdir(path) == -1 && errno != ENOENT){ - dpclose(attr); - dpecodeset(DP_ERMDIR, __FILE__, __LINE__); - return NULL; - } - } - } - errno = 0; - } - if(lstat(name, &sbuf) == -1){ - dpclose(attr); - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - return NULL; - } - inode = sbuf.st_ino; - if(!(depots = malloc(dnum * sizeof(DEPOT *)))){ - dpclose(attr); - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return NULL; - } - for(i = 0; i < dnum; i++){ - sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_DPNAME); - if(!(depots[i] = dpopen(path, dpomode, bnum))){ - for(j = 0; j < i; j++){ - dpclose(depots[j]); - } - free(depots); - dpclose(attr); - return NULL; - } - } - curia = malloc(sizeof(CURIA)); - tname = crstrdup(name); - if(!curia || !tname){ - free(curia); - free(tname); - for(i = 0; i < dnum; i++){ - dpclose(depots[i]); - } - free(depots); - dpclose(attr); - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return NULL; - } - curia->name = tname; - curia->wmode = (omode & CR_OWRITER); - curia->inode = inode; - curia->attr = attr; - curia->depots = depots; - curia->dnum = dnum; - curia->inum = 0; - curia->lrnum = lrnum; - return curia; -} - - -/* Close a database handle. */ -int crclose(CURIA *curia){ - int i, err; - assert(curia); - err = FALSE; - for(i = 0; i < curia->dnum; i++){ - if(!dpclose(curia->depots[i])) err = TRUE; - } - free(curia->depots); - if(curia->wmode){ - if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER)) - err = TRUE; - } - if(!dpclose(curia->attr)) err = TRUE; - free(curia->name); - free(curia); - return err ? FALSE : TRUE; -} - - -/* Store a record. */ -int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ - int dpdmode; - int tnum; - assert(curia && kbuf && vbuf); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(ksiz < 0) ksiz = strlen(kbuf); - switch(dmode){ - case CR_DKEEP: dpdmode = DP_DKEEP; break; - case CR_DCAT: dpdmode = DP_DCAT; break; - default: dpdmode = DP_DOVER; break; - } - tnum = dpouterhash(kbuf, ksiz) % curia->dnum; - return dpput(curia->depots[tnum], kbuf, ksiz, vbuf, vsiz, dpdmode); -} - - -/* Delete a record. */ -int crout(CURIA *curia, const char *kbuf, int ksiz){ - int tnum; - assert(curia && kbuf); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(ksiz < 0) ksiz = strlen(kbuf); - tnum = dpouterhash(kbuf, ksiz) % curia->dnum; - return dpout(curia->depots[tnum], kbuf, ksiz); -} - - -/* Retrieve a record. */ -char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp){ - int tnum; - assert(curia && kbuf && start >= 0); - if(ksiz < 0) ksiz = strlen(kbuf); - tnum = dpouterhash(kbuf, ksiz) % curia->dnum; - return dpget(curia->depots[tnum], kbuf, ksiz, start, max, sp); -} - - -/* Retrieve a record and write the value into a buffer. */ -int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf){ - int tnum; - assert(curia && kbuf && start >= 0 && max >= 0 && vbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - tnum = dpouterhash(kbuf, ksiz) % curia->dnum; - return dpgetwb(curia->depots[tnum], kbuf, ksiz, start, max, vbuf); -} - - -/* Get the size of the value of a record. */ -int crvsiz(CURIA *curia, const char *kbuf, int ksiz){ - int tnum; - assert(curia && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - tnum = dpouterhash(kbuf, ksiz) % curia->dnum; - return dpvsiz(curia->depots[tnum], kbuf, ksiz); -} - - -/* Initialize the iterator of a database handle. */ -int criterinit(CURIA *curia){ - int i, err; - assert(curia); - err = FALSE; - for(i = 0; i < curia->dnum; i++){ - if(!dpiterinit(curia->depots[i])){ - err = TRUE; - break; - } - } - curia->inum = 0; - return err ? FALSE : TRUE; -} - - -/* Get the next key of the iterator. */ -char *criternext(CURIA *curia, int *sp){ - char *kbuf; - assert(curia); - kbuf = NULL; - while(curia->inum < curia->dnum && !(kbuf = dpiternext(curia->depots[curia->inum], sp))){ - if(dpecode != DP_ENOITEM) return NULL; - (curia->inum)++; - } - return kbuf; -} - - -/* Set alignment of a database handle. */ -int crsetalign(CURIA *curia, int align){ - int i, err; - assert(curia); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - for(i = 0; i < curia->dnum; i++){ - if(!dpsetalign(curia->depots[i], align)){ - err = TRUE; - break; - } - } - return err ? FALSE : TRUE; -} - - -/* Set the size of the free block pool of a database handle. */ -int crsetfbpsiz(CURIA *curia, int size){ - int i, err; - assert(curia && size >= 0); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - for(i = 0; i < curia->dnum; i++){ - if(!dpsetfbpsiz(curia->depots[i], size)){ - err = TRUE; - break; - } - } - return err ? FALSE : TRUE; -} - - -/* Synchronize contents of updating a database with the files and the devices. */ -int crsync(CURIA *curia){ - int i, err; - assert(curia); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) || - !dpsync(curia->attr)) err = TRUE; - for(i = 0; i < curia->dnum; i++){ - if(!dpsync(curia->depots[i])){ - err = TRUE; - break; - } - } - return err ? FALSE : TRUE; -} - - -/* Optimize a database. */ -int croptimize(CURIA *curia, int bnum){ - int i, err; - assert(curia); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - for(i = 0; i < curia->dnum; i++){ - if(!dpoptimize(curia->depots[i], bnum)){ - err = TRUE; - break; - } - } - curia->inum = 0; - return err ? FALSE : TRUE; -} - - -/* Get the name of a database. */ -char *crname(CURIA *curia){ - char *name; - assert(curia); - if(!(name = crstrdup(curia->name))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return NULL; - } - return name; -} - - -/* Get the total size of database files. */ -int crfsiz(CURIA *curia){ - int i, sum, rv; - assert(curia); - if((sum = dpfsiz(curia->attr)) == -1) return -1; - for(i = 0; i < curia->dnum; i++){ - if((rv = dpfsiz(curia->depots[i])) == -1) return -1; - sum += rv; - } - return sum; -} - - -/* Get the total size of database files as double-precision value. */ -double crfsizd(CURIA *curia){ - double sum; - int i, rv; - assert(curia); - sum = 0.0; - if((sum = dpfsiz(curia->attr)) < 0) return -1.0; - for(i = 0; i < curia->dnum; i++){ - if((rv = dpfsiz(curia->depots[i])) == -1) return -1.0; - sum += rv; - } - return sum; -} - - -/* Get the total number of the elements of each bucket array. */ -int crbnum(CURIA *curia){ - int i, sum, rv; - assert(curia); - sum = 0; - for(i = 0; i < curia->dnum; i++){ - rv = dpbnum(curia->depots[i]); - if(rv == -1) return -1; - sum += rv; - } - return sum; -} - - -/* Get the total number of the used elements of each bucket array. */ -int crbusenum(CURIA *curia){ - int i, sum, rv; - assert(curia); - sum = 0; - for(i = 0; i < curia->dnum; i++){ - rv = dpbusenum(curia->depots[i]); - if(rv == -1) return -1; - sum += rv; - } - return sum; -} - - -/* Get the number of the records stored in a database. */ -int crrnum(CURIA *curia){ - int i, sum, rv; - assert(curia); - sum = 0; - for(i = 0; i < curia->dnum; i++){ - rv = dprnum(curia->depots[i]); - if(rv == -1) return -1; - sum += rv; - } - return sum; -} - - -/* Check whether a database handle is a writer or not. */ -int crwritable(CURIA *curia){ - assert(curia); - return curia->wmode; -} - - -/* Check whether a database has a fatal error or not. */ -int crfatalerror(CURIA *curia){ - int i; - assert(curia); - if(dpfatalerror(curia->attr)) return TRUE; - for(i = 0; i < curia->dnum; i++){ - if(dpfatalerror(curia->depots[i])) return TRUE; - } - return FALSE; -} - - -/* Get the inode number of a database directory. */ -int crinode(CURIA *curia){ - assert(curia); - return curia->inode; -} - - -/* Get the last modified time of a database. */ -time_t crmtime(CURIA *curia){ - assert(curia); - return dpmtime(curia->attr); -} - - -/* Remove a database directory. */ -int crremove(const char *name){ - struct stat sbuf; - CURIA *curia; - char path[CR_PATHBUFSIZ]; - assert(name); - if(lstat(name, &sbuf) == -1){ - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - return FALSE; - } - if((curia = cropen(name, CR_OWRITER | CR_OTRUNC, 1, 1)) != NULL) crclose(curia); - sprintf(path, "%s%c0001%c%s", name, MYPATHCHR, MYPATHCHR, CR_DPNAME); - dpremove(path); - sprintf(path, "%s%c0001", name, MYPATHCHR); - if(rmdir(path) == -1){ - dpecodeset(DP_ERMDIR, __FILE__, __LINE__); - return FALSE; - } - sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); - if(!dpremove(path)) return FALSE; - if(rmdir(name) == -1){ - dpecodeset(DP_ERMDIR, __FILE__, __LINE__); - return FALSE; - } - return TRUE; -} - - -/* Repair a broken database directory. */ -int crrepair(const char *name){ - CURIA *tcuria; - DEPOT *tdepot; - char path[CR_PATHBUFSIZ], *kbuf, *vbuf; - struct stat sbuf; - int i, j, err, flags, bnum, dnum, ksiz, vsiz; - assert(name); - err = FALSE; - flags = 0; - bnum = 0; - dnum = 0; - sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); - if(lstat(path, &sbuf) != -1){ - if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){ - flags = dpgetflags(tdepot); - dpclose(tdepot); - } - } - for(i = 1; i <= CR_DPMAX; i++){ - sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i, MYPATHCHR, CR_DPNAME); - if(lstat(path, &sbuf) != -1){ - dnum++; - if(!dprepair(path)) err = TRUE; - if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){ - bnum += dpbnum(tdepot); - dpclose(tdepot); - } - } - } - if(dnum < CR_DEFDNUM) dnum = CR_DEFDNUM; - bnum /= dnum; - sprintf(path, "%s%s", name, CR_TMPFSUF); - if((tcuria = cropen(path, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum)) != NULL){ - if(!crsetflags(tcuria, flags)) err = TRUE; - for(i = 1; i <= CR_DPMAX; i++){ - sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i, MYPATHCHR, CR_DPNAME); - if(lstat(path, &sbuf) != -1){ - if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){ - if(!dpiterinit(tdepot)) err = TRUE; - while((kbuf = dpiternext(tdepot, &ksiz)) != NULL){ - if((vbuf = dpget(tdepot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ - if(!crput(tcuria, kbuf, ksiz, vbuf, vsiz, CR_DKEEP)) err = TRUE; - free(vbuf); - } - free(kbuf); - } - dpclose(tdepot); - } else { - err = TRUE; - } - } - for(j = 0; j <= CR_DPMAX; j++){ - sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, j, MYPATHCHR, CR_LOBDIR); - if(lstat(path, &sbuf) != -1){ - if(!crcplobdir(tcuria, path)) err = TRUE; - } - } - } - if(!crclose(tcuria)) err = TRUE; - if(!crremove(name)) err = TRUE; - sprintf(path, "%s%s", name, CR_TMPFSUF); - if(rename(path, name) == -1){ - if(!err) dpecodeset(DP_EMISC, __FILE__, __LINE__); - err = TRUE; - } - } else { - err = TRUE; - } - return err ? FALSE : TRUE; -} - - -/* Dump all records as endian independent data. */ -int crexportdb(CURIA *curia, const char *name){ - char path[CR_PATHBUFSIZ], *kbuf, *vbuf, *pbuf; - int i, err, *fds, ksiz, vsiz, psiz; - assert(curia && name); - if(!(criterinit(curia))) return FALSE; - if(mkdir(name, CR_DIRMODE) == -1 && errno != EEXIST){ - dpecodeset(DP_EMKDIR, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - fds = malloc(sizeof(int) * curia->dnum); - for(i = 0; i < curia->dnum; i++){ - sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1); - if((fds[i] = open(path, O_RDWR | O_CREAT | O_TRUNC, CR_FILEMODE)) == -1){ - if(!err) dpecodeset(DP_EOPEN, __FILE__, __LINE__); - err = TRUE; - break; - } - } - while(!err && (kbuf = criternext(curia, &ksiz)) != NULL){ - if((vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ - if((pbuf = malloc(ksiz + vsiz + CR_NUMBUFSIZ * 2)) != NULL){ - psiz = 0; - psiz += sprintf(pbuf + psiz, "%X\n%X\n", ksiz, vsiz); - memcpy(pbuf + psiz, kbuf, ksiz); - psiz += ksiz; - pbuf[psiz++] = '\n'; - memcpy(pbuf + psiz, vbuf, vsiz); - psiz += vsiz; - pbuf[psiz++] = '\n'; - if(!crwrite(fds[curia->inum], pbuf, psiz)){ - dpecodeset(DP_EWRITE, __FILE__, __LINE__); - err = TRUE; - } - free(pbuf); - } else { - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - err = TRUE; - } - free(vbuf); - } else { - err = TRUE; - } - free(kbuf); - } - for(i = 0; i < curia->dnum; i++){ - if(fds[i] != -1 && close(fds[i]) == -1){ - if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); - err = TRUE; - } - } - free(fds); - return !err && !crfatalerror(curia); -} - - -/* Load all records from endian independent data. */ -int crimportdb(CURIA *curia, const char *name){ - DEPOT *depot; - char ipath[CR_PATHBUFSIZ], opath[CR_PATHBUFSIZ], *kbuf, *vbuf; - int i, err, ksiz, vsiz; - struct stat sbuf; - assert(curia && name); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(crrnum(curia) > 0){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - for(i = 0; !err && i < CR_DPMAX; i++){ - sprintf(ipath, "%s%c%04d", name, MYPATHCHR, i + 1); - if(lstat(ipath, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)) break; - sprintf(opath, "%s%c%04d%s", curia->name, MYPATHCHR, i + 1, CR_TMPFSUF); - if((depot = dpopen(opath, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1)) != NULL){ - if(dpimportdb(depot, ipath)){ - dpiterinit(depot); - while((kbuf = dpiternext(depot, &ksiz)) != NULL){ - if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ - if(!crput(curia, kbuf, ksiz, vbuf, vsiz, CR_DKEEP)) err = TRUE; - free(vbuf); - } else { - err = TRUE; - } - free(kbuf); - } - } else { - err = TRUE; - } - if(!dpclose(depot)) err = TRUE; - if(!dpremove(opath)) err = TRUE; - } else { - err = TRUE; - } - } - return !err && !crfatalerror(curia); -} - - -/* Retrieve a record directly from a database directory. */ -char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp){ - char path[CR_PATHBUFSIZ], *vbuf; - int dnum, vsiz, tnum; - assert(name && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); - if(!(vbuf = dpsnaffle(path, CR_KEYDNUM, -1, &vsiz)) || vsiz != sizeof(int) || - (dnum = *(int *)vbuf) < 1){ - free(vbuf); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - free(vbuf); - tnum = dpouterhash(kbuf, ksiz) % dnum; - sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, tnum + 1, MYPATHCHR, CR_DPNAME); - return dpsnaffle(path, kbuf, ksiz, sp); -} - - -/* Store a large object. */ -int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ - char *path; - int mode, fd, err, be; - struct stat sbuf; - assert(curia && kbuf && vbuf); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(ksiz < 0) ksiz = strlen(kbuf); - if(vsiz < 0) vsiz = strlen(vbuf); - if(!(path = crgetlobpath(curia, kbuf, ksiz))) return FALSE; - if(!crmklobdir(path)){ - free(path); - return FALSE; - } - be = lstat(path, &sbuf) != -1 && S_ISREG(sbuf.st_mode); - mode = O_RDWR | O_CREAT; - if(dmode & CR_DKEEP) mode |= O_EXCL; - if(dmode & CR_DCAT){ - mode |= O_APPEND; - } else { - mode |= O_TRUNC; - } - if((fd = open(path, mode, CR_FILEMODE)) == -1){ - free(path); - dpecodeset(DP_EOPEN, __FILE__, __LINE__); - if(dmode == CR_DKEEP) dpecodeset(DP_EKEEP, __FILE__, __LINE__); - return FALSE; - } - free(path); - err = FALSE; - if(crwrite(fd, vbuf, vsiz) == -1){ - err = TRUE; - dpecodeset(DP_EWRITE, __FILE__, __LINE__); - } - if(close(fd) == -1){ - err = TRUE; - dpecodeset(DP_ECLOSE, __FILE__, __LINE__); - } - if(!err && !be) (curia->lrnum)++; - return err ? FALSE : TRUE; -} - - -/* Delete a large object. */ -int croutlob(CURIA *curia, const char *kbuf, int ksiz){ - char *path; - int err, be; - struct stat sbuf; - assert(curia && kbuf); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(ksiz < 0) ksiz = strlen(kbuf); - if(!(path = crgetlobpath(curia, kbuf, ksiz))) return FALSE; - be = lstat(path, &sbuf) != -1 && S_ISREG(sbuf.st_mode); - err = FALSE; - if(unlink(path) == -1){ - err = TRUE; - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - } - free(path); - if(!err && be) (curia->lrnum)--; - return err ? FALSE : TRUE; -} - - -/* Retrieve a large object. */ -char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp){ - char *path, *buf; - struct stat sbuf; - int fd, size; - assert(curia && kbuf && start >= 0); - if(ksiz < 0) ksiz = strlen(kbuf); - if(!(path = crgetlobpath(curia, kbuf, ksiz))) return NULL; - if((fd = open(path, O_RDONLY, CR_FILEMODE)) == -1){ - free(path); - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return NULL; - } - free(path); - if(fstat(fd, &sbuf) == -1){ - close(fd); - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - return NULL; - } - if(start > sbuf.st_size){ - close(fd); - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return NULL; - } - if(lseek(fd, start, SEEK_SET) == -1){ - close(fd); - dpecodeset(DP_ESEEK, __FILE__, __LINE__); - return NULL; - } - if(max < 0) max = sbuf.st_size; - if(!(buf = malloc(max + 1))){ - close(fd); - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return NULL; - } - size = crread(fd, buf, max); - close(fd); - if(size == -1){ - free(buf); - dpecodeset(DP_EREAD, __FILE__, __LINE__); - return NULL; - } - buf[size] = '\0'; - if(sp) *sp = size; - return buf; -} - - -/* Get the file descriptor of a large object. */ -int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz){ - char *path; - int fd; - assert(curia && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if(!(path = crgetlobpath(curia, kbuf, ksiz))) return -1; - if((fd = open(path, curia->wmode ? O_RDWR: O_RDONLY, CR_FILEMODE)) == -1){ - free(path); - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return -1; - } - free(path); - return fd; -} - - -/* Get the size of the value of a large object. */ -int crvsizlob(CURIA *curia, const char *kbuf, int ksiz){ - char *path; - struct stat sbuf; - assert(curia && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if(!(path = crgetlobpath(curia, kbuf, ksiz))) return -1; - if(lstat(path, &sbuf) == -1){ - free(path); - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return -1; - } - free(path); - return sbuf.st_size; -} - - -/* Get the number of the large objects stored in a database. */ -int crrnumlob(CURIA *curia){ - assert(curia); - return curia->lrnum; -} - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Synchronize updating contents on memory. */ -int crmemsync(CURIA *curia){ - int i, err; - assert(curia); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) || - !dpmemsync(curia->attr)) err = TRUE; - for(i = 0; i < curia->dnum; i++){ - if(!dpmemsync(curia->depots[i])){ - err = TRUE; - break; - } - } - return err ? FALSE : TRUE; -} - - -/* Synchronize updating contents on memory, not physically. */ -int crmemflush(CURIA *curia){ - int i, err; - assert(curia); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) || - !dpmemsync(curia->attr)) err = TRUE; - for(i = 0; i < curia->dnum; i++){ - if(!dpmemflush(curia->depots[i])){ - err = TRUE; - break; - } - } - return err ? FALSE : TRUE; -} - - -/* Get flags of a database. */ -int crgetflags(CURIA *curia){ - assert(curia); - return dpgetflags(curia->attr); -} - - -/* Set flags of a database. */ -int crsetflags(CURIA *curia, int flags){ - assert(curia); - if(!curia->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - return dpsetflags(curia->attr, flags); -} - - - -/************************************************************************************************* - * private objects - *************************************************************************************************/ - - -/* Get a copied string. - `str' specifies an original string. - The return value is a copied string whose region is allocated by `malloc'. */ -static char *crstrdup(const char *str){ - int len; - char *buf; - assert(str); - len = strlen(str); - if(!(buf = malloc(len + 1))) return NULL; - memcpy(buf, str, len + 1); - return buf; -} - - -/* Get an integer from a database. - `depot' specifies an inner database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the key. - The return value is the integer of the corresponding record. */ -static int crdpgetnum(DEPOT *depot, const char *kbuf, int ksiz){ - char *vbuf; - int vsiz, rv; - if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) || vsiz != sizeof(int)){ - free(vbuf); - return INT_MIN; - } - rv = *(int *)vbuf; - free(vbuf); - return rv; -} - - -/* Get the path of a large object. - `curia' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the key. - The return value is a path string whose region is allocated by `malloc'. */ -static char *crgetlobpath(CURIA *curia, const char *kbuf, int ksiz){ - char prefix[CR_PATHBUFSIZ], *wp, *path; - int i, hash; - assert(curia && kbuf && ksiz >= 0); - wp = prefix; - wp += sprintf(wp, "%s%c%04d%c%s%c", - curia->name, MYPATHCHR, dpouterhash(kbuf, ksiz) % curia->dnum + 1, - MYPATHCHR, CR_LOBDIR, MYPATHCHR); - hash = dpinnerhash(kbuf, ksiz); - for(i = 0; i < CR_LOBDDEPTH; i++){ - wp += sprintf(wp, "%02X%c", hash % 0x100, MYPATHCHR); - hash /= 0x100; - } - if(!(path = malloc(strlen(prefix) + ksiz * 2 + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return NULL; - } - wp = path; - wp += sprintf(path, "%s", prefix); - for(i = 0; i < ksiz; i++){ - wp += sprintf(wp, "%02X", ((unsigned char *)kbuf)[i]); - } - return path; -} - - -/* Create directories included in a path. - `path' specifies a path. - The return value is true if successful, else, it is false. */ -static int crmklobdir(const char *path){ - char elem[CR_PATHBUFSIZ], *wp; - const char *dp; - int err, len; - wp = elem; - err = FALSE; - while(*path != '\0' && (dp = strchr(path, MYPATHCHR)) != NULL){ - len = dp - path; - if((wp != elem || dp == path)) wp += sprintf(wp, "%c", MYPATHCHR); - memcpy(wp, path, len); - wp[len] = '\0'; - wp += len; - if(mkdir(elem, CR_DIRMODE) == -1 && errno != EEXIST) err = TRUE; - path = dp + 1; - } - if(err) dpecodeset(DP_EMKDIR, __FILE__, __LINE__); - return err ? FALSE : TRUE; -} - - -/* Remove file and directories under a directory. - `path' specifies a path. - The return value is true if successful, else, it is false. */ -static int crrmlobdir(const char *path){ - char elem[CR_PATHBUFSIZ]; - DIR *DD; - struct dirent *dp; - assert(path); - if(unlink(path) != -1){ - return TRUE; - } else { - if(errno == ENOENT) return TRUE; - if(!(DD = opendir(path))){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - while((dp = readdir(DD)) != NULL){ - if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue; - sprintf(elem, "%s%c%s", path, MYPATHCHR, dp->d_name); - if(!crrmlobdir(elem)){ - closedir(DD); - return FALSE; - } - } - } - if(closedir(DD) == -1){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - if(rmdir(path) == -1){ - dpecodeset(DP_ERMDIR, __FILE__, __LINE__); - return FALSE; - } - return TRUE; -} - - -/* Copy file and directories under a directory for repairing. - `path' specifies a path. - The return value is true if successful, else, it is false. */ -static int crcplobdir(CURIA *curia, const char *path){ - char elem[CR_PATHBUFSIZ], numbuf[3], *rp, *kbuf, *vbuf; - DIR *DD; - struct dirent *dp; - struct stat sbuf; - int i, ksiz, vsiz, fd; - assert(curia && path); - if(lstat(path, &sbuf) == -1){ - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - return FALSE; - } - if(S_ISREG(sbuf.st_mode)){ - rp = strrchr(path, MYPATHCHR) + 1; - for(i = 0; rp[i] != '\0'; i += 2){ - numbuf[0] = rp[i]; - numbuf[1] = rp[i+1]; - numbuf[2] = '\0'; - elem[i/2] = (int)strtol(numbuf, NULL, 16); - } - kbuf = elem; - ksiz = i / 2; - vsiz = sbuf.st_size; - if(!(vbuf = malloc(vsiz + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return FALSE; - } - if((fd = open(path, O_RDONLY, CR_FILEMODE)) == -1){ - free(vbuf); - dpecodeset(DP_EOPEN, __FILE__, __LINE__); - return FALSE; - } - if(crread(fd, vbuf, vsiz) == -1){ - close(fd); - free(vbuf); - dpecodeset(DP_EOPEN, __FILE__, __LINE__); - return FALSE; - } - if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, DP_DOVER)){ - close(fd); - free(vbuf); - return FALSE; - } - close(fd); - free(vbuf); - return TRUE; - } - if(!(DD = opendir(path))){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - while((dp = readdir(DD)) != NULL){ - if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue; - sprintf(elem, "%s%c%s", path, MYPATHCHR, dp->d_name); - if(!crcplobdir(curia, elem)){ - closedir(DD); - return FALSE; - } - } - if(closedir(DD) == -1){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - return TRUE; -} - - -/* Write into a file. - `fd' specifies a file descriptor. - `buf' specifies a buffer to write. - `size' specifies the size of the buffer. - The return value is the size of the written buffer, or, -1 on failure. */ -static int crwrite(int fd, const void *buf, int size){ - char *lbuf; - int rv, wb; - assert(fd >= 0 && buf && size >= 0); - lbuf = (char *)buf; - rv = 0; - do { - wb = write(fd, lbuf, size); - switch(wb){ - case -1: if(errno != EINTR) return -1; - case 0: break; - default: - lbuf += wb; - size -= wb; - rv += wb; - break; - } - } while(size > 0); - return rv; -} - - -/* Read from a file and store the data into a buffer. - `fd' specifies a file descriptor. - `buffer' specifies a buffer to store into. - `size' specifies the size to read with. - The return value is the size read with, or, -1 on failure. */ -static int crread(int fd, void *buf, int size){ - char *lbuf; - int i, bs; - assert(fd >= 0 && buf && size >= 0); - lbuf = buf; - for(i = 0; i < size && (bs = read(fd, lbuf + i, size - i)) != 0; i += bs){ - if(bs == -1 && errno != EINTR) return -1; - } - return i; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/curia.c (from rev 2716, box/trunk/qdbm/curia.c) =================================================================== --- box/trunk/qdbm/curia.c (rev 0) +++ box/trunk/qdbm/curia.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,1192 @@ +/************************************************************************************************* + * Implementation of Curia + * 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. + *************************************************************************************************/ + + +#define QDBM_INTERNAL 1 + +#include "curia.h" +#include "myconf.h" + +#define CR_NAMEMAX 512 /* max size of a database name */ +#define CR_DPMAX 512 /* max number of division of a database */ +#define CR_DIRMODE 00755 /* permission of a creating directory */ +#define CR_FILEMODE 00644 /* permission of a creating file */ +#define CR_PATHBUFSIZ 1024 /* size of a path buffer */ +#define CR_DEFDNUM 5 /* default number of division of a database */ +#define CR_ATTRBNUM 16 /* bucket number of attrubute database */ +#define CR_DPNAME "depot" /* name of each sub database */ +#define CR_KEYDNUM "dnum" /* key of division number */ +#define CR_KEYLRNUM "lrnum" /* key of the number of large objects */ +#define CR_TMPFSUF MYEXTSTR "crtmp" /* suffix of a temporary directory */ +#define CR_LOBDIR "lob" /* name of the directory of large objects */ +#define CR_LOBDDEPTH 2 /* depth of the directories of large objects */ +#define CR_NUMBUFSIZ 32 /* size of a buffer for a number */ +#define CR_IOBUFSIZ 8192 /* size of an I/O buffer */ + + +/* private function prototypes */ +static char *crstrdup(const char *str); +static int crdpgetnum(DEPOT *depot, const char *kbuf, int ksiz); +static char *crgetlobpath(CURIA *curia, const char *kbuf, int ksiz); +static int crmklobdir(const char *path); +static int crrmlobdir(const char *path); +static int crcplobdir(CURIA *curia, const char *path); +static int crwrite(int fd, const void *buf, int size); +static int crread(int fd, void *buf, int size); + + + +/************************************************************************************************* + * public objects + *************************************************************************************************/ + + +/* Get a database handle. */ +CURIA *cropen(const char *name, int omode, int bnum, int dnum){ + DEPOT *attr, **depots; + char path[CR_PATHBUFSIZ], *tname; + int i, j, dpomode, inode, lrnum; + struct stat sbuf; + CURIA *curia; + assert(name); + if(dnum < 1) dnum = CR_DEFDNUM; + if(dnum > CR_DPMAX) dnum = CR_DPMAX; + if(strlen(name) > CR_NAMEMAX){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return NULL; + } + dpomode = DP_OREADER; + if(omode & CR_OWRITER){ + dpomode = DP_OWRITER; + if(omode & CR_OCREAT) dpomode |= DP_OCREAT; + if(omode & CR_OTRUNC) dpomode |= DP_OTRUNC; + if(omode & CR_OSPARSE) dpomode |= DP_OSPARSE; + } + if(omode & CR_ONOLCK) dpomode |= DP_ONOLCK; + if(omode & CR_OLCKNB) dpomode |= DP_OLCKNB; + attr = NULL; + lrnum = 0; + if((omode & CR_OWRITER) && (omode & CR_OCREAT)){ + if(mkdir(name, CR_DIRMODE) == -1 && errno != EEXIST){ + dpecodeset(DP_EMKDIR, __FILE__, __LINE__); + return NULL; + } + sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); + if(!(attr = dpopen(path, dpomode, CR_ATTRBNUM))) return NULL; + if(dprnum(attr) > 0){ + if((dnum = crdpgetnum(attr, CR_KEYDNUM, -1)) < 1 || + (lrnum = crdpgetnum(attr, CR_KEYLRNUM, -1)) < 0){ + dpclose(attr); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + } else { + if(!dpput(attr, CR_KEYDNUM, -1, (char *)&dnum, sizeof(int), DP_DOVER) || + !dpput(attr, CR_KEYLRNUM, -1, (char *)&lrnum, sizeof(int), DP_DOVER)){ + dpclose(attr); + return NULL; + } + for(i = 0; i < dnum; i++){ + sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1); + if(mkdir(path, CR_DIRMODE) == -1 && errno != EEXIST){ + dpclose(attr); + dpecodeset(DP_EMKDIR, __FILE__, __LINE__); + return NULL; + } + } + } + } + if(!attr){ + sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); + if(!(attr = dpopen(path, dpomode, 1))) return NULL; + if(!(omode & CR_OTRUNC)){ + if((dnum = crdpgetnum(attr, CR_KEYDNUM, -1)) < 1 || + (lrnum = crdpgetnum(attr, CR_KEYLRNUM, -1)) < 0){ + dpclose(attr); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + } + } + if(omode & CR_OTRUNC){ + for(i = 0; i < CR_DPMAX; i++){ + sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_DPNAME); + if(unlink(path) == -1 && errno != ENOENT){ + dpclose(attr); + dpecodeset(DP_EUNLINK, __FILE__, __LINE__); + return NULL; + } + sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_LOBDIR); + if(!crrmlobdir(path)){ + dpclose(attr); + return NULL; + } + if(i >= dnum){ + sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1); + if(rmdir(path) == -1 && errno != ENOENT){ + dpclose(attr); + dpecodeset(DP_ERMDIR, __FILE__, __LINE__); + return NULL; + } + } + } + errno = 0; + } + if(lstat(name, &sbuf) == -1){ + dpclose(attr); + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + return NULL; + } + inode = sbuf.st_ino; + if(!(depots = malloc(dnum * sizeof(DEPOT *)))){ + dpclose(attr); + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return NULL; + } + for(i = 0; i < dnum; i++){ + sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_DPNAME); + if(!(depots[i] = dpopen(path, dpomode, bnum))){ + for(j = 0; j < i; j++){ + dpclose(depots[j]); + } + free(depots); + dpclose(attr); + return NULL; + } + } + curia = malloc(sizeof(CURIA)); + tname = crstrdup(name); + if(!curia || !tname){ + free(curia); + free(tname); + for(i = 0; i < dnum; i++){ + dpclose(depots[i]); + } + free(depots); + dpclose(attr); + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return NULL; + } + curia->name = tname; + curia->wmode = (omode & CR_OWRITER); + curia->inode = inode; + curia->attr = attr; + curia->depots = depots; + curia->dnum = dnum; + curia->inum = 0; + curia->lrnum = lrnum; + return curia; +} + + +/* Close a database handle. */ +int crclose(CURIA *curia){ + int i, err; + assert(curia); + err = FALSE; + for(i = 0; i < curia->dnum; i++){ + if(!dpclose(curia->depots[i])) err = TRUE; + } + free(curia->depots); + if(curia->wmode){ + if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER)) + err = TRUE; + } + if(!dpclose(curia->attr)) err = TRUE; + free(curia->name); + free(curia); + return err ? FALSE : TRUE; +} + + +/* Store a record. */ +int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ + int dpdmode; + int tnum; + assert(curia && kbuf && vbuf); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(ksiz < 0) ksiz = strlen(kbuf); + switch(dmode){ + case CR_DKEEP: dpdmode = DP_DKEEP; break; + case CR_DCAT: dpdmode = DP_DCAT; break; + default: dpdmode = DP_DOVER; break; + } + tnum = dpouterhash(kbuf, ksiz) % curia->dnum; + return dpput(curia->depots[tnum], kbuf, ksiz, vbuf, vsiz, dpdmode); +} + + +/* Delete a record. */ +int crout(CURIA *curia, const char *kbuf, int ksiz){ + int tnum; + assert(curia && kbuf); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(ksiz < 0) ksiz = strlen(kbuf); + tnum = dpouterhash(kbuf, ksiz) % curia->dnum; + return dpout(curia->depots[tnum], kbuf, ksiz); +} + + +/* Retrieve a record. */ +char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp){ + int tnum; + assert(curia && kbuf && start >= 0); + if(ksiz < 0) ksiz = strlen(kbuf); + tnum = dpouterhash(kbuf, ksiz) % curia->dnum; + return dpget(curia->depots[tnum], kbuf, ksiz, start, max, sp); +} + + +/* Retrieve a record and write the value into a buffer. */ +int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf){ + int tnum; + assert(curia && kbuf && start >= 0 && max >= 0 && vbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + tnum = dpouterhash(kbuf, ksiz) % curia->dnum; + return dpgetwb(curia->depots[tnum], kbuf, ksiz, start, max, vbuf); +} + + +/* Get the size of the value of a record. */ +int crvsiz(CURIA *curia, const char *kbuf, int ksiz){ + int tnum; + assert(curia && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + tnum = dpouterhash(kbuf, ksiz) % curia->dnum; + return dpvsiz(curia->depots[tnum], kbuf, ksiz); +} + + +/* Initialize the iterator of a database handle. */ +int criterinit(CURIA *curia){ + int i, err; + assert(curia); + err = FALSE; + for(i = 0; i < curia->dnum; i++){ + if(!dpiterinit(curia->depots[i])){ + err = TRUE; + break; + } + } + curia->inum = 0; + return err ? FALSE : TRUE; +} + + +/* Get the next key of the iterator. */ +char *criternext(CURIA *curia, int *sp){ + char *kbuf; + assert(curia); + kbuf = NULL; + while(curia->inum < curia->dnum && !(kbuf = dpiternext(curia->depots[curia->inum], sp))){ + if(dpecode != DP_ENOITEM) return NULL; + (curia->inum)++; + } + return kbuf; +} + + +/* Set alignment of a database handle. */ +int crsetalign(CURIA *curia, int align){ + int i, err; + assert(curia); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + for(i = 0; i < curia->dnum; i++){ + if(!dpsetalign(curia->depots[i], align)){ + err = TRUE; + break; + } + } + return err ? FALSE : TRUE; +} + + +/* Set the size of the free block pool of a database handle. */ +int crsetfbpsiz(CURIA *curia, int size){ + int i, err; + assert(curia && size >= 0); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + for(i = 0; i < curia->dnum; i++){ + if(!dpsetfbpsiz(curia->depots[i], size)){ + err = TRUE; + break; + } + } + return err ? FALSE : TRUE; +} + + +/* Synchronize contents of updating a database with the files and the devices. */ +int crsync(CURIA *curia){ + int i, err; + assert(curia); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) || + !dpsync(curia->attr)) err = TRUE; + for(i = 0; i < curia->dnum; i++){ + if(!dpsync(curia->depots[i])){ + err = TRUE; + break; + } + } + return err ? FALSE : TRUE; +} + + +/* Optimize a database. */ +int croptimize(CURIA *curia, int bnum){ + int i, err; + assert(curia); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + for(i = 0; i < curia->dnum; i++){ + if(!dpoptimize(curia->depots[i], bnum)){ + err = TRUE; + break; + } + } + curia->inum = 0; + return err ? FALSE : TRUE; +} + + +/* Get the name of a database. */ +char *crname(CURIA *curia){ + char *name; + assert(curia); + if(!(name = crstrdup(curia->name))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return NULL; + } + return name; +} + + +/* Get the total size of database files. */ +int crfsiz(CURIA *curia){ + int i, sum, rv; + assert(curia); + if((sum = dpfsiz(curia->attr)) == -1) return -1; + for(i = 0; i < curia->dnum; i++){ + if((rv = dpfsiz(curia->depots[i])) == -1) return -1; + sum += rv; + } + return sum; +} + + +/* Get the total size of database files as double-precision value. */ +double crfsizd(CURIA *curia){ + double sum; + int i, rv; + assert(curia); + sum = 0.0; + if((sum = dpfsiz(curia->attr)) < 0) return -1.0; + for(i = 0; i < curia->dnum; i++){ + if((rv = dpfsiz(curia->depots[i])) == -1) return -1.0; + sum += rv; + } + return sum; +} + + +/* Get the total number of the elements of each bucket array. */ +int crbnum(CURIA *curia){ + int i, sum, rv; + assert(curia); + sum = 0; + for(i = 0; i < curia->dnum; i++){ + rv = dpbnum(curia->depots[i]); + if(rv == -1) return -1; + sum += rv; + } + return sum; +} + + +/* Get the total number of the used elements of each bucket array. */ +int crbusenum(CURIA *curia){ + int i, sum, rv; + assert(curia); + sum = 0; + for(i = 0; i < curia->dnum; i++){ + rv = dpbusenum(curia->depots[i]); + if(rv == -1) return -1; + sum += rv; + } + return sum; +} + + +/* Get the number of the records stored in a database. */ +int crrnum(CURIA *curia){ + int i, sum, rv; + assert(curia); + sum = 0; + for(i = 0; i < curia->dnum; i++){ + rv = dprnum(curia->depots[i]); + if(rv == -1) return -1; + sum += rv; + } + return sum; +} + + +/* Check whether a database handle is a writer or not. */ +int crwritable(CURIA *curia){ + assert(curia); + return curia->wmode; +} + + +/* Check whether a database has a fatal error or not. */ +int crfatalerror(CURIA *curia){ + int i; + assert(curia); + if(dpfatalerror(curia->attr)) return TRUE; + for(i = 0; i < curia->dnum; i++){ + if(dpfatalerror(curia->depots[i])) return TRUE; + } + return FALSE; +} + + +/* Get the inode number of a database directory. */ +int crinode(CURIA *curia){ + assert(curia); + return curia->inode; +} + + +/* Get the last modified time of a database. */ +time_t crmtime(CURIA *curia){ + assert(curia); + return dpmtime(curia->attr); +} + + +/* Remove a database directory. */ +int crremove(const char *name){ + struct stat sbuf; + CURIA *curia; + char path[CR_PATHBUFSIZ]; + assert(name); + if(lstat(name, &sbuf) == -1){ + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + return FALSE; + } + if((curia = cropen(name, CR_OWRITER | CR_OTRUNC, 1, 1)) != NULL) crclose(curia); + sprintf(path, "%s%c0001%c%s", name, MYPATHCHR, MYPATHCHR, CR_DPNAME); + dpremove(path); + sprintf(path, "%s%c0001", name, MYPATHCHR); + if(rmdir(path) == -1){ + dpecodeset(DP_ERMDIR, __FILE__, __LINE__); + return FALSE; + } + sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); + if(!dpremove(path)) return FALSE; + if(rmdir(name) == -1){ + dpecodeset(DP_ERMDIR, __FILE__, __LINE__); + return FALSE; + } + return TRUE; +} + + +/* Repair a broken database directory. */ +int crrepair(const char *name){ + CURIA *tcuria; + DEPOT *tdepot; + char path[CR_PATHBUFSIZ], *kbuf, *vbuf; + struct stat sbuf; + int i, j, err, flags, bnum, dnum, ksiz, vsiz; + assert(name); + err = FALSE; + flags = 0; + bnum = 0; + dnum = 0; + sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); + if(lstat(path, &sbuf) != -1){ + if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){ + flags = dpgetflags(tdepot); + dpclose(tdepot); + } + } + for(i = 1; i <= CR_DPMAX; i++){ + sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i, MYPATHCHR, CR_DPNAME); + if(lstat(path, &sbuf) != -1){ + dnum++; + if(!dprepair(path)) err = TRUE; + if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){ + bnum += dpbnum(tdepot); + dpclose(tdepot); + } + } + } + if(dnum < CR_DEFDNUM) dnum = CR_DEFDNUM; + bnum /= dnum; + sprintf(path, "%s%s", name, CR_TMPFSUF); + if((tcuria = cropen(path, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum)) != NULL){ + if(!crsetflags(tcuria, flags)) err = TRUE; + for(i = 1; i <= CR_DPMAX; i++){ + sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i, MYPATHCHR, CR_DPNAME); + if(lstat(path, &sbuf) != -1){ + if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){ + if(!dpiterinit(tdepot)) err = TRUE; + while((kbuf = dpiternext(tdepot, &ksiz)) != NULL){ + if((vbuf = dpget(tdepot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ + if(!crput(tcuria, kbuf, ksiz, vbuf, vsiz, CR_DKEEP)) err = TRUE; + free(vbuf); + } + free(kbuf); + } + dpclose(tdepot); + } else { + err = TRUE; + } + } + for(j = 0; j <= CR_DPMAX; j++){ + sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, j, MYPATHCHR, CR_LOBDIR); + if(lstat(path, &sbuf) != -1){ + if(!crcplobdir(tcuria, path)) err = TRUE; + } + } + } + if(!crclose(tcuria)) err = TRUE; + if(!crremove(name)) err = TRUE; + sprintf(path, "%s%s", name, CR_TMPFSUF); + if(rename(path, name) == -1){ + if(!err) dpecodeset(DP_EMISC, __FILE__, __LINE__); + err = TRUE; + } + } else { + err = TRUE; + } + return err ? FALSE : TRUE; +} + + +/* Dump all records as endian independent data. */ +int crexportdb(CURIA *curia, const char *name){ + char path[CR_PATHBUFSIZ], *kbuf, *vbuf, *pbuf; + int i, err, *fds, ksiz, vsiz, psiz; + assert(curia && name); + if(!(criterinit(curia))) return FALSE; + if(mkdir(name, CR_DIRMODE) == -1 && errno != EEXIST){ + dpecodeset(DP_EMKDIR, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + fds = malloc(sizeof(int) * curia->dnum); + for(i = 0; i < curia->dnum; i++){ + sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1); + if((fds[i] = open(path, O_RDWR | O_CREAT | O_TRUNC, CR_FILEMODE)) == -1){ + if(!err) dpecodeset(DP_EOPEN, __FILE__, __LINE__); + err = TRUE; + break; + } + } + while(!err && (kbuf = criternext(curia, &ksiz)) != NULL){ + if((vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ + if((pbuf = malloc(ksiz + vsiz + CR_NUMBUFSIZ * 2)) != NULL){ + psiz = 0; + psiz += sprintf(pbuf + psiz, "%X\n%X\n", ksiz, vsiz); + memcpy(pbuf + psiz, kbuf, ksiz); + psiz += ksiz; + pbuf[psiz++] = '\n'; + memcpy(pbuf + psiz, vbuf, vsiz); + psiz += vsiz; + pbuf[psiz++] = '\n'; + if(!crwrite(fds[curia->inum], pbuf, psiz)){ + dpecodeset(DP_EWRITE, __FILE__, __LINE__); + err = TRUE; + } + free(pbuf); + } else { + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + err = TRUE; + } + free(vbuf); + } else { + err = TRUE; + } + free(kbuf); + } + for(i = 0; i < curia->dnum; i++){ + if(fds[i] != -1 && close(fds[i]) == -1){ + if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); + err = TRUE; + } + } + free(fds); + return !err && !crfatalerror(curia); +} + + +/* Load all records from endian independent data. */ +int crimportdb(CURIA *curia, const char *name){ + DEPOT *depot; + char ipath[CR_PATHBUFSIZ], opath[CR_PATHBUFSIZ], *kbuf, *vbuf; + int i, err, ksiz, vsiz; + struct stat sbuf; + assert(curia && name); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(crrnum(curia) > 0){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + for(i = 0; !err && i < CR_DPMAX; i++){ + sprintf(ipath, "%s%c%04d", name, MYPATHCHR, i + 1); + if(lstat(ipath, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)) break; + sprintf(opath, "%s%c%04d%s", curia->name, MYPATHCHR, i + 1, CR_TMPFSUF); + if((depot = dpopen(opath, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1)) != NULL){ + if(dpimportdb(depot, ipath)){ + dpiterinit(depot); + while((kbuf = dpiternext(depot, &ksiz)) != NULL){ + if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ + if(!crput(curia, kbuf, ksiz, vbuf, vsiz, CR_DKEEP)) err = TRUE; + free(vbuf); + } else { + err = TRUE; + } + free(kbuf); + } + } else { + err = TRUE; + } + if(!dpclose(depot)) err = TRUE; + if(!dpremove(opath)) err = TRUE; + } else { + err = TRUE; + } + } + return !err && !crfatalerror(curia); +} + + +/* Retrieve a record directly from a database directory. */ +char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp){ + char path[CR_PATHBUFSIZ], *vbuf; + int dnum, vsiz, tnum; + assert(name && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); + if(!(vbuf = dpsnaffle(path, CR_KEYDNUM, -1, &vsiz)) || vsiz != sizeof(int) || + (dnum = *(int *)vbuf) < 1){ + free(vbuf); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + free(vbuf); + tnum = dpouterhash(kbuf, ksiz) % dnum; + sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, tnum + 1, MYPATHCHR, CR_DPNAME); + return dpsnaffle(path, kbuf, ksiz, sp); +} + + +/* Store a large object. */ +int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ + char *path; + int mode, fd, err, be; + struct stat sbuf; + assert(curia && kbuf && vbuf); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(ksiz < 0) ksiz = strlen(kbuf); + if(vsiz < 0) vsiz = strlen(vbuf); + if(!(path = crgetlobpath(curia, kbuf, ksiz))) return FALSE; + if(!crmklobdir(path)){ + free(path); + return FALSE; + } + be = lstat(path, &sbuf) != -1 && S_ISREG(sbuf.st_mode); + mode = O_RDWR | O_CREAT; + if(dmode & CR_DKEEP) mode |= O_EXCL; + if(dmode & CR_DCAT){ + mode |= O_APPEND; + } else { + mode |= O_TRUNC; + } + if((fd = open(path, mode, CR_FILEMODE)) == -1){ + free(path); + dpecodeset(DP_EOPEN, __FILE__, __LINE__); + if(dmode == CR_DKEEP) dpecodeset(DP_EKEEP, __FILE__, __LINE__); + return FALSE; + } + free(path); + err = FALSE; + if(crwrite(fd, vbuf, vsiz) == -1){ + err = TRUE; + dpecodeset(DP_EWRITE, __FILE__, __LINE__); + } + if(close(fd) == -1){ + err = TRUE; + dpecodeset(DP_ECLOSE, __FILE__, __LINE__); + } + if(!err && !be) (curia->lrnum)++; + return err ? FALSE : TRUE; +} + + +/* Delete a large object. */ +int croutlob(CURIA *curia, const char *kbuf, int ksiz){ + char *path; + int err, be; + struct stat sbuf; + assert(curia && kbuf); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(ksiz < 0) ksiz = strlen(kbuf); + if(!(path = crgetlobpath(curia, kbuf, ksiz))) return FALSE; + be = lstat(path, &sbuf) != -1 && S_ISREG(sbuf.st_mode); + err = FALSE; + if(unlink(path) == -1){ + err = TRUE; + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + } + free(path); + if(!err && be) (curia->lrnum)--; + return err ? FALSE : TRUE; +} + + +/* Retrieve a large object. */ +char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp){ + char *path, *buf; + struct stat sbuf; + int fd, size; + assert(curia && kbuf && start >= 0); + if(ksiz < 0) ksiz = strlen(kbuf); + if(!(path = crgetlobpath(curia, kbuf, ksiz))) return NULL; + if((fd = open(path, O_RDONLY, CR_FILEMODE)) == -1){ + free(path); + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return NULL; + } + free(path); + if(fstat(fd, &sbuf) == -1){ + close(fd); + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + return NULL; + } + if(start > sbuf.st_size){ + close(fd); + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return NULL; + } + if(lseek(fd, start, SEEK_SET) == -1){ + close(fd); + dpecodeset(DP_ESEEK, __FILE__, __LINE__); + return NULL; + } + if(max < 0) max = sbuf.st_size; + if(!(buf = malloc(max + 1))){ + close(fd); + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return NULL; + } + size = crread(fd, buf, max); + close(fd); + if(size == -1){ + free(buf); + dpecodeset(DP_EREAD, __FILE__, __LINE__); + return NULL; + } + buf[size] = '\0'; + if(sp) *sp = size; + return buf; +} + + +/* Get the file descriptor of a large object. */ +int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz){ + char *path; + int fd; + assert(curia && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if(!(path = crgetlobpath(curia, kbuf, ksiz))) return -1; + if((fd = open(path, curia->wmode ? O_RDWR: O_RDONLY, CR_FILEMODE)) == -1){ + free(path); + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return -1; + } + free(path); + return fd; +} + + +/* Get the size of the value of a large object. */ +int crvsizlob(CURIA *curia, const char *kbuf, int ksiz){ + char *path; + struct stat sbuf; + assert(curia && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if(!(path = crgetlobpath(curia, kbuf, ksiz))) return -1; + if(lstat(path, &sbuf) == -1){ + free(path); + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return -1; + } + free(path); + return sbuf.st_size; +} + + +/* Get the number of the large objects stored in a database. */ +int crrnumlob(CURIA *curia){ + assert(curia); + return curia->lrnum; +} + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Synchronize updating contents on memory. */ +int crmemsync(CURIA *curia){ + int i, err; + assert(curia); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) || + !dpmemsync(curia->attr)) err = TRUE; + for(i = 0; i < curia->dnum; i++){ + if(!dpmemsync(curia->depots[i])){ + err = TRUE; + break; + } + } + return err ? FALSE : TRUE; +} + + +/* Synchronize updating contents on memory, not physically. */ +int crmemflush(CURIA *curia){ + int i, err; + assert(curia); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) || + !dpmemsync(curia->attr)) err = TRUE; + for(i = 0; i < curia->dnum; i++){ + if(!dpmemflush(curia->depots[i])){ + err = TRUE; + break; + } + } + return err ? FALSE : TRUE; +} + + +/* Get flags of a database. */ +int crgetflags(CURIA *curia){ + assert(curia); + return dpgetflags(curia->attr); +} + + +/* Set flags of a database. */ +int crsetflags(CURIA *curia, int flags){ + assert(curia); + if(!curia->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + return dpsetflags(curia->attr, flags); +} + + + +/************************************************************************************************* + * private objects + *************************************************************************************************/ + + +/* Get a copied string. + `str' specifies an original string. + The return value is a copied string whose region is allocated by `malloc'. */ +static char *crstrdup(const char *str){ + int len; + char *buf; + assert(str); + len = strlen(str); + if(!(buf = malloc(len + 1))) return NULL; + memcpy(buf, str, len + 1); + return buf; +} + + +/* Get an integer from a database. + `depot' specifies an inner database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the key. + The return value is the integer of the corresponding record. */ +static int crdpgetnum(DEPOT *depot, const char *kbuf, int ksiz){ + char *vbuf; + int vsiz, rv; + if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) || vsiz != sizeof(int)){ + free(vbuf); + return INT_MIN; + } + rv = *(int *)vbuf; + free(vbuf); + return rv; +} + + +/* Get the path of a large object. + `curia' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the key. + The return value is a path string whose region is allocated by `malloc'. */ +static char *crgetlobpath(CURIA *curia, const char *kbuf, int ksiz){ + char prefix[CR_PATHBUFSIZ], *wp, *path; + int i, hash; + assert(curia && kbuf && ksiz >= 0); + wp = prefix; + wp += sprintf(wp, "%s%c%04d%c%s%c", + curia->name, MYPATHCHR, dpouterhash(kbuf, ksiz) % curia->dnum + 1, + MYPATHCHR, CR_LOBDIR, MYPATHCHR); + hash = dpinnerhash(kbuf, ksiz); + for(i = 0; i < CR_LOBDDEPTH; i++){ + wp += sprintf(wp, "%02X%c", hash % 0x100, MYPATHCHR); + hash /= 0x100; + } + if(!(path = malloc(strlen(prefix) + ksiz * 2 + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return NULL; + } + wp = path; + wp += sprintf(path, "%s", prefix); + for(i = 0; i < ksiz; i++){ + wp += sprintf(wp, "%02X", ((unsigned char *)kbuf)[i]); + } + return path; +} + + +/* Create directories included in a path. + `path' specifies a path. + The return value is true if successful, else, it is false. */ +static int crmklobdir(const char *path){ + char elem[CR_PATHBUFSIZ], *wp; + const char *dp; + int err, len; + wp = elem; + err = FALSE; + while(*path != '\0' && (dp = strchr(path, MYPATHCHR)) != NULL){ + len = dp - path; + if((wp != elem || dp == path)) wp += sprintf(wp, "%c", MYPATHCHR); + memcpy(wp, path, len); + wp[len] = '\0'; + wp += len; + if(mkdir(elem, CR_DIRMODE) == -1 && errno != EEXIST) err = TRUE; + path = dp + 1; + } + if(err) dpecodeset(DP_EMKDIR, __FILE__, __LINE__); + return err ? FALSE : TRUE; +} + + +/* Remove file and directories under a directory. + `path' specifies a path. + The return value is true if successful, else, it is false. */ +static int crrmlobdir(const char *path){ + char elem[CR_PATHBUFSIZ]; + DIR *DD; + struct dirent *dp; + assert(path); + if(unlink(path) != -1){ + return TRUE; + } else { + if(errno == ENOENT) return TRUE; + if(!(DD = opendir(path))){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + while((dp = readdir(DD)) != NULL){ + if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue; + sprintf(elem, "%s%c%s", path, MYPATHCHR, dp->d_name); + if(!crrmlobdir(elem)){ + closedir(DD); + return FALSE; + } + } + } + if(closedir(DD) == -1){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + if(rmdir(path) == -1){ + dpecodeset(DP_ERMDIR, __FILE__, __LINE__); + return FALSE; + } + return TRUE; +} + + +/* Copy file and directories under a directory for repairing. + `path' specifies a path. + The return value is true if successful, else, it is false. */ +static int crcplobdir(CURIA *curia, const char *path){ + char elem[CR_PATHBUFSIZ], numbuf[3], *rp, *kbuf, *vbuf; + DIR *DD; + struct dirent *dp; + struct stat sbuf; + int i, ksiz, vsiz, fd; + assert(curia && path); + if(lstat(path, &sbuf) == -1){ + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + return FALSE; + } + if(S_ISREG(sbuf.st_mode)){ + rp = strrchr(path, MYPATHCHR) + 1; + for(i = 0; rp[i] != '\0'; i += 2){ + numbuf[0] = rp[i]; + numbuf[1] = rp[i+1]; + numbuf[2] = '\0'; + elem[i/2] = (int)strtol(numbuf, NULL, 16); + } + kbuf = elem; + ksiz = i / 2; + vsiz = sbuf.st_size; + if(!(vbuf = malloc(vsiz + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return FALSE; + } + if((fd = open(path, O_RDONLY, CR_FILEMODE)) == -1){ + free(vbuf); + dpecodeset(DP_EOPEN, __FILE__, __LINE__); + return FALSE; + } + if(crread(fd, vbuf, vsiz) == -1){ + close(fd); + free(vbuf); + dpecodeset(DP_EOPEN, __FILE__, __LINE__); + return FALSE; + } + if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, DP_DOVER)){ + close(fd); + free(vbuf); + return FALSE; + } + close(fd); + free(vbuf); + return TRUE; + } + if(!(DD = opendir(path))){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + while((dp = readdir(DD)) != NULL){ + if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue; + sprintf(elem, "%s%c%s", path, MYPATHCHR, dp->d_name); + if(!crcplobdir(curia, elem)){ + closedir(DD); + return FALSE; + } + } + if(closedir(DD) == -1){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + return TRUE; +} + + +/* Write into a file. + `fd' specifies a file descriptor. + `buf' specifies a buffer to write. + `size' specifies the size of the buffer. + The return value is the size of the written buffer, or, -1 on failure. */ +static int crwrite(int fd, const void *buf, int size){ + char *lbuf; + int rv, wb; + assert(fd >= 0 && buf && size >= 0); + lbuf = (char *)buf; + rv = 0; + do { + wb = write(fd, lbuf, size); + switch(wb){ + case -1: if(errno != EINTR) return -1; + case 0: break; + default: + lbuf += wb; + size -= wb; + rv += wb; + break; + } + } while(size > 0); + return rv; +} + + +/* Read from a file and store the data into a buffer. + `fd' specifies a file descriptor. + `buffer' specifies a buffer to store into. + `size' specifies the size to read with. + The return value is the size read with, or, -1 on failure. */ +static int crread(int fd, void *buf, int size){ + char *lbuf; + int i, bs; + assert(fd >= 0 && buf && size >= 0); + lbuf = buf; + for(i = 0; i < size && (bs = read(fd, lbuf + i, size - i)) != 0; i += bs){ + if(bs == -1 && errno != EINTR) return -1; + } + return i; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/curia.h =================================================================== --- box/trunk/qdbm/curia.h 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/curia.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,474 +0,0 @@ -/************************************************************************************************* - * The extended API of QDBM - * 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. - *************************************************************************************************/ - - -#ifndef _CURIA_H /* duplication check */ -#define _CURIA_H - -#if defined(__cplusplus) /* export for C++ */ -extern "C" { -#endif - - -#include -#include -#include - - -#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) -#define MYEXTERN extern __declspec(dllimport) -#else -#define MYEXTERN extern -#endif - - - -/************************************************************************************************* - * API - *************************************************************************************************/ - - -typedef struct { /* type of structure for the database handle */ - char *name; /* name of the database directory */ - int wmode; /* whether to be writable */ - int inode; /* inode of the database directory */ - DEPOT *attr; /* database handle for attributes */ - DEPOT **depots; /* handles of the record database */ - int dnum; /* number of record database handles */ - int inum; /* number of the database of the using iterator */ - int lrnum; /* number of large objects */ -} CURIA; - -enum { /* enumeration for open modes */ - CR_OREADER = 1 << 0, /* open as a reader */ - CR_OWRITER = 1 << 1, /* open as a writer */ - CR_OCREAT = 1 << 2, /* a writer creating */ - CR_OTRUNC = 1 << 3, /* a writer truncating */ - CR_ONOLCK = 1 << 4, /* open without locking */ - CR_OLCKNB = 1 << 5, /* lock without blocking */ - CR_OSPARSE = 1 << 6 /* create as sparse files */ -}; - -enum { /* enumeration for write modes */ - CR_DOVER, /* overwrite an existing value */ - CR_DKEEP, /* keep an existing value */ - CR_DCAT /* concatenate values */ -}; - - -/* Get a database handle. - `name' specifies the name of a database directory. - `omode' specifies the connection mode: `CR_OWRITER' as a writer, `CR_OREADER' as a reader. - If the mode is `CR_OWRITER', the following may be added by bitwise or: `CR_OCREAT', which - means it creates a new database if not exist, `CR_OTRUNC', which means it creates a new - database regardless if one exists. Both of `CR_OREADER' and `CR_OWRITER' can be added to by - bitwise or: `CR_ONOLCK', which means it opens a database directory without file locking, or - `CR_OLCKNB', which means locking is performed without blocking. `CR_OCREAT' can be added to - by bitwise or: `CR_OSPARSE', which means it creates database files as sparse files. - `bnum' specifies the number of elements of each bucket array. If it is not more than 0, - the default value is specified. The size of each bucket array is determined on creating, - and can not be changed except for by optimization of the database. Suggested size of each - bucket array is about from 0.5 to 4 times of the number of all records to store. - `dnum' specifies the number of division of the database. If it is not more than 0, the - default value is specified. The number of division can not be changed from the initial value. - The max number of division is 512. - The return value is the database handle or `NULL' if it is not successful. - While connecting as a writer, an exclusive lock is invoked to the database directory. - While connecting as a reader, a shared lock is invoked to the database directory. - The thread blocks until the lock is achieved. If `CR_ONOLCK' is used, the application is - responsible for exclusion control. */ -CURIA *cropen(const char *name, int omode, int bnum, int dnum); - - -/* Close a database handle. - `curia' specifies a database handle. - If successful, the return value is true, else, it is false. - Because the region of a closed handle is released, it becomes impossible to use the handle. - Updating a database is assured to be written when the handle is closed. If a writer opens - a database but does not close it appropriately, the database will be broken. */ -int crclose(CURIA *curia); - - -/* Store a record. - `curia' specifies a database handle connected as a writer. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region of the value. If it is negative, the size is - assigned with `strlen(vbuf)'. - `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', - which means the specified value overwrites the existing one, `CR_DKEEP', which means the - existing value is kept, `CR_DCAT', which means the specified value is concatenated at the - end of the existing value. - If successful, the return value is true, else, it is false. */ -int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); - - -/* Delete a record. - `curia' specifies a database handle connected as a writer. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is true, else, it is false. False is returned when no - record corresponds to the specified key. */ -int crout(CURIA *curia, const char *kbuf, int ksiz); - - -/* Retrieve a record. - `curia' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `start' specifies the offset address of the beginning of the region of the value to be read. - `max' specifies the max size to be read. If it is negative, the size to read is unlimited. - `sp' specifies the pointer to a variable to which the size of the region of the return value - is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to - the specified key or the size of the value of the corresponding record is less than `start'. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. */ -char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp); - - -/* Retrieve a record and write the value into a buffer. - `curia' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `start' specifies the offset address of the beginning of the region of the value to be read. - `max' specifies the max size to be read. It shuld be equal to or less than the size of the - writing buffer. - `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is - written. - If successful, the return value is the size of the written data, else, it is -1. -1 is - returned when no record corresponds to the specified key or the size of the value of the - corresponding record is less than `start'. - Note that no additional zero code is appended at the end of the region of the writing buffer. */ -int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf); - - -/* Get the size of the value of a record. - `curia' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is the size of the value of the corresponding record, else, - it is -1. - Because this function does not read the entity of a record, it is faster than `crget'. */ -int crvsiz(CURIA *curia, const char *kbuf, int ksiz); - - -/* Initialize the iterator of a database handle. - `curia' specifies a database handle. - If successful, the return value is true, else, it is false. - The iterator is used in order to access the key of every record stored in a database. */ -int criterinit(CURIA *curia); - - -/* Get the next key of the iterator. - `curia' specifies a database handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the next key, else, it is - `NULL'. `NULL' is returned when no record is to be get out of the iterator. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. It is possible to access every record by iteration of calling this - function. However, it is not assured if updating the database is occurred while the - iteration. Besides, the order of this traversal access method is arbitrary, so it is not - assured that the order of storing matches the one of the traversal access. */ -char *criternext(CURIA *curia, int *sp); - - -/* Set alignment of a database handle. - `curia' specifies a database handle connected as a writer. - `align' specifies the size of alignment. - If successful, the return value is true, else, it is false. - If alignment is set to a database, the efficiency of overwriting values is improved. - The size of alignment is suggested to be average size of the values of the records to be - stored. If alignment is positive, padding whose size is multiple number of the alignment - is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding - is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not - saved in a database, you should specify alignment every opening a database. */ -int crsetalign(CURIA *curia, int align); - - -/* Set the size of the free block pool of a database handle. - `curia' specifies a database handle connected as a writer. - `size' specifies the size of the free block pool of a database. - If successful, the return value is true, else, it is false. - The default size of the free block pool is 16. If the size is greater, the space efficiency - of overwriting values is improved with the time efficiency sacrificed. */ -int crsetfbpsiz(CURIA *curia, int size); - - -/* Synchronize updating contents with the files and the devices. - `curia' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. - This function is useful when another process uses the connected database directory. */ -int crsync(CURIA *curia); - - -/* Optimize a database. - `curia' specifies a database handle connected as a writer. - `bnum' specifies the number of the elements of each bucket array. If it is not more than 0, - the default value is specified. - If successful, the return value is true, else, it is false. - In an alternating succession of deleting and storing with overwrite or concatenate, - dispensable regions accumulate. This function is useful to do away with them. */ -int croptimize(CURIA *curia, int bnum); - -/* Get the name of a database. - `curia' specifies a database handle. - If successful, the return value is the pointer to the region of the name of the database, - else, it is `NULL'. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *crname(CURIA *curia); - - -/* Get the total size of database files. - `curia' specifies a database handle. - If successful, the return value is the total size of the database files, else, it is -1. - If the total size is more than 2GB, the return value overflows. */ -int crfsiz(CURIA *curia); - - -/* Get the total size of database files as double-precision floating-point number. - `curia' specifies a database handle. - If successful, the return value is the total size of the database files, else, it is -1.0. */ -double crfsizd(CURIA *curia); - - -/* Get the total number of the elements of each bucket array. - `curia' specifies a database handle. - If successful, the return value is the total number of the elements of each bucket array, - else, it is -1. */ -int crbnum(CURIA *curia); - - -/* Get the total number of the used elements of each bucket array. - `curia' specifies a database handle. - If successful, the return value is the total number of the used elements of each bucket - array, else, it is -1. - This function is inefficient because it accesses all elements of each bucket array. */ -int crbusenum(CURIA *curia); - - -/* Get the number of the records stored in a database. - `curia' specifies a database handle. - If successful, the return value is the number of the records stored in the database, else, - it is -1. */ -int crrnum(CURIA *curia); - - -/* Check whether a database handle is a writer or not. - `curia' specifies a database handle. - The return value is true if the handle is a writer, false if not. */ -int crwritable(CURIA *curia); - - -/* Check whether a database has a fatal error or not. - `curia' specifies a database handle. - The return value is true if the database has a fatal error, false if not. */ -int crfatalerror(CURIA *curia); - - -/* Get the inode number of a database directory. - `curia' specifies a database handle. - The return value is the inode number of the database directory. */ -int crinode(CURIA *curia); - - -/* Get the last modified time of a database. - `curia' specifies a database handle. - The return value is the last modified time of the database. */ -time_t crmtime(CURIA *curia); - - -/* Remove a database directory. - `name' specifies the name of a database directory. - If successful, the return value is true, else, it is false. */ -int crremove(const char *name); - - -/* Repair a broken database directory. - `name' specifies the name of a database directory. - If successful, the return value is true, else, it is false. - There is no guarantee that all records in a repaired database directory correspond to the - original or expected state. */ -int crrepair(const char *name); - - -/* Dump all records as endian independent data. - `curia' specifies a database handle. - `name' specifies the name of an output directory. - If successful, the return value is true, else, it is false. - Note that large objects are ignored. */ -int crexportdb(CURIA *curia, const char *name); - - -/* Load all records from endian independent data. - `curia' specifies a database handle connected as a writer. The database of the handle must - be empty. - `name' specifies the name of an input directory. - If successful, the return value is true, else, it is false. - Note that large objects are ignored. */ -int crimportdb(CURIA *curia, const char *name); - - -/* Retrieve a record directly from a database directory. - `name' specifies the name of a database directory. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to - the specified key. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. Although this function can be used even while the database directory is - locked by another process, it is not assured that recent updated is reflected. */ -char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp); - - -/* Store a large object. - `curia' specifies a database handle connected as a writer. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region of the value. If it is negative, the size is - assigned with `strlen(vbuf)'. - `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', - which means the specified value overwrites the existing one, `CR_DKEEP', which means the - existing value is kept, `CR_DCAT', which means the specified value is concatenated at the - end of the existing value. - If successful, the return value is true, else, it is false. */ -int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); - - -/* Delete a large object. - `curia' specifies a database handle connected as a writer. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is true, else, it is false. false is returned when no large - object corresponds to the specified key. */ -int croutlob(CURIA *curia, const char *kbuf, int ksiz); - - -/* Retrieve a large object. - `curia' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `start' specifies the offset address of the beginning of the region of the value to be read. - `max' specifies the max size to be read. If it is negative, the size to read is unlimited. - `sp' specifies the pointer to a variable to which the size of the region of the return value - is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding large object, else, it is `NULL'. `NULL' is returned when no large object - corresponds to the specified key or the size of the value of the corresponding large object - is less than `start'. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. */ -char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp); - - -/* Get the file descriptor of a large object. - `curia' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is the file descriptor of the corresponding large object, - else, it is -1. -1 is returned when no large object corresponds to the specified key. The - returned file descriptor is opened with the `open' call. If the database handle was opened - as a writer, the descriptor is writable (O_RDWR), else, it is not writable (O_RDONLY). The - descriptor should be closed with the `close' call if it is no longer in use. */ -int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz); - - -/* Get the size of the value of a large object. - `curia' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is the size of the value of the corresponding large object, - else, it is -1. - Because this function does not read the entity of a large object, it is faster than - `crgetlob'. */ -int crvsizlob(CURIA *curia, const char *kbuf, int ksiz); - - -/* Get the number of the large objects stored in a database. - `curia' specifies a database handle. - If successful, the return value is the number of the large objects stored in the database, - else, it is -1. */ -int crrnumlob(CURIA *curia); - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Synchronize updating contents on memory. - `curia' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. */ -int crmemsync(CURIA *curia); - - -/* Synchronize updating contents on memory, not physically. - `curia' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. */ -int crmemflush(CURIA *curia); - - -/* Get flags of a database. - `curia' specifies a database handle. - The return value is the flags of a database. */ -int crgetflags(CURIA *curia); - - -/* Set flags of a database. - `curia' specifies a database handle connected as a writer. - `flags' specifies flags to set. Least ten bits are reserved for internal use. - If successful, the return value is true, else, it is false. */ -int crsetflags(CURIA *curia, int flags); - - - -#undef MYEXTERN - -#if defined(__cplusplus) /* export for C++ */ -} -#endif - -#endif /* duplication check */ - - -/* END OF FILE */ Copied: box/trunk/qdbm/curia.h (from rev 2716, box/trunk/qdbm/curia.h) =================================================================== --- box/trunk/qdbm/curia.h (rev 0) +++ box/trunk/qdbm/curia.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,474 @@ +/************************************************************************************************* + * The extended API of QDBM + * 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. + *************************************************************************************************/ + + +#ifndef _CURIA_H /* duplication check */ +#define _CURIA_H + +#if defined(__cplusplus) /* export for C++ */ +extern "C" { +#endif + + +#include +#include +#include + + +#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) +#define MYEXTERN extern __declspec(dllimport) +#else +#define MYEXTERN extern +#endif + + + +/************************************************************************************************* + * API + *************************************************************************************************/ + + +typedef struct { /* type of structure for the database handle */ + char *name; /* name of the database directory */ + int wmode; /* whether to be writable */ + int inode; /* inode of the database directory */ + DEPOT *attr; /* database handle for attributes */ + DEPOT **depots; /* handles of the record database */ + int dnum; /* number of record database handles */ + int inum; /* number of the database of the using iterator */ + int lrnum; /* number of large objects */ +} CURIA; + +enum { /* enumeration for open modes */ + CR_OREADER = 1 << 0, /* open as a reader */ + CR_OWRITER = 1 << 1, /* open as a writer */ + CR_OCREAT = 1 << 2, /* a writer creating */ + CR_OTRUNC = 1 << 3, /* a writer truncating */ + CR_ONOLCK = 1 << 4, /* open without locking */ + CR_OLCKNB = 1 << 5, /* lock without blocking */ + CR_OSPARSE = 1 << 6 /* create as sparse files */ +}; + +enum { /* enumeration for write modes */ + CR_DOVER, /* overwrite an existing value */ + CR_DKEEP, /* keep an existing value */ + CR_DCAT /* concatenate values */ +}; + + +/* Get a database handle. + `name' specifies the name of a database directory. + `omode' specifies the connection mode: `CR_OWRITER' as a writer, `CR_OREADER' as a reader. + If the mode is `CR_OWRITER', the following may be added by bitwise or: `CR_OCREAT', which + means it creates a new database if not exist, `CR_OTRUNC', which means it creates a new + database regardless if one exists. Both of `CR_OREADER' and `CR_OWRITER' can be added to by + bitwise or: `CR_ONOLCK', which means it opens a database directory without file locking, or + `CR_OLCKNB', which means locking is performed without blocking. `CR_OCREAT' can be added to + by bitwise or: `CR_OSPARSE', which means it creates database files as sparse files. + `bnum' specifies the number of elements of each bucket array. If it is not more than 0, + the default value is specified. The size of each bucket array is determined on creating, + and can not be changed except for by optimization of the database. Suggested size of each + bucket array is about from 0.5 to 4 times of the number of all records to store. + `dnum' specifies the number of division of the database. If it is not more than 0, the + default value is specified. The number of division can not be changed from the initial value. + The max number of division is 512. + The return value is the database handle or `NULL' if it is not successful. + While connecting as a writer, an exclusive lock is invoked to the database directory. + While connecting as a reader, a shared lock is invoked to the database directory. + The thread blocks until the lock is achieved. If `CR_ONOLCK' is used, the application is + responsible for exclusion control. */ +CURIA *cropen(const char *name, int omode, int bnum, int dnum); + + +/* Close a database handle. + `curia' specifies a database handle. + If successful, the return value is true, else, it is false. + Because the region of a closed handle is released, it becomes impossible to use the handle. + Updating a database is assured to be written when the handle is closed. If a writer opens + a database but does not close it appropriately, the database will be broken. */ +int crclose(CURIA *curia); + + +/* Store a record. + `curia' specifies a database handle connected as a writer. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region of the value. If it is negative, the size is + assigned with `strlen(vbuf)'. + `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', + which means the specified value overwrites the existing one, `CR_DKEEP', which means the + existing value is kept, `CR_DCAT', which means the specified value is concatenated at the + end of the existing value. + If successful, the return value is true, else, it is false. */ +int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); + + +/* Delete a record. + `curia' specifies a database handle connected as a writer. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is true, else, it is false. False is returned when no + record corresponds to the specified key. */ +int crout(CURIA *curia, const char *kbuf, int ksiz); + + +/* Retrieve a record. + `curia' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `start' specifies the offset address of the beginning of the region of the value to be read. + `max' specifies the max size to be read. If it is negative, the size to read is unlimited. + `sp' specifies the pointer to a variable to which the size of the region of the return value + is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to + the specified key or the size of the value of the corresponding record is less than `start'. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. */ +char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp); + + +/* Retrieve a record and write the value into a buffer. + `curia' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `start' specifies the offset address of the beginning of the region of the value to be read. + `max' specifies the max size to be read. It shuld be equal to or less than the size of the + writing buffer. + `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is + written. + If successful, the return value is the size of the written data, else, it is -1. -1 is + returned when no record corresponds to the specified key or the size of the value of the + corresponding record is less than `start'. + Note that no additional zero code is appended at the end of the region of the writing buffer. */ +int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf); + + +/* Get the size of the value of a record. + `curia' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is the size of the value of the corresponding record, else, + it is -1. + Because this function does not read the entity of a record, it is faster than `crget'. */ +int crvsiz(CURIA *curia, const char *kbuf, int ksiz); + + +/* Initialize the iterator of a database handle. + `curia' specifies a database handle. + If successful, the return value is true, else, it is false. + The iterator is used in order to access the key of every record stored in a database. */ +int criterinit(CURIA *curia); + + +/* Get the next key of the iterator. + `curia' specifies a database handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the next key, else, it is + `NULL'. `NULL' is returned when no record is to be get out of the iterator. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. It is possible to access every record by iteration of calling this + function. However, it is not assured if updating the database is occurred while the + iteration. Besides, the order of this traversal access method is arbitrary, so it is not + assured that the order of storing matches the one of the traversal access. */ +char *criternext(CURIA *curia, int *sp); + + +/* Set alignment of a database handle. + `curia' specifies a database handle connected as a writer. + `align' specifies the size of alignment. + If successful, the return value is true, else, it is false. + If alignment is set to a database, the efficiency of overwriting values is improved. + The size of alignment is suggested to be average size of the values of the records to be + stored. If alignment is positive, padding whose size is multiple number of the alignment + is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding + is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not + saved in a database, you should specify alignment every opening a database. */ +int crsetalign(CURIA *curia, int align); + + +/* Set the size of the free block pool of a database handle. + `curia' specifies a database handle connected as a writer. + `size' specifies the size of the free block pool of a database. + If successful, the return value is true, else, it is false. + The default size of the free block pool is 16. If the size is greater, the space efficiency + of overwriting values is improved with the time efficiency sacrificed. */ +int crsetfbpsiz(CURIA *curia, int size); + + +/* Synchronize updating contents with the files and the devices. + `curia' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. + This function is useful when another process uses the connected database directory. */ +int crsync(CURIA *curia); + + +/* Optimize a database. + `curia' specifies a database handle connected as a writer. + `bnum' specifies the number of the elements of each bucket array. If it is not more than 0, + the default value is specified. + If successful, the return value is true, else, it is false. + In an alternating succession of deleting and storing with overwrite or concatenate, + dispensable regions accumulate. This function is useful to do away with them. */ +int croptimize(CURIA *curia, int bnum); + +/* Get the name of a database. + `curia' specifies a database handle. + If successful, the return value is the pointer to the region of the name of the database, + else, it is `NULL'. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *crname(CURIA *curia); + + +/* Get the total size of database files. + `curia' specifies a database handle. + If successful, the return value is the total size of the database files, else, it is -1. + If the total size is more than 2GB, the return value overflows. */ +int crfsiz(CURIA *curia); + + +/* Get the total size of database files as double-precision floating-point number. + `curia' specifies a database handle. + If successful, the return value is the total size of the database files, else, it is -1.0. */ +double crfsizd(CURIA *curia); + + +/* Get the total number of the elements of each bucket array. + `curia' specifies a database handle. + If successful, the return value is the total number of the elements of each bucket array, + else, it is -1. */ +int crbnum(CURIA *curia); + + +/* Get the total number of the used elements of each bucket array. + `curia' specifies a database handle. + If successful, the return value is the total number of the used elements of each bucket + array, else, it is -1. + This function is inefficient because it accesses all elements of each bucket array. */ +int crbusenum(CURIA *curia); + + +/* Get the number of the records stored in a database. + `curia' specifies a database handle. + If successful, the return value is the number of the records stored in the database, else, + it is -1. */ +int crrnum(CURIA *curia); + + +/* Check whether a database handle is a writer or not. + `curia' specifies a database handle. + The return value is true if the handle is a writer, false if not. */ +int crwritable(CURIA *curia); + + +/* Check whether a database has a fatal error or not. + `curia' specifies a database handle. + The return value is true if the database has a fatal error, false if not. */ +int crfatalerror(CURIA *curia); + + +/* Get the inode number of a database directory. + `curia' specifies a database handle. + The return value is the inode number of the database directory. */ +int crinode(CURIA *curia); + + +/* Get the last modified time of a database. + `curia' specifies a database handle. + The return value is the last modified time of the database. */ +time_t crmtime(CURIA *curia); + + +/* Remove a database directory. + `name' specifies the name of a database directory. + If successful, the return value is true, else, it is false. */ +int crremove(const char *name); + + +/* Repair a broken database directory. + `name' specifies the name of a database directory. + If successful, the return value is true, else, it is false. + There is no guarantee that all records in a repaired database directory correspond to the + original or expected state. */ +int crrepair(const char *name); + + +/* Dump all records as endian independent data. + `curia' specifies a database handle. + `name' specifies the name of an output directory. + If successful, the return value is true, else, it is false. + Note that large objects are ignored. */ +int crexportdb(CURIA *curia, const char *name); + + +/* Load all records from endian independent data. + `curia' specifies a database handle connected as a writer. The database of the handle must + be empty. + `name' specifies the name of an input directory. + If successful, the return value is true, else, it is false. + Note that large objects are ignored. */ +int crimportdb(CURIA *curia, const char *name); + + +/* Retrieve a record directly from a database directory. + `name' specifies the name of a database directory. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to + the specified key. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. Although this function can be used even while the database directory is + locked by another process, it is not assured that recent updated is reflected. */ +char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp); + + +/* Store a large object. + `curia' specifies a database handle connected as a writer. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region of the value. If it is negative, the size is + assigned with `strlen(vbuf)'. + `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', + which means the specified value overwrites the existing one, `CR_DKEEP', which means the + existing value is kept, `CR_DCAT', which means the specified value is concatenated at the + end of the existing value. + If successful, the return value is true, else, it is false. */ +int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); + + +/* Delete a large object. + `curia' specifies a database handle connected as a writer. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is true, else, it is false. false is returned when no large + object corresponds to the specified key. */ +int croutlob(CURIA *curia, const char *kbuf, int ksiz); + + +/* Retrieve a large object. + `curia' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `start' specifies the offset address of the beginning of the region of the value to be read. + `max' specifies the max size to be read. If it is negative, the size to read is unlimited. + `sp' specifies the pointer to a variable to which the size of the region of the return value + is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding large object, else, it is `NULL'. `NULL' is returned when no large object + corresponds to the specified key or the size of the value of the corresponding large object + is less than `start'. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. */ +char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp); + + +/* Get the file descriptor of a large object. + `curia' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is the file descriptor of the corresponding large object, + else, it is -1. -1 is returned when no large object corresponds to the specified key. The + returned file descriptor is opened with the `open' call. If the database handle was opened + as a writer, the descriptor is writable (O_RDWR), else, it is not writable (O_RDONLY). The + descriptor should be closed with the `close' call if it is no longer in use. */ +int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz); + + +/* Get the size of the value of a large object. + `curia' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is the size of the value of the corresponding large object, + else, it is -1. + Because this function does not read the entity of a large object, it is faster than + `crgetlob'. */ +int crvsizlob(CURIA *curia, const char *kbuf, int ksiz); + + +/* Get the number of the large objects stored in a database. + `curia' specifies a database handle. + If successful, the return value is the number of the large objects stored in the database, + else, it is -1. */ +int crrnumlob(CURIA *curia); + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Synchronize updating contents on memory. + `curia' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. */ +int crmemsync(CURIA *curia); + + +/* Synchronize updating contents on memory, not physically. + `curia' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. */ +int crmemflush(CURIA *curia); + + +/* Get flags of a database. + `curia' specifies a database handle. + The return value is the flags of a database. */ +int crgetflags(CURIA *curia); + + +/* Set flags of a database. + `curia' specifies a database handle connected as a writer. + `flags' specifies flags to set. Least ten bits are reserved for internal use. + If successful, the return value is true, else, it is false. */ +int crsetflags(CURIA *curia, int flags); + + + +#undef MYEXTERN + +#if defined(__cplusplus) /* export for C++ */ +} +#endif + +#endif /* duplication check */ + + +/* END OF FILE */ Deleted: box/trunk/qdbm/depot.c =================================================================== --- box/trunk/qdbm/depot.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/depot.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,2219 +0,0 @@ -/************************************************************************************************* - * Implementation of Depot - * 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. - *************************************************************************************************/ - - -#define QDBM_INTERNAL 1 - -#include "depot.h" -#include "myconf.h" - -#define DP_FILEMODE 00644 /* permission of a creating file */ -#define DP_MAGICNUMB "[DEPOT]\n\f" /* magic number on environments of big endian */ -#define DP_MAGICNUML "[depot]\n\f" /* magic number on environments of little endian */ -#define DP_HEADSIZ 48 /* size of the reagion of the header */ -#define DP_LIBVEROFF 12 /* offset of the region for the library version */ -#define DP_FLAGSOFF 16 /* offset of the region for flags */ -#define DP_FSIZOFF 24 /* offset of the region for the file size */ -#define DP_BNUMOFF 32 /* offset of the region for the bucket number */ -#define DP_RNUMOFF 40 /* offset of the region for the record number */ -#define DP_DEFBNUM 8191 /* default bucket number */ -#define DP_FBPOOLSIZ 16 /* size of free block pool */ -#define DP_ENTBUFSIZ 128 /* size of the entity buffer */ -#define DP_STKBUFSIZ 256 /* size of the stack key buffer */ -#define DP_WRTBUFSIZ 8192 /* size of the writing buffer */ -#define DP_FSBLKSIZ 4096 /* size of a block of the file system */ -#define DP_TMPFSUF MYEXTSTR "dptmp" /* suffix of a temporary file */ -#define DP_OPTBLOAD 0.25 /* ratio of bucket loading at optimization */ -#define DP_OPTRUNIT 256 /* number of records in a process of optimization */ -#define DP_NUMBUFSIZ 32 /* size of a buffer for a number */ -#define DP_IOBUFSIZ 8192 /* size of an I/O buffer */ - -/* get the first hash value */ -#define DP_FIRSTHASH(DP_res, DP_kbuf, DP_ksiz) \ - do { \ - const unsigned char *_DP_p; \ - int _DP_ksiz; \ - _DP_p = (const unsigned char *)(DP_kbuf); \ - _DP_ksiz = DP_ksiz; \ - if((_DP_ksiz) == sizeof(int)){ \ - memcpy(&(DP_res), (DP_kbuf), sizeof(int)); \ - } else { \ - (DP_res) = 751; \ - } \ - while(_DP_ksiz--){ \ - (DP_res) = (DP_res) * 31 + *(_DP_p)++; \ - } \ - (DP_res) = ((DP_res) * 87767623) & INT_MAX; \ - } while(FALSE) - -/* get the second hash value */ -#define DP_SECONDHASH(DP_res, DP_kbuf, DP_ksiz) \ - do { \ - const unsigned char *_DP_p; \ - int _DP_ksiz; \ - _DP_p = (const unsigned char *)(DP_kbuf) + DP_ksiz - 1; \ - _DP_ksiz = DP_ksiz; \ - for((DP_res) = 19780211; _DP_ksiz--;){ \ - (DP_res) = (DP_res) * 37 + *(_DP_p)--; \ - } \ - (DP_res) = ((DP_res) * 43321879) & INT_MAX; \ - } while(FALSE) - -/* get the third hash value */ -#define DP_THIRDHASH(DP_res, DP_kbuf, DP_ksiz) \ - do { \ - int _DP_i; \ - (DP_res) = 774831917; \ - for(_DP_i = (DP_ksiz) - 1; _DP_i >= 0; _DP_i--){ \ - (DP_res) = (DP_res) * 29 + ((const unsigned char *)(DP_kbuf))[_DP_i]; \ - } \ - (DP_res) = ((DP_res) * 5157883) & INT_MAX; \ - } while(FALSE) - -enum { /* enumeration for a record header */ - DP_RHIFLAGS, /* offset of flags */ - DP_RHIHASH, /* offset of value of the second hash function */ - DP_RHIKSIZ, /* offset of the size of the key */ - DP_RHIVSIZ, /* offset of the size of the value */ - DP_RHIPSIZ, /* offset of the size of the padding bytes */ - DP_RHILEFT, /* offset of the offset of the left child */ - DP_RHIRIGHT, /* offset of the offset of the right child */ - DP_RHNUM /* number of elements of a header */ -}; - -enum { /* enumeration for the flag of a record */ - DP_RECFDEL = 1 << 0, /* deleted */ - DP_RECFREUSE = 1 << 1 /* reusable */ -}; - - -/* private function prototypes */ -static int dpbigendian(void); -static char *dpstrdup(const char *str); -static int dplock(int fd, int ex, int nb); -static int dpwrite(int fd, const void *buf, int size); -static int dpseekwrite(int fd, int off, const void *buf, int size); -static int dpseekwritenum(int fd, int off, int num); -static int dpread(int fd, void *buf, int size); -static int dpseekread(int fd, int off, void *buf, int size); -static int dpfcopy(int destfd, int destoff, int srcfd, int srcoff); -static int dpgetprime(int num); -static int dppadsize(DEPOT *depot, int ksiz, int vsiz); -static int dprecsize(int *head); -static int dprechead(DEPOT *depot, int off, int *head, char *ebuf, int *eep); -static char *dpreckey(DEPOT *depot, int off, int *head); -static char *dprecval(DEPOT *depot, int off, int *head, int start, int max); -static int dprecvalwb(DEPOT *depot, int off, int *head, int start, int max, char *vbuf); -static int dpkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz); -static int dprecsearch(DEPOT *depot, const char *kbuf, int ksiz, int hash, int *bip, int *offp, - int *entp, int *head, char *ebuf, int *eep, int delhit); -static int dprecrewrite(DEPOT *depot, int off, int rsiz, const char *kbuf, int ksiz, - const char *vbuf, int vsiz, int hash, int left, int right); -static int dprecappend(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, - int hash, int left, int right); -static int dprecover(DEPOT *depot, int off, int *head, const char *vbuf, int vsiz, int cat); -static int dprecdelete(DEPOT *depot, int off, int *head, int reusable); -static void dpfbpoolcoal(DEPOT *depot); -static int dpfbpoolcmp(const void *a, const void *b); - - - -/************************************************************************************************* - * public objects - *************************************************************************************************/ - - -/* String containing the version information. */ -const char *dpversion = _QDBM_VERSION; - - -/* Get a message string corresponding to an error code. */ -const char *dperrmsg(int ecode){ - switch(ecode){ - case DP_ENOERR: return "no error"; - case DP_EFATAL: return "with fatal error"; - case DP_EMODE: return "invalid mode"; - case DP_EBROKEN: return "broken database file"; - case DP_EKEEP: return "existing record"; - case DP_ENOITEM: return "no item found"; - case DP_EALLOC: return "memory allocation error"; - case DP_EMAP: return "memory mapping error"; - case DP_EOPEN: return "open error"; - case DP_ECLOSE: return "close error"; - case DP_ETRUNC: return "trunc error"; - case DP_ESYNC: return "sync error"; - case DP_ESTAT: return "stat error"; - case DP_ESEEK: return "seek error"; - case DP_EREAD: return "read error"; - case DP_EWRITE: return "write error"; - case DP_ELOCK: return "lock error"; - case DP_EUNLINK: return "unlink error"; - case DP_EMKDIR: return "mkdir error"; - case DP_ERMDIR: return "rmdir error"; - case DP_EMISC: return "miscellaneous error"; - } - return "(invalid ecode)"; -} - - -/* Get a database handle. */ -DEPOT *dpopen(const char *name, int omode, int bnum){ - char hbuf[DP_HEADSIZ], *map, c, *tname; - int i, mode, fd, inode, fsiz, rnum, msiz, *fbpool; - struct stat sbuf; - time_t mtime; - DEPOT *depot; - assert(name); - mode = O_RDONLY; - if(omode & DP_OWRITER){ - mode = O_RDWR; - if(omode & DP_OCREAT) mode |= O_CREAT; - } - if((fd = open(name, mode, DP_FILEMODE)) == -1){ - dpecodeset(DP_EOPEN, __FILE__, __LINE__); - return NULL; - } - if(!(omode & DP_ONOLCK)){ - if(!dplock(fd, omode & DP_OWRITER, omode & DP_OLCKNB)){ - close(fd); - return NULL; - } - } - if((omode & DP_OWRITER) && (omode & DP_OTRUNC)){ - if(ftruncate(fd, 0) == -1){ - close(fd); - dpecodeset(DP_ETRUNC, __FILE__, __LINE__); - return NULL; - } - } - if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode) || - (sbuf.st_ino == 0 && lstat(name, &sbuf) == -1)){ - close(fd); - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - return NULL; - } - inode = sbuf.st_ino; - mtime = sbuf.st_mtime; - fsiz = sbuf.st_size; - if((omode & DP_OWRITER) && fsiz == 0){ - memset(hbuf, 0, DP_HEADSIZ); - if(dpbigendian()){ - memcpy(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB)); - } else { - memcpy(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML)); - } - sprintf(hbuf + DP_LIBVEROFF, "%d", _QDBM_LIBVER / 100); - bnum = bnum < 1 ? DP_DEFBNUM : bnum; - bnum = dpgetprime(bnum); - memcpy(hbuf + DP_BNUMOFF, &bnum, sizeof(int)); - rnum = 0; - memcpy(hbuf + DP_RNUMOFF, &rnum, sizeof(int)); - fsiz = DP_HEADSIZ + bnum * sizeof(int); - memcpy(hbuf + DP_FSIZOFF, &fsiz, sizeof(int)); - if(!dpseekwrite(fd, 0, hbuf, DP_HEADSIZ)){ - close(fd); - return NULL; - } - if(omode & DP_OSPARSE){ - c = 0; - if(!dpseekwrite(fd, fsiz - 1, &c, 1)){ - close(fd); - return NULL; - } - } else { - if(!(map = malloc(bnum * sizeof(int)))){ - close(fd); - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return NULL; - } - memset(map, 0, bnum * sizeof(int)); - if(!dpseekwrite(fd, DP_HEADSIZ, map, bnum * sizeof(int))){ - free(map); - close(fd); - return NULL; - } - free(map); - } - } - if(!dpseekread(fd, 0, hbuf, DP_HEADSIZ)){ - close(fd); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - if(!(omode & DP_ONOLCK) && - ((dpbigendian() ? memcmp(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB)) != 0 : - memcmp(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML)) != 0) || - *((int *)(hbuf + DP_FSIZOFF)) != fsiz)){ - close(fd); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - bnum = *((int *)(hbuf + DP_BNUMOFF)); - rnum = *((int *)(hbuf + DP_RNUMOFF)); - if(bnum < 1 || rnum < 0 || fsiz < DP_HEADSIZ + bnum * sizeof(int)){ - close(fd); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - msiz = DP_HEADSIZ + bnum * sizeof(int); - map = mmap(0, msiz, PROT_READ | ((mode & DP_OWRITER) ? PROT_WRITE : 0), MAP_SHARED, fd, 0); - if(map == MAP_FAILED){ - close(fd); - dpecodeset(DP_EMAP, __FILE__, __LINE__); - return NULL; - } - tname = NULL; - fbpool = NULL; - if(!(depot = malloc(sizeof(DEPOT))) || !(tname = dpstrdup(name)) || - !(fbpool = malloc(DP_FBPOOLSIZ * 2 * sizeof(int)))){ - free(fbpool); - free(tname); - free(depot); - munmap(map, msiz); - close(fd); - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return NULL; - } - depot->name = tname; - depot->wmode = (mode & DP_OWRITER); - depot->inode = inode; - depot->mtime = mtime; - depot->fd = fd; - depot->fsiz = fsiz; - depot->map = map; - depot->msiz = msiz; - depot->buckets = (int *)(map + DP_HEADSIZ); - depot->bnum = bnum; - depot->rnum = rnum; - depot->fatal = FALSE; - depot->ioff = 0; - depot->fbpool = fbpool; - for(i = 0; i < DP_FBPOOLSIZ * 2; i += 2){ - depot->fbpool[i] = -1; - depot->fbpool[i+1] = -1; - } - depot->fbpsiz = DP_FBPOOLSIZ * 2; - depot->fbpinc = 0; - depot->align = 0; - return depot; -} - - -/* Close a database handle. */ -int dpclose(DEPOT *depot){ - int fatal, err; - assert(depot); - fatal = depot->fatal; - err = FALSE; - if(depot->wmode){ - *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; - *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; - } - if(depot->map != MAP_FAILED){ - if(munmap(depot->map, depot->msiz) == -1){ - err = TRUE; - dpecodeset(DP_EMAP, __FILE__, __LINE__); - } - } - if(close(depot->fd) == -1){ - err = TRUE; - dpecodeset(DP_ECLOSE, __FILE__, __LINE__); - } - free(depot->fbpool); - free(depot->name); - free(depot); - if(fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - return err ? FALSE : TRUE; -} - - -/* Store a record. */ -int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ - int head[DP_RHNUM], next[DP_RHNUM]; - int i, hash, bi, off, entoff, ee, newoff, rsiz, nsiz, fdel, mroff, mrsiz, mi, min; - char ebuf[DP_ENTBUFSIZ], *tval, *swap; - assert(depot && kbuf && vbuf); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!depot->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(ksiz < 0) ksiz = strlen(kbuf); - if(vsiz < 0) vsiz = strlen(vbuf); - newoff = -1; - DP_SECONDHASH(hash, kbuf, ksiz); - switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, TRUE)){ - case -1: - depot->fatal = TRUE; - return FALSE; - case 0: - fdel = head[DP_RHIFLAGS] & DP_RECFDEL; - if(dmode == DP_DKEEP && !fdel){ - dpecodeset(DP_EKEEP, __FILE__, __LINE__); - return FALSE; - } - if(fdel){ - head[DP_RHIPSIZ] += head[DP_RHIVSIZ]; - head[DP_RHIVSIZ] = 0; - } - rsiz = dprecsize(head); - nsiz = DP_RHNUM * sizeof(int) + ksiz + vsiz; - if(dmode == DP_DCAT) nsiz += head[DP_RHIVSIZ]; - if(off + rsiz >= depot->fsiz){ - if(rsiz < nsiz){ - head[DP_RHIPSIZ] += nsiz - rsiz; - rsiz = nsiz; - depot->fsiz = off + rsiz; - } - } else { - while(nsiz > rsiz && off + rsiz < depot->fsiz){ - if(!dprechead(depot, off + rsiz, next, NULL, NULL)) return FALSE; - if(!(next[DP_RHIFLAGS] & DP_RECFREUSE)) break; - head[DP_RHIPSIZ] += dprecsize(next); - rsiz += dprecsize(next); - } - for(i = 0; i < depot->fbpsiz; i += 2){ - if(depot->fbpool[i] >= off && depot->fbpool[i] < off + rsiz){ - depot->fbpool[i] = -1; - depot->fbpool[i+1] = -1; - } - } - } - if(nsiz <= rsiz){ - if(!dprecover(depot, off, head, vbuf, vsiz, dmode == DP_DCAT)){ - depot->fatal = TRUE; - return FALSE; - } - } else { - tval = NULL; - if(dmode == DP_DCAT){ - if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ - if(!(tval = malloc(head[DP_RHIVSIZ] + vsiz + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - depot->fatal = TRUE; - return FALSE; - } - memcpy(tval, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ]), head[DP_RHIVSIZ]); - } else { - if(!(tval = dprecval(depot, off, head, 0, -1))){ - depot->fatal = TRUE; - return FALSE; - } - if(!(swap = realloc(tval, head[DP_RHIVSIZ] + vsiz + 1))){ - free(tval); - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - depot->fatal = TRUE; - return FALSE; - } - tval = swap; - } - memcpy(tval + head[DP_RHIVSIZ], vbuf, vsiz); - vsiz += head[DP_RHIVSIZ]; - vbuf = tval; - } - mi = -1; - min = -1; - for(i = 0; i < depot->fbpsiz; i += 2){ - if(depot->fbpool[i+1] < nsiz) continue; - if(mi == -1 || depot->fbpool[i+1] < min){ - mi = i; - min = depot->fbpool[i+1]; - } - } - if(mi >= 0){ - mroff = depot->fbpool[mi]; - mrsiz = depot->fbpool[mi+1]; - depot->fbpool[mi] = -1; - depot->fbpool[mi+1] = -1; - } else { - mroff = -1; - mrsiz = -1; - } - if(!dprecdelete(depot, off, head, TRUE)){ - free(tval); - depot->fatal = TRUE; - return FALSE; - } - if(mroff > 0 && nsiz <= mrsiz){ - if(!dprecrewrite(depot, mroff, mrsiz, kbuf, ksiz, vbuf, vsiz, - hash, head[DP_RHILEFT], head[DP_RHIRIGHT])){ - free(tval); - depot->fatal = TRUE; - return FALSE; - } - newoff = mroff; - } else { - if((newoff = dprecappend(depot, kbuf, ksiz, vbuf, vsiz, - hash, head[DP_RHILEFT], head[DP_RHIRIGHT])) == -1){ - free(tval); - depot->fatal = TRUE; - return FALSE; - } - } - free(tval); - } - if(fdel) depot->rnum++; - break; - default: - if((newoff = dprecappend(depot, kbuf, ksiz, vbuf, vsiz, hash, 0, 0)) == -1){ - depot->fatal = TRUE; - return FALSE; - } - depot->rnum++; - break; - } - if(newoff > 0){ - if(entoff > 0){ - if(!dpseekwritenum(depot->fd, entoff, newoff)){ - depot->fatal = TRUE; - return FALSE; - } - } else { - depot->buckets[bi] = newoff; - } - } - return TRUE; -} - - -/* Delete a record. */ -int dpout(DEPOT *depot, const char *kbuf, int ksiz){ - int head[DP_RHNUM], hash, bi, off, entoff, ee; - char ebuf[DP_ENTBUFSIZ]; - assert(depot && kbuf); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!depot->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(ksiz < 0) ksiz = strlen(kbuf); - DP_SECONDHASH(hash, kbuf, ksiz); - switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ - case -1: - depot->fatal = TRUE; - return FALSE; - case 0: - break; - default: - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!dprecdelete(depot, off, head, FALSE)){ - depot->fatal = TRUE; - return FALSE; - } - depot->rnum--; - return TRUE; -} - - -/* Retrieve a record. */ -char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp){ - int head[DP_RHNUM], hash, bi, off, entoff, ee, vsiz; - char ebuf[DP_ENTBUFSIZ], *vbuf; - assert(depot && kbuf && start >= 0); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return NULL; - } - if(ksiz < 0) ksiz = strlen(kbuf); - DP_SECONDHASH(hash, kbuf, ksiz); - switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ - case -1: - depot->fatal = TRUE; - return NULL; - case 0: - break; - default: - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return NULL; - } - if(start > head[DP_RHIVSIZ]){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return NULL; - } - if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ - head[DP_RHIVSIZ] -= start; - if(max < 0){ - vsiz = head[DP_RHIVSIZ]; - } else { - vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; - } - if(!(vbuf = malloc(vsiz + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - depot->fatal = TRUE; - return NULL; - } - memcpy(vbuf, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start), vsiz); - vbuf[vsiz] = '\0'; - } else { - if(!(vbuf = dprecval(depot, off, head, start, max))){ - depot->fatal = TRUE; - return NULL; - } - } - if(sp){ - if(max < 0){ - *sp = head[DP_RHIVSIZ]; - } else { - *sp = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; - } - } - return vbuf; -} - - -/* Retrieve a record and write the value into a buffer. */ -int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf){ - int head[DP_RHNUM], hash, bi, off, entoff, ee, vsiz; - char ebuf[DP_ENTBUFSIZ]; - assert(depot && kbuf && start >= 0 && max >= 0 && vbuf); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - if(ksiz < 0) ksiz = strlen(kbuf); - DP_SECONDHASH(hash, kbuf, ksiz); - switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ - case -1: - depot->fatal = TRUE; - return -1; - case 0: - break; - default: - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return -1; - } - if(start > head[DP_RHIVSIZ]){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return -1; - } - if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ - head[DP_RHIVSIZ] -= start; - vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; - memcpy(vbuf, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start), vsiz); - } else { - if((vsiz = dprecvalwb(depot, off, head, start, max, vbuf)) == -1){ - depot->fatal = TRUE; - return -1; - } - } - return vsiz; -} - - -/* Get the size of the value of a record. */ -int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz){ - int head[DP_RHNUM], hash, bi, off, entoff, ee; - char ebuf[DP_ENTBUFSIZ]; - assert(depot && kbuf); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - if(ksiz < 0) ksiz = strlen(kbuf); - DP_SECONDHASH(hash, kbuf, ksiz); - switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ - case -1: - depot->fatal = TRUE; - return -1; - case 0: - break; - default: - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return -1; - } - return head[DP_RHIVSIZ]; -} - - -/* Initialize the iterator of a database handle. */ -int dpiterinit(DEPOT *depot){ - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - depot->ioff = 0; - return TRUE; -} - - -/* Get the next key of the iterator. */ -char *dpiternext(DEPOT *depot, int *sp){ - int off, head[DP_RHNUM], ee; - char ebuf[DP_ENTBUFSIZ], *kbuf; - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return NULL; - } - off = DP_HEADSIZ + depot->bnum * sizeof(int); - off = off > depot->ioff ? off : depot->ioff; - while(off < depot->fsiz){ - if(!dprechead(depot, off, head, ebuf, &ee)){ - depot->fatal = TRUE; - return NULL; - } - if(head[DP_RHIFLAGS] & DP_RECFDEL){ - off += dprecsize(head); - } else { - if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] <= DP_ENTBUFSIZ){ - if(!(kbuf = malloc(head[DP_RHIKSIZ] + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - depot->fatal = TRUE; - return NULL; - } - memcpy(kbuf, ebuf + (DP_RHNUM * sizeof(int)), head[DP_RHIKSIZ]); - kbuf[head[DP_RHIKSIZ]] = '\0'; - } else { - if(!(kbuf = dpreckey(depot, off, head))){ - depot->fatal = TRUE; - return NULL; - } - } - depot->ioff = off + dprecsize(head); - if(sp) *sp = head[DP_RHIKSIZ]; - return kbuf; - } - } - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return NULL; -} - - -/* Set alignment of a database handle. */ -int dpsetalign(DEPOT *depot, int align){ - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!depot->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - depot->align = align; - return TRUE; -} - - -/* Set the size of the free block pool of a database handle. */ -int dpsetfbpsiz(DEPOT *depot, int size){ - int *fbpool; - int i; - assert(depot && size >= 0); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!depot->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - size *= 2; - if(!(fbpool = realloc(depot->fbpool, size * sizeof(int) + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return FALSE; - } - for(i = 0; i < size; i += 2){ - fbpool[i] = -1; - fbpool[i+1] = -1; - } - depot->fbpool = fbpool; - depot->fbpsiz = size; - return TRUE; -} - - - -/* Synchronize contents of updating a database with the file and the device. */ -int dpsync(DEPOT *depot){ - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!depot->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; - *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; - if(msync(depot->map, depot->msiz, MS_SYNC) == -1){ - dpecodeset(DP_EMAP, __FILE__, __LINE__); - depot->fatal = TRUE; - return FALSE; - } - if(fsync(depot->fd) == -1){ - dpecodeset(DP_ESYNC, __FILE__, __LINE__); - depot->fatal = TRUE; - return FALSE; - } - return TRUE; -} - - -/* Optimize a database. */ -int dpoptimize(DEPOT *depot, int bnum){ - DEPOT *tdepot; - char *name; - int i, err, off, head[DP_RHNUM], ee, ksizs[DP_OPTRUNIT], vsizs[DP_OPTRUNIT], unum; - char ebuf[DP_ENTBUFSIZ], *kbufs[DP_OPTRUNIT], *vbufs[DP_OPTRUNIT]; - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!depot->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(!(name = malloc(strlen(depot->name) + strlen(DP_TMPFSUF) + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - depot->fatal = FALSE; - return FALSE; - } - sprintf(name, "%s%s", depot->name, DP_TMPFSUF); - if(bnum < 0){ - bnum = (int)(depot->rnum * (1.0 / DP_OPTBLOAD)) + 1; - if(bnum < DP_DEFBNUM / 2) bnum = DP_DEFBNUM / 2; - } - if(!(tdepot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, bnum))){ - free(name); - depot->fatal = TRUE; - return FALSE; - } - free(name); - if(!dpsetflags(tdepot, dpgetflags(depot))){ - dpclose(tdepot); - depot->fatal = TRUE; - return FALSE; - } - tdepot->align = depot->align; - err = FALSE; - off = DP_HEADSIZ + depot->bnum * sizeof(int); - unum = 0; - while(off < depot->fsiz){ - if(!dprechead(depot, off, head, ebuf, &ee)){ - err = TRUE; - break; - } - if(!(head[DP_RHIFLAGS] & DP_RECFDEL)){ - if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] <= DP_ENTBUFSIZ){ - if(!(kbufs[unum] = malloc(head[DP_RHIKSIZ] + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - err = TRUE; - break; - } - memcpy(kbufs[unum], ebuf + (DP_RHNUM * sizeof(int)), head[DP_RHIKSIZ]); - if(DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ - if(!(vbufs[unum] = malloc(head[DP_RHIVSIZ] + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - err = TRUE; - break; - } - memcpy(vbufs[unum], ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ]), - head[DP_RHIVSIZ]); - } else { - vbufs[unum] = dprecval(depot, off, head, 0, -1); - } - } else { - kbufs[unum] = dpreckey(depot, off, head); - vbufs[unum] = dprecval(depot, off, head, 0, -1); - } - ksizs[unum] = head[DP_RHIKSIZ]; - vsizs[unum] = head[DP_RHIVSIZ]; - unum++; - if(unum >= DP_OPTRUNIT){ - for(i = 0; i < unum; i++){ - if(kbufs[i] && vbufs[i]){ - if(!dpput(tdepot, kbufs[i], ksizs[i], vbufs[i], vsizs[i], DP_DKEEP)) err = TRUE; - } else { - err = TRUE; - } - free(kbufs[i]); - free(vbufs[i]); - if(err) break; - } - unum = 0; - } - } - off += dprecsize(head); - if(err) break; - } - for(i = 0; i < unum; i++){ - if(kbufs[i] && vbufs[i]){ - if(!dpput(tdepot, kbufs[i], ksizs[i], vbufs[i], vsizs[i], DP_DKEEP)) err = TRUE; - } else { - err = TRUE; - } - free(kbufs[i]); - free(vbufs[i]); - if(err) break; - } - if(!dpsync(tdepot)) err = TRUE; - if(err){ - unlink(tdepot->name); - dpclose(tdepot); - depot->fatal = TRUE; - return FALSE; - } - if(munmap(depot->map, depot->msiz) == -1){ - dpclose(tdepot); - dpecodeset(DP_EMAP, __FILE__, __LINE__); - depot->fatal = TRUE; - return FALSE; - } - depot->map = MAP_FAILED; - if(ftruncate(depot->fd, 0) == -1){ - dpclose(tdepot); - unlink(tdepot->name); - dpecodeset(DP_ETRUNC, __FILE__, __LINE__); - depot->fatal = TRUE; - return FALSE; - } - if(dpfcopy(depot->fd, 0, tdepot->fd, 0) == -1){ - dpclose(tdepot); - unlink(tdepot->name); - depot->fatal = TRUE; - return FALSE; - } - depot->fsiz = tdepot->fsiz; - depot->bnum = tdepot->bnum; - depot->ioff = 0; - for(i = 0; i < depot->fbpsiz; i += 2){ - depot->fbpool[i] = -1; - depot->fbpool[i+1] = -1; - } - depot->msiz = tdepot->msiz; - depot->map = mmap(0, depot->msiz, PROT_READ | PROT_WRITE, MAP_SHARED, depot->fd, 0); - if(depot->map == MAP_FAILED){ - dpecodeset(DP_EMAP, __FILE__, __LINE__); - depot->fatal = TRUE; - return FALSE; - } - depot->buckets = (int *)(depot->map + DP_HEADSIZ); - if(!(name = dpname(tdepot))){ - dpclose(tdepot); - unlink(tdepot->name); - depot->fatal = TRUE; - return FALSE; - } - if(!dpclose(tdepot)){ - free(name); - unlink(tdepot->name); - depot->fatal = TRUE; - return FALSE; - } - if(unlink(name) == -1){ - free(name); - dpecodeset(DP_EUNLINK, __FILE__, __LINE__); - depot->fatal = TRUE; - return FALSE; - } - free(name); - return TRUE; -} - - -/* Get the name of a database. */ -char *dpname(DEPOT *depot){ - char *name; - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return NULL; - } - if(!(name = dpstrdup(depot->name))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - depot->fatal = TRUE; - return NULL; - } - return name; -} - - -/* Get the size of a database file. */ -int dpfsiz(DEPOT *depot){ - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - return depot->fsiz; -} - - -/* Get the number of the elements of the bucket array. */ -int dpbnum(DEPOT *depot){ - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - return depot->bnum; -} - - -/* Get the number of the used elements of the bucket array. */ -int dpbusenum(DEPOT *depot){ - int i, hits; - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - hits = 0; - for(i = 0; i < depot->bnum; i++){ - if(depot->buckets[i]) hits++; - } - return hits; -} - - -/* Get the number of the records stored in a database. */ -int dprnum(DEPOT *depot){ - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - return depot->rnum; -} - - -/* Check whether a database handle is a writer or not. */ -int dpwritable(DEPOT *depot){ - assert(depot); - return depot->wmode; -} - - -/* Check whether a database has a fatal error or not. */ -int dpfatalerror(DEPOT *depot){ - assert(depot); - return depot->fatal; -} - - -/* Get the inode number of a database file. */ -int dpinode(DEPOT *depot){ - assert(depot); - return depot->inode; -} - - -/* Get the last modified time of a database. */ -time_t dpmtime(DEPOT *depot){ - assert(depot); - return depot->mtime; -} - - -/* Get the file descriptor of a database file. */ -int dpfdesc(DEPOT *depot){ - assert(depot); - return depot->fd; -} - - -/* Remove a database file. */ -int dpremove(const char *name){ - struct stat sbuf; - DEPOT *depot; - assert(name); - if(lstat(name, &sbuf) == -1){ - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - return FALSE; - } - if((depot = dpopen(name, DP_OWRITER | DP_OTRUNC, -1)) != NULL) dpclose(depot); - if(unlink(name) == -1){ - dpecodeset(DP_EUNLINK, __FILE__, __LINE__); - return FALSE; - } - return TRUE; -} - - -/* Repair a broken database file. */ -int dprepair(const char *name){ - DEPOT *tdepot; - char dbhead[DP_HEADSIZ], *tname, *kbuf, *vbuf; - int fd, fsiz, flags, bnum, tbnum, err, head[DP_RHNUM], off, rsiz, ksiz, vsiz; - struct stat sbuf; - assert(name); - if(lstat(name, &sbuf) == -1){ - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - return FALSE; - } - fsiz = sbuf.st_size; - if((fd = open(name, O_RDWR, DP_FILEMODE)) == -1){ - dpecodeset(DP_EOPEN, __FILE__, __LINE__); - return FALSE; - } - if(!dpseekread(fd, 0, dbhead, DP_HEADSIZ)){ - close(fd); - return FALSE; - } - flags = *(int *)(dbhead + DP_FLAGSOFF); - bnum = *(int *)(dbhead + DP_BNUMOFF); - tbnum = *(int *)(dbhead + DP_RNUMOFF) * 2; - if(tbnum < DP_DEFBNUM) tbnum = DP_DEFBNUM; - if(!(tname = malloc(strlen(name) + strlen(DP_TMPFSUF) + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return FALSE; - } - sprintf(tname, "%s%s", name, DP_TMPFSUF); - if(!(tdepot = dpopen(tname, DP_OWRITER | DP_OCREAT | DP_OTRUNC, tbnum))){ - free(tname); - close(fd); - return FALSE; - } - err = FALSE; - off = DP_HEADSIZ + bnum * sizeof(int); - while(off < fsiz){ - if(!dpseekread(fd, off, head, DP_RHNUM * sizeof(int))) break; - if(head[DP_RHIFLAGS] & DP_RECFDEL){ - if((rsiz = dprecsize(head)) < 0) break; - off += rsiz; - continue; - } - ksiz = head[DP_RHIKSIZ]; - vsiz = head[DP_RHIVSIZ]; - if(ksiz >= 0 && vsiz >= 0){ - kbuf = malloc(ksiz + 1); - vbuf = malloc(vsiz + 1); - if(kbuf && vbuf){ - if(dpseekread(fd, off + DP_RHNUM * sizeof(int), kbuf, ksiz) && - dpseekread(fd, off + DP_RHNUM * sizeof(int) + ksiz, vbuf, vsiz)){ - if(!dpput(tdepot, kbuf, ksiz, vbuf, vsiz, DP_DKEEP)) err = TRUE; - } else { - err = TRUE; - } - } else { - if(!err) dpecodeset(DP_EALLOC, __FILE__, __LINE__); - err = TRUE; - } - free(vbuf); - free(kbuf); - } else { - if(!err) dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - err = TRUE; - } - if((rsiz = dprecsize(head)) < 0) break; - off += rsiz; - } - if(!dpsetflags(tdepot, flags)) err = TRUE; - if(!dpsync(tdepot)) err = TRUE; - if(ftruncate(fd, 0) == -1){ - if(!err) dpecodeset(DP_ETRUNC, __FILE__, __LINE__); - err = TRUE; - } - if(dpfcopy(fd, 0, tdepot->fd, 0) == -1) err = TRUE; - if(!dpclose(tdepot)) err = TRUE; - if(close(fd) == -1){ - if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); - err = TRUE; - } - if(unlink(tname) == -1){ - if(!err) dpecodeset(DP_EUNLINK, __FILE__, __LINE__); - err = TRUE; - } - free(tname); - return err ? FALSE : TRUE; -} - - -/* Dump all records as endian independent data. */ -int dpexportdb(DEPOT *depot, const char *name){ - char *kbuf, *vbuf, *pbuf; - int fd, err, ksiz, vsiz, psiz; - assert(depot && name); - if(!(dpiterinit(depot))) return FALSE; - if((fd = open(name, O_RDWR | O_CREAT | O_TRUNC, DP_FILEMODE)) == -1){ - dpecodeset(DP_EOPEN, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - while(!err && (kbuf = dpiternext(depot, &ksiz)) != NULL){ - if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ - if((pbuf = malloc(ksiz + vsiz + DP_NUMBUFSIZ * 2)) != NULL){ - psiz = 0; - psiz += sprintf(pbuf + psiz, "%X\n%X\n", ksiz, vsiz); - memcpy(pbuf + psiz, kbuf, ksiz); - psiz += ksiz; - pbuf[psiz++] = '\n'; - memcpy(pbuf + psiz, vbuf, vsiz); - psiz += vsiz; - pbuf[psiz++] = '\n'; - if(!dpwrite(fd, pbuf, psiz)){ - dpecodeset(DP_EWRITE, __FILE__, __LINE__); - err = TRUE; - } - free(pbuf); - } else { - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - err = TRUE; - } - free(vbuf); - } else { - err = TRUE; - } - free(kbuf); - } - if(close(fd) == -1){ - if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); - return FALSE; - } - return !err && !dpfatalerror(depot); -} - - -/* Load all records from endian independent data. */ -int dpimportdb(DEPOT *depot, const char *name){ - char mbuf[DP_IOBUFSIZ], *rbuf; - int i, j, fd, err, fsiz, off, msiz, ksiz, vsiz, hlen; - struct stat sbuf; - assert(depot && name); - if(!depot->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(dprnum(depot) > 0){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - if((fd = open(name, O_RDONLY, DP_FILEMODE)) == -1){ - dpecodeset(DP_EOPEN, __FILE__, __LINE__); - return FALSE; - } - if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){ - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - close(fd); - return FALSE; - } - err = FALSE; - fsiz = sbuf.st_size; - off = 0; - while(!err && off < fsiz){ - msiz = fsiz - off; - if(msiz > DP_IOBUFSIZ) msiz = DP_IOBUFSIZ; - if(!dpseekread(fd, off, mbuf, msiz)){ - err = TRUE; - break; - } - hlen = 0; - ksiz = -1; - vsiz = -1; - for(i = 0; i < msiz; i++){ - if(mbuf[i] == '\n'){ - mbuf[i] = '\0'; - ksiz = strtol(mbuf, NULL, 16); - for(j = i + 1; j < msiz; j++){ - if(mbuf[j] == '\n'){ - mbuf[j] = '\0'; - vsiz = strtol(mbuf + i + 1, NULL, 16); - hlen = j + 1; - break; - } - } - break; - } - } - if(ksiz < 0 || vsiz < 0 || hlen < 4){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - err = TRUE; - break; - } - if(hlen + ksiz + vsiz + 2 < DP_IOBUFSIZ){ - if(!dpput(depot, mbuf + hlen, ksiz, mbuf + hlen + ksiz + 1, vsiz, DP_DKEEP)) err = TRUE; - } else { - if((rbuf = malloc(ksiz + vsiz + 2)) != NULL){ - if(dpseekread(fd, off + hlen, rbuf, ksiz + vsiz + 2)){ - if(!dpput(depot, rbuf, ksiz, rbuf + ksiz + 1, vsiz, DP_DKEEP)) err = TRUE; - } else { - err = TRUE; - } - free(rbuf); - } else { - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - err = TRUE; - } - } - off += hlen + ksiz + vsiz + 2; - } - if(close(fd) == -1){ - if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); - return FALSE; - } - return !err && !dpfatalerror(depot); -} - - -/* Retrieve a record directly from a database file. */ -char *dpsnaffle(const char *name, const char* kbuf, int ksiz, int *sp){ - char hbuf[DP_HEADSIZ], *map, *vbuf, *tkbuf; - int fd, fsiz, bnum, msiz, *buckets, hash, thash, head[DP_RHNUM], err, off, vsiz, tksiz, kcmp; - struct stat sbuf; - assert(name && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if((fd = open(name, O_RDONLY, DP_FILEMODE)) == -1){ - dpecodeset(DP_EOPEN, __FILE__, __LINE__); - return NULL; - } - if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){ - close(fd); - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - return NULL; - } - fsiz = sbuf.st_size; - if(!dpseekread(fd, 0, hbuf, DP_HEADSIZ)){ - close(fd); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - if(dpbigendian() ? memcmp(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB)) != 0 : - memcmp(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML)) != 0){ - close(fd); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - bnum = *((int *)(hbuf + DP_BNUMOFF)); - if(bnum < 1 || fsiz < DP_HEADSIZ + bnum * sizeof(int)){ - close(fd); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - msiz = DP_HEADSIZ + bnum * sizeof(int); - map = mmap(0, msiz, PROT_READ, MAP_SHARED, fd, 0); - if(map == MAP_FAILED){ - close(fd); - dpecodeset(DP_EMAP, __FILE__, __LINE__); - return NULL; - } - buckets = (int *)(map + DP_HEADSIZ); - err = FALSE; - vbuf = NULL; - vsiz = 0; - DP_SECONDHASH(hash, kbuf, ksiz); - DP_FIRSTHASH(thash, kbuf, ksiz); - off = buckets[thash%bnum]; - while(off != 0){ - if(!dpseekread(fd, off, head, DP_RHNUM * sizeof(int))){ - err = TRUE; - break; - } - if(head[DP_RHIKSIZ] < 0 || head[DP_RHIVSIZ] < 0 || head[DP_RHIPSIZ] < 0 || - head[DP_RHILEFT] < 0 || head[DP_RHIRIGHT] < 0){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - err = TRUE; - break; - } - thash = head[DP_RHIHASH]; - if(hash > thash){ - off = head[DP_RHILEFT]; - } else if(hash < thash){ - off = head[DP_RHIRIGHT]; - } else { - tksiz = head[DP_RHIKSIZ]; - if(!(tkbuf = malloc(tksiz + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - err = TRUE; - break; - } - if(!dpseekread(fd, off + DP_RHNUM * sizeof(int), tkbuf, tksiz)){ - free(tkbuf); - err = TRUE; - break; - } - tkbuf[tksiz] = '\0'; - kcmp = dpkeycmp(kbuf, ksiz, tkbuf, tksiz); - free(tkbuf); - if(kcmp > 0){ - off = head[DP_RHILEFT]; - } else if(kcmp < 0){ - off = head[DP_RHIRIGHT]; - } else if(head[DP_RHIFLAGS] & DP_RECFDEL){ - break; - } else { - vsiz = head[DP_RHIVSIZ]; - if(!(vbuf = malloc(vsiz + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - err = TRUE; - break; - } - if(!dpseekread(fd, off + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ], vbuf, vsiz)){ - free(vbuf); - vbuf = NULL; - err = TRUE; - break; - } - vbuf[vsiz] = '\0'; - break; - } - } - } - if(vbuf){ - if(sp) *sp = vsiz; - } else if(!err){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - } - munmap(map, msiz); - close(fd); - return vbuf; -} - - -/* Hash function used inside Depot. */ -int dpinnerhash(const char *kbuf, int ksiz){ - int res; - assert(kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - DP_FIRSTHASH(res, kbuf, ksiz); - return res; -} - - -/* Hash function which is independent from the hash functions used inside Depot. */ -int dpouterhash(const char *kbuf, int ksiz){ - int res; - assert(kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - DP_THIRDHASH(res, kbuf, ksiz); - return res; -} - - -/* Get a natural prime number not less than a number. */ -int dpprimenum(int num){ - assert(num > 0); - return dpgetprime(num); -} - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Name of the operating system. */ -const char *dpsysname = _QDBM_SYSNAME; - - -/* File descriptor for debugging output. */ -int dpdbgfd = -1; - - -/* Whether this build is reentrant. */ -const int dpisreentrant = _qdbm_ptsafe; - - -/* Set the last happened error code. */ -void dpecodeset(int ecode, const char *file, int line){ - char iobuf[DP_IOBUFSIZ]; - assert(ecode >= DP_ENOERR && file && line >= 0); - dpecode = ecode; - if(dpdbgfd >= 0){ - fflush(stdout); - fflush(stderr); - sprintf(iobuf, "* dpecodeset: %s:%d: [%d] %s\n", file, line, ecode, dperrmsg(ecode)); - dpwrite(dpdbgfd, iobuf, strlen(iobuf)); - } -} - - -/* Get the pointer of the variable of the last happened error code. */ -int *dpecodeptr(void){ - static int defdpecode = DP_ENOERR; - void *ptr; - if(_qdbm_ptsafe){ - if(!(ptr = _qdbm_settsd(&defdpecode, sizeof(int), &defdpecode))){ - defdpecode = DP_EMISC; - return &defdpecode; - } - return (int *)ptr; - } - return &defdpecode; -} - - -/* Synchronize updating contents on memory. */ -int dpmemsync(DEPOT *depot){ - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!depot->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; - *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; - if(msync(depot->map, depot->msiz, MS_SYNC) == -1){ - dpecodeset(DP_EMAP, __FILE__, __LINE__); - depot->fatal = TRUE; - return FALSE; - } - return TRUE; -} - - -/* Synchronize updating contents on memory, not physically. */ -int dpmemflush(DEPOT *depot){ - assert(depot); - if(depot->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!depot->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; - *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; - if(mflush(depot->map, depot->msiz, MS_SYNC) == -1){ - dpecodeset(DP_EMAP, __FILE__, __LINE__); - depot->fatal = TRUE; - return FALSE; - } - return TRUE; -} - - -/* Get flags of a database. */ -int dpgetflags(DEPOT *depot){ - int flags; - assert(depot); - memcpy(&flags, depot->map + DP_FLAGSOFF, sizeof(int)); - return flags; -} - - -/* Set flags of a database. */ -int dpsetflags(DEPOT *depot, int flags){ - assert(depot); - if(!depot->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - memcpy(depot->map + DP_FLAGSOFF, &flags, sizeof(int)); - return TRUE; -} - - - -/************************************************************************************************* - * private objects - *************************************************************************************************/ - - -/* Check whether the byte order of the platform is big endian or not. - The return value is true if bigendian, else, it is false. */ -static int dpbigendian(void){ - char buf[sizeof(int)]; - *(int *)buf = 1; - return !buf[0]; -} - - -/* Get a copied string. - `str' specifies an original string. - The return value is a copied string whose region is allocated by `malloc'. */ -static char *dpstrdup(const char *str){ - int len; - char *buf; - assert(str); - len = strlen(str); - if(!(buf = malloc(len + 1))) return NULL; - memcpy(buf, str, len + 1); - return buf; -} - - -/* Lock a file descriptor. - `fd' specifies a file descriptor. - `ex' specifies whether an exclusive lock or a shared lock is performed. - `nb' specifies whether to request with non-blocking. - The return value is true if successful, else, it is false. */ -static int dplock(int fd, int ex, int nb){ - struct flock lock; - assert(fd >= 0); - memset(&lock, 0, sizeof(struct flock)); - lock.l_type = ex ? F_WRLCK : F_RDLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - lock.l_pid = 0; - while(fcntl(fd, nb ? F_SETLK : F_SETLKW, &lock) == -1){ - if(errno != EINTR){ - dpecodeset(DP_ELOCK, __FILE__, __LINE__); - return FALSE; - } - } - return TRUE; -} - - -/* Write into a file. - `fd' specifies a file descriptor. - `buf' specifies a buffer to write. - `size' specifies the size of the buffer. - The return value is the size of the written buffer, or, -1 on failure. */ -static int dpwrite(int fd, const void *buf, int size){ - const char *lbuf; - int rv, wb; - assert(fd >= 0 && buf && size >= 0); - lbuf = buf; - rv = 0; - do { - wb = write(fd, lbuf, size); - switch(wb){ - case -1: if(errno != EINTR) return -1; - case 0: break; - default: - lbuf += wb; - size -= wb; - rv += wb; - break; - } - } while(size > 0); - return rv; -} - - -/* Write into a file at an offset. - `fd' specifies a file descriptor. - `off' specifies an offset of the file. - `buf' specifies a buffer to write. - `size' specifies the size of the buffer. - The return value is true if successful, else, it is false. */ -static int dpseekwrite(int fd, int off, const void *buf, int size){ - assert(fd >= 0 && buf && size >= 0); - if(size < 1) return TRUE; - if(off < 0){ - if(lseek(fd, 0, SEEK_END) == -1){ - dpecodeset(DP_ESEEK, __FILE__, __LINE__); - return FALSE; - } - } else { - if(lseek(fd, off, SEEK_SET) != off){ - dpecodeset(DP_ESEEK, __FILE__, __LINE__); - return FALSE; - } - } - if(dpwrite(fd, buf, size) != size){ - dpecodeset(DP_EWRITE, __FILE__, __LINE__); - return FALSE; - } - return TRUE; -} - - -/* Write an integer into a file at an offset. - `fd' specifies a file descriptor. - `off' specifies an offset of the file. - `num' specifies an integer. - The return value is true if successful, else, it is false. */ -static int dpseekwritenum(int fd, int off, int num){ - assert(fd >= 0); - return dpseekwrite(fd, off, &num, sizeof(int)); -} - - -/* Read from a file and store the data into a buffer. - `fd' specifies a file descriptor. - `buffer' specifies a buffer to store into. - `size' specifies the size to read with. - The return value is the size read with, or, -1 on failure. */ -static int dpread(int fd, void *buf, int size){ - char *lbuf; - int i, bs; - assert(fd >= 0 && buf && size >= 0); - lbuf = buf; - for(i = 0; i < size && (bs = read(fd, lbuf + i, size - i)) != 0; i += bs){ - if(bs == -1 && errno != EINTR) return -1; - } - return i; -} - - -/* Read from a file at an offset and store the data into a buffer. - `fd' specifies a file descriptor. - `off' specifies an offset of the file. - `buffer' specifies a buffer to store into. - `size' specifies the size to read with. - The return value is true if successful, else, it is false. */ -static int dpseekread(int fd, int off, void *buf, int size){ - char *lbuf; - assert(fd >= 0 && off >= 0 && buf && size >= 0); - lbuf = (char *)buf; - if(lseek(fd, off, SEEK_SET) != off){ - dpecodeset(DP_ESEEK, __FILE__, __LINE__); - return FALSE; - } - if(dpread(fd, lbuf, size) != size){ - dpecodeset(DP_EREAD, __FILE__, __LINE__); - return FALSE; - } - return TRUE; -} - - -/* Copy data between files. - `destfd' specifies a file descriptor of a destination file. - `destoff' specifies an offset of the destination file. - `srcfd' specifies a file descriptor of a source file. - `srcoff' specifies an offset of the source file. - The return value is the size copied with, or, -1 on failure. */ -static int dpfcopy(int destfd, int destoff, int srcfd, int srcoff){ - char iobuf[DP_IOBUFSIZ]; - int sum, iosiz; - if(lseek(srcfd, srcoff, SEEK_SET) == -1 || lseek(destfd, destoff, SEEK_SET) == -1){ - dpecodeset(DP_ESEEK, __FILE__, __LINE__); - return -1; - } - sum = 0; - while((iosiz = dpread(srcfd, iobuf, DP_IOBUFSIZ)) > 0){ - if(dpwrite(destfd, iobuf, iosiz) == -1){ - dpecodeset(DP_EWRITE, __FILE__, __LINE__); - return -1; - } - sum += iosiz; - } - if(iosiz < 0){ - dpecodeset(DP_EREAD, __FILE__, __LINE__); - return -1; - } - return sum; -} - - -/* Get a natural prime number not less than a number. - `num' specified a natural number. - The return value is a prime number not less than the specified number. */ -static int dpgetprime(int num){ - int primes[] = { - 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 43, 47, 53, 59, 61, 71, 79, 83, - 89, 103, 109, 113, 127, 139, 157, 173, 191, 199, 223, 239, 251, 283, 317, 349, - 383, 409, 443, 479, 509, 571, 631, 701, 761, 829, 887, 953, 1021, 1151, 1279, - 1399, 1531, 1663, 1789, 1913, 2039, 2297, 2557, 2803, 3067, 3323, 3583, 3833, - 4093, 4603, 5119, 5623, 6143, 6653, 7159, 7673, 8191, 9209, 10223, 11261, - 12281, 13309, 14327, 15359, 16381, 18427, 20479, 22511, 24571, 26597, 28669, - 30713, 32749, 36857, 40949, 45053, 49139, 53239, 57331, 61417, 65521, 73727, - 81919, 90107, 98299, 106487, 114679, 122869, 131071, 147451, 163819, 180221, - 196597, 212987, 229373, 245759, 262139, 294911, 327673, 360439, 393209, 425977, - 458747, 491503, 524287, 589811, 655357, 720887, 786431, 851957, 917503, 982981, - 1048573, 1179641, 1310719, 1441771, 1572853, 1703903, 1835003, 1966079, - 2097143, 2359267, 2621431, 2883577, 3145721, 3407857, 3670013, 3932153, - 4194301, 4718579, 5242877, 5767129, 6291449, 6815741, 7340009, 7864301, - 8388593, 9437179, 10485751, 11534329, 12582893, 13631477, 14680063, 15728611, - 16777213, 18874367, 20971507, 23068667, 25165813, 27262931, 29360087, 31457269, - 33554393, 37748717, 41943023, 46137319, 50331599, 54525917, 58720253, 62914549, - 67108859, 75497467, 83886053, 92274671, 100663291, 109051903, 117440509, - 125829103, 134217689, 150994939, 167772107, 184549373, 201326557, 218103799, - 234881011, 251658227, 268435399, 301989881, 335544301, 369098707, 402653171, - 436207613, 469762043, 503316469, 536870909, 603979769, 671088637, 738197503, - 805306357, 872415211, 939524087, 1006632947, 1073741789, 1207959503, - 1342177237, 1476394991, 1610612711, 1744830457, 1879048183, 2013265907, -1 - }; - int i; - assert(num > 0); - for(i = 0; primes[i] > 0; i++){ - if(num <= primes[i]) return primes[i]; - } - return primes[i-1]; -} - - -/* Get the padding size of a record. - `vsiz' specifies the size of the value of a record. - The return value is the padding size of a record. */ -static int dppadsize(DEPOT *depot, int ksiz, int vsiz){ - int pad; - assert(depot && vsiz >= 0); - if(depot->align > 0){ - return depot->align - (depot->fsiz + DP_RHNUM * sizeof(int) + ksiz + vsiz) % depot->align; - } else if(depot->align < 0){ - pad = (int)(vsiz * (2.0 / (1 << -(depot->align)))); - if(vsiz + pad >= DP_FSBLKSIZ){ - if(vsiz <= DP_FSBLKSIZ) pad = 0; - if(depot->fsiz % DP_FSBLKSIZ == 0){ - return (pad / DP_FSBLKSIZ) * DP_FSBLKSIZ + DP_FSBLKSIZ - - (depot->fsiz + DP_RHNUM * sizeof(int) + ksiz + vsiz) % DP_FSBLKSIZ; - } else { - return (pad / (DP_FSBLKSIZ / 2)) * (DP_FSBLKSIZ / 2) + (DP_FSBLKSIZ / 2) - - (depot->fsiz + DP_RHNUM * sizeof(int) + ksiz + vsiz) % (DP_FSBLKSIZ / 2); - } - } else { - return pad >= DP_RHNUM * sizeof(int) ? pad : DP_RHNUM * sizeof(int); - } - } - return 0; -} - - -/* Get the size of a record in a database file. - `head' specifies the header of a record. - The return value is the size of a record in a database file. */ -static int dprecsize(int *head){ - assert(head); - return DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] + head[DP_RHIPSIZ]; -} - - -/* Read the header of a record. - `depot' specifies a database handle. - `off' specifies an offset of the database file. - `head' specifies a buffer for the header. - `ebuf' specifies the pointer to the entity buffer. - `eep' specifies the pointer to a variable to which whether ebuf was used is assigned. - The return value is true if successful, else, it is false. */ -static int dprechead(DEPOT *depot, int off, int *head, char *ebuf, int *eep){ - assert(depot && off >= 0 && head); - if(off > depot->fsiz){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return FALSE; - } - if(ebuf){ - *eep = FALSE; - if(off < depot->fsiz - DP_ENTBUFSIZ){ - *eep = TRUE; - if(!dpseekread(depot->fd, off, ebuf, DP_ENTBUFSIZ)) return FALSE; - memcpy(head, ebuf, DP_RHNUM * sizeof(int)); - if(head[DP_RHIKSIZ] < 0 || head[DP_RHIVSIZ] < 0 || head[DP_RHIPSIZ] < 0 || - head[DP_RHILEFT] < 0 || head[DP_RHIRIGHT] < 0){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return FALSE; - } - return TRUE; - } - } - if(!dpseekread(depot->fd, off, head, DP_RHNUM * sizeof(int))) return FALSE; - if(head[DP_RHIKSIZ] < 0 || head[DP_RHIVSIZ] < 0 || head[DP_RHIPSIZ] < 0 || - head[DP_RHILEFT] < 0 || head[DP_RHIRIGHT] < 0){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return FALSE; - } - return TRUE; -} - - -/* Read the entitiy of the key of a record. - `depot' specifies a database handle. - `off' specifies an offset of the database file. - `head' specifies the header of a record. - The return value is a key data whose region is allocated by `malloc', or NULL on failure. */ -static char *dpreckey(DEPOT *depot, int off, int *head){ - char *kbuf; - int ksiz; - assert(depot && off >= 0); - ksiz = head[DP_RHIKSIZ]; - if(!(kbuf = malloc(ksiz + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return NULL; - } - if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int), kbuf, ksiz)){ - free(kbuf); - return NULL; - } - kbuf[ksiz] = '\0'; - return kbuf; -} - - -/* Read the entitiy of the value of a record. - `depot' specifies a database handle. - `off' specifies an offset of the database file. - `head' specifies the header of a record. - `start' specifies the offset address of the beginning of the region of the value to be read. - `max' specifies the max size to be read. If it is negative, the size to read is unlimited. - The return value is a value data whose region is allocated by `malloc', or NULL on failure. */ -static char *dprecval(DEPOT *depot, int off, int *head, int start, int max){ - char *vbuf; - int vsiz; - assert(depot && off >= 0 && start >= 0); - head[DP_RHIVSIZ] -= start; - if(max < 0){ - vsiz = head[DP_RHIVSIZ]; - } else { - vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; - } - if(!(vbuf = malloc(vsiz + 1))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return NULL; - } - if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start, vbuf, vsiz)){ - free(vbuf); - return NULL; - } - vbuf[vsiz] = '\0'; - return vbuf; -} - - -/* Read the entitiy of the value of a record and write it into a given buffer. - `depot' specifies a database handle. - `off' specifies an offset of the database file. - `head' specifies the header of a record. - `start' specifies the offset address of the beginning of the region of the value to be read. - `max' specifies the max size to be read. It shuld be less than the size of the writing buffer. - If successful, the return value is the size of the written data, else, it is -1. */ -static int dprecvalwb(DEPOT *depot, int off, int *head, int start, int max, char *vbuf){ - int vsiz; - assert(depot && off >= 0 && start >= 0 && max >= 0 && vbuf); - head[DP_RHIVSIZ] -= start; - vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; - if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start, vbuf, vsiz)) - return -1; - return vsiz; -} - - -/* Compare two keys. - `abuf' specifies the pointer to the region of the former. - `asiz' specifies the size of the region. - `bbuf' specifies the pointer to the region of the latter. - `bsiz' specifies the size of the region. - The return value is 0 if two equals, positive if the formar is big, else, negative. */ -static int dpkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz){ - assert(abuf && asiz >= 0 && bbuf && bsiz >= 0); - if(asiz > bsiz) return 1; - if(asiz < bsiz) return -1; - return memcmp(abuf, bbuf, asiz); -} - - -/* Search for a record. - `depot' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region. - `hash' specifies the second hash value of the key. - `bip' specifies the pointer to the region to assign the index of the corresponding record. - `offp' specifies the pointer to the region to assign the last visited node in the hash chain, - or, -1 if the hash chain is empty. - `entp' specifies the offset of the last used joint, or, -1 if the hash chain is empty. - `head' specifies the pointer to the region to store the header of the last visited record in. - `ebuf' specifies the pointer to the entity buffer. - `eep' specifies the pointer to a variable to which whether ebuf was used is assigned. - `delhit' specifies whether a deleted record corresponds or not. - The return value is 0 if successful, 1 if there is no corresponding record, -1 on error. */ -static int dprecsearch(DEPOT *depot, const char *kbuf, int ksiz, int hash, int *bip, int *offp, - int *entp, int *head, char *ebuf, int *eep, int delhit){ - int off, entoff, thash, kcmp; - char stkey[DP_STKBUFSIZ], *tkey; - assert(depot && kbuf && ksiz >= 0 && hash >= 0 && bip && offp && entp && head && ebuf && eep); - DP_FIRSTHASH(thash, kbuf, ksiz); - *bip = thash % depot->bnum; - off = depot->buckets[*bip]; - *offp = -1; - *entp = -1; - entoff = -1; - *eep = FALSE; - while(off != 0){ - if(!dprechead(depot, off, head, ebuf, eep)) return -1; - thash = head[DP_RHIHASH]; - if(hash > thash){ - entoff = off + DP_RHILEFT * sizeof(int); - off = head[DP_RHILEFT]; - } else if(hash < thash){ - entoff = off + DP_RHIRIGHT * sizeof(int); - off = head[DP_RHIRIGHT]; - } else { - if(*eep && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] <= DP_ENTBUFSIZ){ - kcmp = dpkeycmp(kbuf, ksiz, ebuf + (DP_RHNUM * sizeof(int)), head[DP_RHIKSIZ]); - } else if(head[DP_RHIKSIZ] > DP_STKBUFSIZ){ - if(!(tkey = dpreckey(depot, off, head))) return -1; - kcmp = dpkeycmp(kbuf, ksiz, tkey, head[DP_RHIKSIZ]); - free(tkey); - } else { - if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int), stkey, head[DP_RHIKSIZ])) - return -1; - kcmp = dpkeycmp(kbuf, ksiz, stkey, head[DP_RHIKSIZ]); - } - if(kcmp > 0){ - entoff = off + DP_RHILEFT * sizeof(int); - off = head[DP_RHILEFT]; - } else if(kcmp < 0){ - entoff = off + DP_RHIRIGHT * sizeof(int); - off = head[DP_RHIRIGHT]; - } else { - if(!delhit && (head[DP_RHIFLAGS] & DP_RECFDEL)){ - entoff = off + DP_RHILEFT * sizeof(int); - off = head[DP_RHILEFT]; - } else { - *offp = off; - *entp = entoff; - return 0; - } - } - } - } - *offp = off; - *entp = entoff; - return 1; -} - - -/* Overwrite a record. - `depot' specifies a database handle. - `off' specifies the offset of the database file. - `rsiz' specifies the size of the existing record. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region. - `hash' specifies the second hash value of the key. - `left' specifies the offset of the left child. - `right' specifies the offset of the right child. - The return value is true if successful, or, false on failure. */ -static int dprecrewrite(DEPOT *depot, int off, int rsiz, const char *kbuf, int ksiz, - const char *vbuf, int vsiz, int hash, int left, int right){ - char ebuf[DP_WRTBUFSIZ]; - int i, head[DP_RHNUM], asiz, hoff, koff, voff, mi, min, size; - assert(depot && off >= 1 && rsiz > 0 && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); - head[DP_RHIFLAGS] = 0; - head[DP_RHIHASH] = hash; - head[DP_RHIKSIZ] = ksiz; - head[DP_RHIVSIZ] = vsiz; - head[DP_RHIPSIZ] = rsiz - sizeof(head) - ksiz - vsiz; - head[DP_RHILEFT] = left; - head[DP_RHIRIGHT] = right; - asiz = sizeof(head) + ksiz + vsiz; - if(depot->fbpsiz > DP_FBPOOLSIZ * 4 && head[DP_RHIPSIZ] > asiz){ - rsiz = (head[DP_RHIPSIZ] - asiz) / 2 + asiz; - head[DP_RHIPSIZ] -= rsiz; - } else { - rsiz = 0; - } - if(asiz <= DP_WRTBUFSIZ){ - memcpy(ebuf, head, sizeof(head)); - memcpy(ebuf + sizeof(head), kbuf, ksiz); - memcpy(ebuf + sizeof(head) + ksiz, vbuf, vsiz); - if(!dpseekwrite(depot->fd, off, ebuf, asiz)) return FALSE; - } else { - hoff = off; - koff = hoff + sizeof(head); - voff = koff + ksiz; - if(!dpseekwrite(depot->fd, hoff, head, sizeof(head)) || - !dpseekwrite(depot->fd, koff, kbuf, ksiz) || !dpseekwrite(depot->fd, voff, vbuf, vsiz)) - return FALSE; - } - if(rsiz > 0){ - off += sizeof(head) + ksiz + vsiz + head[DP_RHIPSIZ]; - head[DP_RHIFLAGS] = DP_RECFDEL | DP_RECFREUSE; - head[DP_RHIHASH] = hash; - head[DP_RHIKSIZ] = ksiz; - head[DP_RHIVSIZ] = vsiz; - head[DP_RHIPSIZ] = rsiz - sizeof(head) - ksiz - vsiz; - head[DP_RHILEFT] = 0; - head[DP_RHIRIGHT] = 0; - if(!dpseekwrite(depot->fd, off, head, sizeof(head))) return FALSE; - size = dprecsize(head); - mi = -1; - min = -1; - for(i = 0; i < depot->fbpsiz; i += 2){ - if(depot->fbpool[i] == -1){ - depot->fbpool[i] = off; - depot->fbpool[i+1] = size; - dpfbpoolcoal(depot); - mi = -1; - break; - } - if(mi == -1 || depot->fbpool[i+1] < min){ - mi = i; - min = depot->fbpool[i+1]; - } - } - if(mi >= 0 && size > min){ - depot->fbpool[mi] = off; - depot->fbpool[mi+1] = size; - dpfbpoolcoal(depot); - } - } - return TRUE; -} - - -/* Write a record at the end of a database file. - `depot' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region. - `hash' specifies the second hash value of the key. - `left' specifies the offset of the left child. - `right' specifies the offset of the right child. - The return value is the offset of the record, or, -1 on failure. */ -static int dprecappend(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, - int hash, int left, int right){ - char ebuf[DP_WRTBUFSIZ], *hbuf; - int head[DP_RHNUM], asiz, psiz, off; - assert(depot && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); - psiz = dppadsize(depot, ksiz, vsiz); - head[DP_RHIFLAGS] = 0; - head[DP_RHIHASH] = hash; - head[DP_RHIKSIZ] = ksiz; - head[DP_RHIVSIZ] = vsiz; - head[DP_RHIPSIZ] = psiz; - head[DP_RHILEFT] = left; - head[DP_RHIRIGHT] = right; - asiz = sizeof(head) + ksiz + vsiz + psiz; - off = depot->fsiz; - if(asiz <= DP_WRTBUFSIZ){ - memcpy(ebuf, head, sizeof(head)); - memcpy(ebuf + sizeof(head), kbuf, ksiz); - memcpy(ebuf + sizeof(head) + ksiz, vbuf, vsiz); - memset(ebuf + sizeof(head) + ksiz + vsiz, 0, psiz); - if(!dpseekwrite(depot->fd, off, ebuf, asiz)) return -1; - } else { - if(!(hbuf = malloc(asiz))){ - dpecodeset(DP_EALLOC, __FILE__, __LINE__); - return -1; - } - memcpy(hbuf, head, sizeof(head)); - memcpy(hbuf + sizeof(head), kbuf, ksiz); - memcpy(hbuf + sizeof(head) + ksiz, vbuf, vsiz); - memset(hbuf + sizeof(head) + ksiz + vsiz, 0, psiz); - if(!dpseekwrite(depot->fd, off, hbuf, asiz)){ - free(hbuf); - return -1; - } - free(hbuf); - } - depot->fsiz += asiz; - return off; -} - - -/* Overwrite the value of a record. - `depot' specifies a database handle. - `off' specifies the offset of the database file. - `head' specifies the header of the record. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region. - `cat' specifies whether it is concatenate mode or not. - The return value is true if successful, or, false on failure. */ -static int dprecover(DEPOT *depot, int off, int *head, const char *vbuf, int vsiz, int cat){ - int i, hsiz, hoff, voff; - assert(depot && off >= 0 && head && vbuf && vsiz >= 0); - for(i = 0; i < depot->fbpsiz; i += 2){ - if(depot->fbpool[i] == off){ - depot->fbpool[i] = -1; - depot->fbpool[i+1] = -1; - break; - } - } - if(cat){ - head[DP_RHIFLAGS] = 0; - head[DP_RHIPSIZ] -= vsiz; - head[DP_RHIVSIZ] += vsiz; - hsiz = DP_RHNUM * sizeof(int); - hoff = off; - voff = hoff + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] - vsiz; - } else { - head[DP_RHIFLAGS] = 0; - head[DP_RHIPSIZ] += head[DP_RHIVSIZ] - vsiz; - head[DP_RHIVSIZ] = vsiz; - hsiz = DP_RHNUM * sizeof(int); - hoff = off; - voff = hoff + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ]; - } - if(!dpseekwrite(depot->fd, hoff, head, hsiz) || - !dpseekwrite(depot->fd, voff, vbuf, vsiz)) return FALSE; - return TRUE; -} - - -/* Delete a record. - `depot' specifies a database handle. - `off' specifies the offset of the database file. - `head' specifies the header of the record. - `reusable' specifies whether the region is reusable or not. - The return value is true if successful, or, false on failure. */ -static int dprecdelete(DEPOT *depot, int off, int *head, int reusable){ - int i, mi, min, size; - assert(depot && off >= 0 && head); - if(reusable){ - size = dprecsize(head); - mi = -1; - min = -1; - for(i = 0; i < depot->fbpsiz; i += 2){ - if(depot->fbpool[i] == -1){ - depot->fbpool[i] = off; - depot->fbpool[i+1] = size; - dpfbpoolcoal(depot); - mi = -1; - break; - } - if(mi == -1 || depot->fbpool[i+1] < min){ - mi = i; - min = depot->fbpool[i+1]; - } - } - if(mi >= 0 && size > min){ - depot->fbpool[mi] = off; - depot->fbpool[mi+1] = size; - dpfbpoolcoal(depot); - } - } - return dpseekwritenum(depot->fd, off + DP_RHIFLAGS * sizeof(int), - DP_RECFDEL | (reusable ? DP_RECFREUSE : 0)); -} - - -/* Make contiguous records of the free block pool coalesce. - `depot' specifies a database handle. */ -static void dpfbpoolcoal(DEPOT *depot){ - int i; - assert(depot); - if(depot->fbpinc++ <= depot->fbpsiz / 4) return; - depot->fbpinc = 0; - qsort(depot->fbpool, depot->fbpsiz / 2, sizeof(int) * 2, dpfbpoolcmp); - for(i = 2; i < depot->fbpsiz; i += 2){ - if(depot->fbpool[i-2] > 0 && - depot->fbpool[i-2] + depot->fbpool[i-1] - depot->fbpool[i] == 0){ - depot->fbpool[i] = depot->fbpool[i-2]; - depot->fbpool[i+1] += depot->fbpool[i-1]; - depot->fbpool[i-2] = -1; - depot->fbpool[i-1] = -1; - } - } -} - - -/* Compare two records of the free block pool. - `a' specifies the pointer to one record. - `b' specifies the pointer to the other record. - The return value is 0 if two equals, positive if the formar is big, else, negative. */ -static int dpfbpoolcmp(const void *a, const void *b){ - assert(a && b); - return *(int *)a - *(int *)b; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/depot.c (from rev 2716, box/trunk/qdbm/depot.c) =================================================================== --- box/trunk/qdbm/depot.c (rev 0) +++ box/trunk/qdbm/depot.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,2219 @@ +/************************************************************************************************* + * Implementation of Depot + * 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. + *************************************************************************************************/ + + +#define QDBM_INTERNAL 1 + +#include "depot.h" +#include "myconf.h" + +#define DP_FILEMODE 00644 /* permission of a creating file */ +#define DP_MAGICNUMB "[DEPOT]\n\f" /* magic number on environments of big endian */ +#define DP_MAGICNUML "[depot]\n\f" /* magic number on environments of little endian */ +#define DP_HEADSIZ 48 /* size of the reagion of the header */ +#define DP_LIBVEROFF 12 /* offset of the region for the library version */ +#define DP_FLAGSOFF 16 /* offset of the region for flags */ +#define DP_FSIZOFF 24 /* offset of the region for the file size */ +#define DP_BNUMOFF 32 /* offset of the region for the bucket number */ +#define DP_RNUMOFF 40 /* offset of the region for the record number */ +#define DP_DEFBNUM 8191 /* default bucket number */ +#define DP_FBPOOLSIZ 16 /* size of free block pool */ +#define DP_ENTBUFSIZ 128 /* size of the entity buffer */ +#define DP_STKBUFSIZ 256 /* size of the stack key buffer */ +#define DP_WRTBUFSIZ 8192 /* size of the writing buffer */ +#define DP_FSBLKSIZ 4096 /* size of a block of the file system */ +#define DP_TMPFSUF MYEXTSTR "dptmp" /* suffix of a temporary file */ +#define DP_OPTBLOAD 0.25 /* ratio of bucket loading at optimization */ +#define DP_OPTRUNIT 256 /* number of records in a process of optimization */ +#define DP_NUMBUFSIZ 32 /* size of a buffer for a number */ +#define DP_IOBUFSIZ 8192 /* size of an I/O buffer */ + +/* get the first hash value */ +#define DP_FIRSTHASH(DP_res, DP_kbuf, DP_ksiz) \ + do { \ + const unsigned char *_DP_p; \ + int _DP_ksiz; \ + _DP_p = (const unsigned char *)(DP_kbuf); \ + _DP_ksiz = DP_ksiz; \ + if((_DP_ksiz) == sizeof(int)){ \ + memcpy(&(DP_res), (DP_kbuf), sizeof(int)); \ + } else { \ + (DP_res) = 751; \ + } \ + while(_DP_ksiz--){ \ + (DP_res) = (DP_res) * 31 + *(_DP_p)++; \ + } \ + (DP_res) = ((DP_res) * 87767623) & INT_MAX; \ + } while(FALSE) + +/* get the second hash value */ +#define DP_SECONDHASH(DP_res, DP_kbuf, DP_ksiz) \ + do { \ + const unsigned char *_DP_p; \ + int _DP_ksiz; \ + _DP_p = (const unsigned char *)(DP_kbuf) + DP_ksiz - 1; \ + _DP_ksiz = DP_ksiz; \ + for((DP_res) = 19780211; _DP_ksiz--;){ \ + (DP_res) = (DP_res) * 37 + *(_DP_p)--; \ + } \ + (DP_res) = ((DP_res) * 43321879) & INT_MAX; \ + } while(FALSE) + +/* get the third hash value */ +#define DP_THIRDHASH(DP_res, DP_kbuf, DP_ksiz) \ + do { \ + int _DP_i; \ + (DP_res) = 774831917; \ + for(_DP_i = (DP_ksiz) - 1; _DP_i >= 0; _DP_i--){ \ + (DP_res) = (DP_res) * 29 + ((const unsigned char *)(DP_kbuf))[_DP_i]; \ + } \ + (DP_res) = ((DP_res) * 5157883) & INT_MAX; \ + } while(FALSE) + +enum { /* enumeration for a record header */ + DP_RHIFLAGS, /* offset of flags */ + DP_RHIHASH, /* offset of value of the second hash function */ + DP_RHIKSIZ, /* offset of the size of the key */ + DP_RHIVSIZ, /* offset of the size of the value */ + DP_RHIPSIZ, /* offset of the size of the padding bytes */ + DP_RHILEFT, /* offset of the offset of the left child */ + DP_RHIRIGHT, /* offset of the offset of the right child */ + DP_RHNUM /* number of elements of a header */ +}; + +enum { /* enumeration for the flag of a record */ + DP_RECFDEL = 1 << 0, /* deleted */ + DP_RECFREUSE = 1 << 1 /* reusable */ +}; + + +/* private function prototypes */ +static int dpbigendian(void); +static char *dpstrdup(const char *str); +static int dplock(int fd, int ex, int nb); +static int dpwrite(int fd, const void *buf, int size); +static int dpseekwrite(int fd, int off, const void *buf, int size); +static int dpseekwritenum(int fd, int off, int num); +static int dpread(int fd, void *buf, int size); +static int dpseekread(int fd, int off, void *buf, int size); +static int dpfcopy(int destfd, int destoff, int srcfd, int srcoff); +static int dpgetprime(int num); +static int dppadsize(DEPOT *depot, int ksiz, int vsiz); +static int dprecsize(int *head); +static int dprechead(DEPOT *depot, int off, int *head, char *ebuf, int *eep); +static char *dpreckey(DEPOT *depot, int off, int *head); +static char *dprecval(DEPOT *depot, int off, int *head, int start, int max); +static int dprecvalwb(DEPOT *depot, int off, int *head, int start, int max, char *vbuf); +static int dpkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz); +static int dprecsearch(DEPOT *depot, const char *kbuf, int ksiz, int hash, int *bip, int *offp, + int *entp, int *head, char *ebuf, int *eep, int delhit); +static int dprecrewrite(DEPOT *depot, int off, int rsiz, const char *kbuf, int ksiz, + const char *vbuf, int vsiz, int hash, int left, int right); +static int dprecappend(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, + int hash, int left, int right); +static int dprecover(DEPOT *depot, int off, int *head, const char *vbuf, int vsiz, int cat); +static int dprecdelete(DEPOT *depot, int off, int *head, int reusable); +static void dpfbpoolcoal(DEPOT *depot); +static int dpfbpoolcmp(const void *a, const void *b); + + + +/************************************************************************************************* + * public objects + *************************************************************************************************/ + + +/* String containing the version information. */ +const char *dpversion = _QDBM_VERSION; + + +/* Get a message string corresponding to an error code. */ +const char *dperrmsg(int ecode){ + switch(ecode){ + case DP_ENOERR: return "no error"; + case DP_EFATAL: return "with fatal error"; + case DP_EMODE: return "invalid mode"; + case DP_EBROKEN: return "broken database file"; + case DP_EKEEP: return "existing record"; + case DP_ENOITEM: return "no item found"; + case DP_EALLOC: return "memory allocation error"; + case DP_EMAP: return "memory mapping error"; + case DP_EOPEN: return "open error"; + case DP_ECLOSE: return "close error"; + case DP_ETRUNC: return "trunc error"; + case DP_ESYNC: return "sync error"; + case DP_ESTAT: return "stat error"; + case DP_ESEEK: return "seek error"; + case DP_EREAD: return "read error"; + case DP_EWRITE: return "write error"; + case DP_ELOCK: return "lock error"; + case DP_EUNLINK: return "unlink error"; + case DP_EMKDIR: return "mkdir error"; + case DP_ERMDIR: return "rmdir error"; + case DP_EMISC: return "miscellaneous error"; + } + return "(invalid ecode)"; +} + + +/* Get a database handle. */ +DEPOT *dpopen(const char *name, int omode, int bnum){ + char hbuf[DP_HEADSIZ], *map, c, *tname; + int i, mode, fd, inode, fsiz, rnum, msiz, *fbpool; + struct stat sbuf; + time_t mtime; + DEPOT *depot; + assert(name); + mode = O_RDONLY; + if(omode & DP_OWRITER){ + mode = O_RDWR; + if(omode & DP_OCREAT) mode |= O_CREAT; + } + if((fd = open(name, mode, DP_FILEMODE)) == -1){ + dpecodeset(DP_EOPEN, __FILE__, __LINE__); + return NULL; + } + if(!(omode & DP_ONOLCK)){ + if(!dplock(fd, omode & DP_OWRITER, omode & DP_OLCKNB)){ + close(fd); + return NULL; + } + } + if((omode & DP_OWRITER) && (omode & DP_OTRUNC)){ + if(ftruncate(fd, 0) == -1){ + close(fd); + dpecodeset(DP_ETRUNC, __FILE__, __LINE__); + return NULL; + } + } + if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode) || + (sbuf.st_ino == 0 && lstat(name, &sbuf) == -1)){ + close(fd); + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + return NULL; + } + inode = sbuf.st_ino; + mtime = sbuf.st_mtime; + fsiz = sbuf.st_size; + if((omode & DP_OWRITER) && fsiz == 0){ + memset(hbuf, 0, DP_HEADSIZ); + if(dpbigendian()){ + memcpy(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB)); + } else { + memcpy(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML)); + } + sprintf(hbuf + DP_LIBVEROFF, "%d", _QDBM_LIBVER / 100); + bnum = bnum < 1 ? DP_DEFBNUM : bnum; + bnum = dpgetprime(bnum); + memcpy(hbuf + DP_BNUMOFF, &bnum, sizeof(int)); + rnum = 0; + memcpy(hbuf + DP_RNUMOFF, &rnum, sizeof(int)); + fsiz = DP_HEADSIZ + bnum * sizeof(int); + memcpy(hbuf + DP_FSIZOFF, &fsiz, sizeof(int)); + if(!dpseekwrite(fd, 0, hbuf, DP_HEADSIZ)){ + close(fd); + return NULL; + } + if(omode & DP_OSPARSE){ + c = 0; + if(!dpseekwrite(fd, fsiz - 1, &c, 1)){ + close(fd); + return NULL; + } + } else { + if(!(map = malloc(bnum * sizeof(int)))){ + close(fd); + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return NULL; + } + memset(map, 0, bnum * sizeof(int)); + if(!dpseekwrite(fd, DP_HEADSIZ, map, bnum * sizeof(int))){ + free(map); + close(fd); + return NULL; + } + free(map); + } + } + if(!dpseekread(fd, 0, hbuf, DP_HEADSIZ)){ + close(fd); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + if(!(omode & DP_ONOLCK) && + ((dpbigendian() ? memcmp(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB)) != 0 : + memcmp(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML)) != 0) || + *((int *)(hbuf + DP_FSIZOFF)) != fsiz)){ + close(fd); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + bnum = *((int *)(hbuf + DP_BNUMOFF)); + rnum = *((int *)(hbuf + DP_RNUMOFF)); + if(bnum < 1 || rnum < 0 || fsiz < DP_HEADSIZ + bnum * sizeof(int)){ + close(fd); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + msiz = DP_HEADSIZ + bnum * sizeof(int); + map = mmap(0, msiz, PROT_READ | ((mode & DP_OWRITER) ? PROT_WRITE : 0), MAP_SHARED, fd, 0); + if(map == MAP_FAILED){ + close(fd); + dpecodeset(DP_EMAP, __FILE__, __LINE__); + return NULL; + } + tname = NULL; + fbpool = NULL; + if(!(depot = malloc(sizeof(DEPOT))) || !(tname = dpstrdup(name)) || + !(fbpool = malloc(DP_FBPOOLSIZ * 2 * sizeof(int)))){ + free(fbpool); + free(tname); + free(depot); + munmap(map, msiz); + close(fd); + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return NULL; + } + depot->name = tname; + depot->wmode = (mode & DP_OWRITER); + depot->inode = inode; + depot->mtime = mtime; + depot->fd = fd; + depot->fsiz = fsiz; + depot->map = map; + depot->msiz = msiz; + depot->buckets = (int *)(map + DP_HEADSIZ); + depot->bnum = bnum; + depot->rnum = rnum; + depot->fatal = FALSE; + depot->ioff = 0; + depot->fbpool = fbpool; + for(i = 0; i < DP_FBPOOLSIZ * 2; i += 2){ + depot->fbpool[i] = -1; + depot->fbpool[i+1] = -1; + } + depot->fbpsiz = DP_FBPOOLSIZ * 2; + depot->fbpinc = 0; + depot->align = 0; + return depot; +} + + +/* Close a database handle. */ +int dpclose(DEPOT *depot){ + int fatal, err; + assert(depot); + fatal = depot->fatal; + err = FALSE; + if(depot->wmode){ + *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; + *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; + } + if(depot->map != MAP_FAILED){ + if(munmap(depot->map, depot->msiz) == -1){ + err = TRUE; + dpecodeset(DP_EMAP, __FILE__, __LINE__); + } + } + if(close(depot->fd) == -1){ + err = TRUE; + dpecodeset(DP_ECLOSE, __FILE__, __LINE__); + } + free(depot->fbpool); + free(depot->name); + free(depot); + if(fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + return err ? FALSE : TRUE; +} + + +/* Store a record. */ +int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ + int head[DP_RHNUM], next[DP_RHNUM]; + int i, hash, bi, off, entoff, ee, newoff, rsiz, nsiz, fdel, mroff, mrsiz, mi, min; + char ebuf[DP_ENTBUFSIZ], *tval, *swap; + assert(depot && kbuf && vbuf); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!depot->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(ksiz < 0) ksiz = strlen(kbuf); + if(vsiz < 0) vsiz = strlen(vbuf); + newoff = -1; + DP_SECONDHASH(hash, kbuf, ksiz); + switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, TRUE)){ + case -1: + depot->fatal = TRUE; + return FALSE; + case 0: + fdel = head[DP_RHIFLAGS] & DP_RECFDEL; + if(dmode == DP_DKEEP && !fdel){ + dpecodeset(DP_EKEEP, __FILE__, __LINE__); + return FALSE; + } + if(fdel){ + head[DP_RHIPSIZ] += head[DP_RHIVSIZ]; + head[DP_RHIVSIZ] = 0; + } + rsiz = dprecsize(head); + nsiz = DP_RHNUM * sizeof(int) + ksiz + vsiz; + if(dmode == DP_DCAT) nsiz += head[DP_RHIVSIZ]; + if(off + rsiz >= depot->fsiz){ + if(rsiz < nsiz){ + head[DP_RHIPSIZ] += nsiz - rsiz; + rsiz = nsiz; + depot->fsiz = off + rsiz; + } + } else { + while(nsiz > rsiz && off + rsiz < depot->fsiz){ + if(!dprechead(depot, off + rsiz, next, NULL, NULL)) return FALSE; + if(!(next[DP_RHIFLAGS] & DP_RECFREUSE)) break; + head[DP_RHIPSIZ] += dprecsize(next); + rsiz += dprecsize(next); + } + for(i = 0; i < depot->fbpsiz; i += 2){ + if(depot->fbpool[i] >= off && depot->fbpool[i] < off + rsiz){ + depot->fbpool[i] = -1; + depot->fbpool[i+1] = -1; + } + } + } + if(nsiz <= rsiz){ + if(!dprecover(depot, off, head, vbuf, vsiz, dmode == DP_DCAT)){ + depot->fatal = TRUE; + return FALSE; + } + } else { + tval = NULL; + if(dmode == DP_DCAT){ + if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ + if(!(tval = malloc(head[DP_RHIVSIZ] + vsiz + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + depot->fatal = TRUE; + return FALSE; + } + memcpy(tval, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ]), head[DP_RHIVSIZ]); + } else { + if(!(tval = dprecval(depot, off, head, 0, -1))){ + depot->fatal = TRUE; + return FALSE; + } + if(!(swap = realloc(tval, head[DP_RHIVSIZ] + vsiz + 1))){ + free(tval); + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + depot->fatal = TRUE; + return FALSE; + } + tval = swap; + } + memcpy(tval + head[DP_RHIVSIZ], vbuf, vsiz); + vsiz += head[DP_RHIVSIZ]; + vbuf = tval; + } + mi = -1; + min = -1; + for(i = 0; i < depot->fbpsiz; i += 2){ + if(depot->fbpool[i+1] < nsiz) continue; + if(mi == -1 || depot->fbpool[i+1] < min){ + mi = i; + min = depot->fbpool[i+1]; + } + } + if(mi >= 0){ + mroff = depot->fbpool[mi]; + mrsiz = depot->fbpool[mi+1]; + depot->fbpool[mi] = -1; + depot->fbpool[mi+1] = -1; + } else { + mroff = -1; + mrsiz = -1; + } + if(!dprecdelete(depot, off, head, TRUE)){ + free(tval); + depot->fatal = TRUE; + return FALSE; + } + if(mroff > 0 && nsiz <= mrsiz){ + if(!dprecrewrite(depot, mroff, mrsiz, kbuf, ksiz, vbuf, vsiz, + hash, head[DP_RHILEFT], head[DP_RHIRIGHT])){ + free(tval); + depot->fatal = TRUE; + return FALSE; + } + newoff = mroff; + } else { + if((newoff = dprecappend(depot, kbuf, ksiz, vbuf, vsiz, + hash, head[DP_RHILEFT], head[DP_RHIRIGHT])) == -1){ + free(tval); + depot->fatal = TRUE; + return FALSE; + } + } + free(tval); + } + if(fdel) depot->rnum++; + break; + default: + if((newoff = dprecappend(depot, kbuf, ksiz, vbuf, vsiz, hash, 0, 0)) == -1){ + depot->fatal = TRUE; + return FALSE; + } + depot->rnum++; + break; + } + if(newoff > 0){ + if(entoff > 0){ + if(!dpseekwritenum(depot->fd, entoff, newoff)){ + depot->fatal = TRUE; + return FALSE; + } + } else { + depot->buckets[bi] = newoff; + } + } + return TRUE; +} + + +/* Delete a record. */ +int dpout(DEPOT *depot, const char *kbuf, int ksiz){ + int head[DP_RHNUM], hash, bi, off, entoff, ee; + char ebuf[DP_ENTBUFSIZ]; + assert(depot && kbuf); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!depot->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(ksiz < 0) ksiz = strlen(kbuf); + DP_SECONDHASH(hash, kbuf, ksiz); + switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ + case -1: + depot->fatal = TRUE; + return FALSE; + case 0: + break; + default: + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!dprecdelete(depot, off, head, FALSE)){ + depot->fatal = TRUE; + return FALSE; + } + depot->rnum--; + return TRUE; +} + + +/* Retrieve a record. */ +char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp){ + int head[DP_RHNUM], hash, bi, off, entoff, ee, vsiz; + char ebuf[DP_ENTBUFSIZ], *vbuf; + assert(depot && kbuf && start >= 0); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return NULL; + } + if(ksiz < 0) ksiz = strlen(kbuf); + DP_SECONDHASH(hash, kbuf, ksiz); + switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ + case -1: + depot->fatal = TRUE; + return NULL; + case 0: + break; + default: + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return NULL; + } + if(start > head[DP_RHIVSIZ]){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return NULL; + } + if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ + head[DP_RHIVSIZ] -= start; + if(max < 0){ + vsiz = head[DP_RHIVSIZ]; + } else { + vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; + } + if(!(vbuf = malloc(vsiz + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + depot->fatal = TRUE; + return NULL; + } + memcpy(vbuf, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start), vsiz); + vbuf[vsiz] = '\0'; + } else { + if(!(vbuf = dprecval(depot, off, head, start, max))){ + depot->fatal = TRUE; + return NULL; + } + } + if(sp){ + if(max < 0){ + *sp = head[DP_RHIVSIZ]; + } else { + *sp = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; + } + } + return vbuf; +} + + +/* Retrieve a record and write the value into a buffer. */ +int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf){ + int head[DP_RHNUM], hash, bi, off, entoff, ee, vsiz; + char ebuf[DP_ENTBUFSIZ]; + assert(depot && kbuf && start >= 0 && max >= 0 && vbuf); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + if(ksiz < 0) ksiz = strlen(kbuf); + DP_SECONDHASH(hash, kbuf, ksiz); + switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ + case -1: + depot->fatal = TRUE; + return -1; + case 0: + break; + default: + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return -1; + } + if(start > head[DP_RHIVSIZ]){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return -1; + } + if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ + head[DP_RHIVSIZ] -= start; + vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; + memcpy(vbuf, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start), vsiz); + } else { + if((vsiz = dprecvalwb(depot, off, head, start, max, vbuf)) == -1){ + depot->fatal = TRUE; + return -1; + } + } + return vsiz; +} + + +/* Get the size of the value of a record. */ +int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz){ + int head[DP_RHNUM], hash, bi, off, entoff, ee; + char ebuf[DP_ENTBUFSIZ]; + assert(depot && kbuf); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + if(ksiz < 0) ksiz = strlen(kbuf); + DP_SECONDHASH(hash, kbuf, ksiz); + switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ + case -1: + depot->fatal = TRUE; + return -1; + case 0: + break; + default: + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return -1; + } + return head[DP_RHIVSIZ]; +} + + +/* Initialize the iterator of a database handle. */ +int dpiterinit(DEPOT *depot){ + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + depot->ioff = 0; + return TRUE; +} + + +/* Get the next key of the iterator. */ +char *dpiternext(DEPOT *depot, int *sp){ + int off, head[DP_RHNUM], ee; + char ebuf[DP_ENTBUFSIZ], *kbuf; + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return NULL; + } + off = DP_HEADSIZ + depot->bnum * sizeof(int); + off = off > depot->ioff ? off : depot->ioff; + while(off < depot->fsiz){ + if(!dprechead(depot, off, head, ebuf, &ee)){ + depot->fatal = TRUE; + return NULL; + } + if(head[DP_RHIFLAGS] & DP_RECFDEL){ + off += dprecsize(head); + } else { + if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] <= DP_ENTBUFSIZ){ + if(!(kbuf = malloc(head[DP_RHIKSIZ] + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + depot->fatal = TRUE; + return NULL; + } + memcpy(kbuf, ebuf + (DP_RHNUM * sizeof(int)), head[DP_RHIKSIZ]); + kbuf[head[DP_RHIKSIZ]] = '\0'; + } else { + if(!(kbuf = dpreckey(depot, off, head))){ + depot->fatal = TRUE; + return NULL; + } + } + depot->ioff = off + dprecsize(head); + if(sp) *sp = head[DP_RHIKSIZ]; + return kbuf; + } + } + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return NULL; +} + + +/* Set alignment of a database handle. */ +int dpsetalign(DEPOT *depot, int align){ + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!depot->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + depot->align = align; + return TRUE; +} + + +/* Set the size of the free block pool of a database handle. */ +int dpsetfbpsiz(DEPOT *depot, int size){ + int *fbpool; + int i; + assert(depot && size >= 0); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!depot->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + size *= 2; + if(!(fbpool = realloc(depot->fbpool, size * sizeof(int) + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return FALSE; + } + for(i = 0; i < size; i += 2){ + fbpool[i] = -1; + fbpool[i+1] = -1; + } + depot->fbpool = fbpool; + depot->fbpsiz = size; + return TRUE; +} + + + +/* Synchronize contents of updating a database with the file and the device. */ +int dpsync(DEPOT *depot){ + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!depot->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; + *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; + if(msync(depot->map, depot->msiz, MS_SYNC) == -1){ + dpecodeset(DP_EMAP, __FILE__, __LINE__); + depot->fatal = TRUE; + return FALSE; + } + if(fsync(depot->fd) == -1){ + dpecodeset(DP_ESYNC, __FILE__, __LINE__); + depot->fatal = TRUE; + return FALSE; + } + return TRUE; +} + + +/* Optimize a database. */ +int dpoptimize(DEPOT *depot, int bnum){ + DEPOT *tdepot; + char *name; + int i, err, off, head[DP_RHNUM], ee, ksizs[DP_OPTRUNIT], vsizs[DP_OPTRUNIT], unum; + char ebuf[DP_ENTBUFSIZ], *kbufs[DP_OPTRUNIT], *vbufs[DP_OPTRUNIT]; + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!depot->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(!(name = malloc(strlen(depot->name) + strlen(DP_TMPFSUF) + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + depot->fatal = FALSE; + return FALSE; + } + sprintf(name, "%s%s", depot->name, DP_TMPFSUF); + if(bnum < 0){ + bnum = (int)(depot->rnum * (1.0 / DP_OPTBLOAD)) + 1; + if(bnum < DP_DEFBNUM / 2) bnum = DP_DEFBNUM / 2; + } + if(!(tdepot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, bnum))){ + free(name); + depot->fatal = TRUE; + return FALSE; + } + free(name); + if(!dpsetflags(tdepot, dpgetflags(depot))){ + dpclose(tdepot); + depot->fatal = TRUE; + return FALSE; + } + tdepot->align = depot->align; + err = FALSE; + off = DP_HEADSIZ + depot->bnum * sizeof(int); + unum = 0; + while(off < depot->fsiz){ + if(!dprechead(depot, off, head, ebuf, &ee)){ + err = TRUE; + break; + } + if(!(head[DP_RHIFLAGS] & DP_RECFDEL)){ + if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] <= DP_ENTBUFSIZ){ + if(!(kbufs[unum] = malloc(head[DP_RHIKSIZ] + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + err = TRUE; + break; + } + memcpy(kbufs[unum], ebuf + (DP_RHNUM * sizeof(int)), head[DP_RHIKSIZ]); + if(DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ + if(!(vbufs[unum] = malloc(head[DP_RHIVSIZ] + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + err = TRUE; + break; + } + memcpy(vbufs[unum], ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ]), + head[DP_RHIVSIZ]); + } else { + vbufs[unum] = dprecval(depot, off, head, 0, -1); + } + } else { + kbufs[unum] = dpreckey(depot, off, head); + vbufs[unum] = dprecval(depot, off, head, 0, -1); + } + ksizs[unum] = head[DP_RHIKSIZ]; + vsizs[unum] = head[DP_RHIVSIZ]; + unum++; + if(unum >= DP_OPTRUNIT){ + for(i = 0; i < unum; i++){ + if(kbufs[i] && vbufs[i]){ + if(!dpput(tdepot, kbufs[i], ksizs[i], vbufs[i], vsizs[i], DP_DKEEP)) err = TRUE; + } else { + err = TRUE; + } + free(kbufs[i]); + free(vbufs[i]); + if(err) break; + } + unum = 0; + } + } + off += dprecsize(head); + if(err) break; + } + for(i = 0; i < unum; i++){ + if(kbufs[i] && vbufs[i]){ + if(!dpput(tdepot, kbufs[i], ksizs[i], vbufs[i], vsizs[i], DP_DKEEP)) err = TRUE; + } else { + err = TRUE; + } + free(kbufs[i]); + free(vbufs[i]); + if(err) break; + } + if(!dpsync(tdepot)) err = TRUE; + if(err){ + unlink(tdepot->name); + dpclose(tdepot); + depot->fatal = TRUE; + return FALSE; + } + if(munmap(depot->map, depot->msiz) == -1){ + dpclose(tdepot); + dpecodeset(DP_EMAP, __FILE__, __LINE__); + depot->fatal = TRUE; + return FALSE; + } + depot->map = MAP_FAILED; + if(ftruncate(depot->fd, 0) == -1){ + dpclose(tdepot); + unlink(tdepot->name); + dpecodeset(DP_ETRUNC, __FILE__, __LINE__); + depot->fatal = TRUE; + return FALSE; + } + if(dpfcopy(depot->fd, 0, tdepot->fd, 0) == -1){ + dpclose(tdepot); + unlink(tdepot->name); + depot->fatal = TRUE; + return FALSE; + } + depot->fsiz = tdepot->fsiz; + depot->bnum = tdepot->bnum; + depot->ioff = 0; + for(i = 0; i < depot->fbpsiz; i += 2){ + depot->fbpool[i] = -1; + depot->fbpool[i+1] = -1; + } + depot->msiz = tdepot->msiz; + depot->map = mmap(0, depot->msiz, PROT_READ | PROT_WRITE, MAP_SHARED, depot->fd, 0); + if(depot->map == MAP_FAILED){ + dpecodeset(DP_EMAP, __FILE__, __LINE__); + depot->fatal = TRUE; + return FALSE; + } + depot->buckets = (int *)(depot->map + DP_HEADSIZ); + if(!(name = dpname(tdepot))){ + dpclose(tdepot); + unlink(tdepot->name); + depot->fatal = TRUE; + return FALSE; + } + if(!dpclose(tdepot)){ + free(name); + unlink(tdepot->name); + depot->fatal = TRUE; + return FALSE; + } + if(unlink(name) == -1){ + free(name); + dpecodeset(DP_EUNLINK, __FILE__, __LINE__); + depot->fatal = TRUE; + return FALSE; + } + free(name); + return TRUE; +} + + +/* Get the name of a database. */ +char *dpname(DEPOT *depot){ + char *name; + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return NULL; + } + if(!(name = dpstrdup(depot->name))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + depot->fatal = TRUE; + return NULL; + } + return name; +} + + +/* Get the size of a database file. */ +int dpfsiz(DEPOT *depot){ + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + return depot->fsiz; +} + + +/* Get the number of the elements of the bucket array. */ +int dpbnum(DEPOT *depot){ + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + return depot->bnum; +} + + +/* Get the number of the used elements of the bucket array. */ +int dpbusenum(DEPOT *depot){ + int i, hits; + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + hits = 0; + for(i = 0; i < depot->bnum; i++){ + if(depot->buckets[i]) hits++; + } + return hits; +} + + +/* Get the number of the records stored in a database. */ +int dprnum(DEPOT *depot){ + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + return depot->rnum; +} + + +/* Check whether a database handle is a writer or not. */ +int dpwritable(DEPOT *depot){ + assert(depot); + return depot->wmode; +} + + +/* Check whether a database has a fatal error or not. */ +int dpfatalerror(DEPOT *depot){ + assert(depot); + return depot->fatal; +} + + +/* Get the inode number of a database file. */ +int dpinode(DEPOT *depot){ + assert(depot); + return depot->inode; +} + + +/* Get the last modified time of a database. */ +time_t dpmtime(DEPOT *depot){ + assert(depot); + return depot->mtime; +} + + +/* Get the file descriptor of a database file. */ +int dpfdesc(DEPOT *depot){ + assert(depot); + return depot->fd; +} + + +/* Remove a database file. */ +int dpremove(const char *name){ + struct stat sbuf; + DEPOT *depot; + assert(name); + if(lstat(name, &sbuf) == -1){ + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + return FALSE; + } + if((depot = dpopen(name, DP_OWRITER | DP_OTRUNC, -1)) != NULL) dpclose(depot); + if(unlink(name) == -1){ + dpecodeset(DP_EUNLINK, __FILE__, __LINE__); + return FALSE; + } + return TRUE; +} + + +/* Repair a broken database file. */ +int dprepair(const char *name){ + DEPOT *tdepot; + char dbhead[DP_HEADSIZ], *tname, *kbuf, *vbuf; + int fd, fsiz, flags, bnum, tbnum, err, head[DP_RHNUM], off, rsiz, ksiz, vsiz; + struct stat sbuf; + assert(name); + if(lstat(name, &sbuf) == -1){ + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + return FALSE; + } + fsiz = sbuf.st_size; + if((fd = open(name, O_RDWR, DP_FILEMODE)) == -1){ + dpecodeset(DP_EOPEN, __FILE__, __LINE__); + return FALSE; + } + if(!dpseekread(fd, 0, dbhead, DP_HEADSIZ)){ + close(fd); + return FALSE; + } + flags = *(int *)(dbhead + DP_FLAGSOFF); + bnum = *(int *)(dbhead + DP_BNUMOFF); + tbnum = *(int *)(dbhead + DP_RNUMOFF) * 2; + if(tbnum < DP_DEFBNUM) tbnum = DP_DEFBNUM; + if(!(tname = malloc(strlen(name) + strlen(DP_TMPFSUF) + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return FALSE; + } + sprintf(tname, "%s%s", name, DP_TMPFSUF); + if(!(tdepot = dpopen(tname, DP_OWRITER | DP_OCREAT | DP_OTRUNC, tbnum))){ + free(tname); + close(fd); + return FALSE; + } + err = FALSE; + off = DP_HEADSIZ + bnum * sizeof(int); + while(off < fsiz){ + if(!dpseekread(fd, off, head, DP_RHNUM * sizeof(int))) break; + if(head[DP_RHIFLAGS] & DP_RECFDEL){ + if((rsiz = dprecsize(head)) < 0) break; + off += rsiz; + continue; + } + ksiz = head[DP_RHIKSIZ]; + vsiz = head[DP_RHIVSIZ]; + if(ksiz >= 0 && vsiz >= 0){ + kbuf = malloc(ksiz + 1); + vbuf = malloc(vsiz + 1); + if(kbuf && vbuf){ + if(dpseekread(fd, off + DP_RHNUM * sizeof(int), kbuf, ksiz) && + dpseekread(fd, off + DP_RHNUM * sizeof(int) + ksiz, vbuf, vsiz)){ + if(!dpput(tdepot, kbuf, ksiz, vbuf, vsiz, DP_DKEEP)) err = TRUE; + } else { + err = TRUE; + } + } else { + if(!err) dpecodeset(DP_EALLOC, __FILE__, __LINE__); + err = TRUE; + } + free(vbuf); + free(kbuf); + } else { + if(!err) dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + err = TRUE; + } + if((rsiz = dprecsize(head)) < 0) break; + off += rsiz; + } + if(!dpsetflags(tdepot, flags)) err = TRUE; + if(!dpsync(tdepot)) err = TRUE; + if(ftruncate(fd, 0) == -1){ + if(!err) dpecodeset(DP_ETRUNC, __FILE__, __LINE__); + err = TRUE; + } + if(dpfcopy(fd, 0, tdepot->fd, 0) == -1) err = TRUE; + if(!dpclose(tdepot)) err = TRUE; + if(close(fd) == -1){ + if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); + err = TRUE; + } + if(unlink(tname) == -1){ + if(!err) dpecodeset(DP_EUNLINK, __FILE__, __LINE__); + err = TRUE; + } + free(tname); + return err ? FALSE : TRUE; +} + + +/* Dump all records as endian independent data. */ +int dpexportdb(DEPOT *depot, const char *name){ + char *kbuf, *vbuf, *pbuf; + int fd, err, ksiz, vsiz, psiz; + assert(depot && name); + if(!(dpiterinit(depot))) return FALSE; + if((fd = open(name, O_RDWR | O_CREAT | O_TRUNC, DP_FILEMODE)) == -1){ + dpecodeset(DP_EOPEN, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + while(!err && (kbuf = dpiternext(depot, &ksiz)) != NULL){ + if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ + if((pbuf = malloc(ksiz + vsiz + DP_NUMBUFSIZ * 2)) != NULL){ + psiz = 0; + psiz += sprintf(pbuf + psiz, "%X\n%X\n", ksiz, vsiz); + memcpy(pbuf + psiz, kbuf, ksiz); + psiz += ksiz; + pbuf[psiz++] = '\n'; + memcpy(pbuf + psiz, vbuf, vsiz); + psiz += vsiz; + pbuf[psiz++] = '\n'; + if(!dpwrite(fd, pbuf, psiz)){ + dpecodeset(DP_EWRITE, __FILE__, __LINE__); + err = TRUE; + } + free(pbuf); + } else { + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + err = TRUE; + } + free(vbuf); + } else { + err = TRUE; + } + free(kbuf); + } + if(close(fd) == -1){ + if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); + return FALSE; + } + return !err && !dpfatalerror(depot); +} + + +/* Load all records from endian independent data. */ +int dpimportdb(DEPOT *depot, const char *name){ + char mbuf[DP_IOBUFSIZ], *rbuf; + int i, j, fd, err, fsiz, off, msiz, ksiz, vsiz, hlen; + struct stat sbuf; + assert(depot && name); + if(!depot->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(dprnum(depot) > 0){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + if((fd = open(name, O_RDONLY, DP_FILEMODE)) == -1){ + dpecodeset(DP_EOPEN, __FILE__, __LINE__); + return FALSE; + } + if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){ + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + close(fd); + return FALSE; + } + err = FALSE; + fsiz = sbuf.st_size; + off = 0; + while(!err && off < fsiz){ + msiz = fsiz - off; + if(msiz > DP_IOBUFSIZ) msiz = DP_IOBUFSIZ; + if(!dpseekread(fd, off, mbuf, msiz)){ + err = TRUE; + break; + } + hlen = 0; + ksiz = -1; + vsiz = -1; + for(i = 0; i < msiz; i++){ + if(mbuf[i] == '\n'){ + mbuf[i] = '\0'; + ksiz = strtol(mbuf, NULL, 16); + for(j = i + 1; j < msiz; j++){ + if(mbuf[j] == '\n'){ + mbuf[j] = '\0'; + vsiz = strtol(mbuf + i + 1, NULL, 16); + hlen = j + 1; + break; + } + } + break; + } + } + if(ksiz < 0 || vsiz < 0 || hlen < 4){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + err = TRUE; + break; + } + if(hlen + ksiz + vsiz + 2 < DP_IOBUFSIZ){ + if(!dpput(depot, mbuf + hlen, ksiz, mbuf + hlen + ksiz + 1, vsiz, DP_DKEEP)) err = TRUE; + } else { + if((rbuf = malloc(ksiz + vsiz + 2)) != NULL){ + if(dpseekread(fd, off + hlen, rbuf, ksiz + vsiz + 2)){ + if(!dpput(depot, rbuf, ksiz, rbuf + ksiz + 1, vsiz, DP_DKEEP)) err = TRUE; + } else { + err = TRUE; + } + free(rbuf); + } else { + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + err = TRUE; + } + } + off += hlen + ksiz + vsiz + 2; + } + if(close(fd) == -1){ + if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); + return FALSE; + } + return !err && !dpfatalerror(depot); +} + + +/* Retrieve a record directly from a database file. */ +char *dpsnaffle(const char *name, const char* kbuf, int ksiz, int *sp){ + char hbuf[DP_HEADSIZ], *map, *vbuf, *tkbuf; + int fd, fsiz, bnum, msiz, *buckets, hash, thash, head[DP_RHNUM], err, off, vsiz, tksiz, kcmp; + struct stat sbuf; + assert(name && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if((fd = open(name, O_RDONLY, DP_FILEMODE)) == -1){ + dpecodeset(DP_EOPEN, __FILE__, __LINE__); + return NULL; + } + if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){ + close(fd); + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + return NULL; + } + fsiz = sbuf.st_size; + if(!dpseekread(fd, 0, hbuf, DP_HEADSIZ)){ + close(fd); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + if(dpbigendian() ? memcmp(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB)) != 0 : + memcmp(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML)) != 0){ + close(fd); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + bnum = *((int *)(hbuf + DP_BNUMOFF)); + if(bnum < 1 || fsiz < DP_HEADSIZ + bnum * sizeof(int)){ + close(fd); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + msiz = DP_HEADSIZ + bnum * sizeof(int); + map = mmap(0, msiz, PROT_READ, MAP_SHARED, fd, 0); + if(map == MAP_FAILED){ + close(fd); + dpecodeset(DP_EMAP, __FILE__, __LINE__); + return NULL; + } + buckets = (int *)(map + DP_HEADSIZ); + err = FALSE; + vbuf = NULL; + vsiz = 0; + DP_SECONDHASH(hash, kbuf, ksiz); + DP_FIRSTHASH(thash, kbuf, ksiz); + off = buckets[thash%bnum]; + while(off != 0){ + if(!dpseekread(fd, off, head, DP_RHNUM * sizeof(int))){ + err = TRUE; + break; + } + if(head[DP_RHIKSIZ] < 0 || head[DP_RHIVSIZ] < 0 || head[DP_RHIPSIZ] < 0 || + head[DP_RHILEFT] < 0 || head[DP_RHIRIGHT] < 0){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + err = TRUE; + break; + } + thash = head[DP_RHIHASH]; + if(hash > thash){ + off = head[DP_RHILEFT]; + } else if(hash < thash){ + off = head[DP_RHIRIGHT]; + } else { + tksiz = head[DP_RHIKSIZ]; + if(!(tkbuf = malloc(tksiz + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + err = TRUE; + break; + } + if(!dpseekread(fd, off + DP_RHNUM * sizeof(int), tkbuf, tksiz)){ + free(tkbuf); + err = TRUE; + break; + } + tkbuf[tksiz] = '\0'; + kcmp = dpkeycmp(kbuf, ksiz, tkbuf, tksiz); + free(tkbuf); + if(kcmp > 0){ + off = head[DP_RHILEFT]; + } else if(kcmp < 0){ + off = head[DP_RHIRIGHT]; + } else if(head[DP_RHIFLAGS] & DP_RECFDEL){ + break; + } else { + vsiz = head[DP_RHIVSIZ]; + if(!(vbuf = malloc(vsiz + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + err = TRUE; + break; + } + if(!dpseekread(fd, off + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ], vbuf, vsiz)){ + free(vbuf); + vbuf = NULL; + err = TRUE; + break; + } + vbuf[vsiz] = '\0'; + break; + } + } + } + if(vbuf){ + if(sp) *sp = vsiz; + } else if(!err){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + } + munmap(map, msiz); + close(fd); + return vbuf; +} + + +/* Hash function used inside Depot. */ +int dpinnerhash(const char *kbuf, int ksiz){ + int res; + assert(kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + DP_FIRSTHASH(res, kbuf, ksiz); + return res; +} + + +/* Hash function which is independent from the hash functions used inside Depot. */ +int dpouterhash(const char *kbuf, int ksiz){ + int res; + assert(kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + DP_THIRDHASH(res, kbuf, ksiz); + return res; +} + + +/* Get a natural prime number not less than a number. */ +int dpprimenum(int num){ + assert(num > 0); + return dpgetprime(num); +} + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Name of the operating system. */ +const char *dpsysname = _QDBM_SYSNAME; + + +/* File descriptor for debugging output. */ +int dpdbgfd = -1; + + +/* Whether this build is reentrant. */ +const int dpisreentrant = _qdbm_ptsafe; + + +/* Set the last happened error code. */ +void dpecodeset(int ecode, const char *file, int line){ + char iobuf[DP_IOBUFSIZ]; + assert(ecode >= DP_ENOERR && file && line >= 0); + dpecode = ecode; + if(dpdbgfd >= 0){ + fflush(stdout); + fflush(stderr); + sprintf(iobuf, "* dpecodeset: %s:%d: [%d] %s\n", file, line, ecode, dperrmsg(ecode)); + dpwrite(dpdbgfd, iobuf, strlen(iobuf)); + } +} + + +/* Get the pointer of the variable of the last happened error code. */ +int *dpecodeptr(void){ + static int defdpecode = DP_ENOERR; + void *ptr; + if(_qdbm_ptsafe){ + if(!(ptr = _qdbm_settsd(&defdpecode, sizeof(int), &defdpecode))){ + defdpecode = DP_EMISC; + return &defdpecode; + } + return (int *)ptr; + } + return &defdpecode; +} + + +/* Synchronize updating contents on memory. */ +int dpmemsync(DEPOT *depot){ + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!depot->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; + *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; + if(msync(depot->map, depot->msiz, MS_SYNC) == -1){ + dpecodeset(DP_EMAP, __FILE__, __LINE__); + depot->fatal = TRUE; + return FALSE; + } + return TRUE; +} + + +/* Synchronize updating contents on memory, not physically. */ +int dpmemflush(DEPOT *depot){ + assert(depot); + if(depot->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!depot->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; + *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; + if(mflush(depot->map, depot->msiz, MS_SYNC) == -1){ + dpecodeset(DP_EMAP, __FILE__, __LINE__); + depot->fatal = TRUE; + return FALSE; + } + return TRUE; +} + + +/* Get flags of a database. */ +int dpgetflags(DEPOT *depot){ + int flags; + assert(depot); + memcpy(&flags, depot->map + DP_FLAGSOFF, sizeof(int)); + return flags; +} + + +/* Set flags of a database. */ +int dpsetflags(DEPOT *depot, int flags){ + assert(depot); + if(!depot->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + memcpy(depot->map + DP_FLAGSOFF, &flags, sizeof(int)); + return TRUE; +} + + + +/************************************************************************************************* + * private objects + *************************************************************************************************/ + + +/* Check whether the byte order of the platform is big endian or not. + The return value is true if bigendian, else, it is false. */ +static int dpbigendian(void){ + char buf[sizeof(int)]; + *(int *)buf = 1; + return !buf[0]; +} + + +/* Get a copied string. + `str' specifies an original string. + The return value is a copied string whose region is allocated by `malloc'. */ +static char *dpstrdup(const char *str){ + int len; + char *buf; + assert(str); + len = strlen(str); + if(!(buf = malloc(len + 1))) return NULL; + memcpy(buf, str, len + 1); + return buf; +} + + +/* Lock a file descriptor. + `fd' specifies a file descriptor. + `ex' specifies whether an exclusive lock or a shared lock is performed. + `nb' specifies whether to request with non-blocking. + The return value is true if successful, else, it is false. */ +static int dplock(int fd, int ex, int nb){ + struct flock lock; + assert(fd >= 0); + memset(&lock, 0, sizeof(struct flock)); + lock.l_type = ex ? F_WRLCK : F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + while(fcntl(fd, nb ? F_SETLK : F_SETLKW, &lock) == -1){ + if(errno != EINTR){ + dpecodeset(DP_ELOCK, __FILE__, __LINE__); + return FALSE; + } + } + return TRUE; +} + + +/* Write into a file. + `fd' specifies a file descriptor. + `buf' specifies a buffer to write. + `size' specifies the size of the buffer. + The return value is the size of the written buffer, or, -1 on failure. */ +static int dpwrite(int fd, const void *buf, int size){ + const char *lbuf; + int rv, wb; + assert(fd >= 0 && buf && size >= 0); + lbuf = buf; + rv = 0; + do { + wb = write(fd, lbuf, size); + switch(wb){ + case -1: if(errno != EINTR) return -1; + case 0: break; + default: + lbuf += wb; + size -= wb; + rv += wb; + break; + } + } while(size > 0); + return rv; +} + + +/* Write into a file at an offset. + `fd' specifies a file descriptor. + `off' specifies an offset of the file. + `buf' specifies a buffer to write. + `size' specifies the size of the buffer. + The return value is true if successful, else, it is false. */ +static int dpseekwrite(int fd, int off, const void *buf, int size){ + assert(fd >= 0 && buf && size >= 0); + if(size < 1) return TRUE; + if(off < 0){ + if(lseek(fd, 0, SEEK_END) == -1){ + dpecodeset(DP_ESEEK, __FILE__, __LINE__); + return FALSE; + } + } else { + if(lseek(fd, off, SEEK_SET) != off){ + dpecodeset(DP_ESEEK, __FILE__, __LINE__); + return FALSE; + } + } + if(dpwrite(fd, buf, size) != size){ + dpecodeset(DP_EWRITE, __FILE__, __LINE__); + return FALSE; + } + return TRUE; +} + + +/* Write an integer into a file at an offset. + `fd' specifies a file descriptor. + `off' specifies an offset of the file. + `num' specifies an integer. + The return value is true if successful, else, it is false. */ +static int dpseekwritenum(int fd, int off, int num){ + assert(fd >= 0); + return dpseekwrite(fd, off, &num, sizeof(int)); +} + + +/* Read from a file and store the data into a buffer. + `fd' specifies a file descriptor. + `buffer' specifies a buffer to store into. + `size' specifies the size to read with. + The return value is the size read with, or, -1 on failure. */ +static int dpread(int fd, void *buf, int size){ + char *lbuf; + int i, bs; + assert(fd >= 0 && buf && size >= 0); + lbuf = buf; + for(i = 0; i < size && (bs = read(fd, lbuf + i, size - i)) != 0; i += bs){ + if(bs == -1 && errno != EINTR) return -1; + } + return i; +} + + +/* Read from a file at an offset and store the data into a buffer. + `fd' specifies a file descriptor. + `off' specifies an offset of the file. + `buffer' specifies a buffer to store into. + `size' specifies the size to read with. + The return value is true if successful, else, it is false. */ +static int dpseekread(int fd, int off, void *buf, int size){ + char *lbuf; + assert(fd >= 0 && off >= 0 && buf && size >= 0); + lbuf = (char *)buf; + if(lseek(fd, off, SEEK_SET) != off){ + dpecodeset(DP_ESEEK, __FILE__, __LINE__); + return FALSE; + } + if(dpread(fd, lbuf, size) != size){ + dpecodeset(DP_EREAD, __FILE__, __LINE__); + return FALSE; + } + return TRUE; +} + + +/* Copy data between files. + `destfd' specifies a file descriptor of a destination file. + `destoff' specifies an offset of the destination file. + `srcfd' specifies a file descriptor of a source file. + `srcoff' specifies an offset of the source file. + The return value is the size copied with, or, -1 on failure. */ +static int dpfcopy(int destfd, int destoff, int srcfd, int srcoff){ + char iobuf[DP_IOBUFSIZ]; + int sum, iosiz; + if(lseek(srcfd, srcoff, SEEK_SET) == -1 || lseek(destfd, destoff, SEEK_SET) == -1){ + dpecodeset(DP_ESEEK, __FILE__, __LINE__); + return -1; + } + sum = 0; + while((iosiz = dpread(srcfd, iobuf, DP_IOBUFSIZ)) > 0){ + if(dpwrite(destfd, iobuf, iosiz) == -1){ + dpecodeset(DP_EWRITE, __FILE__, __LINE__); + return -1; + } + sum += iosiz; + } + if(iosiz < 0){ + dpecodeset(DP_EREAD, __FILE__, __LINE__); + return -1; + } + return sum; +} + + +/* Get a natural prime number not less than a number. + `num' specified a natural number. + The return value is a prime number not less than the specified number. */ +static int dpgetprime(int num){ + int primes[] = { + 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 43, 47, 53, 59, 61, 71, 79, 83, + 89, 103, 109, 113, 127, 139, 157, 173, 191, 199, 223, 239, 251, 283, 317, 349, + 383, 409, 443, 479, 509, 571, 631, 701, 761, 829, 887, 953, 1021, 1151, 1279, + 1399, 1531, 1663, 1789, 1913, 2039, 2297, 2557, 2803, 3067, 3323, 3583, 3833, + 4093, 4603, 5119, 5623, 6143, 6653, 7159, 7673, 8191, 9209, 10223, 11261, + 12281, 13309, 14327, 15359, 16381, 18427, 20479, 22511, 24571, 26597, 28669, + 30713, 32749, 36857, 40949, 45053, 49139, 53239, 57331, 61417, 65521, 73727, + 81919, 90107, 98299, 106487, 114679, 122869, 131071, 147451, 163819, 180221, + 196597, 212987, 229373, 245759, 262139, 294911, 327673, 360439, 393209, 425977, + 458747, 491503, 524287, 589811, 655357, 720887, 786431, 851957, 917503, 982981, + 1048573, 1179641, 1310719, 1441771, 1572853, 1703903, 1835003, 1966079, + 2097143, 2359267, 2621431, 2883577, 3145721, 3407857, 3670013, 3932153, + 4194301, 4718579, 5242877, 5767129, 6291449, 6815741, 7340009, 7864301, + 8388593, 9437179, 10485751, 11534329, 12582893, 13631477, 14680063, 15728611, + 16777213, 18874367, 20971507, 23068667, 25165813, 27262931, 29360087, 31457269, + 33554393, 37748717, 41943023, 46137319, 50331599, 54525917, 58720253, 62914549, + 67108859, 75497467, 83886053, 92274671, 100663291, 109051903, 117440509, + 125829103, 134217689, 150994939, 167772107, 184549373, 201326557, 218103799, + 234881011, 251658227, 268435399, 301989881, 335544301, 369098707, 402653171, + 436207613, 469762043, 503316469, 536870909, 603979769, 671088637, 738197503, + 805306357, 872415211, 939524087, 1006632947, 1073741789, 1207959503, + 1342177237, 1476394991, 1610612711, 1744830457, 1879048183, 2013265907, -1 + }; + int i; + assert(num > 0); + for(i = 0; primes[i] > 0; i++){ + if(num <= primes[i]) return primes[i]; + } + return primes[i-1]; +} + + +/* Get the padding size of a record. + `vsiz' specifies the size of the value of a record. + The return value is the padding size of a record. */ +static int dppadsize(DEPOT *depot, int ksiz, int vsiz){ + int pad; + assert(depot && vsiz >= 0); + if(depot->align > 0){ + return depot->align - (depot->fsiz + DP_RHNUM * sizeof(int) + ksiz + vsiz) % depot->align; + } else if(depot->align < 0){ + pad = (int)(vsiz * (2.0 / (1 << -(depot->align)))); + if(vsiz + pad >= DP_FSBLKSIZ){ + if(vsiz <= DP_FSBLKSIZ) pad = 0; + if(depot->fsiz % DP_FSBLKSIZ == 0){ + return (pad / DP_FSBLKSIZ) * DP_FSBLKSIZ + DP_FSBLKSIZ - + (depot->fsiz + DP_RHNUM * sizeof(int) + ksiz + vsiz) % DP_FSBLKSIZ; + } else { + return (pad / (DP_FSBLKSIZ / 2)) * (DP_FSBLKSIZ / 2) + (DP_FSBLKSIZ / 2) - + (depot->fsiz + DP_RHNUM * sizeof(int) + ksiz + vsiz) % (DP_FSBLKSIZ / 2); + } + } else { + return pad >= DP_RHNUM * sizeof(int) ? pad : DP_RHNUM * sizeof(int); + } + } + return 0; +} + + +/* Get the size of a record in a database file. + `head' specifies the header of a record. + The return value is the size of a record in a database file. */ +static int dprecsize(int *head){ + assert(head); + return DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] + head[DP_RHIPSIZ]; +} + + +/* Read the header of a record. + `depot' specifies a database handle. + `off' specifies an offset of the database file. + `head' specifies a buffer for the header. + `ebuf' specifies the pointer to the entity buffer. + `eep' specifies the pointer to a variable to which whether ebuf was used is assigned. + The return value is true if successful, else, it is false. */ +static int dprechead(DEPOT *depot, int off, int *head, char *ebuf, int *eep){ + assert(depot && off >= 0 && head); + if(off > depot->fsiz){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return FALSE; + } + if(ebuf){ + *eep = FALSE; + if(off < depot->fsiz - DP_ENTBUFSIZ){ + *eep = TRUE; + if(!dpseekread(depot->fd, off, ebuf, DP_ENTBUFSIZ)) return FALSE; + memcpy(head, ebuf, DP_RHNUM * sizeof(int)); + if(head[DP_RHIKSIZ] < 0 || head[DP_RHIVSIZ] < 0 || head[DP_RHIPSIZ] < 0 || + head[DP_RHILEFT] < 0 || head[DP_RHIRIGHT] < 0){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return FALSE; + } + return TRUE; + } + } + if(!dpseekread(depot->fd, off, head, DP_RHNUM * sizeof(int))) return FALSE; + if(head[DP_RHIKSIZ] < 0 || head[DP_RHIVSIZ] < 0 || head[DP_RHIPSIZ] < 0 || + head[DP_RHILEFT] < 0 || head[DP_RHIRIGHT] < 0){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return FALSE; + } + return TRUE; +} + + +/* Read the entitiy of the key of a record. + `depot' specifies a database handle. + `off' specifies an offset of the database file. + `head' specifies the header of a record. + The return value is a key data whose region is allocated by `malloc', or NULL on failure. */ +static char *dpreckey(DEPOT *depot, int off, int *head){ + char *kbuf; + int ksiz; + assert(depot && off >= 0); + ksiz = head[DP_RHIKSIZ]; + if(!(kbuf = malloc(ksiz + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return NULL; + } + if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int), kbuf, ksiz)){ + free(kbuf); + return NULL; + } + kbuf[ksiz] = '\0'; + return kbuf; +} + + +/* Read the entitiy of the value of a record. + `depot' specifies a database handle. + `off' specifies an offset of the database file. + `head' specifies the header of a record. + `start' specifies the offset address of the beginning of the region of the value to be read. + `max' specifies the max size to be read. If it is negative, the size to read is unlimited. + The return value is a value data whose region is allocated by `malloc', or NULL on failure. */ +static char *dprecval(DEPOT *depot, int off, int *head, int start, int max){ + char *vbuf; + int vsiz; + assert(depot && off >= 0 && start >= 0); + head[DP_RHIVSIZ] -= start; + if(max < 0){ + vsiz = head[DP_RHIVSIZ]; + } else { + vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; + } + if(!(vbuf = malloc(vsiz + 1))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return NULL; + } + if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start, vbuf, vsiz)){ + free(vbuf); + return NULL; + } + vbuf[vsiz] = '\0'; + return vbuf; +} + + +/* Read the entitiy of the value of a record and write it into a given buffer. + `depot' specifies a database handle. + `off' specifies an offset of the database file. + `head' specifies the header of a record. + `start' specifies the offset address of the beginning of the region of the value to be read. + `max' specifies the max size to be read. It shuld be less than the size of the writing buffer. + If successful, the return value is the size of the written data, else, it is -1. */ +static int dprecvalwb(DEPOT *depot, int off, int *head, int start, int max, char *vbuf){ + int vsiz; + assert(depot && off >= 0 && start >= 0 && max >= 0 && vbuf); + head[DP_RHIVSIZ] -= start; + vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; + if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start, vbuf, vsiz)) + return -1; + return vsiz; +} + + +/* Compare two keys. + `abuf' specifies the pointer to the region of the former. + `asiz' specifies the size of the region. + `bbuf' specifies the pointer to the region of the latter. + `bsiz' specifies the size of the region. + The return value is 0 if two equals, positive if the formar is big, else, negative. */ +static int dpkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz){ + assert(abuf && asiz >= 0 && bbuf && bsiz >= 0); + if(asiz > bsiz) return 1; + if(asiz < bsiz) return -1; + return memcmp(abuf, bbuf, asiz); +} + + +/* Search for a record. + `depot' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region. + `hash' specifies the second hash value of the key. + `bip' specifies the pointer to the region to assign the index of the corresponding record. + `offp' specifies the pointer to the region to assign the last visited node in the hash chain, + or, -1 if the hash chain is empty. + `entp' specifies the offset of the last used joint, or, -1 if the hash chain is empty. + `head' specifies the pointer to the region to store the header of the last visited record in. + `ebuf' specifies the pointer to the entity buffer. + `eep' specifies the pointer to a variable to which whether ebuf was used is assigned. + `delhit' specifies whether a deleted record corresponds or not. + The return value is 0 if successful, 1 if there is no corresponding record, -1 on error. */ +static int dprecsearch(DEPOT *depot, const char *kbuf, int ksiz, int hash, int *bip, int *offp, + int *entp, int *head, char *ebuf, int *eep, int delhit){ + int off, entoff, thash, kcmp; + char stkey[DP_STKBUFSIZ], *tkey; + assert(depot && kbuf && ksiz >= 0 && hash >= 0 && bip && offp && entp && head && ebuf && eep); + DP_FIRSTHASH(thash, kbuf, ksiz); + *bip = thash % depot->bnum; + off = depot->buckets[*bip]; + *offp = -1; + *entp = -1; + entoff = -1; + *eep = FALSE; + while(off != 0){ + if(!dprechead(depot, off, head, ebuf, eep)) return -1; + thash = head[DP_RHIHASH]; + if(hash > thash){ + entoff = off + DP_RHILEFT * sizeof(int); + off = head[DP_RHILEFT]; + } else if(hash < thash){ + entoff = off + DP_RHIRIGHT * sizeof(int); + off = head[DP_RHIRIGHT]; + } else { + if(*eep && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] <= DP_ENTBUFSIZ){ + kcmp = dpkeycmp(kbuf, ksiz, ebuf + (DP_RHNUM * sizeof(int)), head[DP_RHIKSIZ]); + } else if(head[DP_RHIKSIZ] > DP_STKBUFSIZ){ + if(!(tkey = dpreckey(depot, off, head))) return -1; + kcmp = dpkeycmp(kbuf, ksiz, tkey, head[DP_RHIKSIZ]); + free(tkey); + } else { + if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int), stkey, head[DP_RHIKSIZ])) + return -1; + kcmp = dpkeycmp(kbuf, ksiz, stkey, head[DP_RHIKSIZ]); + } + if(kcmp > 0){ + entoff = off + DP_RHILEFT * sizeof(int); + off = head[DP_RHILEFT]; + } else if(kcmp < 0){ + entoff = off + DP_RHIRIGHT * sizeof(int); + off = head[DP_RHIRIGHT]; + } else { + if(!delhit && (head[DP_RHIFLAGS] & DP_RECFDEL)){ + entoff = off + DP_RHILEFT * sizeof(int); + off = head[DP_RHILEFT]; + } else { + *offp = off; + *entp = entoff; + return 0; + } + } + } + } + *offp = off; + *entp = entoff; + return 1; +} + + +/* Overwrite a record. + `depot' specifies a database handle. + `off' specifies the offset of the database file. + `rsiz' specifies the size of the existing record. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region. + `hash' specifies the second hash value of the key. + `left' specifies the offset of the left child. + `right' specifies the offset of the right child. + The return value is true if successful, or, false on failure. */ +static int dprecrewrite(DEPOT *depot, int off, int rsiz, const char *kbuf, int ksiz, + const char *vbuf, int vsiz, int hash, int left, int right){ + char ebuf[DP_WRTBUFSIZ]; + int i, head[DP_RHNUM], asiz, hoff, koff, voff, mi, min, size; + assert(depot && off >= 1 && rsiz > 0 && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); + head[DP_RHIFLAGS] = 0; + head[DP_RHIHASH] = hash; + head[DP_RHIKSIZ] = ksiz; + head[DP_RHIVSIZ] = vsiz; + head[DP_RHIPSIZ] = rsiz - sizeof(head) - ksiz - vsiz; + head[DP_RHILEFT] = left; + head[DP_RHIRIGHT] = right; + asiz = sizeof(head) + ksiz + vsiz; + if(depot->fbpsiz > DP_FBPOOLSIZ * 4 && head[DP_RHIPSIZ] > asiz){ + rsiz = (head[DP_RHIPSIZ] - asiz) / 2 + asiz; + head[DP_RHIPSIZ] -= rsiz; + } else { + rsiz = 0; + } + if(asiz <= DP_WRTBUFSIZ){ + memcpy(ebuf, head, sizeof(head)); + memcpy(ebuf + sizeof(head), kbuf, ksiz); + memcpy(ebuf + sizeof(head) + ksiz, vbuf, vsiz); + if(!dpseekwrite(depot->fd, off, ebuf, asiz)) return FALSE; + } else { + hoff = off; + koff = hoff + sizeof(head); + voff = koff + ksiz; + if(!dpseekwrite(depot->fd, hoff, head, sizeof(head)) || + !dpseekwrite(depot->fd, koff, kbuf, ksiz) || !dpseekwrite(depot->fd, voff, vbuf, vsiz)) + return FALSE; + } + if(rsiz > 0){ + off += sizeof(head) + ksiz + vsiz + head[DP_RHIPSIZ]; + head[DP_RHIFLAGS] = DP_RECFDEL | DP_RECFREUSE; + head[DP_RHIHASH] = hash; + head[DP_RHIKSIZ] = ksiz; + head[DP_RHIVSIZ] = vsiz; + head[DP_RHIPSIZ] = rsiz - sizeof(head) - ksiz - vsiz; + head[DP_RHILEFT] = 0; + head[DP_RHIRIGHT] = 0; + if(!dpseekwrite(depot->fd, off, head, sizeof(head))) return FALSE; + size = dprecsize(head); + mi = -1; + min = -1; + for(i = 0; i < depot->fbpsiz; i += 2){ + if(depot->fbpool[i] == -1){ + depot->fbpool[i] = off; + depot->fbpool[i+1] = size; + dpfbpoolcoal(depot); + mi = -1; + break; + } + if(mi == -1 || depot->fbpool[i+1] < min){ + mi = i; + min = depot->fbpool[i+1]; + } + } + if(mi >= 0 && size > min){ + depot->fbpool[mi] = off; + depot->fbpool[mi+1] = size; + dpfbpoolcoal(depot); + } + } + return TRUE; +} + + +/* Write a record at the end of a database file. + `depot' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region. + `hash' specifies the second hash value of the key. + `left' specifies the offset of the left child. + `right' specifies the offset of the right child. + The return value is the offset of the record, or, -1 on failure. */ +static int dprecappend(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, + int hash, int left, int right){ + char ebuf[DP_WRTBUFSIZ], *hbuf; + int head[DP_RHNUM], asiz, psiz, off; + assert(depot && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); + psiz = dppadsize(depot, ksiz, vsiz); + head[DP_RHIFLAGS] = 0; + head[DP_RHIHASH] = hash; + head[DP_RHIKSIZ] = ksiz; + head[DP_RHIVSIZ] = vsiz; + head[DP_RHIPSIZ] = psiz; + head[DP_RHILEFT] = left; + head[DP_RHIRIGHT] = right; + asiz = sizeof(head) + ksiz + vsiz + psiz; + off = depot->fsiz; + if(asiz <= DP_WRTBUFSIZ){ + memcpy(ebuf, head, sizeof(head)); + memcpy(ebuf + sizeof(head), kbuf, ksiz); + memcpy(ebuf + sizeof(head) + ksiz, vbuf, vsiz); + memset(ebuf + sizeof(head) + ksiz + vsiz, 0, psiz); + if(!dpseekwrite(depot->fd, off, ebuf, asiz)) return -1; + } else { + if(!(hbuf = malloc(asiz))){ + dpecodeset(DP_EALLOC, __FILE__, __LINE__); + return -1; + } + memcpy(hbuf, head, sizeof(head)); + memcpy(hbuf + sizeof(head), kbuf, ksiz); + memcpy(hbuf + sizeof(head) + ksiz, vbuf, vsiz); + memset(hbuf + sizeof(head) + ksiz + vsiz, 0, psiz); + if(!dpseekwrite(depot->fd, off, hbuf, asiz)){ + free(hbuf); + return -1; + } + free(hbuf); + } + depot->fsiz += asiz; + return off; +} + + +/* Overwrite the value of a record. + `depot' specifies a database handle. + `off' specifies the offset of the database file. + `head' specifies the header of the record. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region. + `cat' specifies whether it is concatenate mode or not. + The return value is true if successful, or, false on failure. */ +static int dprecover(DEPOT *depot, int off, int *head, const char *vbuf, int vsiz, int cat){ + int i, hsiz, hoff, voff; + assert(depot && off >= 0 && head && vbuf && vsiz >= 0); + for(i = 0; i < depot->fbpsiz; i += 2){ + if(depot->fbpool[i] == off){ + depot->fbpool[i] = -1; + depot->fbpool[i+1] = -1; + break; + } + } + if(cat){ + head[DP_RHIFLAGS] = 0; + head[DP_RHIPSIZ] -= vsiz; + head[DP_RHIVSIZ] += vsiz; + hsiz = DP_RHNUM * sizeof(int); + hoff = off; + voff = hoff + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] - vsiz; + } else { + head[DP_RHIFLAGS] = 0; + head[DP_RHIPSIZ] += head[DP_RHIVSIZ] - vsiz; + head[DP_RHIVSIZ] = vsiz; + hsiz = DP_RHNUM * sizeof(int); + hoff = off; + voff = hoff + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ]; + } + if(!dpseekwrite(depot->fd, hoff, head, hsiz) || + !dpseekwrite(depot->fd, voff, vbuf, vsiz)) return FALSE; + return TRUE; +} + + +/* Delete a record. + `depot' specifies a database handle. + `off' specifies the offset of the database file. + `head' specifies the header of the record. + `reusable' specifies whether the region is reusable or not. + The return value is true if successful, or, false on failure. */ +static int dprecdelete(DEPOT *depot, int off, int *head, int reusable){ + int i, mi, min, size; + assert(depot && off >= 0 && head); + if(reusable){ + size = dprecsize(head); + mi = -1; + min = -1; + for(i = 0; i < depot->fbpsiz; i += 2){ + if(depot->fbpool[i] == -1){ + depot->fbpool[i] = off; + depot->fbpool[i+1] = size; + dpfbpoolcoal(depot); + mi = -1; + break; + } + if(mi == -1 || depot->fbpool[i+1] < min){ + mi = i; + min = depot->fbpool[i+1]; + } + } + if(mi >= 0 && size > min){ + depot->fbpool[mi] = off; + depot->fbpool[mi+1] = size; + dpfbpoolcoal(depot); + } + } + return dpseekwritenum(depot->fd, off + DP_RHIFLAGS * sizeof(int), + DP_RECFDEL | (reusable ? DP_RECFREUSE : 0)); +} + + +/* Make contiguous records of the free block pool coalesce. + `depot' specifies a database handle. */ +static void dpfbpoolcoal(DEPOT *depot){ + int i; + assert(depot); + if(depot->fbpinc++ <= depot->fbpsiz / 4) return; + depot->fbpinc = 0; + qsort(depot->fbpool, depot->fbpsiz / 2, sizeof(int) * 2, dpfbpoolcmp); + for(i = 2; i < depot->fbpsiz; i += 2){ + if(depot->fbpool[i-2] > 0 && + depot->fbpool[i-2] + depot->fbpool[i-1] - depot->fbpool[i] == 0){ + depot->fbpool[i] = depot->fbpool[i-2]; + depot->fbpool[i+1] += depot->fbpool[i-1]; + depot->fbpool[i-2] = -1; + depot->fbpool[i-1] = -1; + } + } +} + + +/* Compare two records of the free block pool. + `a' specifies the pointer to one record. + `b' specifies the pointer to the other record. + The return value is 0 if two equals, positive if the formar is big, else, negative. */ +static int dpfbpoolcmp(const void *a, const void *b){ + assert(a && b); + return *(int *)a - *(int *)b; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/depot.h =================================================================== --- box/trunk/qdbm/depot.h 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/depot.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,492 +0,0 @@ -/************************************************************************************************* - * The basic API of QDBM - * 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. - *************************************************************************************************/ - - -#ifndef _DEPOT_H /* duplication check */ -#define _DEPOT_H - -#if defined(__cplusplus) /* export for C++ */ -extern "C" { -#endif - - -#include -#include - - -#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) -#define MYEXTERN extern __declspec(dllimport) -#else -#define MYEXTERN extern -#endif - - - -/************************************************************************************************* - * API - *************************************************************************************************/ - - -typedef struct { /* type of structure for a database handle */ - char *name; /* name of the database file */ - int wmode; /* whether to be writable */ - int inode; /* inode of the database file */ - time_t mtime; /* last modified time of the database */ - int fd; /* file descriptor of the database file */ - int fsiz; /* size of the database file */ - char *map; /* pointer to the mapped memory */ - int msiz; /* size of the mapped memory */ - int *buckets; /* pointer to the bucket array */ - int bnum; /* number of the bucket array */ - int rnum; /* number of records */ - int fatal; /* whether a fatal error occured */ - int ioff; /* offset of the iterator */ - int *fbpool; /* free block pool */ - int fbpsiz; /* size of the free block pool */ - int fbpinc; /* incrementor of update of the free block pool */ - int align; /* basic size of alignment */ -} DEPOT; - -enum { /* enumeration for error codes */ - DP_ENOERR, /* no error */ - DP_EFATAL, /* with fatal error */ - DP_EMODE, /* invalid mode */ - DP_EBROKEN, /* broken database file */ - DP_EKEEP, /* existing record */ - DP_ENOITEM, /* no item found */ - DP_EALLOC, /* memory allocation error */ - DP_EMAP, /* memory mapping error */ - DP_EOPEN, /* open error */ - DP_ECLOSE, /* close error */ - DP_ETRUNC, /* trunc error */ - DP_ESYNC, /* sync error */ - DP_ESTAT, /* stat error */ - DP_ESEEK, /* seek error */ - DP_EREAD, /* read error */ - DP_EWRITE, /* write error */ - DP_ELOCK, /* lock error */ - DP_EUNLINK, /* unlink error */ - DP_EMKDIR, /* mkdir error */ - DP_ERMDIR, /* rmdir error */ - DP_EMISC /* miscellaneous error */ -}; - -enum { /* enumeration for open modes */ - DP_OREADER = 1 << 0, /* open as a reader */ - DP_OWRITER = 1 << 1, /* open as a writer */ - DP_OCREAT = 1 << 2, /* a writer creating */ - DP_OTRUNC = 1 << 3, /* a writer truncating */ - DP_ONOLCK = 1 << 4, /* open without locking */ - DP_OLCKNB = 1 << 5, /* lock without blocking */ - DP_OSPARSE = 1 << 6 /* create as a sparse file */ -}; - -enum { /* enumeration for write modes */ - DP_DOVER, /* overwrite an existing value */ - DP_DKEEP, /* keep an existing value */ - DP_DCAT /* concatenate values */ -}; - - -/* String containing the version information. */ -MYEXTERN const char *dpversion; - - -/* Last happened error code. */ -#define dpecode (*dpecodeptr()) - - -/* Get a message string corresponding to an error code. - `ecode' specifies an error code. - The return value is the message string of the error code. The region of the return value - is not writable. */ -const char *dperrmsg(int ecode); - - -/* Get a database handle. - `name' specifies the name of a database file. - `omode' specifies the connection mode: `DP_OWRITER' as a writer, `DP_OREADER' as a reader. - If the mode is `DP_OWRITER', the following may be added by bitwise or: `DP_OCREAT', which - means it creates a new database if not exist, `DP_OTRUNC', which means it creates a new - database regardless if one exists. Both of `DP_OREADER' and `DP_OWRITER' can be added to by - bitwise or: `DP_ONOLCK', which means it opens a database file without file locking, or - `DP_OLCKNB', which means locking is performed without blocking. `DP_OCREAT' can be added to - by bitwise or: `DP_OSPARSE', which means it creates a database file as a sparse file. - `bnum' specifies the number of elements of the bucket array. If it is not more than 0, - the default value is specified. The size of a bucket array is determined on creating, - and can not be changed except for by optimization of the database. Suggested size of a - bucket array is about from 0.5 to 4 times of the number of all records to store. - The return value is the database handle or `NULL' if it is not successful. - While connecting as a writer, an exclusive lock is invoked to the database file. - While connecting as a reader, a shared lock is invoked to the database file. The thread - blocks until the lock is achieved. If `DP_ONOLCK' is used, the application is responsible - for exclusion control. */ -DEPOT *dpopen(const char *name, int omode, int bnum); - - -/* Close a database handle. - `depot' specifies a database handle. - If successful, the return value is true, else, it is false. - Because the region of a closed handle is released, it becomes impossible to use the handle. - Updating a database is assured to be written when the handle is closed. If a writer opens - a database but does not close it appropriately, the database will be broken. */ -int dpclose(DEPOT *depot); - - -/* Store a record. - `depot' specifies a database handle connected as a writer. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region of the value. If it is negative, the size is - assigned with `strlen(vbuf)'. - `dmode' specifies behavior when the key overlaps, by the following values: `DP_DOVER', - which means the specified value overwrites the existing one, `DP_DKEEP', which means the - existing value is kept, `DP_DCAT', which means the specified value is concatenated at the - end of the existing value. - If successful, the return value is true, else, it is false. */ -int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); - - -/* Delete a record. - `depot' specifies a database handle connected as a writer. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is true, else, it is false. False is returned when no - record corresponds to the specified key. */ -int dpout(DEPOT *depot, const char *kbuf, int ksiz); - - -/* Retrieve a record. - `depot' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `start' specifies the offset address of the beginning of the region of the value to be read. - `max' specifies the max size to be read. If it is negative, the size to read is unlimited. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to - the specified key or the size of the value of the corresponding record is less than `start'. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. */ -char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp); - - -/* Retrieve a record and write the value into a buffer. - `depot' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `start' specifies the offset address of the beginning of the region of the value to be read. - `max' specifies the max size to be read. It shuld be equal to or less than the size of the - writing buffer. - `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is - written. - If successful, the return value is the size of the written data, else, it is -1. -1 is - returned when no record corresponds to the specified key or the size of the value of the - corresponding record is less than `start'. - Note that no additional zero code is appended at the end of the region of the writing buffer. */ -int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf); - - -/* Get the size of the value of a record. - `depot' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is the size of the value of the corresponding record, else, - it is -1. - Because this function does not read the entity of a record, it is faster than `dpget'. */ -int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz); - - -/* Initialize the iterator of a database handle. - `depot' specifies a database handle. - If successful, the return value is true, else, it is false. - The iterator is used in order to access the key of every record stored in a database. */ -int dpiterinit(DEPOT *depot); - - -/* Get the next key of the iterator. - `depot' specifies a database handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the next key, else, it is - `NULL'. `NULL' is returned when no record is to be get out of the iterator. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if - it is no longer in use. It is possible to access every record by iteration of calling - this function. However, it is not assured if updating the database is occurred while the - iteration. Besides, the order of this traversal access method is arbitrary, so it is not - assured that the order of storing matches the one of the traversal access. */ -char *dpiternext(DEPOT *depot, int *sp); - - -/* Set alignment of a database handle. - `depot' specifies a database handle connected as a writer. - `align' specifies the size of alignment. - If successful, the return value is true, else, it is false. - If alignment is set to a database, the efficiency of overwriting values is improved. - The size of alignment is suggested to be average size of the values of the records to be - stored. If alignment is positive, padding whose size is multiple number of the alignment - is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding - is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not - saved in a database, you should specify alignment every opening a database. */ -int dpsetalign(DEPOT *depot, int align); - - -/* Set the size of the free block pool of a database handle. - `depot' specifies a database handle connected as a writer. - `size' specifies the size of the free block pool of a database. - If successful, the return value is true, else, it is false. - The default size of the free block pool is 16. If the size is greater, the space efficiency - of overwriting values is improved with the time efficiency sacrificed. */ -int dpsetfbpsiz(DEPOT *depot, int size); - - -/* Synchronize updating contents with the file and the device. - `depot' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. - This function is useful when another process uses the connected database file. */ -int dpsync(DEPOT *depot); - - -/* Optimize a database. - `depot' specifies a database handle connected as a writer. - `bnum' specifies the number of the elements of the bucket array. If it is not more than 0, - the default value is specified. - If successful, the return value is true, else, it is false. - In an alternating succession of deleting and storing with overwrite or concatenate, - dispensable regions accumulate. This function is useful to do away with them. */ -int dpoptimize(DEPOT *depot, int bnum); - - -/* Get the name of a database. - `depot' specifies a database handle. - If successful, the return value is the pointer to the region of the name of the database, - else, it is `NULL'. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *dpname(DEPOT *depot); - - -/* Get the size of a database file. - `depot' specifies a database handle. - If successful, the return value is the size of the database file, else, it is -1. */ -int dpfsiz(DEPOT *depot); - - -/* Get the number of the elements of the bucket array. - `depot' specifies a database handle. - If successful, the return value is the number of the elements of the bucket array, else, it - is -1. */ -int dpbnum(DEPOT *depot); - - -/* Get the number of the used elements of the bucket array. - `depot' specifies a database handle. - If successful, the return value is the number of the used elements of the bucket array, - else, it is -1. - This function is inefficient because it accesses all elements of the bucket array. */ -int dpbusenum(DEPOT *depot); - - -/* Get the number of the records stored in a database. - `depot' specifies a database handle. - If successful, the return value is the number of the records stored in the database, else, - it is -1. */ -int dprnum(DEPOT *depot); - - -/* Check whether a database handle is a writer or not. - `depot' specifies a database handle. - The return value is true if the handle is a writer, false if not. */ -int dpwritable(DEPOT *depot); - - -/* Check whether a database has a fatal error or not. - `depot' specifies a database handle. - The return value is true if the database has a fatal error, false if not. */ -int dpfatalerror(DEPOT *depot); - - -/* Get the inode number of a database file. - `depot' specifies a database handle. - The return value is the inode number of the database file. */ -int dpinode(DEPOT *depot); - - -/* Get the last modified time of a database. - `depot' specifies a database handle. - The return value is the last modified time of the database. */ -time_t dpmtime(DEPOT *depot); - - -/* Get the file descriptor of a database file. - `depot' specifies a database handle. - The return value is the file descriptor of the database file. - Handling the file descriptor of a database file directly is not suggested. */ -int dpfdesc(DEPOT *depot); - - -/* Remove a database file. - `name' specifies the name of a database file. - If successful, the return value is true, else, it is false. */ -int dpremove(const char *name); - - -/* Repair a broken database file. - `name' specifies the name of a database file. - If successful, the return value is true, else, it is false. - There is no guarantee that all records in a repaired database file correspond to the original - or expected state. */ -int dprepair(const char *name); - - -/* Dump all records as endian independent data. - `depot' specifies a database handle. - `name' specifies the name of an output file. - If successful, the return value is true, else, it is false. */ -int dpexportdb(DEPOT *depot, const char *name); - - -/* Load all records from endian independent data. - `depot' specifies a database handle connected as a writer. The database of the handle must - be empty. - `name' specifies the name of an input file. - If successful, the return value is true, else, it is false. */ -int dpimportdb(DEPOT *depot, const char *name); - - -/* Retrieve a record directly from a database file. - `name' specifies the name of a database file. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to - the specified key. - Because an additional zero code is appended at the end of the region of the return value, - the return value can be treated as a character string. Because the region of the return - value is allocated with the `malloc' call, it should be released with the `free' call if it - is no longer in use. Although this function can be used even while the database file is - locked by another process, it is not assured that recent updated is reflected. */ -char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp); - - -/* Hash function used inside Depot. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - The return value is the hash value of 31 bits length computed from the key. - This function is useful when an application calculates the state of the inside bucket array. */ -int dpinnerhash(const char *kbuf, int ksiz); - - -/* Hash function which is independent from the hash functions used inside Depot. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - The return value is the hash value of 31 bits length computed from the key. - This function is useful when an application uses its own hash algorithm outside Depot. */ -int dpouterhash(const char *kbuf, int ksiz); - - -/* Get a natural prime number not less than a number. - `num' specified a natural number. - The return value is a natural prime number not less than the specified number. - This function is useful when an application determines the size of a bucket array of its - own hash algorithm. */ -int dpprimenum(int num); - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -#define _QDBM_VERSION "1.8.77" -#define _QDBM_LIBVER 1413 - - -/* Name of the operating system. */ -MYEXTERN const char *dpsysname; - - -/* File descriptor for debugging output. */ -MYEXTERN int dpdbgfd; - - -/* Whether this build is reentrant. */ -MYEXTERN const int dpisreentrant; - - -/* Set the last happened error code. - `ecode' specifies the error code. - `line' specifies the number of the line where the error happened. */ -void dpecodeset(int ecode, const char *file, int line); - - -/* Get the pointer of the variable of the last happened error code. - The return value is the pointer of the variable. */ -int *dpecodeptr(void); - - -/* Synchronize updating contents on memory. - `depot' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. */ -int dpmemsync(DEPOT *depot); - - -/* Synchronize updating contents on memory, not physically. - `depot' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. */ -int dpmemflush(DEPOT *depot); - - -/* Get flags of a database. - `depot' specifies a database handle. - The return value is the flags of a database. */ -int dpgetflags(DEPOT *depot); - - -/* Set flags of a database. - `depot' specifies a database handle connected as a writer. - `flags' specifies flags to set. Least ten bits are reserved for internal use. - If successful, the return value is true, else, it is false. */ -int dpsetflags(DEPOT *depot, int flags); - - - -#undef MYEXTERN - -#if defined(__cplusplus) /* export for C++ */ -} -#endif - -#endif /* duplication check */ - - -/* END OF FILE */ Copied: box/trunk/qdbm/depot.h (from rev 2716, box/trunk/qdbm/depot.h) =================================================================== --- box/trunk/qdbm/depot.h (rev 0) +++ box/trunk/qdbm/depot.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,492 @@ +/************************************************************************************************* + * The basic API of QDBM + * 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. + *************************************************************************************************/ + + +#ifndef _DEPOT_H /* duplication check */ +#define _DEPOT_H + +#if defined(__cplusplus) /* export for C++ */ +extern "C" { +#endif + + +#include +#include + + +#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) +#define MYEXTERN extern __declspec(dllimport) +#else +#define MYEXTERN extern +#endif + + + +/************************************************************************************************* + * API + *************************************************************************************************/ + + +typedef struct { /* type of structure for a database handle */ + char *name; /* name of the database file */ + int wmode; /* whether to be writable */ + int inode; /* inode of the database file */ + time_t mtime; /* last modified time of the database */ + int fd; /* file descriptor of the database file */ + int fsiz; /* size of the database file */ + char *map; /* pointer to the mapped memory */ + int msiz; /* size of the mapped memory */ + int *buckets; /* pointer to the bucket array */ + int bnum; /* number of the bucket array */ + int rnum; /* number of records */ + int fatal; /* whether a fatal error occured */ + int ioff; /* offset of the iterator */ + int *fbpool; /* free block pool */ + int fbpsiz; /* size of the free block pool */ + int fbpinc; /* incrementor of update of the free block pool */ + int align; /* basic size of alignment */ +} DEPOT; + +enum { /* enumeration for error codes */ + DP_ENOERR, /* no error */ + DP_EFATAL, /* with fatal error */ + DP_EMODE, /* invalid mode */ + DP_EBROKEN, /* broken database file */ + DP_EKEEP, /* existing record */ + DP_ENOITEM, /* no item found */ + DP_EALLOC, /* memory allocation error */ + DP_EMAP, /* memory mapping error */ + DP_EOPEN, /* open error */ + DP_ECLOSE, /* close error */ + DP_ETRUNC, /* trunc error */ + DP_ESYNC, /* sync error */ + DP_ESTAT, /* stat error */ + DP_ESEEK, /* seek error */ + DP_EREAD, /* read error */ + DP_EWRITE, /* write error */ + DP_ELOCK, /* lock error */ + DP_EUNLINK, /* unlink error */ + DP_EMKDIR, /* mkdir error */ + DP_ERMDIR, /* rmdir error */ + DP_EMISC /* miscellaneous error */ +}; + +enum { /* enumeration for open modes */ + DP_OREADER = 1 << 0, /* open as a reader */ + DP_OWRITER = 1 << 1, /* open as a writer */ + DP_OCREAT = 1 << 2, /* a writer creating */ + DP_OTRUNC = 1 << 3, /* a writer truncating */ + DP_ONOLCK = 1 << 4, /* open without locking */ + DP_OLCKNB = 1 << 5, /* lock without blocking */ + DP_OSPARSE = 1 << 6 /* create as a sparse file */ +}; + +enum { /* enumeration for write modes */ + DP_DOVER, /* overwrite an existing value */ + DP_DKEEP, /* keep an existing value */ + DP_DCAT /* concatenate values */ +}; + + +/* String containing the version information. */ +MYEXTERN const char *dpversion; + + +/* Last happened error code. */ +#define dpecode (*dpecodeptr()) + + +/* Get a message string corresponding to an error code. + `ecode' specifies an error code. + The return value is the message string of the error code. The region of the return value + is not writable. */ +const char *dperrmsg(int ecode); + + +/* Get a database handle. + `name' specifies the name of a database file. + `omode' specifies the connection mode: `DP_OWRITER' as a writer, `DP_OREADER' as a reader. + If the mode is `DP_OWRITER', the following may be added by bitwise or: `DP_OCREAT', which + means it creates a new database if not exist, `DP_OTRUNC', which means it creates a new + database regardless if one exists. Both of `DP_OREADER' and `DP_OWRITER' can be added to by + bitwise or: `DP_ONOLCK', which means it opens a database file without file locking, or + `DP_OLCKNB', which means locking is performed without blocking. `DP_OCREAT' can be added to + by bitwise or: `DP_OSPARSE', which means it creates a database file as a sparse file. + `bnum' specifies the number of elements of the bucket array. If it is not more than 0, + the default value is specified. The size of a bucket array is determined on creating, + and can not be changed except for by optimization of the database. Suggested size of a + bucket array is about from 0.5 to 4 times of the number of all records to store. + The return value is the database handle or `NULL' if it is not successful. + While connecting as a writer, an exclusive lock is invoked to the database file. + While connecting as a reader, a shared lock is invoked to the database file. The thread + blocks until the lock is achieved. If `DP_ONOLCK' is used, the application is responsible + for exclusion control. */ +DEPOT *dpopen(const char *name, int omode, int bnum); + + +/* Close a database handle. + `depot' specifies a database handle. + If successful, the return value is true, else, it is false. + Because the region of a closed handle is released, it becomes impossible to use the handle. + Updating a database is assured to be written when the handle is closed. If a writer opens + a database but does not close it appropriately, the database will be broken. */ +int dpclose(DEPOT *depot); + + +/* Store a record. + `depot' specifies a database handle connected as a writer. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region of the value. If it is negative, the size is + assigned with `strlen(vbuf)'. + `dmode' specifies behavior when the key overlaps, by the following values: `DP_DOVER', + which means the specified value overwrites the existing one, `DP_DKEEP', which means the + existing value is kept, `DP_DCAT', which means the specified value is concatenated at the + end of the existing value. + If successful, the return value is true, else, it is false. */ +int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); + + +/* Delete a record. + `depot' specifies a database handle connected as a writer. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is true, else, it is false. False is returned when no + record corresponds to the specified key. */ +int dpout(DEPOT *depot, const char *kbuf, int ksiz); + + +/* Retrieve a record. + `depot' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `start' specifies the offset address of the beginning of the region of the value to be read. + `max' specifies the max size to be read. If it is negative, the size to read is unlimited. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to + the specified key or the size of the value of the corresponding record is less than `start'. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. */ +char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp); + + +/* Retrieve a record and write the value into a buffer. + `depot' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `start' specifies the offset address of the beginning of the region of the value to be read. + `max' specifies the max size to be read. It shuld be equal to or less than the size of the + writing buffer. + `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is + written. + If successful, the return value is the size of the written data, else, it is -1. -1 is + returned when no record corresponds to the specified key or the size of the value of the + corresponding record is less than `start'. + Note that no additional zero code is appended at the end of the region of the writing buffer. */ +int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf); + + +/* Get the size of the value of a record. + `depot' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is the size of the value of the corresponding record, else, + it is -1. + Because this function does not read the entity of a record, it is faster than `dpget'. */ +int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz); + + +/* Initialize the iterator of a database handle. + `depot' specifies a database handle. + If successful, the return value is true, else, it is false. + The iterator is used in order to access the key of every record stored in a database. */ +int dpiterinit(DEPOT *depot); + + +/* Get the next key of the iterator. + `depot' specifies a database handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the next key, else, it is + `NULL'. `NULL' is returned when no record is to be get out of the iterator. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if + it is no longer in use. It is possible to access every record by iteration of calling + this function. However, it is not assured if updating the database is occurred while the + iteration. Besides, the order of this traversal access method is arbitrary, so it is not + assured that the order of storing matches the one of the traversal access. */ +char *dpiternext(DEPOT *depot, int *sp); + + +/* Set alignment of a database handle. + `depot' specifies a database handle connected as a writer. + `align' specifies the size of alignment. + If successful, the return value is true, else, it is false. + If alignment is set to a database, the efficiency of overwriting values is improved. + The size of alignment is suggested to be average size of the values of the records to be + stored. If alignment is positive, padding whose size is multiple number of the alignment + is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding + is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not + saved in a database, you should specify alignment every opening a database. */ +int dpsetalign(DEPOT *depot, int align); + + +/* Set the size of the free block pool of a database handle. + `depot' specifies a database handle connected as a writer. + `size' specifies the size of the free block pool of a database. + If successful, the return value is true, else, it is false. + The default size of the free block pool is 16. If the size is greater, the space efficiency + of overwriting values is improved with the time efficiency sacrificed. */ +int dpsetfbpsiz(DEPOT *depot, int size); + + +/* Synchronize updating contents with the file and the device. + `depot' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. + This function is useful when another process uses the connected database file. */ +int dpsync(DEPOT *depot); + + +/* Optimize a database. + `depot' specifies a database handle connected as a writer. + `bnum' specifies the number of the elements of the bucket array. If it is not more than 0, + the default value is specified. + If successful, the return value is true, else, it is false. + In an alternating succession of deleting and storing with overwrite or concatenate, + dispensable regions accumulate. This function is useful to do away with them. */ +int dpoptimize(DEPOT *depot, int bnum); + + +/* Get the name of a database. + `depot' specifies a database handle. + If successful, the return value is the pointer to the region of the name of the database, + else, it is `NULL'. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *dpname(DEPOT *depot); + + +/* Get the size of a database file. + `depot' specifies a database handle. + If successful, the return value is the size of the database file, else, it is -1. */ +int dpfsiz(DEPOT *depot); + + +/* Get the number of the elements of the bucket array. + `depot' specifies a database handle. + If successful, the return value is the number of the elements of the bucket array, else, it + is -1. */ +int dpbnum(DEPOT *depot); + + +/* Get the number of the used elements of the bucket array. + `depot' specifies a database handle. + If successful, the return value is the number of the used elements of the bucket array, + else, it is -1. + This function is inefficient because it accesses all elements of the bucket array. */ +int dpbusenum(DEPOT *depot); + + +/* Get the number of the records stored in a database. + `depot' specifies a database handle. + If successful, the return value is the number of the records stored in the database, else, + it is -1. */ +int dprnum(DEPOT *depot); + + +/* Check whether a database handle is a writer or not. + `depot' specifies a database handle. + The return value is true if the handle is a writer, false if not. */ +int dpwritable(DEPOT *depot); + + +/* Check whether a database has a fatal error or not. + `depot' specifies a database handle. + The return value is true if the database has a fatal error, false if not. */ +int dpfatalerror(DEPOT *depot); + + +/* Get the inode number of a database file. + `depot' specifies a database handle. + The return value is the inode number of the database file. */ +int dpinode(DEPOT *depot); + + +/* Get the last modified time of a database. + `depot' specifies a database handle. + The return value is the last modified time of the database. */ +time_t dpmtime(DEPOT *depot); + + +/* Get the file descriptor of a database file. + `depot' specifies a database handle. + The return value is the file descriptor of the database file. + Handling the file descriptor of a database file directly is not suggested. */ +int dpfdesc(DEPOT *depot); + + +/* Remove a database file. + `name' specifies the name of a database file. + If successful, the return value is true, else, it is false. */ +int dpremove(const char *name); + + +/* Repair a broken database file. + `name' specifies the name of a database file. + If successful, the return value is true, else, it is false. + There is no guarantee that all records in a repaired database file correspond to the original + or expected state. */ +int dprepair(const char *name); + + +/* Dump all records as endian independent data. + `depot' specifies a database handle. + `name' specifies the name of an output file. + If successful, the return value is true, else, it is false. */ +int dpexportdb(DEPOT *depot, const char *name); + + +/* Load all records from endian independent data. + `depot' specifies a database handle connected as a writer. The database of the handle must + be empty. + `name' specifies the name of an input file. + If successful, the return value is true, else, it is false. */ +int dpimportdb(DEPOT *depot, const char *name); + + +/* Retrieve a record directly from a database file. + `name' specifies the name of a database file. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to + the specified key. + Because an additional zero code is appended at the end of the region of the return value, + the return value can be treated as a character string. Because the region of the return + value is allocated with the `malloc' call, it should be released with the `free' call if it + is no longer in use. Although this function can be used even while the database file is + locked by another process, it is not assured that recent updated is reflected. */ +char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp); + + +/* Hash function used inside Depot. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + The return value is the hash value of 31 bits length computed from the key. + This function is useful when an application calculates the state of the inside bucket array. */ +int dpinnerhash(const char *kbuf, int ksiz); + + +/* Hash function which is independent from the hash functions used inside Depot. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + The return value is the hash value of 31 bits length computed from the key. + This function is useful when an application uses its own hash algorithm outside Depot. */ +int dpouterhash(const char *kbuf, int ksiz); + + +/* Get a natural prime number not less than a number. + `num' specified a natural number. + The return value is a natural prime number not less than the specified number. + This function is useful when an application determines the size of a bucket array of its + own hash algorithm. */ +int dpprimenum(int num); + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +#define _QDBM_VERSION "1.8.77" +#define _QDBM_LIBVER 1413 + + +/* Name of the operating system. */ +MYEXTERN const char *dpsysname; + + +/* File descriptor for debugging output. */ +MYEXTERN int dpdbgfd; + + +/* Whether this build is reentrant. */ +MYEXTERN const int dpisreentrant; + + +/* Set the last happened error code. + `ecode' specifies the error code. + `line' specifies the number of the line where the error happened. */ +void dpecodeset(int ecode, const char *file, int line); + + +/* Get the pointer of the variable of the last happened error code. + The return value is the pointer of the variable. */ +int *dpecodeptr(void); + + +/* Synchronize updating contents on memory. + `depot' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. */ +int dpmemsync(DEPOT *depot); + + +/* Synchronize updating contents on memory, not physically. + `depot' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. */ +int dpmemflush(DEPOT *depot); + + +/* Get flags of a database. + `depot' specifies a database handle. + The return value is the flags of a database. */ +int dpgetflags(DEPOT *depot); + + +/* Set flags of a database. + `depot' specifies a database handle connected as a writer. + `flags' specifies flags to set. Least ten bits are reserved for internal use. + If successful, the return value is true, else, it is false. */ +int dpsetflags(DEPOT *depot, int flags); + + + +#undef MYEXTERN + +#if defined(__cplusplus) /* export for C++ */ +} +#endif + +#endif /* duplication check */ + + +/* END OF FILE */ Deleted: box/trunk/qdbm/dpmgr.c =================================================================== --- box/trunk/qdbm/dpmgr.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/dpmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,916 +0,0 @@ -/************************************************************************************************* - * Utility for debugging Depot and its applications - * 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 -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define ALIGNSIZ 32 /* basic size of alignment */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -char *hextoobj(const char *str, int *sp); -char *dectoiobj(const char *str, int *sp); -int runcreate(int argc, char **argv); -int runput(int argc, char **argv); -int runout(int argc, char **argv); -int runget(int argc, char **argv); -int runlist(int argc, char **argv); -int runoptimize(int argc, char **argv); -int runinform(int argc, char **argv); -int runremove(int argc, char **argv); -int runrepair(int argc, char **argv); -int runexportdb(int argc, char **argv); -int runimportdb(int argc, char **argv); -int runsnaffle(int argc, char **argv); -void pdperror(const char *name); -void printobj(const char *obj, int size); -void printobjhex(const char *obj, int size); -int docreate(const char *name, int bnum, int sparse); -int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, - int dmode, int align); -int doout(const char *name, const char *kbuf, int ksiz); -int doget(const char *name, int opts, const char *kbuf, int ksiz, - int start, int max, int ox, int nb); -int dolist(const char *name, int opts, int kb, int vb, int ox); -int dooptimize(const char *name, int bnum, int align); -int doinform(const char *name, int opts); -int doremove(const char *name); -int dorepair(const char *name); -int doexportdb(const char *name, const char *file); -int doimportdb(const char *name, const char *file, int bnum); -int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb); - - -/* main routine */ -int main(int argc, char **argv){ - char *env; - int rv; - cbstdiobin(); - progname = argv[0]; - if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "create")){ - rv = runcreate(argc, argv); - } else if(!strcmp(argv[1], "put")){ - rv = runput(argc, argv); - } else if(!strcmp(argv[1], "out")){ - rv = runout(argc, argv); - } else if(!strcmp(argv[1], "get")){ - rv = runget(argc, argv); - } else if(!strcmp(argv[1], "list")){ - rv = runlist(argc, argv); - } else if(!strcmp(argv[1], "optimize")){ - rv = runoptimize(argc, argv); - } else if(!strcmp(argv[1], "inform")){ - rv = runinform(argc, argv); - } else if(!strcmp(argv[1], "remove")){ - rv = runremove(argc, argv); - } else if(!strcmp(argv[1], "repair")){ - rv = runrepair(argc, argv); - } else if(!strcmp(argv[1], "exportdb")){ - rv = runexportdb(argc, argv); - } else if(!strcmp(argv[1], "importdb")){ - rv = runimportdb(argc, argv); - } else if(!strcmp(argv[1], "snaffle")){ - rv = runsnaffle(argc, argv); - } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ - printf("Powered by QDBM version %s on %s%s\n", - dpversion, dpsysname, dpisreentrant ? " (reentrant)" : ""); - printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); - rv = 0; - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: administration utility for Depot\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s create [-s] [-bnum num] name\n", progname); - fprintf(stderr, " %s put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-na] name key val\n", - progname); - fprintf(stderr, " %s out [-kx|-ki] name key\n", progname); - fprintf(stderr, " %s get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-n] name key\n", - progname); - fprintf(stderr, " %s list [-nl] [-k|-v] [-ox] name\n", progname); - fprintf(stderr, " %s optimize [-bnum num] [-na] name\n", progname); - fprintf(stderr, " %s inform [-nl] name\n", progname); - fprintf(stderr, " %s remove name\n", progname); - fprintf(stderr, " %s repair name\n", progname); - fprintf(stderr, " %s exportdb name file\n", progname); - fprintf(stderr, " %s importdb [-bnum num] name file\n", progname); - fprintf(stderr, " %s snaffle [-kx|-ki] [-ox] [-n] name key\n", progname); - fprintf(stderr, " %s version\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* create a binary object from a hexadecimal string */ -char *hextoobj(const char *str, int *sp){ - char *buf, mbuf[3]; - int len, i, j; - len = strlen(str); - if(!(buf = malloc(len + 1))) return NULL; - j = 0; - for(i = 0; i < len; i += 2){ - while(strchr(" \n\r\t\f\v", str[i])){ - i++; - } - if((mbuf[0] = str[i]) == '\0') break; - if((mbuf[1] = str[i+1]) == '\0') break; - mbuf[2] = '\0'; - buf[j++] = (char)strtol(mbuf, NULL, 16); - } - buf[j] = '\0'; - *sp = j; - return buf; -} - - -/* create a integer object from a decimal string */ -char *dectoiobj(const char *str, int *sp){ - char *buf; - int num; - num = atoi(str); - if(!(buf = malloc(sizeof(int)))) return NULL; - *(int *)buf = num; - *sp = sizeof(int); - return buf; -} - - -/* parse arguments of create command */ -int runcreate(int argc, char **argv){ - char *name; - int i, sb, bnum, rv; - name = NULL; - sb = FALSE; - bnum = -1; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-s")){ - sb = TRUE; - } else if(!strcmp(argv[i], "-bnum")){ - if(++i >= argc) usage(); - bnum = atoi(argv[i]); - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = docreate(name, bnum, sb); - return rv; -} - - -/* parse arguments of put command */ -int runput(int argc, char **argv){ - char *name, *key, *val, *kbuf, *vbuf; - int i, kx, ki, vx, vi, vf, align, ksiz, vsiz, rv; - int dmode; - name = NULL; - kx = FALSE; - ki = FALSE; - vx = FALSE; - vi = FALSE; - vf = FALSE; - align = ALIGNSIZ; - key = NULL; - val = NULL; - dmode = DP_DOVER; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else if(!strcmp(argv[i], "-vx")){ - vx = TRUE; - } else if(!strcmp(argv[i], "-vi")){ - vi = TRUE; - } else if(!strcmp(argv[i], "-vf")){ - vf = TRUE; - } else if(!strcmp(argv[i], "-keep")){ - dmode = DP_DKEEP; - } else if(!strcmp(argv[i], "-cat")){ - dmode = DP_DCAT; - } else if(!strcmp(argv[i], "-na")){ - align = 0; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else if(!val){ - val = argv[i]; - } else { - usage(); - } - } - if(!name || !key || !val) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(vx){ - vbuf = hextoobj(val, &vsiz); - } else if(vi){ - vbuf = dectoiobj(val, &vsiz); - } else if(vf){ - vbuf = cbreadfile(val, &vsiz); - } else { - vbuf = cbmemdup(val, -1); - vsiz = -1; - } - if(kbuf && vbuf){ - rv = doput(name, kbuf, ksiz, vbuf, vsiz, dmode, align); - } else { - if(vf){ - fprintf(stderr, "%s: %s: cannot read\n", progname, val); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - } - rv = 1; - } - free(kbuf); - free(vbuf); - return rv; -} - - -/* parse arguments of out command */ -int runout(int argc, char **argv){ - char *name, *key, *kbuf; - int i, kx, ki, ksiz, rv; - name = NULL; - kx = FALSE; - ki = FALSE; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(kbuf){ - rv = doout(name, kbuf, ksiz); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* parse arguments of get command */ -int runget(int argc, char **argv){ - char *name, *key, *kbuf; - int i, opts, kx, ki, ox, nb, start, max, ksiz, rv; - name = NULL; - opts = 0; - kx = FALSE; - ki = FALSE; - ox = FALSE; - nb = FALSE; - start = 0; - max = -1; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-nl")){ - opts |= DP_ONOLCK; - } else if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else if(!strcmp(argv[i], "-n")){ - nb = TRUE; - } else if(!strcmp(argv[i], "-start")){ - if(++i >= argc) usage(); - start = atoi(argv[i]); - } else if(!strcmp(argv[i], "-max")){ - if(++i >= argc) usage(); - max = atoi(argv[i]); - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key || start < 0) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(kbuf){ - rv = doget(name, opts, kbuf, ksiz, start, max, ox, nb); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* parse arguments of list command */ -int runlist(int argc, char **argv){ - char *name; - int i, opts, kb, vb, ox, rv; - name = NULL; - opts = 0; - kb = FALSE; - vb = FALSE; - ox = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-nl")){ - opts |= DP_ONOLCK; - } else if(!strcmp(argv[i], "-k")){ - kb = TRUE; - } else if(!strcmp(argv[i], "-v")){ - vb = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dolist(name, opts, kb, vb, ox); - return rv; -} - - -/* parse arguments of optimize command */ -int runoptimize(int argc, char **argv){ - char *name; - int i, bnum, align, rv; - name = NULL; - bnum = -1; - align = ALIGNSIZ; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-bnum")){ - if(++i >= argc) usage(); - bnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-na")){ - align = 0; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dooptimize(name, bnum, align); - return rv; -} - - -/* parse arguments of inform command */ -int runinform(int argc, char **argv){ - char *name; - int i, opts, rv; - name = NULL; - opts = 0; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-nl")){ - opts |= DP_ONOLCK; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doinform(name, opts); - return rv; -} - - -/* parse arguments of remove command */ -int runremove(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doremove(name); - return rv; -} - - -/* parse arguments of repair command */ -int runrepair(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dorepair(name); - return rv; -} - - -/* parse arguments of exportdb command */ -int runexportdb(int argc, char **argv){ - char *name, *file; - int i, rv; - name = NULL; - file = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - if(!name || !file) usage(); - rv = doexportdb(name, file); - return rv; -} - - -/* parse arguments of importdb command */ -int runimportdb(int argc, char **argv){ - char *name, *file; - int i, bnum, rv; - name = NULL; - file = NULL; - bnum = -1; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-bnum")){ - if(++i >= argc) usage(); - bnum = atoi(argv[i]); - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - if(!name || !file) usage(); - rv = doimportdb(name, file, bnum); - return rv; -} - - -/* parse arguments of snaffle command */ -int runsnaffle(int argc, char **argv){ - char *name, *key, *kbuf; - int i, kx, ki, ox, nb, start, max, ksiz, rv; - name = NULL; - kx = FALSE; - ki = FALSE; - ox = FALSE; - nb = FALSE; - start = 0; - max = -1; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else if(!strcmp(argv[i], "-n")){ - nb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key || start < 0) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(kbuf){ - rv = dosnaffle(name, kbuf, ksiz, ox, nb); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* print an object */ -void printobj(const char *obj, int size){ - int i; - for(i = 0; i < size; i++){ - putchar(obj[i]); - } -} - - -/* print an object as a hexadecimal string */ -void printobjhex(const char *obj, int size){ - int i; - for(i = 0; i < size; i++){ - printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); - } -} - - -/* perform create command */ -int docreate(const char *name, int bnum, int sparse){ - DEPOT *depot; - int omode; - omode = DP_OWRITER | DP_OCREAT | DP_OTRUNC | (sparse ? DP_OSPARSE : 0); - if(!(depot = dpopen(name, omode, bnum))){ - pdperror(name); - return 1; - } - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform put command */ -int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, - int dmode, int align){ - DEPOT *depot; - if(!(depot = dpopen(name, DP_OWRITER, -1))){ - pdperror(name); - return 1; - } - if(align > 0 && !dpsetalign(depot, align)){ - pdperror(name); - dpclose(depot); - return 1; - } - if(!dpput(depot, kbuf, ksiz, vbuf, vsiz, dmode)){ - pdperror(name); - dpclose(depot); - return 1; - } - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform out command */ -int doout(const char *name, const char *kbuf, int ksiz){ - DEPOT *depot; - if(!(depot = dpopen(name, DP_OWRITER, -1))){ - pdperror(name); - return 1; - } - if(!dpout(depot, kbuf, ksiz)){ - pdperror(name); - dpclose(depot); - return 1; - } - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform get command */ -int doget(const char *name, int opts, const char *kbuf, int ksiz, - int start, int max, int ox, int nb){ - DEPOT *depot; - char *vbuf; - int vsiz; - if(!(depot = dpopen(name, DP_OREADER | opts, -1))){ - pdperror(name); - return 1; - } - if(!(vbuf = dpget(depot, kbuf, ksiz, start, max, &vsiz))){ - pdperror(name); - dpclose(depot); - return 1; - } - if(ox){ - printobjhex(vbuf, vsiz); - } else { - printobj(vbuf, vsiz); - } - free(vbuf); - if(!nb) putchar('\n'); - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform list command */ -int dolist(const char *name, int opts, int kb, int vb, int ox){ - DEPOT *depot; - char *kbuf, *vbuf; - int ksiz, vsiz; - if(!(depot = dpopen(name, DP_OREADER | opts, -1))){ - pdperror(name); - return 1; - } - dpiterinit(depot); - while((kbuf = dpiternext(depot, &ksiz)) != NULL){ - if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz))){ - pdperror(name); - free(kbuf); - break; - } - if(ox){ - if(!vb) printobjhex(kbuf, ksiz); - if(!kb && !vb) putchar('\t'); - if(!kb) printobjhex(vbuf, vsiz); - } else { - if(!vb) printobj(kbuf, ksiz); - if(!kb && !vb) putchar('\t'); - if(!kb) printobj(vbuf, vsiz); - } - putchar('\n'); - free(vbuf); - free(kbuf); - } - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform optimize command */ -int dooptimize(const char *name, int bnum, int align){ - DEPOT *depot; - if(!(depot = dpopen(name, DP_OWRITER, -1))){ - pdperror(name); - return 1; - } - if(align > 0 && !dpsetalign(depot, align)){ - pdperror(name); - dpclose(depot); - return 1; - } - if(!dpoptimize(depot, bnum)){ - pdperror(name); - dpclose(depot); - return 1; - } - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform inform command */ -int doinform(const char *name, int opts){ - DEPOT *depot; - char *tmp; - if(!(depot = dpopen(name, DP_OREADER | opts, -1))){ - pdperror(name); - return 1; - } - tmp = dpname(depot); - printf("name: %s\n", tmp ? tmp : "(null)"); - free(tmp); - printf("file size: %d\n", dpfsiz(depot)); - printf("all buckets: %d\n", dpbnum(depot)); - printf("used buckets: %d\n", dpbusenum(depot)); - printf("records: %d\n", dprnum(depot)); - printf("inode number: %d\n", dpinode(depot)); - printf("modified time: %.0f\n", (double)dpmtime(depot)); - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform remove command */ -int doremove(const char *name){ - if(!dpremove(name)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform repair command */ -int dorepair(const char *name){ - if(!dprepair(name)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform exportdb command */ -int doexportdb(const char *name, const char *file){ - DEPOT *depot; - if(!(depot = dpopen(name, DP_OREADER, -1))){ - pdperror(name); - return 1; - } - if(!dpexportdb(depot, file)){ - pdperror(name); - dpclose(depot); - return 1; - } - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform importdb command */ -int doimportdb(const char *name, const char *file, int bnum){ - DEPOT *depot; - if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, bnum))){ - pdperror(name); - return 1; - } - if(!dpimportdb(depot, file)){ - pdperror(name); - dpclose(depot); - return 1; - } - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform snaffle command */ -int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb){ - char *vbuf; - int vsiz; - if(!(vbuf = dpsnaffle(name, kbuf, ksiz, &vsiz))){ - pdperror(name); - return 1; - } - if(ox){ - printobjhex(vbuf, vsiz); - } else { - printobj(vbuf, vsiz); - } - free(vbuf); - if(!nb) putchar('\n'); - return 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/dpmgr.c (from rev 2716, box/trunk/qdbm/dpmgr.c) =================================================================== --- box/trunk/qdbm/dpmgr.c (rev 0) +++ box/trunk/qdbm/dpmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,916 @@ +/************************************************************************************************* + * Utility for debugging Depot and its applications + * 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 +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define ALIGNSIZ 32 /* basic size of alignment */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +char *hextoobj(const char *str, int *sp); +char *dectoiobj(const char *str, int *sp); +int runcreate(int argc, char **argv); +int runput(int argc, char **argv); +int runout(int argc, char **argv); +int runget(int argc, char **argv); +int runlist(int argc, char **argv); +int runoptimize(int argc, char **argv); +int runinform(int argc, char **argv); +int runremove(int argc, char **argv); +int runrepair(int argc, char **argv); +int runexportdb(int argc, char **argv); +int runimportdb(int argc, char **argv); +int runsnaffle(int argc, char **argv); +void pdperror(const char *name); +void printobj(const char *obj, int size); +void printobjhex(const char *obj, int size); +int docreate(const char *name, int bnum, int sparse); +int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, + int dmode, int align); +int doout(const char *name, const char *kbuf, int ksiz); +int doget(const char *name, int opts, const char *kbuf, int ksiz, + int start, int max, int ox, int nb); +int dolist(const char *name, int opts, int kb, int vb, int ox); +int dooptimize(const char *name, int bnum, int align); +int doinform(const char *name, int opts); +int doremove(const char *name); +int dorepair(const char *name); +int doexportdb(const char *name, const char *file); +int doimportdb(const char *name, const char *file, int bnum); +int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb); + + +/* main routine */ +int main(int argc, char **argv){ + char *env; + int rv; + cbstdiobin(); + progname = argv[0]; + if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "create")){ + rv = runcreate(argc, argv); + } else if(!strcmp(argv[1], "put")){ + rv = runput(argc, argv); + } else if(!strcmp(argv[1], "out")){ + rv = runout(argc, argv); + } else if(!strcmp(argv[1], "get")){ + rv = runget(argc, argv); + } else if(!strcmp(argv[1], "list")){ + rv = runlist(argc, argv); + } else if(!strcmp(argv[1], "optimize")){ + rv = runoptimize(argc, argv); + } else if(!strcmp(argv[1], "inform")){ + rv = runinform(argc, argv); + } else if(!strcmp(argv[1], "remove")){ + rv = runremove(argc, argv); + } else if(!strcmp(argv[1], "repair")){ + rv = runrepair(argc, argv); + } else if(!strcmp(argv[1], "exportdb")){ + rv = runexportdb(argc, argv); + } else if(!strcmp(argv[1], "importdb")){ + rv = runimportdb(argc, argv); + } else if(!strcmp(argv[1], "snaffle")){ + rv = runsnaffle(argc, argv); + } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ + printf("Powered by QDBM version %s on %s%s\n", + dpversion, dpsysname, dpisreentrant ? " (reentrant)" : ""); + printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); + rv = 0; + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: administration utility for Depot\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s create [-s] [-bnum num] name\n", progname); + fprintf(stderr, " %s put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-na] name key val\n", + progname); + fprintf(stderr, " %s out [-kx|-ki] name key\n", progname); + fprintf(stderr, " %s get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-n] name key\n", + progname); + fprintf(stderr, " %s list [-nl] [-k|-v] [-ox] name\n", progname); + fprintf(stderr, " %s optimize [-bnum num] [-na] name\n", progname); + fprintf(stderr, " %s inform [-nl] name\n", progname); + fprintf(stderr, " %s remove name\n", progname); + fprintf(stderr, " %s repair name\n", progname); + fprintf(stderr, " %s exportdb name file\n", progname); + fprintf(stderr, " %s importdb [-bnum num] name file\n", progname); + fprintf(stderr, " %s snaffle [-kx|-ki] [-ox] [-n] name key\n", progname); + fprintf(stderr, " %s version\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* create a binary object from a hexadecimal string */ +char *hextoobj(const char *str, int *sp){ + char *buf, mbuf[3]; + int len, i, j; + len = strlen(str); + if(!(buf = malloc(len + 1))) return NULL; + j = 0; + for(i = 0; i < len; i += 2){ + while(strchr(" \n\r\t\f\v", str[i])){ + i++; + } + if((mbuf[0] = str[i]) == '\0') break; + if((mbuf[1] = str[i+1]) == '\0') break; + mbuf[2] = '\0'; + buf[j++] = (char)strtol(mbuf, NULL, 16); + } + buf[j] = '\0'; + *sp = j; + return buf; +} + + +/* create a integer object from a decimal string */ +char *dectoiobj(const char *str, int *sp){ + char *buf; + int num; + num = atoi(str); + if(!(buf = malloc(sizeof(int)))) return NULL; + *(int *)buf = num; + *sp = sizeof(int); + return buf; +} + + +/* parse arguments of create command */ +int runcreate(int argc, char **argv){ + char *name; + int i, sb, bnum, rv; + name = NULL; + sb = FALSE; + bnum = -1; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-s")){ + sb = TRUE; + } else if(!strcmp(argv[i], "-bnum")){ + if(++i >= argc) usage(); + bnum = atoi(argv[i]); + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = docreate(name, bnum, sb); + return rv; +} + + +/* parse arguments of put command */ +int runput(int argc, char **argv){ + char *name, *key, *val, *kbuf, *vbuf; + int i, kx, ki, vx, vi, vf, align, ksiz, vsiz, rv; + int dmode; + name = NULL; + kx = FALSE; + ki = FALSE; + vx = FALSE; + vi = FALSE; + vf = FALSE; + align = ALIGNSIZ; + key = NULL; + val = NULL; + dmode = DP_DOVER; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else if(!strcmp(argv[i], "-vx")){ + vx = TRUE; + } else if(!strcmp(argv[i], "-vi")){ + vi = TRUE; + } else if(!strcmp(argv[i], "-vf")){ + vf = TRUE; + } else if(!strcmp(argv[i], "-keep")){ + dmode = DP_DKEEP; + } else if(!strcmp(argv[i], "-cat")){ + dmode = DP_DCAT; + } else if(!strcmp(argv[i], "-na")){ + align = 0; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else if(!val){ + val = argv[i]; + } else { + usage(); + } + } + if(!name || !key || !val) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(vx){ + vbuf = hextoobj(val, &vsiz); + } else if(vi){ + vbuf = dectoiobj(val, &vsiz); + } else if(vf){ + vbuf = cbreadfile(val, &vsiz); + } else { + vbuf = cbmemdup(val, -1); + vsiz = -1; + } + if(kbuf && vbuf){ + rv = doput(name, kbuf, ksiz, vbuf, vsiz, dmode, align); + } else { + if(vf){ + fprintf(stderr, "%s: %s: cannot read\n", progname, val); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + } + rv = 1; + } + free(kbuf); + free(vbuf); + return rv; +} + + +/* parse arguments of out command */ +int runout(int argc, char **argv){ + char *name, *key, *kbuf; + int i, kx, ki, ksiz, rv; + name = NULL; + kx = FALSE; + ki = FALSE; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(kbuf){ + rv = doout(name, kbuf, ksiz); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* parse arguments of get command */ +int runget(int argc, char **argv){ + char *name, *key, *kbuf; + int i, opts, kx, ki, ox, nb, start, max, ksiz, rv; + name = NULL; + opts = 0; + kx = FALSE; + ki = FALSE; + ox = FALSE; + nb = FALSE; + start = 0; + max = -1; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-nl")){ + opts |= DP_ONOLCK; + } else if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else if(!strcmp(argv[i], "-n")){ + nb = TRUE; + } else if(!strcmp(argv[i], "-start")){ + if(++i >= argc) usage(); + start = atoi(argv[i]); + } else if(!strcmp(argv[i], "-max")){ + if(++i >= argc) usage(); + max = atoi(argv[i]); + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key || start < 0) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(kbuf){ + rv = doget(name, opts, kbuf, ksiz, start, max, ox, nb); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* parse arguments of list command */ +int runlist(int argc, char **argv){ + char *name; + int i, opts, kb, vb, ox, rv; + name = NULL; + opts = 0; + kb = FALSE; + vb = FALSE; + ox = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-nl")){ + opts |= DP_ONOLCK; + } else if(!strcmp(argv[i], "-k")){ + kb = TRUE; + } else if(!strcmp(argv[i], "-v")){ + vb = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dolist(name, opts, kb, vb, ox); + return rv; +} + + +/* parse arguments of optimize command */ +int runoptimize(int argc, char **argv){ + char *name; + int i, bnum, align, rv; + name = NULL; + bnum = -1; + align = ALIGNSIZ; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-bnum")){ + if(++i >= argc) usage(); + bnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-na")){ + align = 0; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dooptimize(name, bnum, align); + return rv; +} + + +/* parse arguments of inform command */ +int runinform(int argc, char **argv){ + char *name; + int i, opts, rv; + name = NULL; + opts = 0; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-nl")){ + opts |= DP_ONOLCK; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doinform(name, opts); + return rv; +} + + +/* parse arguments of remove command */ +int runremove(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doremove(name); + return rv; +} + + +/* parse arguments of repair command */ +int runrepair(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dorepair(name); + return rv; +} + + +/* parse arguments of exportdb command */ +int runexportdb(int argc, char **argv){ + char *name, *file; + int i, rv; + name = NULL; + file = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + if(!name || !file) usage(); + rv = doexportdb(name, file); + return rv; +} + + +/* parse arguments of importdb command */ +int runimportdb(int argc, char **argv){ + char *name, *file; + int i, bnum, rv; + name = NULL; + file = NULL; + bnum = -1; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-bnum")){ + if(++i >= argc) usage(); + bnum = atoi(argv[i]); + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + if(!name || !file) usage(); + rv = doimportdb(name, file, bnum); + return rv; +} + + +/* parse arguments of snaffle command */ +int runsnaffle(int argc, char **argv){ + char *name, *key, *kbuf; + int i, kx, ki, ox, nb, start, max, ksiz, rv; + name = NULL; + kx = FALSE; + ki = FALSE; + ox = FALSE; + nb = FALSE; + start = 0; + max = -1; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else if(!strcmp(argv[i], "-n")){ + nb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key || start < 0) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(kbuf){ + rv = dosnaffle(name, kbuf, ksiz, ox, nb); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* print an object */ +void printobj(const char *obj, int size){ + int i; + for(i = 0; i < size; i++){ + putchar(obj[i]); + } +} + + +/* print an object as a hexadecimal string */ +void printobjhex(const char *obj, int size){ + int i; + for(i = 0; i < size; i++){ + printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); + } +} + + +/* perform create command */ +int docreate(const char *name, int bnum, int sparse){ + DEPOT *depot; + int omode; + omode = DP_OWRITER | DP_OCREAT | DP_OTRUNC | (sparse ? DP_OSPARSE : 0); + if(!(depot = dpopen(name, omode, bnum))){ + pdperror(name); + return 1; + } + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform put command */ +int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, + int dmode, int align){ + DEPOT *depot; + if(!(depot = dpopen(name, DP_OWRITER, -1))){ + pdperror(name); + return 1; + } + if(align > 0 && !dpsetalign(depot, align)){ + pdperror(name); + dpclose(depot); + return 1; + } + if(!dpput(depot, kbuf, ksiz, vbuf, vsiz, dmode)){ + pdperror(name); + dpclose(depot); + return 1; + } + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform out command */ +int doout(const char *name, const char *kbuf, int ksiz){ + DEPOT *depot; + if(!(depot = dpopen(name, DP_OWRITER, -1))){ + pdperror(name); + return 1; + } + if(!dpout(depot, kbuf, ksiz)){ + pdperror(name); + dpclose(depot); + return 1; + } + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform get command */ +int doget(const char *name, int opts, const char *kbuf, int ksiz, + int start, int max, int ox, int nb){ + DEPOT *depot; + char *vbuf; + int vsiz; + if(!(depot = dpopen(name, DP_OREADER | opts, -1))){ + pdperror(name); + return 1; + } + if(!(vbuf = dpget(depot, kbuf, ksiz, start, max, &vsiz))){ + pdperror(name); + dpclose(depot); + return 1; + } + if(ox){ + printobjhex(vbuf, vsiz); + } else { + printobj(vbuf, vsiz); + } + free(vbuf); + if(!nb) putchar('\n'); + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform list command */ +int dolist(const char *name, int opts, int kb, int vb, int ox){ + DEPOT *depot; + char *kbuf, *vbuf; + int ksiz, vsiz; + if(!(depot = dpopen(name, DP_OREADER | opts, -1))){ + pdperror(name); + return 1; + } + dpiterinit(depot); + while((kbuf = dpiternext(depot, &ksiz)) != NULL){ + if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz))){ + pdperror(name); + free(kbuf); + break; + } + if(ox){ + if(!vb) printobjhex(kbuf, ksiz); + if(!kb && !vb) putchar('\t'); + if(!kb) printobjhex(vbuf, vsiz); + } else { + if(!vb) printobj(kbuf, ksiz); + if(!kb && !vb) putchar('\t'); + if(!kb) printobj(vbuf, vsiz); + } + putchar('\n'); + free(vbuf); + free(kbuf); + } + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform optimize command */ +int dooptimize(const char *name, int bnum, int align){ + DEPOT *depot; + if(!(depot = dpopen(name, DP_OWRITER, -1))){ + pdperror(name); + return 1; + } + if(align > 0 && !dpsetalign(depot, align)){ + pdperror(name); + dpclose(depot); + return 1; + } + if(!dpoptimize(depot, bnum)){ + pdperror(name); + dpclose(depot); + return 1; + } + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform inform command */ +int doinform(const char *name, int opts){ + DEPOT *depot; + char *tmp; + if(!(depot = dpopen(name, DP_OREADER | opts, -1))){ + pdperror(name); + return 1; + } + tmp = dpname(depot); + printf("name: %s\n", tmp ? tmp : "(null)"); + free(tmp); + printf("file size: %d\n", dpfsiz(depot)); + printf("all buckets: %d\n", dpbnum(depot)); + printf("used buckets: %d\n", dpbusenum(depot)); + printf("records: %d\n", dprnum(depot)); + printf("inode number: %d\n", dpinode(depot)); + printf("modified time: %.0f\n", (double)dpmtime(depot)); + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform remove command */ +int doremove(const char *name){ + if(!dpremove(name)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform repair command */ +int dorepair(const char *name){ + if(!dprepair(name)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform exportdb command */ +int doexportdb(const char *name, const char *file){ + DEPOT *depot; + if(!(depot = dpopen(name, DP_OREADER, -1))){ + pdperror(name); + return 1; + } + if(!dpexportdb(depot, file)){ + pdperror(name); + dpclose(depot); + return 1; + } + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform importdb command */ +int doimportdb(const char *name, const char *file, int bnum){ + DEPOT *depot; + if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, bnum))){ + pdperror(name); + return 1; + } + if(!dpimportdb(depot, file)){ + pdperror(name); + dpclose(depot); + return 1; + } + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform snaffle command */ +int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb){ + char *vbuf; + int vsiz; + if(!(vbuf = dpsnaffle(name, kbuf, ksiz, &vsiz))){ + pdperror(name); + return 1; + } + if(ox){ + printobjhex(vbuf, vsiz); + } else { + printobj(vbuf, vsiz); + } + free(vbuf); + if(!nb) putchar('\n'); + return 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/dptest.c =================================================================== --- box/trunk/qdbm/dptest.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/dptest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,836 +0,0 @@ -/************************************************************************************************* - * Test cases of Depot - * 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 -#include -#include -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define RECBUFSIZ 32 /* buffer for records */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -int runwrite(int argc, char **argv); -int runread(int argc, char **argv); -int runrcat(int argc, char **argv); -int runcombo(int argc, char **argv); -int runwicked(int argc, char **argv); -int printfflush(const char *format, ...); -void pdperror(const char *name); -int myrand(void); -int dowrite(const char *name, int rnum, int bnum, int sparse); -int doread(const char *name, int wb); -int dorcat(const char *name, int rnum, int bnum, int pnum, int align, int fbpsiz, int cb); -int docombo(const char *name); -int dowicked(const char *name, int rnum, int cb); - - -/* main routine */ -int main(int argc, char **argv){ - char *env; - int rv; - cbstdiobin(); - if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "write")){ - rv = runwrite(argc, argv); - } else if(!strcmp(argv[1], "read")){ - rv = runread(argc, argv); - } else if(!strcmp(argv[1], "rcat")){ - rv = runrcat(argc, argv); - } else if(!strcmp(argv[1], "combo")){ - rv = runcombo(argc, argv); - } else if(!strcmp(argv[1], "wicked")){ - rv = runwicked(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: test cases for Depot\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s write [-s] name rnum bnum\n", progname); - fprintf(stderr, " %s read [-wb] name\n", progname); - fprintf(stderr, " %s rcat [-c] name rnum bnum pnum align fbpsiz\n", progname); - fprintf(stderr, " %s combo name\n", progname); - fprintf(stderr, " %s wicked [-c] name rnum\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of write command */ -int runwrite(int argc, char **argv){ - char *name, *rstr, *bstr; - int i, rnum, bnum, sb, rv; - name = NULL; - rstr = NULL; - bstr = NULL; - rnum = 0; - bnum = 0; - sb = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-s")){ - sb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else if(!bstr){ - bstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr || !bstr) usage(); - rnum = atoi(rstr); - bnum = atoi(bstr); - if(rnum < 1 || bnum < 1) usage(); - rv = dowrite(name, rnum, bnum, sb); - return rv; -} - - -/* parse arguments of read command */ -int runread(int argc, char **argv){ - char *name; - int i, wb, rv; - name = NULL; - wb = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-wb")){ - wb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doread(name, wb); - return rv; -} - - -/* parse arguments of rcat command */ -int runrcat(int argc, char **argv){ - char *name, *rstr, *bstr, *pstr, *astr, *fstr; - int i, rnum, bnum, pnum, align, fbpsiz, cb, rv; - name = NULL; - rstr = NULL; - bstr = NULL; - pstr = NULL; - astr = NULL; - fstr = NULL; - rnum = 0; - bnum = 0; - pnum = 0; - align = 0; - fbpsiz = 0; - cb = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-c")){ - cb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else if(!bstr){ - bstr = argv[i]; - } else if(!pstr){ - pstr = argv[i]; - } else if(!astr){ - astr = argv[i]; - } else if(!fstr){ - fstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr || !bstr || !pstr || !astr || !fstr) usage(); - rnum = atoi(rstr); - bnum = atoi(bstr); - pnum = atoi(pstr); - align = atoi(astr); - fbpsiz= atoi(fstr); - if(rnum < 1 || bnum < 1 || pnum < 1 || fbpsiz < 0) usage(); - rv = dorcat(name, rnum, bnum, pnum, align, fbpsiz, cb); - return rv; -} - - -/* parse arguments of combo command */ -int runcombo(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = docombo(name); - return rv; -} - - -/* parse arguments of wicked command */ -int runwicked(int argc, char **argv){ - char *name, *rstr; - int i, rnum, cb, rv; - name = NULL; - rstr = NULL; - rnum = 0; - cb = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-c")){ - cb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = dowicked(name, rnum, cb); - return rv; -} - - -/* print formatted string and flush the buffer */ -int printfflush(const char *format, ...){ - va_list ap; - int rv; - va_start(ap, format); - rv = vprintf(format, ap); - if(fflush(stdout) == EOF) rv = -1; - va_end(ap); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* pseudo random number generator */ -int myrand(void){ - static int cnt = 0; - if(cnt == 0) srand(time(NULL)); - return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; -} - - -/* perform write command */ -int dowrite(const char *name, int rnum, int bnum, int sparse){ - DEPOT *depot; - int i, omode, err, len; - char buf[RECBUFSIZ]; - printfflush("\n name=%s rnum=%d bnum=%d s=%d\n\n", name, rnum, bnum, sparse); - /* open a database */ - omode = DP_OWRITER | DP_OCREAT | DP_OTRUNC | (sparse ? DP_OSPARSE : 0); - if(!(depot = dpopen(name, omode, bnum))){ - pdperror(name); - return 1; - } - err = FALSE; - /* loop for each record */ - for(i = 1; i <= rnum; i++){ - /* store a record */ - len = sprintf(buf, "%08d", i); - if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ - pdperror(name); - err = TRUE; - break; - } - /* print progression */ - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform read command */ -int doread(const char *name, int wb){ - DEPOT *depot; - int i, rnum, err, len; - char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; - printfflush("\n name=%s wb=%d\n\n", name, wb); - /* open a database */ - if(!(depot = dpopen(name, DP_OREADER, -1))){ - pdperror(name); - return 1; - } - /* get the number of records */ - rnum = dprnum(depot); - err = FALSE; - /* loop for each record */ - for(i = 1; i <= rnum; i++){ - /* retrieve a record */ - len = sprintf(buf, "%08d", i); - if(wb){ - if(dpgetwb(depot, buf, len, 0, RECBUFSIZ, vbuf) == -1){ - pdperror(name); - err = TRUE; - break; - } - } else { - if(!(val = dpget(depot, buf, len, 0, -1, NULL))){ - pdperror(name); - err = TRUE; - break; - } - free(val); - } - /* print progression */ - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform rcat command */ -int dorcat(const char *name, int rnum, int bnum, int pnum, int align, int fbpsiz, int cb){ - DEPOT *depot; - CBMAP *map; - int i, err, len, ksiz, vsiz, rsiz; - const char *kbuf, *vbuf; - char buf[RECBUFSIZ], *rbuf; - printfflush("\n name=%s rnum=%d bnum=%d pnum=%d align=%d" - " fbpsiz=%d c=%d\n\n", name, rnum, bnum, pnum, align, fbpsiz, cb); - if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, bnum))){ - pdperror(name); - return 1; - } - if(!dpsetalign(depot, align) || !dpsetfbpsiz(depot, fbpsiz)){ - pdperror(name); - dpclose(depot); - return 1; - } - map = NULL; - if(cb) map = cbmapopen(); - err = FALSE; - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", myrand() % pnum + 1); - if(!dpput(depot, buf, len, buf, len, DP_DCAT)){ - pdperror(name); - err = TRUE; - break; - } - if(map) cbmapputcat(map, buf, len, buf, len); - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d: fsiz=%d rnum=%d)\n", i, dpfsiz(depot), dprnum(depot)); - } - } - } - if(map){ - printfflush("Matching records ... "); - cbmapiterinit(map); - while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ - vbuf = cbmapget(map, kbuf, ksiz, &vsiz); - if(!(rbuf = dpget(depot, kbuf, ksiz, 0, -1, &rsiz))){ - pdperror(name); - err = TRUE; - break; - } - if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){ - fprintf(stderr, "%s: %s: unmatched record\n", progname, name); - free(rbuf); - err = TRUE; - break; - } - free(rbuf); - } - cbmapclose(map); - if(!err) printfflush("ok\n"); - } - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform combo command */ -int docombo(const char *name){ - DEPOT *depot; - char buf[RECBUFSIZ], wbuf[RECBUFSIZ], *vbuf; - int i, len, wlen, vsiz; - printfflush("\n name=%s\n\n", name); - printfflush("Creating a database with bnum 3 ... "); - if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 3))){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Setting alignment as 16 ... "); - if(!dpsetalign(depot, 16)){ - pdperror(name); - dpclose(depot); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 20 records ... "); - for(i = 1; i <= 20; i++){ - len = sprintf(buf, "%08d", i); - if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ - pdperror(name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking records ... "); - for(i = 1; i <= 20; i++){ - len = sprintf(buf, "%08d", i); - if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ - pdperror(name); - dpclose(depot); - return 1; - } - free(vbuf); - if(vsiz != dpvsiz(depot, buf, len)){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Overwriting top 10 records without moving rooms ... "); - for(i = 1; i <= 10; i++){ - len = sprintf(buf, "%08d", i); - if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ - pdperror(name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Overwriting top 5 records with moving rooms ... "); - for(i = 1; i <= 5; i++){ - len = sprintf(buf, "%08d", i); - wlen = sprintf(wbuf, "%024d", i); - if(!dpput(depot, buf, len, wbuf, wlen, DP_DOVER)){ - pdperror(name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); - for(i = 1; i <= 15; i++){ - len = sprintf(buf, "%08d", i); - wlen = sprintf(wbuf, "========================"); - if(!dpput(depot, buf, len, wbuf, wlen, DP_DCAT)){ - pdperror(name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking records ... "); - for(i = 1; i <= 20; i++){ - len = sprintf(buf, "%08d", i); - if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ - pdperror(name); - dpclose(depot); - return 1; - } - free(vbuf); - if(vsiz != dpvsiz(depot, buf, len)){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Deleting top 10 records ... "); - for(i = 1; i <= 10; i++){ - len = sprintf(buf, "%08d", i); - if(!dpout(depot, buf, len)){ - pdperror(name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking deleted records ... "); - for(i = 1; i <= 10; i++){ - len = sprintf(buf, "%08d", i); - vbuf = dpget(depot, buf, len, 0, -1, &vsiz); - free(vbuf); - if(vbuf || dpecode != DP_ENOITEM){ - fprintf(stderr, "%s: %s: deleting failed\n", progname, name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); - for(i = 1; i <= 15; i++){ - len = sprintf(buf, "%08d", i); - wlen = sprintf(wbuf, "========================"); - if(!dpput(depot, buf, len, wbuf, wlen, DP_DCAT)){ - pdperror(name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking records ... "); - for(i = 1; i <= 20; i++){ - len = sprintf(buf, "%08d", i); - if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ - pdperror(name); - dpclose(depot); - return 1; - } - free(vbuf); - if(vsiz != dpvsiz(depot, buf, len)){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Optimizing the database ... "); - if(!dpoptimize(depot, -1)){ - pdperror(name); - dpclose(depot); - return 1; - } - printfflush("ok\n"); - printfflush("Checking records ... "); - for(i = 1; i <= 20; i++){ - len = sprintf(buf, "%08d", i); - if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ - pdperror(name); - dpclose(depot); - return 1; - } - free(vbuf); - if(vsiz != dpvsiz(depot, buf, len)){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Closing the database ... "); - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Creating a database with bnum 1000000 ... "); - if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 1000000))){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 1000 records ... "); - for(i = 1; i <= 1000; i++){ - len = sprintf(buf, "%08d", i); - if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ - pdperror(name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Adding 64 records ... "); - for(i = 1; i <= 1000; i++){ - len = sprintf(buf, "%o", i); - if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ - pdperror(name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Syncing the database ... "); - if(!dpsync(depot)){ - pdperror(name); - dpclose(depot); - return 1; - } - printfflush("ok\n"); - printfflush("Retrieving records directly ... "); - for(i = 1; i <= 64; i++){ - len = sprintf(buf, "%o", i); - if(!(vbuf = dpsnaffle(name, buf, len, &vsiz))){ - pdperror(name); - dpclose(depot); - return 1; - } - if(strcmp(vbuf, buf)){ - fprintf(stderr, "%s: %s: invalid content\n", progname, name); - free(vbuf); - dpclose(depot); - return 1; - } - free(vbuf); - if(vsiz != dpvsiz(depot, buf, len)){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - dpclose(depot); - return 1; - } - } - printfflush("ok\n"); - printfflush("Optimizing the database ... "); - if(!dpoptimize(depot, -1)){ - pdperror(name); - dpclose(depot); - return 1; - } - printfflush("ok\n"); - printfflush("Closing the database ... "); - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("all ok\n\n"); - return 0; -} - - -/* perform wicked command */ -int dowicked(const char *name, int rnum, int cb){ - DEPOT *depot; - CBMAP *map; - int i, len, err, align, mksiz, mvsiz, rsiz; - const char *mkbuf, *mvbuf; - char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; - printfflush("\n name=%s rnum=%d\n\n", name, rnum); - err = FALSE; - if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, rnum / 10))){ - pdperror(name); - return 1; - } - if(!dpsetalign(depot, 16) || !dpsetfbpsiz(depot, 256)){ - pdperror(name); - err = TRUE; - } - map = NULL; - if(cb) map = cbmapopen(); - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", myrand() % rnum + 1); - switch(myrand() % 16){ - case 0: - putchar('O'); - if(!dpput(depot, buf, len, buf, len, DP_DOVER)) err = TRUE; - if(map) cbmapput(map, buf, len, buf, len, TRUE); - break; - case 1: - putchar('K'); - if(!dpput(depot, buf, len, buf, len, DP_DKEEP) && dpecode != DP_EKEEP) err = TRUE; - if(map) cbmapput(map, buf, len, buf, len, FALSE); - break; - case 2: - putchar('D'); - if(!dpout(depot, buf, len) && dpecode != DP_ENOITEM) err = TRUE; - if(map) cbmapout(map, buf, len); - break; - case 3: - putchar('G'); - if(dpgetwb(depot, buf, len, 2, RECBUFSIZ, vbuf) == -1 && dpecode != DP_ENOITEM) err = TRUE; - break; - case 4: - putchar('V'); - if(dpvsiz(depot, buf, len) == -1 && dpecode != DP_ENOITEM) err = TRUE; - break; - default: - putchar('C'); - if(!dpput(depot, buf, len, buf, len, DP_DCAT)) err = TRUE; - if(map) cbmapputcat(map, buf, len, buf, len); - break; - } - if(i % 50 == 0) printfflush(" (%08d)\n", i); - if(!err && rnum > 100 && myrand() % (rnum / 100) == 0){ - if(myrand() % 10 == 0){ - align = (myrand() % 4 + 1) * -1; - } else { - align = myrand() % 32; - } - if(!dpsetalign(depot, align)) err = TRUE; - } - if(err){ - pdperror(name); - break; - } - } - if(!dpoptimize(depot, -1)){ - pdperror(name); - err = TRUE; - } - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", i); - if(!dpput(depot, buf, len, ":", -1, DP_DCAT)){ - pdperror(name); - err = TRUE; - break; - } - if(map) cbmapputcat(map, buf, len, ":", -1); - putchar(':'); - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - if(!dpoptimize(depot, -1)){ - pdperror(name); - err = TRUE; - } - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", i); - if(!(val = dpget(depot, buf, len, 0, -1, NULL))){ - pdperror(name); - err = TRUE; - break; - } - free(val); - putchar('='); - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - if(!dpiterinit(depot)){ - pdperror(name); - err = TRUE; - } - for(i = 1; i <= rnum; i++){ - if(!(val = dpiternext(depot, NULL))){ - pdperror(name); - err = TRUE; - break; - } - free(val); - putchar('@'); - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - if(map){ - printfflush("Matching records ... "); - cbmapiterinit(map); - while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){ - mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz); - if(!(val = dpget(depot, mkbuf, mksiz, 0, -1, &rsiz))){ - pdperror(name); - err = TRUE; - break; - } - if(rsiz != mvsiz || memcmp(val, mvbuf, rsiz)){ - fprintf(stderr, "%s: %s: unmatched record\n", progname, name); - free(val); - err = TRUE; - break; - } - free(val); - } - cbmapclose(map); - if(!err) printfflush("ok\n"); - } - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/dptest.c (from rev 2716, box/trunk/qdbm/dptest.c) =================================================================== --- box/trunk/qdbm/dptest.c (rev 0) +++ box/trunk/qdbm/dptest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,836 @@ +/************************************************************************************************* + * Test cases of Depot + * 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 +#include +#include +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define RECBUFSIZ 32 /* buffer for records */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +int runwrite(int argc, char **argv); +int runread(int argc, char **argv); +int runrcat(int argc, char **argv); +int runcombo(int argc, char **argv); +int runwicked(int argc, char **argv); +int printfflush(const char *format, ...); +void pdperror(const char *name); +int myrand(void); +int dowrite(const char *name, int rnum, int bnum, int sparse); +int doread(const char *name, int wb); +int dorcat(const char *name, int rnum, int bnum, int pnum, int align, int fbpsiz, int cb); +int docombo(const char *name); +int dowicked(const char *name, int rnum, int cb); + + +/* main routine */ +int main(int argc, char **argv){ + char *env; + int rv; + cbstdiobin(); + if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "write")){ + rv = runwrite(argc, argv); + } else if(!strcmp(argv[1], "read")){ + rv = runread(argc, argv); + } else if(!strcmp(argv[1], "rcat")){ + rv = runrcat(argc, argv); + } else if(!strcmp(argv[1], "combo")){ + rv = runcombo(argc, argv); + } else if(!strcmp(argv[1], "wicked")){ + rv = runwicked(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: test cases for Depot\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s write [-s] name rnum bnum\n", progname); + fprintf(stderr, " %s read [-wb] name\n", progname); + fprintf(stderr, " %s rcat [-c] name rnum bnum pnum align fbpsiz\n", progname); + fprintf(stderr, " %s combo name\n", progname); + fprintf(stderr, " %s wicked [-c] name rnum\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of write command */ +int runwrite(int argc, char **argv){ + char *name, *rstr, *bstr; + int i, rnum, bnum, sb, rv; + name = NULL; + rstr = NULL; + bstr = NULL; + rnum = 0; + bnum = 0; + sb = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-s")){ + sb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else if(!bstr){ + bstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr || !bstr) usage(); + rnum = atoi(rstr); + bnum = atoi(bstr); + if(rnum < 1 || bnum < 1) usage(); + rv = dowrite(name, rnum, bnum, sb); + return rv; +} + + +/* parse arguments of read command */ +int runread(int argc, char **argv){ + char *name; + int i, wb, rv; + name = NULL; + wb = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-wb")){ + wb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doread(name, wb); + return rv; +} + + +/* parse arguments of rcat command */ +int runrcat(int argc, char **argv){ + char *name, *rstr, *bstr, *pstr, *astr, *fstr; + int i, rnum, bnum, pnum, align, fbpsiz, cb, rv; + name = NULL; + rstr = NULL; + bstr = NULL; + pstr = NULL; + astr = NULL; + fstr = NULL; + rnum = 0; + bnum = 0; + pnum = 0; + align = 0; + fbpsiz = 0; + cb = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-c")){ + cb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else if(!bstr){ + bstr = argv[i]; + } else if(!pstr){ + pstr = argv[i]; + } else if(!astr){ + astr = argv[i]; + } else if(!fstr){ + fstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr || !bstr || !pstr || !astr || !fstr) usage(); + rnum = atoi(rstr); + bnum = atoi(bstr); + pnum = atoi(pstr); + align = atoi(astr); + fbpsiz= atoi(fstr); + if(rnum < 1 || bnum < 1 || pnum < 1 || fbpsiz < 0) usage(); + rv = dorcat(name, rnum, bnum, pnum, align, fbpsiz, cb); + return rv; +} + + +/* parse arguments of combo command */ +int runcombo(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = docombo(name); + return rv; +} + + +/* parse arguments of wicked command */ +int runwicked(int argc, char **argv){ + char *name, *rstr; + int i, rnum, cb, rv; + name = NULL; + rstr = NULL; + rnum = 0; + cb = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-c")){ + cb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = dowicked(name, rnum, cb); + return rv; +} + + +/* print formatted string and flush the buffer */ +int printfflush(const char *format, ...){ + va_list ap; + int rv; + va_start(ap, format); + rv = vprintf(format, ap); + if(fflush(stdout) == EOF) rv = -1; + va_end(ap); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* pseudo random number generator */ +int myrand(void){ + static int cnt = 0; + if(cnt == 0) srand(time(NULL)); + return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; +} + + +/* perform write command */ +int dowrite(const char *name, int rnum, int bnum, int sparse){ + DEPOT *depot; + int i, omode, err, len; + char buf[RECBUFSIZ]; + printfflush("\n name=%s rnum=%d bnum=%d s=%d\n\n", name, rnum, bnum, sparse); + /* open a database */ + omode = DP_OWRITER | DP_OCREAT | DP_OTRUNC | (sparse ? DP_OSPARSE : 0); + if(!(depot = dpopen(name, omode, bnum))){ + pdperror(name); + return 1; + } + err = FALSE; + /* loop for each record */ + for(i = 1; i <= rnum; i++){ + /* store a record */ + len = sprintf(buf, "%08d", i); + if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ + pdperror(name); + err = TRUE; + break; + } + /* print progression */ + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform read command */ +int doread(const char *name, int wb){ + DEPOT *depot; + int i, rnum, err, len; + char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; + printfflush("\n name=%s wb=%d\n\n", name, wb); + /* open a database */ + if(!(depot = dpopen(name, DP_OREADER, -1))){ + pdperror(name); + return 1; + } + /* get the number of records */ + rnum = dprnum(depot); + err = FALSE; + /* loop for each record */ + for(i = 1; i <= rnum; i++){ + /* retrieve a record */ + len = sprintf(buf, "%08d", i); + if(wb){ + if(dpgetwb(depot, buf, len, 0, RECBUFSIZ, vbuf) == -1){ + pdperror(name); + err = TRUE; + break; + } + } else { + if(!(val = dpget(depot, buf, len, 0, -1, NULL))){ + pdperror(name); + err = TRUE; + break; + } + free(val); + } + /* print progression */ + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform rcat command */ +int dorcat(const char *name, int rnum, int bnum, int pnum, int align, int fbpsiz, int cb){ + DEPOT *depot; + CBMAP *map; + int i, err, len, ksiz, vsiz, rsiz; + const char *kbuf, *vbuf; + char buf[RECBUFSIZ], *rbuf; + printfflush("\n name=%s rnum=%d bnum=%d pnum=%d align=%d" + " fbpsiz=%d c=%d\n\n", name, rnum, bnum, pnum, align, fbpsiz, cb); + if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, bnum))){ + pdperror(name); + return 1; + } + if(!dpsetalign(depot, align) || !dpsetfbpsiz(depot, fbpsiz)){ + pdperror(name); + dpclose(depot); + return 1; + } + map = NULL; + if(cb) map = cbmapopen(); + err = FALSE; + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", myrand() % pnum + 1); + if(!dpput(depot, buf, len, buf, len, DP_DCAT)){ + pdperror(name); + err = TRUE; + break; + } + if(map) cbmapputcat(map, buf, len, buf, len); + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d: fsiz=%d rnum=%d)\n", i, dpfsiz(depot), dprnum(depot)); + } + } + } + if(map){ + printfflush("Matching records ... "); + cbmapiterinit(map); + while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ + vbuf = cbmapget(map, kbuf, ksiz, &vsiz); + if(!(rbuf = dpget(depot, kbuf, ksiz, 0, -1, &rsiz))){ + pdperror(name); + err = TRUE; + break; + } + if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){ + fprintf(stderr, "%s: %s: unmatched record\n", progname, name); + free(rbuf); + err = TRUE; + break; + } + free(rbuf); + } + cbmapclose(map); + if(!err) printfflush("ok\n"); + } + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform combo command */ +int docombo(const char *name){ + DEPOT *depot; + char buf[RECBUFSIZ], wbuf[RECBUFSIZ], *vbuf; + int i, len, wlen, vsiz; + printfflush("\n name=%s\n\n", name); + printfflush("Creating a database with bnum 3 ... "); + if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 3))){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Setting alignment as 16 ... "); + if(!dpsetalign(depot, 16)){ + pdperror(name); + dpclose(depot); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 20 records ... "); + for(i = 1; i <= 20; i++){ + len = sprintf(buf, "%08d", i); + if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ + pdperror(name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking records ... "); + for(i = 1; i <= 20; i++){ + len = sprintf(buf, "%08d", i); + if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ + pdperror(name); + dpclose(depot); + return 1; + } + free(vbuf); + if(vsiz != dpvsiz(depot, buf, len)){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Overwriting top 10 records without moving rooms ... "); + for(i = 1; i <= 10; i++){ + len = sprintf(buf, "%08d", i); + if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ + pdperror(name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Overwriting top 5 records with moving rooms ... "); + for(i = 1; i <= 5; i++){ + len = sprintf(buf, "%08d", i); + wlen = sprintf(wbuf, "%024d", i); + if(!dpput(depot, buf, len, wbuf, wlen, DP_DOVER)){ + pdperror(name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); + for(i = 1; i <= 15; i++){ + len = sprintf(buf, "%08d", i); + wlen = sprintf(wbuf, "========================"); + if(!dpput(depot, buf, len, wbuf, wlen, DP_DCAT)){ + pdperror(name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking records ... "); + for(i = 1; i <= 20; i++){ + len = sprintf(buf, "%08d", i); + if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ + pdperror(name); + dpclose(depot); + return 1; + } + free(vbuf); + if(vsiz != dpvsiz(depot, buf, len)){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Deleting top 10 records ... "); + for(i = 1; i <= 10; i++){ + len = sprintf(buf, "%08d", i); + if(!dpout(depot, buf, len)){ + pdperror(name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking deleted records ... "); + for(i = 1; i <= 10; i++){ + len = sprintf(buf, "%08d", i); + vbuf = dpget(depot, buf, len, 0, -1, &vsiz); + free(vbuf); + if(vbuf || dpecode != DP_ENOITEM){ + fprintf(stderr, "%s: %s: deleting failed\n", progname, name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); + for(i = 1; i <= 15; i++){ + len = sprintf(buf, "%08d", i); + wlen = sprintf(wbuf, "========================"); + if(!dpput(depot, buf, len, wbuf, wlen, DP_DCAT)){ + pdperror(name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking records ... "); + for(i = 1; i <= 20; i++){ + len = sprintf(buf, "%08d", i); + if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ + pdperror(name); + dpclose(depot); + return 1; + } + free(vbuf); + if(vsiz != dpvsiz(depot, buf, len)){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Optimizing the database ... "); + if(!dpoptimize(depot, -1)){ + pdperror(name); + dpclose(depot); + return 1; + } + printfflush("ok\n"); + printfflush("Checking records ... "); + for(i = 1; i <= 20; i++){ + len = sprintf(buf, "%08d", i); + if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ + pdperror(name); + dpclose(depot); + return 1; + } + free(vbuf); + if(vsiz != dpvsiz(depot, buf, len)){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Closing the database ... "); + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Creating a database with bnum 1000000 ... "); + if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 1000000))){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 1000 records ... "); + for(i = 1; i <= 1000; i++){ + len = sprintf(buf, "%08d", i); + if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ + pdperror(name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Adding 64 records ... "); + for(i = 1; i <= 1000; i++){ + len = sprintf(buf, "%o", i); + if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ + pdperror(name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Syncing the database ... "); + if(!dpsync(depot)){ + pdperror(name); + dpclose(depot); + return 1; + } + printfflush("ok\n"); + printfflush("Retrieving records directly ... "); + for(i = 1; i <= 64; i++){ + len = sprintf(buf, "%o", i); + if(!(vbuf = dpsnaffle(name, buf, len, &vsiz))){ + pdperror(name); + dpclose(depot); + return 1; + } + if(strcmp(vbuf, buf)){ + fprintf(stderr, "%s: %s: invalid content\n", progname, name); + free(vbuf); + dpclose(depot); + return 1; + } + free(vbuf); + if(vsiz != dpvsiz(depot, buf, len)){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + dpclose(depot); + return 1; + } + } + printfflush("ok\n"); + printfflush("Optimizing the database ... "); + if(!dpoptimize(depot, -1)){ + pdperror(name); + dpclose(depot); + return 1; + } + printfflush("ok\n"); + printfflush("Closing the database ... "); + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("all ok\n\n"); + return 0; +} + + +/* perform wicked command */ +int dowicked(const char *name, int rnum, int cb){ + DEPOT *depot; + CBMAP *map; + int i, len, err, align, mksiz, mvsiz, rsiz; + const char *mkbuf, *mvbuf; + char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; + printfflush("\n name=%s rnum=%d\n\n", name, rnum); + err = FALSE; + if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, rnum / 10))){ + pdperror(name); + return 1; + } + if(!dpsetalign(depot, 16) || !dpsetfbpsiz(depot, 256)){ + pdperror(name); + err = TRUE; + } + map = NULL; + if(cb) map = cbmapopen(); + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", myrand() % rnum + 1); + switch(myrand() % 16){ + case 0: + putchar('O'); + if(!dpput(depot, buf, len, buf, len, DP_DOVER)) err = TRUE; + if(map) cbmapput(map, buf, len, buf, len, TRUE); + break; + case 1: + putchar('K'); + if(!dpput(depot, buf, len, buf, len, DP_DKEEP) && dpecode != DP_EKEEP) err = TRUE; + if(map) cbmapput(map, buf, len, buf, len, FALSE); + break; + case 2: + putchar('D'); + if(!dpout(depot, buf, len) && dpecode != DP_ENOITEM) err = TRUE; + if(map) cbmapout(map, buf, len); + break; + case 3: + putchar('G'); + if(dpgetwb(depot, buf, len, 2, RECBUFSIZ, vbuf) == -1 && dpecode != DP_ENOITEM) err = TRUE; + break; + case 4: + putchar('V'); + if(dpvsiz(depot, buf, len) == -1 && dpecode != DP_ENOITEM) err = TRUE; + break; + default: + putchar('C'); + if(!dpput(depot, buf, len, buf, len, DP_DCAT)) err = TRUE; + if(map) cbmapputcat(map, buf, len, buf, len); + break; + } + if(i % 50 == 0) printfflush(" (%08d)\n", i); + if(!err && rnum > 100 && myrand() % (rnum / 100) == 0){ + if(myrand() % 10 == 0){ + align = (myrand() % 4 + 1) * -1; + } else { + align = myrand() % 32; + } + if(!dpsetalign(depot, align)) err = TRUE; + } + if(err){ + pdperror(name); + break; + } + } + if(!dpoptimize(depot, -1)){ + pdperror(name); + err = TRUE; + } + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", i); + if(!dpput(depot, buf, len, ":", -1, DP_DCAT)){ + pdperror(name); + err = TRUE; + break; + } + if(map) cbmapputcat(map, buf, len, ":", -1); + putchar(':'); + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + if(!dpoptimize(depot, -1)){ + pdperror(name); + err = TRUE; + } + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", i); + if(!(val = dpget(depot, buf, len, 0, -1, NULL))){ + pdperror(name); + err = TRUE; + break; + } + free(val); + putchar('='); + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + if(!dpiterinit(depot)){ + pdperror(name); + err = TRUE; + } + for(i = 1; i <= rnum; i++){ + if(!(val = dpiternext(depot, NULL))){ + pdperror(name); + err = TRUE; + break; + } + free(val); + putchar('@'); + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + if(map){ + printfflush("Matching records ... "); + cbmapiterinit(map); + while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){ + mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz); + if(!(val = dpget(depot, mkbuf, mksiz, 0, -1, &rsiz))){ + pdperror(name); + err = TRUE; + break; + } + if(rsiz != mvsiz || memcmp(val, mvbuf, rsiz)){ + fprintf(stderr, "%s: %s: unmatched record\n", progname, name); + free(val); + err = TRUE; + break; + } + free(val); + } + cbmapclose(map); + if(!err) printfflush("ok\n"); + } + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/dptsv.c =================================================================== --- box/trunk/qdbm/dptsv.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/dptsv.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,261 +0,0 @@ -/************************************************************************************************* - * Mutual converter between a database of Depot and a TSV text - * 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 -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -int runimport(int argc, char **argv); -int runexport(int argc, char **argv); -void pdperror(const char *name); -char *getl(void); -int doimport(const char *name, int bnum, int bin); -int doexport(const char *name, int bin); - - -/* main routine */ -int main(int argc, char **argv){ - int rv; - cbstdiobin(); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "import")){ - rv = runimport(argc, argv); - } else if(!strcmp(argv[1], "export")){ - rv = runexport(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: mutual converter between TSV and Depot database\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s import [-bnum num] [-bin] name\n", progname); - fprintf(stderr, " %s export [-bin] name\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of import command */ -int runimport(int argc, char **argv){ - char *name; - int i, bnum, bin, rv; - name = NULL; - bnum = -1; - bin = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-bnum")){ - if(++i >= argc) usage(); - bnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-bin")){ - bin = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doimport(name, bnum, bin); - return rv; -} - - -/* parse arguments of export command */ -int runexport(int argc, char **argv){ - char *name; - int i, bin, rv; - name = NULL; - bin = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-bin")){ - bin = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doexport(name, bin); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* read a line */ -char *getl(void){ - char *buf; - int c, len, blen; - buf = NULL; - len = 0; - blen = 256; - while((c = getchar()) != EOF){ - if(blen <= len) blen *= 2; - buf = cbrealloc(buf, blen + 1); - if(c == '\n') c = '\0'; - buf[len++] = c; - if(c == '\0') break; - } - if(!buf) return NULL; - buf[len] = '\0'; - return buf; -} - - -/* perform import command */ -int doimport(const char *name, int bnum, int bin){ - DEPOT *depot; - char *buf, *kbuf, *vbuf, *ktmp, *vtmp; - int i, err, ktsiz, vtsiz; - /* open a database */ - if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT, bnum))){ - pdperror(name); - return 1; - } - /* loop for each line */ - err = FALSE; - for(i = 1; (buf = getl()) != NULL; i++){ - kbuf = buf; - if((vbuf = strchr(buf, '\t')) != NULL){ - *vbuf = '\0'; - vbuf++; - /* store a record */ - if(bin){ - ktmp = cbbasedecode(kbuf, &ktsiz); - vtmp = cbbasedecode(vbuf, &vtsiz); - if(!dpput(depot, ktmp, ktsiz, vtmp, vtsiz, DP_DOVER)){ - pdperror(name); - err = TRUE; - } - free(vtmp); - free(ktmp); - } else { - if(!dpput(depot, kbuf, -1, vbuf, -1, DP_DOVER)){ - pdperror(name); - err = TRUE; - } - } - } else { - fprintf(stderr, "%s: %s: invalid format in line %d\n", progname, name, i); - } - free(buf); - if(err) break; - } - /* close the database */ - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return err ? 1 : 0; -} - - -/* perform export command */ -int doexport(const char *name, int bin){ - DEPOT *depot; - char *kbuf, *vbuf, *tmp; - int err, ksiz, vsiz; - /* open a database */ - if(!(depot = dpopen(name, DP_OREADER, -1))){ - pdperror(name); - return 1; - } - /* initialize the iterator */ - dpiterinit(depot); - /* loop for each key */ - err = FALSE; - while((kbuf = dpiternext(depot, &ksiz)) != NULL){ - /* retrieve a value with a key */ - if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz))){ - pdperror(name); - free(kbuf); - err = TRUE; - break; - } - /* output data */ - if(bin){ - tmp = cbbaseencode(kbuf, ksiz); - printf("%s\t", tmp); - free(tmp); - tmp = cbbaseencode(vbuf, vsiz); - printf("%s\n", tmp); - free(tmp); - } else { - printf("%s\t%s\n", kbuf, vbuf); - } - /* free resources */ - free(vbuf); - free(kbuf); - } - /* check whether all records were retrieved */ - if(dpecode != DP_ENOITEM){ - pdperror(name); - err = TRUE; - } - /* close the database */ - if(!dpclose(depot)){ - pdperror(name); - return 1; - } - return err ? 1 : 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/dptsv.c (from rev 2716, box/trunk/qdbm/dptsv.c) =================================================================== --- box/trunk/qdbm/dptsv.c (rev 0) +++ box/trunk/qdbm/dptsv.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,261 @@ +/************************************************************************************************* + * Mutual converter between a database of Depot and a TSV text + * 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 +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +int runimport(int argc, char **argv); +int runexport(int argc, char **argv); +void pdperror(const char *name); +char *getl(void); +int doimport(const char *name, int bnum, int bin); +int doexport(const char *name, int bin); + + +/* main routine */ +int main(int argc, char **argv){ + int rv; + cbstdiobin(); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "import")){ + rv = runimport(argc, argv); + } else if(!strcmp(argv[1], "export")){ + rv = runexport(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: mutual converter between TSV and Depot database\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s import [-bnum num] [-bin] name\n", progname); + fprintf(stderr, " %s export [-bin] name\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of import command */ +int runimport(int argc, char **argv){ + char *name; + int i, bnum, bin, rv; + name = NULL; + bnum = -1; + bin = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-bnum")){ + if(++i >= argc) usage(); + bnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-bin")){ + bin = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doimport(name, bnum, bin); + return rv; +} + + +/* parse arguments of export command */ +int runexport(int argc, char **argv){ + char *name; + int i, bin, rv; + name = NULL; + bin = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-bin")){ + bin = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doexport(name, bin); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* read a line */ +char *getl(void){ + char *buf; + int c, len, blen; + buf = NULL; + len = 0; + blen = 256; + while((c = getchar()) != EOF){ + if(blen <= len) blen *= 2; + buf = cbrealloc(buf, blen + 1); + if(c == '\n') c = '\0'; + buf[len++] = c; + if(c == '\0') break; + } + if(!buf) return NULL; + buf[len] = '\0'; + return buf; +} + + +/* perform import command */ +int doimport(const char *name, int bnum, int bin){ + DEPOT *depot; + char *buf, *kbuf, *vbuf, *ktmp, *vtmp; + int i, err, ktsiz, vtsiz; + /* open a database */ + if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT, bnum))){ + pdperror(name); + return 1; + } + /* loop for each line */ + err = FALSE; + for(i = 1; (buf = getl()) != NULL; i++){ + kbuf = buf; + if((vbuf = strchr(buf, '\t')) != NULL){ + *vbuf = '\0'; + vbuf++; + /* store a record */ + if(bin){ + ktmp = cbbasedecode(kbuf, &ktsiz); + vtmp = cbbasedecode(vbuf, &vtsiz); + if(!dpput(depot, ktmp, ktsiz, vtmp, vtsiz, DP_DOVER)){ + pdperror(name); + err = TRUE; + } + free(vtmp); + free(ktmp); + } else { + if(!dpput(depot, kbuf, -1, vbuf, -1, DP_DOVER)){ + pdperror(name); + err = TRUE; + } + } + } else { + fprintf(stderr, "%s: %s: invalid format in line %d\n", progname, name, i); + } + free(buf); + if(err) break; + } + /* close the database */ + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return err ? 1 : 0; +} + + +/* perform export command */ +int doexport(const char *name, int bin){ + DEPOT *depot; + char *kbuf, *vbuf, *tmp; + int err, ksiz, vsiz; + /* open a database */ + if(!(depot = dpopen(name, DP_OREADER, -1))){ + pdperror(name); + return 1; + } + /* initialize the iterator */ + dpiterinit(depot); + /* loop for each key */ + err = FALSE; + while((kbuf = dpiternext(depot, &ksiz)) != NULL){ + /* retrieve a value with a key */ + if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz))){ + pdperror(name); + free(kbuf); + err = TRUE; + break; + } + /* output data */ + if(bin){ + tmp = cbbaseencode(kbuf, ksiz); + printf("%s\t", tmp); + free(tmp); + tmp = cbbaseencode(vbuf, vsiz); + printf("%s\n", tmp); + free(tmp); + } else { + printf("%s\t%s\n", kbuf, vbuf); + } + /* free resources */ + free(vbuf); + free(kbuf); + } + /* check whether all records were retrieved */ + if(dpecode != DP_ENOITEM){ + pdperror(name); + err = TRUE; + } + /* close the database */ + if(!dpclose(depot)){ + pdperror(name); + return 1; + } + return err ? 1 : 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/hovel.c =================================================================== --- box/trunk/qdbm/hovel.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/hovel.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,568 +0,0 @@ -/************************************************************************************************* - * Implementation of Hovel - * 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. - *************************************************************************************************/ - - -#define QDBM_INTERNAL 1 - -#include "hovel.h" -#include "myconf.h" - -#define HV_INITBNUM 32749 /* initial bucket number */ -#define HV_ALIGNSIZ 16 /* size of alignment */ - - -/* private function prototypes */ -static int gdbm_geterrno(int ecode); - - - -/************************************************************************************************* - * public objects - *************************************************************************************************/ - - -/* String containing the version information. */ -char *gdbm_version = "Powered by QDBM"; - - -/* Get a message string corresponding to an error code. */ -char *gdbm_strerror(gdbm_error gdbmerrno){ - switch(gdbmerrno){ - case GDBM_NO_ERROR: return "No error"; - case GDBM_MALLOC_ERROR: return "Malloc error"; - case GDBM_BLOCK_SIZE_ERROR: return "Block size error"; - case GDBM_FILE_OPEN_ERROR: return "File open error"; - case GDBM_FILE_WRITE_ERROR: return "File write error"; - case GDBM_FILE_SEEK_ERROR: return "File seek error"; - case GDBM_FILE_READ_ERROR: return "File read error"; - case GDBM_BAD_MAGIC_NUMBER: return "Bad magic number"; - case GDBM_EMPTY_DATABASE: return "Empty database"; - case GDBM_CANT_BE_READER: return "Can't be reader"; - case GDBM_CANT_BE_WRITER: return "Can't be writer"; - case GDBM_READER_CANT_DELETE: return "Reader can't delete"; - case GDBM_READER_CANT_STORE: return "Reader can't store"; - case GDBM_READER_CANT_REORGANIZE: return "Reader can't reorganize"; - case GDBM_UNKNOWN_UPDATE: return "Unknown update"; - case GDBM_ITEM_NOT_FOUND: return "Item not found"; - case GDBM_REORGANIZE_FAILED: return "Reorganize failed"; - case GDBM_CANNOT_REPLACE: return "Cannot replace"; - case GDBM_ILLEGAL_DATA: return "Illegal data"; - case GDBM_OPT_ALREADY_SET: return "Option already set"; - case GDBM_OPT_ILLEGAL: return "Illegal option"; - } - return "(invalid ecode)"; -} - - -/* Get a database handle after the fashion of GDBM. */ -GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, - void (*fatal_func)(void)){ - GDBM_FILE dbf; - int dpomode; - DEPOT *depot; - int flags, fd; - assert(name); - dpomode = DP_OREADER; - flags = O_RDONLY; - if(read_write & GDBM_READER){ - dpomode = GDBM_READER; - if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; - if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; - flags = O_RDONLY; - } else if(read_write & GDBM_WRITER){ - dpomode = DP_OWRITER; - if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; - if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; - flags = O_RDWR; - } else if(read_write & GDBM_WRCREAT){ - dpomode = DP_OWRITER | DP_OCREAT; - if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; - if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; - if(read_write & GDBM_SPARSE) dpomode |= DP_OSPARSE; - flags = O_RDWR | O_CREAT; - } else if(read_write & GDBM_NEWDB){ - dpomode = DP_OWRITER | DP_OCREAT | DP_OTRUNC; - if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; - if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; - if(read_write & GDBM_SPARSE) dpomode |= DP_OSPARSE; - flags = O_RDWR | O_CREAT | O_TRUNC; - } else { - gdbm_errno = GDBM_ILLEGAL_DATA; - return NULL; - } - mode |= 00600; - if((fd = open(name, flags, mode)) == -1 || close(fd) == -1){ - gdbm_errno = GDBM_FILE_OPEN_ERROR; - return NULL; - } - if(!(depot = dpopen(name, dpomode, HV_INITBNUM))){ - gdbm_errno = gdbm_geterrno(dpecode); - if(dpecode == DP_ESTAT) gdbm_errno = GDBM_FILE_OPEN_ERROR; - return NULL; - } - if(dpomode & DP_OWRITER){ - if(!dpsetalign(depot, HV_ALIGNSIZ)){ - gdbm_errno = gdbm_geterrno(dpecode); - dpclose(depot); - } - } - if((dpomode & DP_OWRITER) && (read_write & GDBM_SYNC)){ - if(!dpsync(depot)){ - gdbm_errno = gdbm_geterrno(dpecode); - dpclose(depot); - } - } - if(!(dbf = malloc(sizeof(GDBM)))){ - gdbm_errno = GDBM_MALLOC_ERROR; - dpclose(depot); - return NULL; - } - dbf->depot = depot; - dbf->curia = NULL; - dbf->syncmode = (dpomode & DP_OWRITER) && (read_write & GDBM_SYNC) ? TRUE : FALSE; - return dbf; -} - - -/* Get a database handle after the fashion of QDBM. */ -GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align){ - GDBM_FILE dbf; - int dpomode, cromode, flags, fd; - struct stat sbuf; - DEPOT *depot; - CURIA *curia; - assert(name); - dpomode = DP_OREADER; - cromode = CR_OREADER; - flags = O_RDONLY; - if(read_write & GDBM_READER){ - dpomode = DP_OREADER; - cromode = CR_OREADER; - if(read_write & GDBM_NOLOCK){ - dpomode |= DP_ONOLCK; - cromode |= CR_ONOLCK; - } - if(read_write & GDBM_LOCKNB){ - dpomode |= DP_OLCKNB; - cromode |= CR_OLCKNB; - } - flags = O_RDONLY; - } else if(read_write & GDBM_WRITER){ - dpomode = DP_OWRITER; - cromode = CR_OWRITER; - if(read_write & GDBM_NOLOCK){ - dpomode |= DP_ONOLCK; - cromode |= CR_ONOLCK; - } - if(read_write & GDBM_LOCKNB){ - dpomode |= DP_OLCKNB; - cromode |= CR_OLCKNB; - } - flags = O_RDWR; - } else if(read_write & GDBM_WRCREAT){ - dpomode = DP_OWRITER | DP_OCREAT; - cromode = CR_OWRITER | CR_OCREAT; - if(read_write & GDBM_NOLOCK){ - dpomode |= DP_ONOLCK; - cromode |= CR_ONOLCK; - } - if(read_write & GDBM_LOCKNB){ - dpomode |= DP_OLCKNB; - cromode |= CR_OLCKNB; - } - if(read_write & GDBM_SPARSE){ - dpomode |= DP_OSPARSE; - cromode |= CR_OSPARSE; - } - flags = O_RDWR | O_CREAT; - } else if(read_write & GDBM_NEWDB){ - dpomode = DP_OWRITER | DP_OCREAT | DP_OTRUNC; - cromode = CR_OWRITER | CR_OCREAT | CR_OTRUNC; - if(read_write & GDBM_NOLOCK){ - dpomode |= DP_ONOLCK; - cromode |= CR_ONOLCK; - } - if(read_write & GDBM_LOCKNB){ - dpomode |= DP_OLCKNB; - cromode |= CR_OLCKNB; - } - if(read_write & GDBM_SPARSE){ - dpomode |= DP_OSPARSE; - cromode |= CR_OSPARSE; - } - flags = O_RDWR | O_CREAT | O_TRUNC; - } else { - gdbm_errno = GDBM_ILLEGAL_DATA; - return NULL; - } - if(lstat(name, &sbuf) != -1){ - if(S_ISDIR(sbuf.st_mode)){ - if(dnum < 1) dnum = 1; - } else { - dnum = 0; - } - } - depot = NULL; - curia = NULL; - if(dnum > 0){ - mode |= 00700; - if((cromode & CR_OCREAT)){ - if(mkdir(name, mode) == -1 && errno != EEXIST){ - gdbm_errno = GDBM_FILE_OPEN_ERROR; - return NULL; - } - } - if(!(curia = cropen(name, cromode, bnum, dnum))){ - gdbm_errno = gdbm_geterrno(dpecode); - return NULL; - } - if(cromode & CR_OWRITER) crsetalign(curia, align); - if((cromode & CR_OWRITER) && (read_write & GDBM_SYNC)) crsync(curia); - } else { - mode |= 00600; - if(dpomode & DP_OWRITER){ - if((fd = open(name, flags, mode)) == -1 || close(fd) == -1){ - gdbm_errno = GDBM_FILE_OPEN_ERROR; - return NULL; - } - } - if(!(depot = dpopen(name, dpomode, bnum))){ - gdbm_errno = gdbm_geterrno(dpecode); - return NULL; - } - if(dpomode & DP_OWRITER) dpsetalign(depot, align); - if((dpomode & DP_OWRITER) && (read_write & GDBM_SYNC)) dpsync(depot); - } - if(!(dbf = malloc(sizeof(GDBM)))){ - gdbm_errno = GDBM_MALLOC_ERROR; - if(depot) dpclose(depot); - if(curia) crclose(curia); - return NULL; - } - dbf->depot = depot; - dbf->curia = curia; - dbf->syncmode = (dpomode & DP_OWRITER) && (read_write & GDBM_SYNC) ? TRUE : FALSE; - return dbf; -} - - -/* Close a database handle. */ -void gdbm_close(GDBM_FILE dbf){ - assert(dbf); - if(dbf->depot){ - if(dbf->syncmode) dpsync(dbf->depot); - dpclose(dbf->depot); - } else { - if(dbf->syncmode) crsync(dbf->curia); - crclose(dbf->curia); - } - free(dbf); -} - - -/* Store a record. */ -int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag){ - int dmode; - assert(dbf); - if(!key.dptr || key.dsize < 0 || !content.dptr || content.dsize < 0){ - gdbm_errno = GDBM_ILLEGAL_DATA; - return -1; - } - if(dbf->depot){ - if(!dpwritable(dbf->depot)){ - gdbm_errno = GDBM_READER_CANT_STORE; - return -1; - } - dmode = (flag == GDBM_INSERT) ? DP_DKEEP : DP_DOVER; - if(!dpput(dbf->depot, key.dptr, key.dsize, content.dptr, content.dsize, dmode)){ - gdbm_errno = gdbm_geterrno(dpecode); - if(dpecode == DP_EKEEP) return 1; - return -1; - } - if(dbf->syncmode && !dpsync(dbf->depot)){ - gdbm_errno = gdbm_geterrno(dpecode); - return -1; - } - } else { - if(!crwritable(dbf->curia)){ - gdbm_errno = GDBM_READER_CANT_STORE; - return -1; - } - dmode = (flag == GDBM_INSERT) ? CR_DKEEP : CR_DOVER; - if(!crput(dbf->curia, key.dptr, key.dsize, content.dptr, content.dsize, dmode)){ - gdbm_errno = gdbm_geterrno(dpecode); - if(dpecode == DP_EKEEP) return 1; - return -1; - } - if(dbf->syncmode && !crsync(dbf->curia)){ - gdbm_errno = gdbm_geterrno(dpecode); - return -1; - } - } - return 0; -} - - -/* Delete a record. */ -int gdbm_delete(GDBM_FILE dbf, datum key){ - assert(dbf); - if(!key.dptr || key.dsize < 0){ - gdbm_errno = GDBM_ILLEGAL_DATA; - return -1; - } - if(dbf->depot){ - if(!dpwritable(dbf->depot)){ - gdbm_errno = GDBM_READER_CANT_DELETE; - return -1; - } - if(!dpout(dbf->depot, key.dptr, key.dsize)){ - gdbm_errno = gdbm_geterrno(dpecode); - return -1; - } - if(dbf->syncmode && !dpsync(dbf->depot)){ - gdbm_errno = gdbm_geterrno(dpecode); - return -1; - } - } else { - if(!crwritable(dbf->curia)){ - gdbm_errno = GDBM_READER_CANT_DELETE; - return -1; - } - if(!crout(dbf->curia, key.dptr, key.dsize)){ - gdbm_errno = gdbm_geterrno(dpecode); - return -1; - } - if(dbf->syncmode && !crsync(dbf->curia)){ - gdbm_errno = gdbm_geterrno(dpecode); - return -1; - } - } - return 0; -} - - -/* Retrieve a record. */ -datum gdbm_fetch(GDBM_FILE dbf, datum key){ - datum content; - char *vbuf; - int vsiz; - assert(dbf); - if(!key.dptr || key.dsize < 0){ - gdbm_errno = GDBM_ILLEGAL_DATA; - content.dptr = NULL; - content.dsize = 0; - return content; - } - if(dbf->depot){ - if(!(vbuf = dpget(dbf->depot, key.dptr, key.dsize, 0, -1, &vsiz))){ - gdbm_errno = gdbm_geterrno(dpecode); - content.dptr = NULL; - content.dsize = 0; - return content; - } - } else { - if(!(vbuf = crget(dbf->curia, key.dptr, key.dsize, 0, -1, &vsiz))){ - gdbm_errno = gdbm_geterrno(dpecode); - content.dptr = NULL; - content.dsize = 0; - return content; - } - } - content.dptr = vbuf; - content.dsize = vsiz; - return content; -} - - -/* Check whether a record exists or not. */ -int gdbm_exists(GDBM_FILE dbf, datum key){ - assert(dbf); - if(!key.dptr || key.dsize < 0){ - gdbm_errno = GDBM_ILLEGAL_DATA; - return FALSE; - } - if(dbf->depot){ - if(dpvsiz(dbf->depot, key.dptr, key.dsize) == -1){ - gdbm_errno = gdbm_geterrno(dpecode); - return FALSE; - } - } else { - if(crvsiz(dbf->curia, key.dptr, key.dsize) == -1){ - gdbm_errno = gdbm_geterrno(dpecode); - return FALSE; - } - } - return TRUE; -} - - -/* Get the first key of a database. */ -datum gdbm_firstkey(GDBM_FILE dbf){ - datum key; - assert(dbf); - memset(&key, 0, sizeof(datum)); - if(dbf->depot){ - if(dprnum(dbf->depot) < 1){ - gdbm_errno = GDBM_EMPTY_DATABASE; - key.dptr = NULL; - key.dsize = 0; - return key; - } - dpiterinit(dbf->depot); - return gdbm_nextkey(dbf, key); - } else { - if(crrnum(dbf->curia) < 1){ - gdbm_errno = GDBM_EMPTY_DATABASE; - key.dptr = NULL; - key.dsize = 0; - return key; - } - criterinit(dbf->curia); - return gdbm_nextkey(dbf, key); - } -} - - -/* Get the next key of a database. */ -datum gdbm_nextkey(GDBM_FILE dbf, datum key){ - char *kbuf; - int ksiz; - assert(dbf); - if(dbf->depot){ - if(!(kbuf = dpiternext(dbf->depot, &ksiz))){ - gdbm_errno = gdbm_geterrno(dpecode); - key.dptr = NULL; - key.dsize = 0; - return key; - } - } else { - if(!(kbuf = criternext(dbf->curia, &ksiz))){ - gdbm_errno = gdbm_geterrno(dpecode); - key.dptr = NULL; - key.dsize = 0; - return key; - } - } - key.dptr = kbuf; - key.dsize = ksiz; - return key; -} - - -/* Synchronize contents of updating with the file and the device. */ -void gdbm_sync(GDBM_FILE dbf){ - assert(dbf); - if(dbf->depot){ - if(!dpsync(dbf->depot)) gdbm_errno = gdbm_geterrno(dpecode); - } else { - if(!crsync(dbf->curia)) gdbm_errno = gdbm_geterrno(dpecode); - } -} - - -/* Reorganize a database. */ -int gdbm_reorganize(GDBM_FILE dbf){ - assert(dbf); - if(dbf->depot){ - if(!dpwritable(dbf->depot)){ - gdbm_errno = GDBM_READER_CANT_REORGANIZE; - return -1; - } - if(!dpoptimize(dbf->depot, dprnum(dbf->depot) >= HV_INITBNUM ? -1 : HV_INITBNUM)){ - gdbm_errno = gdbm_geterrno(dpecode); - return -1; - } - } else { - if(!crwritable(dbf->curia)){ - gdbm_errno = GDBM_READER_CANT_REORGANIZE; - return -1; - } - if(!croptimize(dbf->curia, crrnum(dbf->curia) >= HV_INITBNUM ? -1 : HV_INITBNUM)){ - gdbm_errno = gdbm_geterrno(dpecode); - return -1; - } - } - return 0; -} - - -/* Get the file descriptor of a database file. */ -int gdbm_fdesc(GDBM_FILE dbf){ - assert(dbf); - if(dbf->depot){ - return dpfdesc(dbf->depot); - } else { - return -1; - } -} - - -/* No effect. */ -int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size){ - assert(dbf); - return 0; -} - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Get the pointer of the last happened error code. */ -int *gdbm_errnoptr(void){ - static int deferrno = GDBM_NO_ERROR; - void *ptr; - if(_qdbm_ptsafe){ - if(!(ptr = _qdbm_settsd(&deferrno, sizeof(int), &deferrno))){ - deferrno = GDBM_ILLEGAL_DATA; - return &deferrno; - } - return (int *)ptr; - } - return &deferrno; -} - - - -/************************************************************************************************* - * private objects - *************************************************************************************************/ - - -/* Get the error code of GDBM corresponding to an error code of Depot. - `ecode' specifies an error code of Depot. - The return value is the error code of GDBM. */ -static int gdbm_geterrno(int ecode){ - switch(ecode){ - case DP_ENOERR: return GDBM_NO_ERROR; - case DP_EBROKEN: return GDBM_BAD_MAGIC_NUMBER; - case DP_EKEEP: return GDBM_CANNOT_REPLACE; - case DP_ENOITEM: return GDBM_ITEM_NOT_FOUND; - case DP_EALLOC: return GDBM_MALLOC_ERROR; - case DP_EOPEN: return GDBM_FILE_OPEN_ERROR; - case DP_ESEEK: return GDBM_FILE_SEEK_ERROR; - case DP_EREAD: return GDBM_FILE_READ_ERROR; - case DP_EWRITE: return GDBM_FILE_WRITE_ERROR; - case DP_EMKDIR: return GDBM_FILE_OPEN_ERROR; - default: break; - } - return GDBM_ILLEGAL_DATA; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/hovel.c (from rev 2716, box/trunk/qdbm/hovel.c) =================================================================== --- box/trunk/qdbm/hovel.c (rev 0) +++ box/trunk/qdbm/hovel.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,568 @@ +/************************************************************************************************* + * Implementation of Hovel + * 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. + *************************************************************************************************/ + + +#define QDBM_INTERNAL 1 + +#include "hovel.h" +#include "myconf.h" + +#define HV_INITBNUM 32749 /* initial bucket number */ +#define HV_ALIGNSIZ 16 /* size of alignment */ + + +/* private function prototypes */ +static int gdbm_geterrno(int ecode); + + + +/************************************************************************************************* + * public objects + *************************************************************************************************/ + + +/* String containing the version information. */ +char *gdbm_version = "Powered by QDBM"; + + +/* Get a message string corresponding to an error code. */ +char *gdbm_strerror(gdbm_error gdbmerrno){ + switch(gdbmerrno){ + case GDBM_NO_ERROR: return "No error"; + case GDBM_MALLOC_ERROR: return "Malloc error"; + case GDBM_BLOCK_SIZE_ERROR: return "Block size error"; + case GDBM_FILE_OPEN_ERROR: return "File open error"; + case GDBM_FILE_WRITE_ERROR: return "File write error"; + case GDBM_FILE_SEEK_ERROR: return "File seek error"; + case GDBM_FILE_READ_ERROR: return "File read error"; + case GDBM_BAD_MAGIC_NUMBER: return "Bad magic number"; + case GDBM_EMPTY_DATABASE: return "Empty database"; + case GDBM_CANT_BE_READER: return "Can't be reader"; + case GDBM_CANT_BE_WRITER: return "Can't be writer"; + case GDBM_READER_CANT_DELETE: return "Reader can't delete"; + case GDBM_READER_CANT_STORE: return "Reader can't store"; + case GDBM_READER_CANT_REORGANIZE: return "Reader can't reorganize"; + case GDBM_UNKNOWN_UPDATE: return "Unknown update"; + case GDBM_ITEM_NOT_FOUND: return "Item not found"; + case GDBM_REORGANIZE_FAILED: return "Reorganize failed"; + case GDBM_CANNOT_REPLACE: return "Cannot replace"; + case GDBM_ILLEGAL_DATA: return "Illegal data"; + case GDBM_OPT_ALREADY_SET: return "Option already set"; + case GDBM_OPT_ILLEGAL: return "Illegal option"; + } + return "(invalid ecode)"; +} + + +/* Get a database handle after the fashion of GDBM. */ +GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, + void (*fatal_func)(void)){ + GDBM_FILE dbf; + int dpomode; + DEPOT *depot; + int flags, fd; + assert(name); + dpomode = DP_OREADER; + flags = O_RDONLY; + if(read_write & GDBM_READER){ + dpomode = GDBM_READER; + if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; + if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; + flags = O_RDONLY; + } else if(read_write & GDBM_WRITER){ + dpomode = DP_OWRITER; + if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; + if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; + flags = O_RDWR; + } else if(read_write & GDBM_WRCREAT){ + dpomode = DP_OWRITER | DP_OCREAT; + if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; + if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; + if(read_write & GDBM_SPARSE) dpomode |= DP_OSPARSE; + flags = O_RDWR | O_CREAT; + } else if(read_write & GDBM_NEWDB){ + dpomode = DP_OWRITER | DP_OCREAT | DP_OTRUNC; + if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; + if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; + if(read_write & GDBM_SPARSE) dpomode |= DP_OSPARSE; + flags = O_RDWR | O_CREAT | O_TRUNC; + } else { + gdbm_errno = GDBM_ILLEGAL_DATA; + return NULL; + } + mode |= 00600; + if((fd = open(name, flags, mode)) == -1 || close(fd) == -1){ + gdbm_errno = GDBM_FILE_OPEN_ERROR; + return NULL; + } + if(!(depot = dpopen(name, dpomode, HV_INITBNUM))){ + gdbm_errno = gdbm_geterrno(dpecode); + if(dpecode == DP_ESTAT) gdbm_errno = GDBM_FILE_OPEN_ERROR; + return NULL; + } + if(dpomode & DP_OWRITER){ + if(!dpsetalign(depot, HV_ALIGNSIZ)){ + gdbm_errno = gdbm_geterrno(dpecode); + dpclose(depot); + } + } + if((dpomode & DP_OWRITER) && (read_write & GDBM_SYNC)){ + if(!dpsync(depot)){ + gdbm_errno = gdbm_geterrno(dpecode); + dpclose(depot); + } + } + if(!(dbf = malloc(sizeof(GDBM)))){ + gdbm_errno = GDBM_MALLOC_ERROR; + dpclose(depot); + return NULL; + } + dbf->depot = depot; + dbf->curia = NULL; + dbf->syncmode = (dpomode & DP_OWRITER) && (read_write & GDBM_SYNC) ? TRUE : FALSE; + return dbf; +} + + +/* Get a database handle after the fashion of QDBM. */ +GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align){ + GDBM_FILE dbf; + int dpomode, cromode, flags, fd; + struct stat sbuf; + DEPOT *depot; + CURIA *curia; + assert(name); + dpomode = DP_OREADER; + cromode = CR_OREADER; + flags = O_RDONLY; + if(read_write & GDBM_READER){ + dpomode = DP_OREADER; + cromode = CR_OREADER; + if(read_write & GDBM_NOLOCK){ + dpomode |= DP_ONOLCK; + cromode |= CR_ONOLCK; + } + if(read_write & GDBM_LOCKNB){ + dpomode |= DP_OLCKNB; + cromode |= CR_OLCKNB; + } + flags = O_RDONLY; + } else if(read_write & GDBM_WRITER){ + dpomode = DP_OWRITER; + cromode = CR_OWRITER; + if(read_write & GDBM_NOLOCK){ + dpomode |= DP_ONOLCK; + cromode |= CR_ONOLCK; + } + if(read_write & GDBM_LOCKNB){ + dpomode |= DP_OLCKNB; + cromode |= CR_OLCKNB; + } + flags = O_RDWR; + } else if(read_write & GDBM_WRCREAT){ + dpomode = DP_OWRITER | DP_OCREAT; + cromode = CR_OWRITER | CR_OCREAT; + if(read_write & GDBM_NOLOCK){ + dpomode |= DP_ONOLCK; + cromode |= CR_ONOLCK; + } + if(read_write & GDBM_LOCKNB){ + dpomode |= DP_OLCKNB; + cromode |= CR_OLCKNB; + } + if(read_write & GDBM_SPARSE){ + dpomode |= DP_OSPARSE; + cromode |= CR_OSPARSE; + } + flags = O_RDWR | O_CREAT; + } else if(read_write & GDBM_NEWDB){ + dpomode = DP_OWRITER | DP_OCREAT | DP_OTRUNC; + cromode = CR_OWRITER | CR_OCREAT | CR_OTRUNC; + if(read_write & GDBM_NOLOCK){ + dpomode |= DP_ONOLCK; + cromode |= CR_ONOLCK; + } + if(read_write & GDBM_LOCKNB){ + dpomode |= DP_OLCKNB; + cromode |= CR_OLCKNB; + } + if(read_write & GDBM_SPARSE){ + dpomode |= DP_OSPARSE; + cromode |= CR_OSPARSE; + } + flags = O_RDWR | O_CREAT | O_TRUNC; + } else { + gdbm_errno = GDBM_ILLEGAL_DATA; + return NULL; + } + if(lstat(name, &sbuf) != -1){ + if(S_ISDIR(sbuf.st_mode)){ + if(dnum < 1) dnum = 1; + } else { + dnum = 0; + } + } + depot = NULL; + curia = NULL; + if(dnum > 0){ + mode |= 00700; + if((cromode & CR_OCREAT)){ + if(mkdir(name, mode) == -1 && errno != EEXIST){ + gdbm_errno = GDBM_FILE_OPEN_ERROR; + return NULL; + } + } + if(!(curia = cropen(name, cromode, bnum, dnum))){ + gdbm_errno = gdbm_geterrno(dpecode); + return NULL; + } + if(cromode & CR_OWRITER) crsetalign(curia, align); + if((cromode & CR_OWRITER) && (read_write & GDBM_SYNC)) crsync(curia); + } else { + mode |= 00600; + if(dpomode & DP_OWRITER){ + if((fd = open(name, flags, mode)) == -1 || close(fd) == -1){ + gdbm_errno = GDBM_FILE_OPEN_ERROR; + return NULL; + } + } + if(!(depot = dpopen(name, dpomode, bnum))){ + gdbm_errno = gdbm_geterrno(dpecode); + return NULL; + } + if(dpomode & DP_OWRITER) dpsetalign(depot, align); + if((dpomode & DP_OWRITER) && (read_write & GDBM_SYNC)) dpsync(depot); + } + if(!(dbf = malloc(sizeof(GDBM)))){ + gdbm_errno = GDBM_MALLOC_ERROR; + if(depot) dpclose(depot); + if(curia) crclose(curia); + return NULL; + } + dbf->depot = depot; + dbf->curia = curia; + dbf->syncmode = (dpomode & DP_OWRITER) && (read_write & GDBM_SYNC) ? TRUE : FALSE; + return dbf; +} + + +/* Close a database handle. */ +void gdbm_close(GDBM_FILE dbf){ + assert(dbf); + if(dbf->depot){ + if(dbf->syncmode) dpsync(dbf->depot); + dpclose(dbf->depot); + } else { + if(dbf->syncmode) crsync(dbf->curia); + crclose(dbf->curia); + } + free(dbf); +} + + +/* Store a record. */ +int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag){ + int dmode; + assert(dbf); + if(!key.dptr || key.dsize < 0 || !content.dptr || content.dsize < 0){ + gdbm_errno = GDBM_ILLEGAL_DATA; + return -1; + } + if(dbf->depot){ + if(!dpwritable(dbf->depot)){ + gdbm_errno = GDBM_READER_CANT_STORE; + return -1; + } + dmode = (flag == GDBM_INSERT) ? DP_DKEEP : DP_DOVER; + if(!dpput(dbf->depot, key.dptr, key.dsize, content.dptr, content.dsize, dmode)){ + gdbm_errno = gdbm_geterrno(dpecode); + if(dpecode == DP_EKEEP) return 1; + return -1; + } + if(dbf->syncmode && !dpsync(dbf->depot)){ + gdbm_errno = gdbm_geterrno(dpecode); + return -1; + } + } else { + if(!crwritable(dbf->curia)){ + gdbm_errno = GDBM_READER_CANT_STORE; + return -1; + } + dmode = (flag == GDBM_INSERT) ? CR_DKEEP : CR_DOVER; + if(!crput(dbf->curia, key.dptr, key.dsize, content.dptr, content.dsize, dmode)){ + gdbm_errno = gdbm_geterrno(dpecode); + if(dpecode == DP_EKEEP) return 1; + return -1; + } + if(dbf->syncmode && !crsync(dbf->curia)){ + gdbm_errno = gdbm_geterrno(dpecode); + return -1; + } + } + return 0; +} + + +/* Delete a record. */ +int gdbm_delete(GDBM_FILE dbf, datum key){ + assert(dbf); + if(!key.dptr || key.dsize < 0){ + gdbm_errno = GDBM_ILLEGAL_DATA; + return -1; + } + if(dbf->depot){ + if(!dpwritable(dbf->depot)){ + gdbm_errno = GDBM_READER_CANT_DELETE; + return -1; + } + if(!dpout(dbf->depot, key.dptr, key.dsize)){ + gdbm_errno = gdbm_geterrno(dpecode); + return -1; + } + if(dbf->syncmode && !dpsync(dbf->depot)){ + gdbm_errno = gdbm_geterrno(dpecode); + return -1; + } + } else { + if(!crwritable(dbf->curia)){ + gdbm_errno = GDBM_READER_CANT_DELETE; + return -1; + } + if(!crout(dbf->curia, key.dptr, key.dsize)){ + gdbm_errno = gdbm_geterrno(dpecode); + return -1; + } + if(dbf->syncmode && !crsync(dbf->curia)){ + gdbm_errno = gdbm_geterrno(dpecode); + return -1; + } + } + return 0; +} + + +/* Retrieve a record. */ +datum gdbm_fetch(GDBM_FILE dbf, datum key){ + datum content; + char *vbuf; + int vsiz; + assert(dbf); + if(!key.dptr || key.dsize < 0){ + gdbm_errno = GDBM_ILLEGAL_DATA; + content.dptr = NULL; + content.dsize = 0; + return content; + } + if(dbf->depot){ + if(!(vbuf = dpget(dbf->depot, key.dptr, key.dsize, 0, -1, &vsiz))){ + gdbm_errno = gdbm_geterrno(dpecode); + content.dptr = NULL; + content.dsize = 0; + return content; + } + } else { + if(!(vbuf = crget(dbf->curia, key.dptr, key.dsize, 0, -1, &vsiz))){ + gdbm_errno = gdbm_geterrno(dpecode); + content.dptr = NULL; + content.dsize = 0; + return content; + } + } + content.dptr = vbuf; + content.dsize = vsiz; + return content; +} + + +/* Check whether a record exists or not. */ +int gdbm_exists(GDBM_FILE dbf, datum key){ + assert(dbf); + if(!key.dptr || key.dsize < 0){ + gdbm_errno = GDBM_ILLEGAL_DATA; + return FALSE; + } + if(dbf->depot){ + if(dpvsiz(dbf->depot, key.dptr, key.dsize) == -1){ + gdbm_errno = gdbm_geterrno(dpecode); + return FALSE; + } + } else { + if(crvsiz(dbf->curia, key.dptr, key.dsize) == -1){ + gdbm_errno = gdbm_geterrno(dpecode); + return FALSE; + } + } + return TRUE; +} + + +/* Get the first key of a database. */ +datum gdbm_firstkey(GDBM_FILE dbf){ + datum key; + assert(dbf); + memset(&key, 0, sizeof(datum)); + if(dbf->depot){ + if(dprnum(dbf->depot) < 1){ + gdbm_errno = GDBM_EMPTY_DATABASE; + key.dptr = NULL; + key.dsize = 0; + return key; + } + dpiterinit(dbf->depot); + return gdbm_nextkey(dbf, key); + } else { + if(crrnum(dbf->curia) < 1){ + gdbm_errno = GDBM_EMPTY_DATABASE; + key.dptr = NULL; + key.dsize = 0; + return key; + } + criterinit(dbf->curia); + return gdbm_nextkey(dbf, key); + } +} + + +/* Get the next key of a database. */ +datum gdbm_nextkey(GDBM_FILE dbf, datum key){ + char *kbuf; + int ksiz; + assert(dbf); + if(dbf->depot){ + if(!(kbuf = dpiternext(dbf->depot, &ksiz))){ + gdbm_errno = gdbm_geterrno(dpecode); + key.dptr = NULL; + key.dsize = 0; + return key; + } + } else { + if(!(kbuf = criternext(dbf->curia, &ksiz))){ + gdbm_errno = gdbm_geterrno(dpecode); + key.dptr = NULL; + key.dsize = 0; + return key; + } + } + key.dptr = kbuf; + key.dsize = ksiz; + return key; +} + + +/* Synchronize contents of updating with the file and the device. */ +void gdbm_sync(GDBM_FILE dbf){ + assert(dbf); + if(dbf->depot){ + if(!dpsync(dbf->depot)) gdbm_errno = gdbm_geterrno(dpecode); + } else { + if(!crsync(dbf->curia)) gdbm_errno = gdbm_geterrno(dpecode); + } +} + + +/* Reorganize a database. */ +int gdbm_reorganize(GDBM_FILE dbf){ + assert(dbf); + if(dbf->depot){ + if(!dpwritable(dbf->depot)){ + gdbm_errno = GDBM_READER_CANT_REORGANIZE; + return -1; + } + if(!dpoptimize(dbf->depot, dprnum(dbf->depot) >= HV_INITBNUM ? -1 : HV_INITBNUM)){ + gdbm_errno = gdbm_geterrno(dpecode); + return -1; + } + } else { + if(!crwritable(dbf->curia)){ + gdbm_errno = GDBM_READER_CANT_REORGANIZE; + return -1; + } + if(!croptimize(dbf->curia, crrnum(dbf->curia) >= HV_INITBNUM ? -1 : HV_INITBNUM)){ + gdbm_errno = gdbm_geterrno(dpecode); + return -1; + } + } + return 0; +} + + +/* Get the file descriptor of a database file. */ +int gdbm_fdesc(GDBM_FILE dbf){ + assert(dbf); + if(dbf->depot){ + return dpfdesc(dbf->depot); + } else { + return -1; + } +} + + +/* No effect. */ +int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size){ + assert(dbf); + return 0; +} + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Get the pointer of the last happened error code. */ +int *gdbm_errnoptr(void){ + static int deferrno = GDBM_NO_ERROR; + void *ptr; + if(_qdbm_ptsafe){ + if(!(ptr = _qdbm_settsd(&deferrno, sizeof(int), &deferrno))){ + deferrno = GDBM_ILLEGAL_DATA; + return &deferrno; + } + return (int *)ptr; + } + return &deferrno; +} + + + +/************************************************************************************************* + * private objects + *************************************************************************************************/ + + +/* Get the error code of GDBM corresponding to an error code of Depot. + `ecode' specifies an error code of Depot. + The return value is the error code of GDBM. */ +static int gdbm_geterrno(int ecode){ + switch(ecode){ + case DP_ENOERR: return GDBM_NO_ERROR; + case DP_EBROKEN: return GDBM_BAD_MAGIC_NUMBER; + case DP_EKEEP: return GDBM_CANNOT_REPLACE; + case DP_ENOITEM: return GDBM_ITEM_NOT_FOUND; + case DP_EALLOC: return GDBM_MALLOC_ERROR; + case DP_EOPEN: return GDBM_FILE_OPEN_ERROR; + case DP_ESEEK: return GDBM_FILE_SEEK_ERROR; + case DP_EREAD: return GDBM_FILE_READ_ERROR; + case DP_EWRITE: return GDBM_FILE_WRITE_ERROR; + case DP_EMKDIR: return GDBM_FILE_OPEN_ERROR; + default: break; + } + return GDBM_ILLEGAL_DATA; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/hovel.h =================================================================== --- box/trunk/qdbm/hovel.h 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/hovel.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,278 +0,0 @@ -/************************************************************************************************* - * The GDBM-compatible API of QDBM - * 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. - *************************************************************************************************/ - - -#ifndef _HOVEL_H /* duplication check */ -#define _HOVEL_H - -#if defined(__cplusplus) /* export for C++ */ -extern "C" { -#endif - - -#include -#include -#include -#include -#include - - -#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) -#define MYEXTERN extern __declspec(dllimport) -#else -#define MYEXTERN extern -#endif - - - -/************************************************************************************************* - * API - *************************************************************************************************/ - - -enum { /* enumeration for error codes */ - GDBM_NO_ERROR, /* no error */ - GDBM_MALLOC_ERROR, /* malloc error */ - GDBM_BLOCK_SIZE_ERROR, /* block size error */ - GDBM_FILE_OPEN_ERROR, /* file open error */ - GDBM_FILE_WRITE_ERROR, /* file write error */ - GDBM_FILE_SEEK_ERROR, /* file seek error */ - GDBM_FILE_READ_ERROR, /* file read error */ - GDBM_BAD_MAGIC_NUMBER, /* bad magic number */ - GDBM_EMPTY_DATABASE, /* empty database */ - GDBM_CANT_BE_READER, /* can't be reader */ - GDBM_CANT_BE_WRITER, /* can't be writer */ - GDBM_READER_CANT_DELETE, /* reader can't delete */ - GDBM_READER_CANT_STORE, /* reader can't store */ - GDBM_READER_CANT_REORGANIZE, /* reader can't reorganize */ - GDBM_UNKNOWN_UPDATE, /* unknown update */ - GDBM_ITEM_NOT_FOUND, /* item not found */ - GDBM_REORGANIZE_FAILED, /* reorganize failed */ - GDBM_CANNOT_REPLACE, /* cannot replace */ - GDBM_ILLEGAL_DATA, /* illegal data */ - GDBM_OPT_ALREADY_SET, /* option already set */ - GDBM_OPT_ILLEGAL /* option illegal */ -}; - -typedef int gdbm_error; /* type of error codes */ - -typedef struct { /* type of structure for a database handle */ - DEPOT *depot; /* internal database handle of Depot */ - CURIA *curia; /* internal database handle of Curia */ - int syncmode; /* whether to be besyncronous mode */ -} GDBM; - -typedef GDBM *GDBM_FILE; /* type of pointer to a database handle */ - -typedef struct { /* type of structure for a key or a value */ - char *dptr; /* pointer to the region */ - size_t dsize; /* size of the region */ -} datum; - -enum { /* enumeration for open modes */ - GDBM_READER = 1 << 0, /* open as a reader */ - GDBM_WRITER = 1 << 1, /* open as a writer */ - GDBM_WRCREAT = 1 << 2, /* a writer creating */ - GDBM_NEWDB = 1 << 3, /* a writer creating and truncating */ - GDBM_SYNC = 1 << 4, /* syncronous mode */ - GDBM_NOLOCK = 1 << 5, /* no lock mode */ - GDBM_LOCKNB = 1 << 6, /* non-blocking lock mode */ - GDBM_FAST = 1 << 7, /* fast mode */ - GDBM_SPARSE = 1 << 8 /* create as sparse file */ -}; - -enum { /* enumeration for write modes */ - GDBM_INSERT, /* keep an existing value */ - GDBM_REPLACE /* overwrite an existing value */ -}; - -enum { /* enumeration for options */ - GDBM_CACHESIZE, /* set cache size */ - GDBM_FASTMODE, /* set fast mode */ - GDBM_SYNCMODE, /* set syncronous mode */ - GDBM_CENTFREE, /* set free block pool */ - GDBM_COALESCEBLKS /* set free block marging */ -}; - - -/* String containing the version information. */ -MYEXTERN char *gdbm_version; - - -/* Last happened error code. */ -#define gdbm_errno (*gdbm_errnoptr()) - - -/* Get a message string corresponding to an error code. - `gdbmerrno' specifies an error code. - The return value is the message string of the error code. The region of the return value - is not writable. */ -char *gdbm_strerror(gdbm_error gdbmerrno); - - -/* Get a database handle after the fashion of GDBM. - `name' specifies a name of a database. - `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', - `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or - directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. - You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', - `GDBM_LCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized - after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. - `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. - `GDBM_SPARSE' is an original mode of QDBM and makes database a sparse file. - `mode' specifies a mode of a database file or a database directory as the one of `open' - or `mkdir' call does. - `bnum' specifies the number of elements of each bucket array. If it is not more than 0, - the default value is specified. - `dnum' specifies the number of division of the database. If it is not more than 0, the - returning handle is created as a wrapper of Depot, else, it is as a wrapper of Curia. - The return value is the database handle or `NULL' if it is not successful. - If the database already exists, whether it is one of Depot or Curia is measured - automatically. */ -GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, - void (*fatal_func)(void)); - - -/* Get a database handle after the fashion of QDBM. - `name' specifies a name of a database. - `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', - `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or - directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. - You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', - `GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized - after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. - `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. - `GDBM_SPARSE' is an original mode of QDBM and makes database sparse files. - `mode' specifies a mode of a database file as the one of `open' or `mkdir' call does. - `bnum' specifies the number of elements of each bucket array. If it is not more than 0, - the default value is specified. - `dnum' specifies the number of division of the database. If it is not more than 0, the - returning handle is created as a wrapper of Depot, else, it is as a wrapper of Curia. - `align' specifies the basic size of alignment. - The return value is the database handle or `NULL' if it is not successful. */ -GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align); - - -/* Close a database handle. - `dbf' specifies a database handle. - Because the region of the closed handle is released, it becomes impossible to use the - handle. */ -void gdbm_close(GDBM_FILE dbf); - - -/* Store a record. - `dbf' specifies a database handle connected as a writer. - `key' specifies a structure of a key. `content' specifies a structure of a value. - `flag' specifies behavior when the key overlaps, by the following values: `GDBM_REPLACE', - which means the specified value overwrites the existing one, `GDBM_INSERT', which means - the existing value is kept. - The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, - -1 if other error occurs. */ -int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag); - - -/* Delete a record. - `dbf' specifies a database handle connected as a writer. - `key' specifies a structure of a key. - The return value is 0 if it is successful, -1 if some errors occur. */ -int gdbm_delete(GDBM_FILE dbf, datum key); - - -/* Retrieve a record. - `dbf' specifies a database handle. - `key' specifies a structure of a key. - The return value is a structure of the result. - If a record corresponds, the member `dptr' of the structure is the pointer to the region - of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. Because - the region pointed to by `dptr' is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -datum gdbm_fetch(GDBM_FILE dbf, datum key); - - -/* Check whether a record exists or not. - `dbf' specifies a database handle. - `key' specifies a structure of a key. - The return value is true if a record corresponds and no error occurs, or false, else, - it is false. */ -int gdbm_exists(GDBM_FILE dbf, datum key); - - -/* Get the first key of a database. - `dbf' specifies a database handle. - The return value is a structure of the result. - If a record corresponds, the member `dptr' of the structure is the pointer to the region - of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. - Because the region pointed to by `dptr' is allocated with the `malloc' call, it should - be released with the `free' call if it is no longer in use. */ -datum gdbm_firstkey(GDBM_FILE dbf); - - -/* Get the next key of a database. - `dbf' specifies a database handle. - The return value is a structure of the result. - If a record corresponds, the member `dptr' of the structure is the pointer to the region - of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. - Because the region pointed to by `dptr' is allocated with the `malloc' call, it should - be released with the `free' call if it is no longer in use. */ -datum gdbm_nextkey(GDBM_FILE dbf, datum key); - - -/* Synchronize updating contents with the file and the device. - `dbf' specifies a database handle connected as a writer. */ -void gdbm_sync(GDBM_FILE dbf); - - -/* Reorganize a database. - `dbf' specifies a database handle connected as a writer. - If successful, the return value is 0, else -1. */ -int gdbm_reorganize(GDBM_FILE dbf); - - -/* Get the file descriptor of a database file. - `dbf' specifies a database handle connected as a writer. - The return value is the file descriptor of the database file. - If the database is a directory the return value is -1. */ -int gdbm_fdesc(GDBM_FILE dbf); - - -/* No effect. - `dbf' specifies a database handle. - `option' is ignored. `size' is ignored. - The return value is 0. - The function is only for compatibility. */ -int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size); - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Get the pointer of the last happened error code. */ -int *gdbm_errnoptr(void); - - - -#undef MYEXTERN - -#if defined(__cplusplus) /* export for C++ */ -} -#endif - -#endif /* duplication check */ - - -/* END OF FILE */ Copied: box/trunk/qdbm/hovel.h (from rev 2716, box/trunk/qdbm/hovel.h) =================================================================== --- box/trunk/qdbm/hovel.h (rev 0) +++ box/trunk/qdbm/hovel.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,278 @@ +/************************************************************************************************* + * The GDBM-compatible API of QDBM + * 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. + *************************************************************************************************/ + + +#ifndef _HOVEL_H /* duplication check */ +#define _HOVEL_H + +#if defined(__cplusplus) /* export for C++ */ +extern "C" { +#endif + + +#include +#include +#include +#include +#include + + +#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) +#define MYEXTERN extern __declspec(dllimport) +#else +#define MYEXTERN extern +#endif + + + +/************************************************************************************************* + * API + *************************************************************************************************/ + + +enum { /* enumeration for error codes */ + GDBM_NO_ERROR, /* no error */ + GDBM_MALLOC_ERROR, /* malloc error */ + GDBM_BLOCK_SIZE_ERROR, /* block size error */ + GDBM_FILE_OPEN_ERROR, /* file open error */ + GDBM_FILE_WRITE_ERROR, /* file write error */ + GDBM_FILE_SEEK_ERROR, /* file seek error */ + GDBM_FILE_READ_ERROR, /* file read error */ + GDBM_BAD_MAGIC_NUMBER, /* bad magic number */ + GDBM_EMPTY_DATABASE, /* empty database */ + GDBM_CANT_BE_READER, /* can't be reader */ + GDBM_CANT_BE_WRITER, /* can't be writer */ + GDBM_READER_CANT_DELETE, /* reader can't delete */ + GDBM_READER_CANT_STORE, /* reader can't store */ + GDBM_READER_CANT_REORGANIZE, /* reader can't reorganize */ + GDBM_UNKNOWN_UPDATE, /* unknown update */ + GDBM_ITEM_NOT_FOUND, /* item not found */ + GDBM_REORGANIZE_FAILED, /* reorganize failed */ + GDBM_CANNOT_REPLACE, /* cannot replace */ + GDBM_ILLEGAL_DATA, /* illegal data */ + GDBM_OPT_ALREADY_SET, /* option already set */ + GDBM_OPT_ILLEGAL /* option illegal */ +}; + +typedef int gdbm_error; /* type of error codes */ + +typedef struct { /* type of structure for a database handle */ + DEPOT *depot; /* internal database handle of Depot */ + CURIA *curia; /* internal database handle of Curia */ + int syncmode; /* whether to be besyncronous mode */ +} GDBM; + +typedef GDBM *GDBM_FILE; /* type of pointer to a database handle */ + +typedef struct { /* type of structure for a key or a value */ + char *dptr; /* pointer to the region */ + size_t dsize; /* size of the region */ +} datum; + +enum { /* enumeration for open modes */ + GDBM_READER = 1 << 0, /* open as a reader */ + GDBM_WRITER = 1 << 1, /* open as a writer */ + GDBM_WRCREAT = 1 << 2, /* a writer creating */ + GDBM_NEWDB = 1 << 3, /* a writer creating and truncating */ + GDBM_SYNC = 1 << 4, /* syncronous mode */ + GDBM_NOLOCK = 1 << 5, /* no lock mode */ + GDBM_LOCKNB = 1 << 6, /* non-blocking lock mode */ + GDBM_FAST = 1 << 7, /* fast mode */ + GDBM_SPARSE = 1 << 8 /* create as sparse file */ +}; + +enum { /* enumeration for write modes */ + GDBM_INSERT, /* keep an existing value */ + GDBM_REPLACE /* overwrite an existing value */ +}; + +enum { /* enumeration for options */ + GDBM_CACHESIZE, /* set cache size */ + GDBM_FASTMODE, /* set fast mode */ + GDBM_SYNCMODE, /* set syncronous mode */ + GDBM_CENTFREE, /* set free block pool */ + GDBM_COALESCEBLKS /* set free block marging */ +}; + + +/* String containing the version information. */ +MYEXTERN char *gdbm_version; + + +/* Last happened error code. */ +#define gdbm_errno (*gdbm_errnoptr()) + + +/* Get a message string corresponding to an error code. + `gdbmerrno' specifies an error code. + The return value is the message string of the error code. The region of the return value + is not writable. */ +char *gdbm_strerror(gdbm_error gdbmerrno); + + +/* Get a database handle after the fashion of GDBM. + `name' specifies a name of a database. + `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', + `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or + directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. + You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', + `GDBM_LCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized + after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. + `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. + `GDBM_SPARSE' is an original mode of QDBM and makes database a sparse file. + `mode' specifies a mode of a database file or a database directory as the one of `open' + or `mkdir' call does. + `bnum' specifies the number of elements of each bucket array. If it is not more than 0, + the default value is specified. + `dnum' specifies the number of division of the database. If it is not more than 0, the + returning handle is created as a wrapper of Depot, else, it is as a wrapper of Curia. + The return value is the database handle or `NULL' if it is not successful. + If the database already exists, whether it is one of Depot or Curia is measured + automatically. */ +GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, + void (*fatal_func)(void)); + + +/* Get a database handle after the fashion of QDBM. + `name' specifies a name of a database. + `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', + `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or + directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. + You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', + `GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized + after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. + `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. + `GDBM_SPARSE' is an original mode of QDBM and makes database sparse files. + `mode' specifies a mode of a database file as the one of `open' or `mkdir' call does. + `bnum' specifies the number of elements of each bucket array. If it is not more than 0, + the default value is specified. + `dnum' specifies the number of division of the database. If it is not more than 0, the + returning handle is created as a wrapper of Depot, else, it is as a wrapper of Curia. + `align' specifies the basic size of alignment. + The return value is the database handle or `NULL' if it is not successful. */ +GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align); + + +/* Close a database handle. + `dbf' specifies a database handle. + Because the region of the closed handle is released, it becomes impossible to use the + handle. */ +void gdbm_close(GDBM_FILE dbf); + + +/* Store a record. + `dbf' specifies a database handle connected as a writer. + `key' specifies a structure of a key. `content' specifies a structure of a value. + `flag' specifies behavior when the key overlaps, by the following values: `GDBM_REPLACE', + which means the specified value overwrites the existing one, `GDBM_INSERT', which means + the existing value is kept. + The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, + -1 if other error occurs. */ +int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag); + + +/* Delete a record. + `dbf' specifies a database handle connected as a writer. + `key' specifies a structure of a key. + The return value is 0 if it is successful, -1 if some errors occur. */ +int gdbm_delete(GDBM_FILE dbf, datum key); + + +/* Retrieve a record. + `dbf' specifies a database handle. + `key' specifies a structure of a key. + The return value is a structure of the result. + If a record corresponds, the member `dptr' of the structure is the pointer to the region + of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. Because + the region pointed to by `dptr' is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +datum gdbm_fetch(GDBM_FILE dbf, datum key); + + +/* Check whether a record exists or not. + `dbf' specifies a database handle. + `key' specifies a structure of a key. + The return value is true if a record corresponds and no error occurs, or false, else, + it is false. */ +int gdbm_exists(GDBM_FILE dbf, datum key); + + +/* Get the first key of a database. + `dbf' specifies a database handle. + The return value is a structure of the result. + If a record corresponds, the member `dptr' of the structure is the pointer to the region + of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. + Because the region pointed to by `dptr' is allocated with the `malloc' call, it should + be released with the `free' call if it is no longer in use. */ +datum gdbm_firstkey(GDBM_FILE dbf); + + +/* Get the next key of a database. + `dbf' specifies a database handle. + The return value is a structure of the result. + If a record corresponds, the member `dptr' of the structure is the pointer to the region + of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. + Because the region pointed to by `dptr' is allocated with the `malloc' call, it should + be released with the `free' call if it is no longer in use. */ +datum gdbm_nextkey(GDBM_FILE dbf, datum key); + + +/* Synchronize updating contents with the file and the device. + `dbf' specifies a database handle connected as a writer. */ +void gdbm_sync(GDBM_FILE dbf); + + +/* Reorganize a database. + `dbf' specifies a database handle connected as a writer. + If successful, the return value is 0, else -1. */ +int gdbm_reorganize(GDBM_FILE dbf); + + +/* Get the file descriptor of a database file. + `dbf' specifies a database handle connected as a writer. + The return value is the file descriptor of the database file. + If the database is a directory the return value is -1. */ +int gdbm_fdesc(GDBM_FILE dbf); + + +/* No effect. + `dbf' specifies a database handle. + `option' is ignored. `size' is ignored. + The return value is 0. + The function is only for compatibility. */ +int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size); + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Get the pointer of the last happened error code. */ +int *gdbm_errnoptr(void); + + + +#undef MYEXTERN + +#if defined(__cplusplus) /* export for C++ */ +} +#endif + +#endif /* duplication check */ + + +/* END OF FILE */ Deleted: box/trunk/qdbm/hvmgr.c =================================================================== --- box/trunk/qdbm/hvmgr.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/hvmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,582 +0,0 @@ -/************************************************************************************************* - * Utility for debugging Hovel and its applications - * 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 -#include -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define ALIGNSIZ 16 /* basic size of alignment */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -char *hextoobj(const char *str, int *sp); -int runcreate(int argc, char **argv); -int runstore(int argc, char **argv); -int rundelete(int argc, char **argv); -int runfetch(int argc, char **argv); -int runlist(int argc, char **argv); -int runoptimize(int argc, char **argv); -void pgerror(const char *name); -void printobj(const char *obj, int size); -void printobjhex(const char *obj, int size); -int docreate(char *name, int qdbm, int bnum, int dnum, int sparse); -int dostore(char *name, int qdbm, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins); -int dodelete(char *name, int qdbm, const char *kbuf, int ksiz); -int dofetch(char *name, int qdbm, const char *kbuf, int ksiz, int ox, int nb); -int dolist(char *name, int qdbm, int ox); -int dooptimize(char *name, int qdbm); - - -/* main routine */ -int main(int argc, char **argv){ - int rv; - cbstdiobin(); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "create")){ - rv = runcreate(argc, argv); - } else if(!strcmp(argv[1], "store")){ - rv = runstore(argc, argv); - } else if(!strcmp(argv[1], "delete")){ - rv = rundelete(argc, argv); - } else if(!strcmp(argv[1], "fetch")){ - rv = runfetch(argc, argv); - } else if(!strcmp(argv[1], "list")){ - rv = runlist(argc, argv); - } else if(!strcmp(argv[1], "optimize")){ - rv = runoptimize(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: administration utility for Hovel\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s create [-qdbm bnum dnum] [-s] name\n", progname); - fprintf(stderr, " %s store [-qdbm] [-kx] [-vx|-vf] [-insert] name key val\n", progname); - fprintf(stderr, " %s delete [-qdbm] [-kx] name key\n", progname); - fprintf(stderr, " %s fetch [-qdbm] [-kx] [-ox] [-n] name key\n", progname); - fprintf(stderr, " %s list [-qdbm] [-ox] name\n", progname); - fprintf(stderr, " %s optimize [-qdbm] name\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* create a binary object from a hexadecimal string */ -char *hextoobj(const char *str, int *sp){ - char *buf, mbuf[3]; - int len, i, j; - len = strlen(str); - if(!(buf = malloc(len + 1))) return NULL; - j = 0; - for(i = 0; i < len; i += 2){ - while(strchr(" \n\r\t\f\v", str[i])){ - i++; - } - if((mbuf[0] = str[i]) == '\0') break; - if((mbuf[1] = str[i+1]) == '\0') break; - mbuf[2] = '\0'; - buf[j++] = (char)strtol(mbuf, NULL, 16); - } - buf[j] = '\0'; - *sp = j; - return buf; -} - - -/* parse arguments of create command */ -int runcreate(int argc, char **argv){ - char *name; - int i, sb, qdbm, bnum, dnum, rv; - name = NULL; - sb = FALSE; - qdbm = FALSE; - bnum = -1; - dnum = -1; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-qdbm")){ - qdbm = TRUE; - if(++i >= argc) usage(); - bnum = atoi(argv[i]); - if(++i >= argc) usage(); - dnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-s")){ - sb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = docreate(name, qdbm, bnum, dnum, sb); - return rv; -} - - -/* parse arguments of store command */ -int runstore(int argc, char **argv){ - char *name, *key, *val, *kbuf, *vbuf; - int i, qdbm, kx, vx, vf, ins, ksiz, vsiz, rv; - name = NULL; - qdbm = FALSE; - kx = FALSE; - vx = FALSE; - vf = FALSE; - ins = FALSE; - key = NULL; - val = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-qdbm")){ - qdbm = TRUE; - } else if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-vx")){ - vx = TRUE; - } else if(!strcmp(argv[i], "-vf")){ - vf = TRUE; - } else if(!strcmp(argv[i], "-insert")){ - ins = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else if(!val){ - val = argv[i]; - } else { - usage(); - } - } - if(!name || !key || !val) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = strlen(kbuf); - } - if(vx){ - vbuf = hextoobj(val, &vsiz); - } else if(vf){ - vbuf = cbreadfile(val, &vsiz); - } else { - vbuf = cbmemdup(val, -1); - vsiz = strlen(vbuf); - } - if(kbuf && vbuf){ - rv = dostore(name, qdbm, kbuf, ksiz, vbuf, vsiz, ins); - } else { - if(vf){ - fprintf(stderr, "%s: %s: cannot read\n", progname, val); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - } - rv = 1; - } - free(kbuf); - free(vbuf); - return rv; -} - - -/* parse arguments of delete command */ -int rundelete(int argc, char **argv){ - char *name, *key, *kbuf; - int i, qdbm, kx, ksiz, rv; - name = NULL; - qdbm = FALSE; - kx = FALSE; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-qdbm")){ - qdbm = TRUE; - } else if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = strlen(kbuf); - } - if(kbuf){ - rv = dodelete(name, qdbm, kbuf, ksiz); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* parse arguments of fetch command */ -int runfetch(int argc, char **argv){ - char *name, *key, *kbuf; - int i, qdbm, kx, ox, nb, ksiz, rv; - name = NULL; - qdbm = FALSE; - kx = FALSE; - ox = FALSE; - nb = FALSE; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-qdbm")){ - qdbm = TRUE; - } else if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else if(!strcmp(argv[i], "-n")){ - nb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = strlen(kbuf); - } - if(kbuf){ - rv = dofetch(name, qdbm, kbuf, ksiz, ox, nb); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* parse arguments of list command */ -int runlist(int argc, char **argv){ - char *name; - int i, qdbm, ox, rv; - name = NULL; - qdbm = FALSE; - ox = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-qdbm")){ - qdbm = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dolist(name, qdbm, ox); - return rv; -} - - -/* parse arguments of optimize command */ -int runoptimize(int argc, char **argv){ - char *name; - int i, qdbm, rv; - name = NULL; - qdbm = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-qdbm")){ - qdbm = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dooptimize(name, qdbm); - return rv; -} - - -/* print an error message */ -void pgerror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, gdbm_strerror(gdbm_errno)); -} - - -/* print an object */ -void printobj(const char *obj, int size){ - int i; - for(i = 0; i < size; i++){ - putchar(obj[i]); - } -} - - -/* print an object as a hexadecimal string */ -void printobjhex(const char *obj, int size){ - int i; - for(i = 0; i < size; i++){ - printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); - } -} - - -/* perform create command */ -int docreate(char *name, int qdbm, int bnum, int dnum, int sparse){ - GDBM_FILE dbf; - int rwmode; - rwmode = GDBM_NEWDB | (sparse ? GDBM_SPARSE : 0); - if(qdbm){ - if(!(dbf = gdbm_open2(name, rwmode, 00644, bnum, dnum, ALIGNSIZ))){ - pgerror(name); - return 1; - } - } else { - if(!(dbf = gdbm_open(name, 0, rwmode, 00644, NULL))){ - pgerror(name); - return 1; - } - } - gdbm_close(dbf); - return 0; -} - - -/* perform store command */ -int dostore(char *name, int qdbm, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins){ - GDBM_FILE dbf; - datum key, content; - int rv; - if(qdbm){ - if(!(dbf = gdbm_open2(name, GDBM_WRITER, 00644, -1, -1, ALIGNSIZ))){ - pgerror(name); - return 1; - } - } else { - if(!(dbf = gdbm_open(name, 0, GDBM_WRITER, 00644, NULL))){ - pgerror(name); - return 1; - } - } - key.dptr = (char *)kbuf; - key.dsize = ksiz; - content.dptr = (char *)vbuf; - content.dsize = vsiz; - rv = 0; - if(gdbm_store(dbf, key, content, ins ? GDBM_INSERT : GDBM_REPLACE) != 0){ - pgerror(name); - rv = 1; - } - gdbm_close(dbf); - return rv; -} - - -/* perform delete command */ -int dodelete(char *name, int qdbm, const char *kbuf, int ksiz){ - GDBM_FILE dbf; - datum key; - int rv; - if(qdbm){ - if(!(dbf = gdbm_open2(name, GDBM_WRITER, 00644, -1, -1, ALIGNSIZ))){ - pgerror(name); - return 1; - } - } else { - if(!(dbf = gdbm_open(name, 0, GDBM_WRITER, 00644, NULL))){ - pgerror(name); - return 1; - } - } - key.dptr = (char *)kbuf; - key.dsize = ksiz; - if(gdbm_delete(dbf, key) == 0){ - rv = 0; - } else { - pgerror(name); - rv = 1; - } - gdbm_close(dbf); - return rv; -} - - -/* perform fetch command */ -int dofetch(char *name, int qdbm, const char *kbuf, int ksiz, int ox, int nb){ - GDBM_FILE dbf; - datum key, content; - int rv; - if(qdbm){ - if(!(dbf = gdbm_open2(name, GDBM_READER, 00644, -1, -1, -1))){ - pgerror(name); - return 1; - } - } else { - if(!(dbf = gdbm_open(name, 0, GDBM_READER, 00644, NULL))){ - pgerror(name); - return 1; - } - } - key.dptr = (char *)kbuf; - key.dsize = ksiz; - content = gdbm_fetch(dbf, key); - if(content.dptr){ - if(ox){ - printobjhex(content.dptr, content.dsize); - } else { - printobj(content.dptr, content.dsize); - } - if(!nb) putchar('\n'); - rv = 0; - free(content.dptr); - } else { - pgerror(name); - rv = 1; - } - gdbm_close(dbf); - return rv; -} - - -/* perform list command */ -int dolist(char *name, int qdbm, int ox){ - GDBM_FILE dbf; - datum key, val; - if(qdbm){ - if(!(dbf = gdbm_open2(name, GDBM_READER, 00644, -1, -1, -1))){ - pgerror(name); - return 1; - } - } else { - if(!(dbf = gdbm_open(name, 0, GDBM_READER, 00644, NULL))){ - pgerror(name); - return 1; - } - } - for(key = gdbm_firstkey(dbf); key.dptr != NULL; key = gdbm_nextkey(dbf, key)){ - val = gdbm_fetch(dbf, key); - if(!val.dptr){ - free(key.dptr); - break; - } - if(ox){ - printobjhex(key.dptr, key.dsize); - putchar('\t'); - printobjhex(val.dptr, val.dsize); - } else { - printobj(key.dptr, key.dsize); - putchar('\t'); - printobj(val.dptr, val.dsize); - } - putchar('\n'); - free(val.dptr); - free(key.dptr); - } - gdbm_close(dbf); - return 0; -} - - -/* perform optimize command */ -int dooptimize(char *name, int qdbm){ - GDBM_FILE dbf; - int rv; - if(qdbm){ - if(!(dbf = gdbm_open2(name, GDBM_WRITER, 00644, -1, -1, ALIGNSIZ))){ - pgerror(name); - return 1; - } - } else { - if(!(dbf = gdbm_open(name, 0, GDBM_WRITER, 00644, NULL))){ - pgerror(name); - return 1; - } - } - rv = 0; - if(gdbm_reorganize(dbf) != 0){ - pgerror(name); - rv = 1; - } - gdbm_close(dbf); - return rv; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/hvmgr.c (from rev 2716, box/trunk/qdbm/hvmgr.c) =================================================================== --- box/trunk/qdbm/hvmgr.c (rev 0) +++ box/trunk/qdbm/hvmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,582 @@ +/************************************************************************************************* + * Utility for debugging Hovel and its applications + * 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 +#include +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define ALIGNSIZ 16 /* basic size of alignment */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +char *hextoobj(const char *str, int *sp); +int runcreate(int argc, char **argv); +int runstore(int argc, char **argv); +int rundelete(int argc, char **argv); +int runfetch(int argc, char **argv); +int runlist(int argc, char **argv); +int runoptimize(int argc, char **argv); +void pgerror(const char *name); +void printobj(const char *obj, int size); +void printobjhex(const char *obj, int size); +int docreate(char *name, int qdbm, int bnum, int dnum, int sparse); +int dostore(char *name, int qdbm, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins); +int dodelete(char *name, int qdbm, const char *kbuf, int ksiz); +int dofetch(char *name, int qdbm, const char *kbuf, int ksiz, int ox, int nb); +int dolist(char *name, int qdbm, int ox); +int dooptimize(char *name, int qdbm); + + +/* main routine */ +int main(int argc, char **argv){ + int rv; + cbstdiobin(); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "create")){ + rv = runcreate(argc, argv); + } else if(!strcmp(argv[1], "store")){ + rv = runstore(argc, argv); + } else if(!strcmp(argv[1], "delete")){ + rv = rundelete(argc, argv); + } else if(!strcmp(argv[1], "fetch")){ + rv = runfetch(argc, argv); + } else if(!strcmp(argv[1], "list")){ + rv = runlist(argc, argv); + } else if(!strcmp(argv[1], "optimize")){ + rv = runoptimize(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: administration utility for Hovel\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s create [-qdbm bnum dnum] [-s] name\n", progname); + fprintf(stderr, " %s store [-qdbm] [-kx] [-vx|-vf] [-insert] name key val\n", progname); + fprintf(stderr, " %s delete [-qdbm] [-kx] name key\n", progname); + fprintf(stderr, " %s fetch [-qdbm] [-kx] [-ox] [-n] name key\n", progname); + fprintf(stderr, " %s list [-qdbm] [-ox] name\n", progname); + fprintf(stderr, " %s optimize [-qdbm] name\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* create a binary object from a hexadecimal string */ +char *hextoobj(const char *str, int *sp){ + char *buf, mbuf[3]; + int len, i, j; + len = strlen(str); + if(!(buf = malloc(len + 1))) return NULL; + j = 0; + for(i = 0; i < len; i += 2){ + while(strchr(" \n\r\t\f\v", str[i])){ + i++; + } + if((mbuf[0] = str[i]) == '\0') break; + if((mbuf[1] = str[i+1]) == '\0') break; + mbuf[2] = '\0'; + buf[j++] = (char)strtol(mbuf, NULL, 16); + } + buf[j] = '\0'; + *sp = j; + return buf; +} + + +/* parse arguments of create command */ +int runcreate(int argc, char **argv){ + char *name; + int i, sb, qdbm, bnum, dnum, rv; + name = NULL; + sb = FALSE; + qdbm = FALSE; + bnum = -1; + dnum = -1; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-qdbm")){ + qdbm = TRUE; + if(++i >= argc) usage(); + bnum = atoi(argv[i]); + if(++i >= argc) usage(); + dnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-s")){ + sb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = docreate(name, qdbm, bnum, dnum, sb); + return rv; +} + + +/* parse arguments of store command */ +int runstore(int argc, char **argv){ + char *name, *key, *val, *kbuf, *vbuf; + int i, qdbm, kx, vx, vf, ins, ksiz, vsiz, rv; + name = NULL; + qdbm = FALSE; + kx = FALSE; + vx = FALSE; + vf = FALSE; + ins = FALSE; + key = NULL; + val = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-qdbm")){ + qdbm = TRUE; + } else if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-vx")){ + vx = TRUE; + } else if(!strcmp(argv[i], "-vf")){ + vf = TRUE; + } else if(!strcmp(argv[i], "-insert")){ + ins = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else if(!val){ + val = argv[i]; + } else { + usage(); + } + } + if(!name || !key || !val) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = strlen(kbuf); + } + if(vx){ + vbuf = hextoobj(val, &vsiz); + } else if(vf){ + vbuf = cbreadfile(val, &vsiz); + } else { + vbuf = cbmemdup(val, -1); + vsiz = strlen(vbuf); + } + if(kbuf && vbuf){ + rv = dostore(name, qdbm, kbuf, ksiz, vbuf, vsiz, ins); + } else { + if(vf){ + fprintf(stderr, "%s: %s: cannot read\n", progname, val); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + } + rv = 1; + } + free(kbuf); + free(vbuf); + return rv; +} + + +/* parse arguments of delete command */ +int rundelete(int argc, char **argv){ + char *name, *key, *kbuf; + int i, qdbm, kx, ksiz, rv; + name = NULL; + qdbm = FALSE; + kx = FALSE; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-qdbm")){ + qdbm = TRUE; + } else if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = strlen(kbuf); + } + if(kbuf){ + rv = dodelete(name, qdbm, kbuf, ksiz); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* parse arguments of fetch command */ +int runfetch(int argc, char **argv){ + char *name, *key, *kbuf; + int i, qdbm, kx, ox, nb, ksiz, rv; + name = NULL; + qdbm = FALSE; + kx = FALSE; + ox = FALSE; + nb = FALSE; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-qdbm")){ + qdbm = TRUE; + } else if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else if(!strcmp(argv[i], "-n")){ + nb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = strlen(kbuf); + } + if(kbuf){ + rv = dofetch(name, qdbm, kbuf, ksiz, ox, nb); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* parse arguments of list command */ +int runlist(int argc, char **argv){ + char *name; + int i, qdbm, ox, rv; + name = NULL; + qdbm = FALSE; + ox = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-qdbm")){ + qdbm = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dolist(name, qdbm, ox); + return rv; +} + + +/* parse arguments of optimize command */ +int runoptimize(int argc, char **argv){ + char *name; + int i, qdbm, rv; + name = NULL; + qdbm = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-qdbm")){ + qdbm = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dooptimize(name, qdbm); + return rv; +} + + +/* print an error message */ +void pgerror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, gdbm_strerror(gdbm_errno)); +} + + +/* print an object */ +void printobj(const char *obj, int size){ + int i; + for(i = 0; i < size; i++){ + putchar(obj[i]); + } +} + + +/* print an object as a hexadecimal string */ +void printobjhex(const char *obj, int size){ + int i; + for(i = 0; i < size; i++){ + printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); + } +} + + +/* perform create command */ +int docreate(char *name, int qdbm, int bnum, int dnum, int sparse){ + GDBM_FILE dbf; + int rwmode; + rwmode = GDBM_NEWDB | (sparse ? GDBM_SPARSE : 0); + if(qdbm){ + if(!(dbf = gdbm_open2(name, rwmode, 00644, bnum, dnum, ALIGNSIZ))){ + pgerror(name); + return 1; + } + } else { + if(!(dbf = gdbm_open(name, 0, rwmode, 00644, NULL))){ + pgerror(name); + return 1; + } + } + gdbm_close(dbf); + return 0; +} + + +/* perform store command */ +int dostore(char *name, int qdbm, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins){ + GDBM_FILE dbf; + datum key, content; + int rv; + if(qdbm){ + if(!(dbf = gdbm_open2(name, GDBM_WRITER, 00644, -1, -1, ALIGNSIZ))){ + pgerror(name); + return 1; + } + } else { + if(!(dbf = gdbm_open(name, 0, GDBM_WRITER, 00644, NULL))){ + pgerror(name); + return 1; + } + } + key.dptr = (char *)kbuf; + key.dsize = ksiz; + content.dptr = (char *)vbuf; + content.dsize = vsiz; + rv = 0; + if(gdbm_store(dbf, key, content, ins ? GDBM_INSERT : GDBM_REPLACE) != 0){ + pgerror(name); + rv = 1; + } + gdbm_close(dbf); + return rv; +} + + +/* perform delete command */ +int dodelete(char *name, int qdbm, const char *kbuf, int ksiz){ + GDBM_FILE dbf; + datum key; + int rv; + if(qdbm){ + if(!(dbf = gdbm_open2(name, GDBM_WRITER, 00644, -1, -1, ALIGNSIZ))){ + pgerror(name); + return 1; + } + } else { + if(!(dbf = gdbm_open(name, 0, GDBM_WRITER, 00644, NULL))){ + pgerror(name); + return 1; + } + } + key.dptr = (char *)kbuf; + key.dsize = ksiz; + if(gdbm_delete(dbf, key) == 0){ + rv = 0; + } else { + pgerror(name); + rv = 1; + } + gdbm_close(dbf); + return rv; +} + + +/* perform fetch command */ +int dofetch(char *name, int qdbm, const char *kbuf, int ksiz, int ox, int nb){ + GDBM_FILE dbf; + datum key, content; + int rv; + if(qdbm){ + if(!(dbf = gdbm_open2(name, GDBM_READER, 00644, -1, -1, -1))){ + pgerror(name); + return 1; + } + } else { + if(!(dbf = gdbm_open(name, 0, GDBM_READER, 00644, NULL))){ + pgerror(name); + return 1; + } + } + key.dptr = (char *)kbuf; + key.dsize = ksiz; + content = gdbm_fetch(dbf, key); + if(content.dptr){ + if(ox){ + printobjhex(content.dptr, content.dsize); + } else { + printobj(content.dptr, content.dsize); + } + if(!nb) putchar('\n'); + rv = 0; + free(content.dptr); + } else { + pgerror(name); + rv = 1; + } + gdbm_close(dbf); + return rv; +} + + +/* perform list command */ +int dolist(char *name, int qdbm, int ox){ + GDBM_FILE dbf; + datum key, val; + if(qdbm){ + if(!(dbf = gdbm_open2(name, GDBM_READER, 00644, -1, -1, -1))){ + pgerror(name); + return 1; + } + } else { + if(!(dbf = gdbm_open(name, 0, GDBM_READER, 00644, NULL))){ + pgerror(name); + return 1; + } + } + for(key = gdbm_firstkey(dbf); key.dptr != NULL; key = gdbm_nextkey(dbf, key)){ + val = gdbm_fetch(dbf, key); + if(!val.dptr){ + free(key.dptr); + break; + } + if(ox){ + printobjhex(key.dptr, key.dsize); + putchar('\t'); + printobjhex(val.dptr, val.dsize); + } else { + printobj(key.dptr, key.dsize); + putchar('\t'); + printobj(val.dptr, val.dsize); + } + putchar('\n'); + free(val.dptr); + free(key.dptr); + } + gdbm_close(dbf); + return 0; +} + + +/* perform optimize command */ +int dooptimize(char *name, int qdbm){ + GDBM_FILE dbf; + int rv; + if(qdbm){ + if(!(dbf = gdbm_open2(name, GDBM_WRITER, 00644, -1, -1, ALIGNSIZ))){ + pgerror(name); + return 1; + } + } else { + if(!(dbf = gdbm_open(name, 0, GDBM_WRITER, 00644, NULL))){ + pgerror(name); + return 1; + } + } + rv = 0; + if(gdbm_reorganize(dbf) != 0){ + pgerror(name); + rv = 1; + } + gdbm_close(dbf); + return rv; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/hvtest.c =================================================================== --- box/trunk/qdbm/hvtest.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/hvtest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,272 +0,0 @@ -/************************************************************************************************* - * Test cases of Hovel - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define DIVNUM 5 /* number of division */ -#define ALIGNSIZ 16 /* basic size of alignment */ -#define RECBUFSIZ 32 /* buffer for records */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -int runwrite(int argc, char **argv); -int runread(int argc, char **argv); -int printfflush(const char *format, ...); -void pgerror(const char *name); -int dowrite(char *name, int rnum, int qdbm, int sparse); -int doread(char *name, int rnum, int qdbm); - - -/* main routine */ -int main(int argc, char **argv){ - int rv; - cbstdiobin(); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "write")){ - rv = runwrite(argc, argv); - } else if(!strcmp(argv[1], "read")){ - rv = runread(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: test cases for Hovel\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s write [-qdbm] [-s] name rnum\n", progname); - fprintf(stderr, " %s read [-qdbm] name rnum\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of write command */ -int runwrite(int argc, char **argv){ - char *name, *rstr; - int i, sb, qdbm, rnum, rv; - name = NULL; - rstr = NULL; - rnum = 0; - sb = FALSE; - qdbm = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-qdbm")){ - qdbm = TRUE; - } else if(!strcmp(argv[i], "-s")){ - sb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = dowrite(name, rnum, qdbm, sb); - return rv; -} - - -/* parse arguments of read command */ -int runread(int argc, char **argv){ - char *name, *rstr; - int i, qdbm, rnum, rv; - name = NULL; - rstr = NULL; - rnum = 0; - qdbm = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-qdbm")){ - qdbm = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = doread(name, rnum, qdbm); - return rv; -} - - -/* print formatted string and flush the buffer */ -int printfflush(const char *format, ...){ - va_list ap; - int rv; - va_start(ap, format); - rv = vprintf(format, ap); - if(fflush(stdout) == EOF) rv = -1; - va_end(ap); - return rv; -} - - -/* print an error message */ -void pgerror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, gdbm_strerror(gdbm_errno)); -} - - -/* perform write command */ -int dowrite(char *name, int rnum, int qdbm, int sparse){ - GDBM_FILE dbf; - datum key, content; - int i, rwmode, err, len; - char buf[RECBUFSIZ]; - printfflush("\n name=%s rnum=%d qdbm=%d\n\n", name, rnum, qdbm); - /* open a database */ - rwmode = GDBM_NEWDB | (sparse ? GDBM_SPARSE : 0); - if(qdbm){ - if(!(dbf = gdbm_open2(name, rwmode, 00644, rnum / DIVNUM, DIVNUM, ALIGNSIZ))){ - pgerror(name); - return 1; - } - } else { - if(!(dbf = gdbm_open(name, 0, rwmode, 00644, NULL))){ - pgerror(name); - return 1; - } - } - err = FALSE; - /* loop for each record */ - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", i); - key.dptr = buf; - key.dsize = len; - content.dptr = buf; - content.dsize = len; - /* store a record */ - if(gdbm_store(dbf, key, content, GDBM_REPLACE) != 0){ - pgerror(name); - err = TRUE; - break; - } - /* print progression */ - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - gdbm_close(dbf); - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform read command */ -int doread(char *name, int rnum, int qdbm){ - GDBM_FILE dbf; - datum key, content; - int i, err, len; - char buf[RECBUFSIZ]; - printfflush("\n name=%s rnum=%d qdbm=%d\n\n", name, rnum, qdbm); - /* open a database */ - if(qdbm){ - if(!(dbf = gdbm_open2(name, GDBM_READER, 00644, -1, -1, -1))){ - pgerror(name); - return 1; - } - } else { - if(!(dbf = gdbm_open(name, 0, GDBM_READER, 00644, NULL))){ - pgerror(name); - return 1; - } - } - err = FALSE; - /* loop for each record */ - for(i = 1; i <= rnum; i++){ - /* retrieve a record */ - len = sprintf(buf, "%08d", i); - key.dptr = buf; - key.dsize = len; - content = gdbm_fetch(dbf, key); - if(!content.dptr){ - pgerror(name); - err = TRUE; - break; - } - free(content.dptr); - /* print progression */ - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - gdbm_close(dbf); - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/hvtest.c (from rev 2716, box/trunk/qdbm/hvtest.c) =================================================================== --- box/trunk/qdbm/hvtest.c (rev 0) +++ box/trunk/qdbm/hvtest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,272 @@ +/************************************************************************************************* + * Test cases of Hovel + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define DIVNUM 5 /* number of division */ +#define ALIGNSIZ 16 /* basic size of alignment */ +#define RECBUFSIZ 32 /* buffer for records */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +int runwrite(int argc, char **argv); +int runread(int argc, char **argv); +int printfflush(const char *format, ...); +void pgerror(const char *name); +int dowrite(char *name, int rnum, int qdbm, int sparse); +int doread(char *name, int rnum, int qdbm); + + +/* main routine */ +int main(int argc, char **argv){ + int rv; + cbstdiobin(); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "write")){ + rv = runwrite(argc, argv); + } else if(!strcmp(argv[1], "read")){ + rv = runread(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: test cases for Hovel\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s write [-qdbm] [-s] name rnum\n", progname); + fprintf(stderr, " %s read [-qdbm] name rnum\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of write command */ +int runwrite(int argc, char **argv){ + char *name, *rstr; + int i, sb, qdbm, rnum, rv; + name = NULL; + rstr = NULL; + rnum = 0; + sb = FALSE; + qdbm = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-qdbm")){ + qdbm = TRUE; + } else if(!strcmp(argv[i], "-s")){ + sb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = dowrite(name, rnum, qdbm, sb); + return rv; +} + + +/* parse arguments of read command */ +int runread(int argc, char **argv){ + char *name, *rstr; + int i, qdbm, rnum, rv; + name = NULL; + rstr = NULL; + rnum = 0; + qdbm = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-qdbm")){ + qdbm = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = doread(name, rnum, qdbm); + return rv; +} + + +/* print formatted string and flush the buffer */ +int printfflush(const char *format, ...){ + va_list ap; + int rv; + va_start(ap, format); + rv = vprintf(format, ap); + if(fflush(stdout) == EOF) rv = -1; + va_end(ap); + return rv; +} + + +/* print an error message */ +void pgerror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, gdbm_strerror(gdbm_errno)); +} + + +/* perform write command */ +int dowrite(char *name, int rnum, int qdbm, int sparse){ + GDBM_FILE dbf; + datum key, content; + int i, rwmode, err, len; + char buf[RECBUFSIZ]; + printfflush("\n name=%s rnum=%d qdbm=%d\n\n", name, rnum, qdbm); + /* open a database */ + rwmode = GDBM_NEWDB | (sparse ? GDBM_SPARSE : 0); + if(qdbm){ + if(!(dbf = gdbm_open2(name, rwmode, 00644, rnum / DIVNUM, DIVNUM, ALIGNSIZ))){ + pgerror(name); + return 1; + } + } else { + if(!(dbf = gdbm_open(name, 0, rwmode, 00644, NULL))){ + pgerror(name); + return 1; + } + } + err = FALSE; + /* loop for each record */ + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", i); + key.dptr = buf; + key.dsize = len; + content.dptr = buf; + content.dsize = len; + /* store a record */ + if(gdbm_store(dbf, key, content, GDBM_REPLACE) != 0){ + pgerror(name); + err = TRUE; + break; + } + /* print progression */ + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + gdbm_close(dbf); + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform read command */ +int doread(char *name, int rnum, int qdbm){ + GDBM_FILE dbf; + datum key, content; + int i, err, len; + char buf[RECBUFSIZ]; + printfflush("\n name=%s rnum=%d qdbm=%d\n\n", name, rnum, qdbm); + /* open a database */ + if(qdbm){ + if(!(dbf = gdbm_open2(name, GDBM_READER, 00644, -1, -1, -1))){ + pgerror(name); + return 1; + } + } else { + if(!(dbf = gdbm_open(name, 0, GDBM_READER, 00644, NULL))){ + pgerror(name); + return 1; + } + } + err = FALSE; + /* loop for each record */ + for(i = 1; i <= rnum; i++){ + /* retrieve a record */ + len = sprintf(buf, "%08d", i); + key.dptr = buf; + key.dsize = len; + content = gdbm_fetch(dbf, key); + if(!content.dptr){ + pgerror(name); + err = TRUE; + break; + } + free(content.dptr); + /* print progression */ + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + gdbm_close(dbf); + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/misc/COPYING.txt =================================================================== --- box/trunk/qdbm/misc/COPYING.txt 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/misc/COPYING.txt 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library 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 (at your option) any later version. - - This library 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 this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - Copied: box/trunk/qdbm/misc/COPYING.txt (from rev 2716, box/trunk/qdbm/misc/COPYING.txt) =================================================================== --- box/trunk/qdbm/misc/COPYING.txt (rev 0) +++ box/trunk/qdbm/misc/COPYING.txt 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library 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 (at your option) any later version. + + This library 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 this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + Deleted: box/trunk/qdbm/misc/README-win32.txt =================================================================== --- box/trunk/qdbm/misc/README-win32.txt 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/misc/README-win32.txt 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,101 +0,0 @@ -================================================================ - QDBM: Quick Database Manager - Copyright (C) 2000-2007 Mikio Hirabayashi -================================================================ - -This is a package of Win32 binaries of QDBM. It contains C/Java -APIs, their utility commands, and CGI scripts. - -See http://qdbm.sourceforge.net/ for more information. - - -The following are documents of specifications. - - spex.html : fundamental specifications - spex-ja.html : fundamental specifications in Japanese - jspex.html : specifications of Java API - jspex-ja.html : specifications of Java API in Japanese - japidoc/ : documents of Java API - - -The following are header files of C language. -Include them at source codes of your applications. - - depot.h - curia.h - relic.h - hovel.h - cabin.h - villa.h - vista.h - odeum.h - - -The following are dynamic linking libraries for the API of C. -Copy them to the system directory or a directory of your project. - - qdbm.dll : QDBM itself - libqdbm.dll.a : import library for `qdbm.dll' - mgwz.dll : ZLIB - libiconv-2.dll : ICONV - - -The following is a dynamic linking library for the API of Java. -Copy it to the system directory or a directory of your project. - - jqdbm.dll - - -The following is a Java archive of the classes. -Include it in the CLASSPATH of your environment. - - qdbm.jar - - -The following are utility commands for testing and debugging. - - dpmgr.exe - dptest.exe - dptsv.exe - crmgr.exe - crtest.exe - crtsv.exe - rlmgr.exe - rltest.exe - hvmgr.exe - hvtest.exe - cbtest.exe - cbcodec.exe - vlmgr.exe - vltest.exe - vltsv.exe - odmgr.exe - odtest.exe - odidx.exe - qmttest.exe - - -The sub directory `cgi' contains CGI scripts, their configuration -files, and their specifications. - -If you want an import library or a static library for Visual C++, -please obtain the source package and use VCmakefile in it. - - -QDBM was released under the terms of the GNU Lesser General Public -License. See the file `COPYING.txt' for details. - -QDBM was written by Mikio Hirabayashi. You can contact the author -by e-mail to `mikio at users.sourceforge.net'. However, as for -topics which can be shared among other users, pleae send it to -the mailing list. To join the mailing list, refer to the following -URL. - - http://lists.sourceforge.net/lists/listinfo/qdbm-users - - -Thanks. - - - -== END OF FILE == Copied: box/trunk/qdbm/misc/README-win32.txt (from rev 2716, box/trunk/qdbm/misc/README-win32.txt) =================================================================== --- box/trunk/qdbm/misc/README-win32.txt (rev 0) +++ box/trunk/qdbm/misc/README-win32.txt 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,101 @@ +================================================================ + QDBM: Quick Database Manager + Copyright (C) 2000-2007 Mikio Hirabayashi +================================================================ + +This is a package of Win32 binaries of QDBM. It contains C/Java +APIs, their utility commands, and CGI scripts. + +See http://qdbm.sourceforge.net/ for more information. + + +The following are documents of specifications. + + spex.html : fundamental specifications + spex-ja.html : fundamental specifications in Japanese + jspex.html : specifications of Java API + jspex-ja.html : specifications of Java API in Japanese + japidoc/ : documents of Java API + + +The following are header files of C language. +Include them at source codes of your applications. + + depot.h + curia.h + relic.h + hovel.h + cabin.h + villa.h + vista.h + odeum.h + + +The following are dynamic linking libraries for the API of C. +Copy them to the system directory or a directory of your project. + + qdbm.dll : QDBM itself + libqdbm.dll.a : import library for `qdbm.dll' + mgwz.dll : ZLIB + libiconv-2.dll : ICONV + + +The following is a dynamic linking library for the API of Java. +Copy it to the system directory or a directory of your project. + + jqdbm.dll + + +The following is a Java archive of the classes. +Include it in the CLASSPATH of your environment. + + qdbm.jar + + +The following are utility commands for testing and debugging. + + dpmgr.exe + dptest.exe + dptsv.exe + crmgr.exe + crtest.exe + crtsv.exe + rlmgr.exe + rltest.exe + hvmgr.exe + hvtest.exe + cbtest.exe + cbcodec.exe + vlmgr.exe + vltest.exe + vltsv.exe + odmgr.exe + odtest.exe + odidx.exe + qmttest.exe + + +The sub directory `cgi' contains CGI scripts, their configuration +files, and their specifications. + +If you want an import library or a static library for Visual C++, +please obtain the source package and use VCmakefile in it. + + +QDBM was released under the terms of the GNU Lesser General Public +License. See the file `COPYING.txt' for details. + +QDBM was written by Mikio Hirabayashi. You can contact the author +by e-mail to `mikio at users.sourceforge.net'. However, as for +topics which can be shared among other users, pleae send it to +the mailing list. To join the mailing list, refer to the following +URL. + + http://lists.sourceforge.net/lists/listinfo/qdbm-users + + +Thanks. + + + +== END OF FILE == Deleted: box/trunk/qdbm/misc/VCmakefile-old =================================================================== --- box/trunk/qdbm/misc/VCmakefile-old 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/misc/VCmakefile-old 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,169 +0,0 @@ -# Makefile to build QDBM using Microsoft Visual C++ - - - -#================================================================ -# Setting Variables -#================================================================ - - -# Targets -MYLIBS = qdbm.lib -LIBOBJS = depot.obj curia.obj relic.obj hovel.obj \ - cabin.obj villa.obj vista.obj odeum.obj myconf.obj -MYBINS = dpmgr.exe dptest.exe dptsv.exe crmgr.exe crtest.exe crtsv.exe \ - rlmgr.exe rltest.exe hvmgr.exe hvtest.exe cbtest.exe cbcodec.exe \ - vlmgr.exe vltest.exe vltsv.exe odmgr.exe odtest.exe odidx.exe - -# VC++ directory -VCPATH = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7 - -# Building binaries -CLFLAGS = /I "$(VCPATH)\Include" /I "$(VCPATH)\PlatformSDK\Include" /I "." /O2 /nologo -LIBFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." /nologo -LINKFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." /nologo - - - -#================================================================ -# Suffix rules -#================================================================ - - -.SUFFIXES : -.SUFFIXES : .c .obj - -.c.obj : - cl /c $(CLFLAGS) $< - - - -#================================================================ -# Actions -#================================================================ - - -all : $(MYLIBS) $(MYBINS) - - -clean : - del *.obj *.lib *.dll *.exp *.exe - - - -#================================================================ -# Building binaries -#================================================================ - - -qdbm.lib : $(LIBOBJS) - lib $(LIBFLAGS) /OUT:$@ $(LIBOBJS) - - -dpmgr.exe : dpmgr.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ dpmgr.obj qdbm.lib - - -dptest.exe : dptest.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ dptest.obj qdbm.lib - - -dptsv.exe : dptsv.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ dptsv.obj qdbm.lib - - -crmgr.exe : crmgr.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ crmgr.obj qdbm.lib - - -crtest.exe : crtest.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ crtest.obj qdbm.lib - - -crtsv.exe : crtsv.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ crtsv.obj qdbm.lib - - -rlmgr.exe : rlmgr.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ rlmgr.obj qdbm.lib - - -rltest.exe : rltest.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ rltest.obj qdbm.lib - - -hvmgr.exe : hvmgr.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ hvmgr.obj qdbm.lib - - -hvtest.exe : hvtest.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ hvtest.obj qdbm.lib - - -cbtest.exe : cbtest.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ cbtest.obj qdbm.lib - - -cbcodec.exe : cbcodec.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ cbcodec.obj qdbm.lib - - -vlmgr.exe : vlmgr.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ vlmgr.obj qdbm.lib - - -vltest.exe : vltest.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ vltest.obj qdbm.lib - - -vltsv.exe : vltsv.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ vltsv.obj qdbm.lib - - -odmgr.exe : odmgr.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ odmgr.obj qdbm.lib - - -odtest.exe : odtest.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ odtest.obj qdbm.lib - - -odidx.exe : odidx.obj qdbm.lib - link $(LINKFLAGS) /OUT:$@ odidx.obj qdbm.lib - - -depot.obj : depot.h myconf.h - -curia.obj : depot.h curia.h myconf.h - -relic.obj : depot.h relic.h myconf.h - -hovel.obj : depot.h curia.h hovel.h myconf.h - -cabin.obj : cabin.h myconf.h - -villa.obj : depot.h cabin.h villa.h myconf.h - -vista.obj : depot.h curia.h cabin.h villa.h vista.h myconf.h - -odeum.obj : depot.h curia.h cabin.h villa.h myconf.h - -myconf.obj : myconf.h - -dpmgr.obj dptest.obj dptsv.obj : depot.h cabin.h - -crmgr.obj crtest.obj crtsv.obj : depot.h curia.h cabin.h - -rlmgr.obj rltest.obj : depot.h relic.h cabin.h - -hvmgr.obj hvtest.obj : depot.h curia.h hovel.h cabin.h - -cbtest.obj cbcodec.obj : cabin.h - -vlmgr.obj vltest.obj vltsv.obj : depot.h cabin.h villa.h - -odmgr.obj odtest.obj odidx.obj : depot.h curia.h cabin.h villa.h odeum.h - - - -# END OF FILE Copied: box/trunk/qdbm/misc/VCmakefile-old (from rev 2716, box/trunk/qdbm/misc/VCmakefile-old) =================================================================== --- box/trunk/qdbm/misc/VCmakefile-old (rev 0) +++ box/trunk/qdbm/misc/VCmakefile-old 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,169 @@ +# Makefile to build QDBM using Microsoft Visual C++ + + + +#================================================================ +# Setting Variables +#================================================================ + + +# Targets +MYLIBS = qdbm.lib +LIBOBJS = depot.obj curia.obj relic.obj hovel.obj \ + cabin.obj villa.obj vista.obj odeum.obj myconf.obj +MYBINS = dpmgr.exe dptest.exe dptsv.exe crmgr.exe crtest.exe crtsv.exe \ + rlmgr.exe rltest.exe hvmgr.exe hvtest.exe cbtest.exe cbcodec.exe \ + vlmgr.exe vltest.exe vltsv.exe odmgr.exe odtest.exe odidx.exe + +# VC++ directory +VCPATH = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7 + +# Building binaries +CLFLAGS = /I "$(VCPATH)\Include" /I "$(VCPATH)\PlatformSDK\Include" /I "." /O2 /nologo +LIBFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." /nologo +LINKFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." /nologo + + + +#================================================================ +# Suffix rules +#================================================================ + + +.SUFFIXES : +.SUFFIXES : .c .obj + +.c.obj : + cl /c $(CLFLAGS) $< + + + +#================================================================ +# Actions +#================================================================ + + +all : $(MYLIBS) $(MYBINS) + + +clean : + del *.obj *.lib *.dll *.exp *.exe + + + +#================================================================ +# Building binaries +#================================================================ + + +qdbm.lib : $(LIBOBJS) + lib $(LIBFLAGS) /OUT:$@ $(LIBOBJS) + + +dpmgr.exe : dpmgr.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ dpmgr.obj qdbm.lib + + +dptest.exe : dptest.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ dptest.obj qdbm.lib + + +dptsv.exe : dptsv.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ dptsv.obj qdbm.lib + + +crmgr.exe : crmgr.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ crmgr.obj qdbm.lib + + +crtest.exe : crtest.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ crtest.obj qdbm.lib + + +crtsv.exe : crtsv.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ crtsv.obj qdbm.lib + + +rlmgr.exe : rlmgr.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ rlmgr.obj qdbm.lib + + +rltest.exe : rltest.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ rltest.obj qdbm.lib + + +hvmgr.exe : hvmgr.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ hvmgr.obj qdbm.lib + + +hvtest.exe : hvtest.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ hvtest.obj qdbm.lib + + +cbtest.exe : cbtest.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ cbtest.obj qdbm.lib + + +cbcodec.exe : cbcodec.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ cbcodec.obj qdbm.lib + + +vlmgr.exe : vlmgr.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ vlmgr.obj qdbm.lib + + +vltest.exe : vltest.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ vltest.obj qdbm.lib + + +vltsv.exe : vltsv.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ vltsv.obj qdbm.lib + + +odmgr.exe : odmgr.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ odmgr.obj qdbm.lib + + +odtest.exe : odtest.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ odtest.obj qdbm.lib + + +odidx.exe : odidx.obj qdbm.lib + link $(LINKFLAGS) /OUT:$@ odidx.obj qdbm.lib + + +depot.obj : depot.h myconf.h + +curia.obj : depot.h curia.h myconf.h + +relic.obj : depot.h relic.h myconf.h + +hovel.obj : depot.h curia.h hovel.h myconf.h + +cabin.obj : cabin.h myconf.h + +villa.obj : depot.h cabin.h villa.h myconf.h + +vista.obj : depot.h curia.h cabin.h villa.h vista.h myconf.h + +odeum.obj : depot.h curia.h cabin.h villa.h myconf.h + +myconf.obj : myconf.h + +dpmgr.obj dptest.obj dptsv.obj : depot.h cabin.h + +crmgr.obj crtest.obj crtsv.obj : depot.h curia.h cabin.h + +rlmgr.obj rltest.obj : depot.h relic.h cabin.h + +hvmgr.obj hvtest.obj : depot.h curia.h hovel.h cabin.h + +cbtest.obj cbcodec.obj : cabin.h + +vlmgr.obj vltest.obj vltsv.obj : depot.h cabin.h villa.h + +odmgr.obj odtest.obj odidx.obj : depot.h curia.h cabin.h villa.h odeum.h + + + +# END OF FILE Deleted: box/trunk/qdbm/misc/benchmark.pdf =================================================================== --- box/trunk/qdbm/misc/benchmark.pdf 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/misc/benchmark.pdf 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,588 +0,0 @@ -%PDF-1.2 -%???? -3 0 obj -<< -/Linearized 1 -/O 5 -/H [ 997 194 ] -/L 52196 -/E 51873 -/N 1 -/T 52019 ->> -endobj - xref -3 30 -0000000016 00000 n -0000000944 00000 n -0000001191 00000 n -0000001395 00000 n -0000001539 00000 n -0000001745 00000 n -0000002240 00000 n -0000002419 00000 n -0000002440 00000 n -0000003096 00000 n -0000003117 00000 n -0000003679 00000 n -0000003700 00000 n -0000004424 00000 n -0000004445 00000 n -0000004888 00000 n -0000004909 00000 n -0000005424 00000 n -0000005632 00000 n -0000005979 00000 n -0000006000 00000 n -0000006581 00000 n -0000006602 00000 n -0000007090 00000 n -0000007111 00000 n -0000007620 00000 n -0000029117 00000 n -0000051731 00000 n -0000000997 00000 n -0000001171 00000 n -trailer -<< -/Size 33 -/Info 2 0 R -/Root 4 0 R -/Prev 52010 -/ID[<21b37df8f836949f6a724722f5ba950d><21b37df8f836949f6a724722f5ba950d>] ->> -startxref -0 -%%EOF - -4 0 obj -<< -/Type /Catalog -/Pages 1 0 R ->> -endobj -31 0 obj -<< /S 36 /Filter /FlateDecode /Length 32 0 R >> -stream -H?b``?a``~?Gw1`PZ?????A???1?? -? ??mX????L00|g????? ???`????%???&?' }??V -endstream -endobj -32 0 obj -90 -endobj -5 0 obj -<< -/Type /Page -/Parent 1 0 R -/Resources 6 0 R -/Contents [ 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R 23 0 R 25 0 R 27 0 R ] -/MediaBox [ 0 0 595 842 ] -/CropBox [ 0 0 595 842 ] -/Rotate 0 ->> -endobj -6 0 obj -<< -/ProcSet [ /PDF /Text ] -/Font << /TT2 8 0 R /TT4 21 0 R >> -/ExtGState << /GS1 30 0 R >> -/ColorSpace << /Cs5 9 0 R >> ->> -endobj -7 0 obj -<< -/Type /FontDescriptor -/Ascent 985 -/CapHeight 0 -/Descent -216 -/Flags 34 -/FontBBox [ -165 -307 1246 1201 ] -/FontName /ADKHFG+Century -/ItalicAngle 0 -/StemV 0 -/FontFile2 28 0 R ->> -endobj -8 0 obj -<< -/Type /Font -/Subtype /TrueType -/FirstChar 32 -/LastChar 122 -/Widths [ 278 0 0 0 0 0 0 204 333 333 0 606 278 333 278 0 556 556 556 556 556 -556 556 556 556 556 278 0 0 0 0 0 0 722 722 722 778 722 667 778 -833 407 0 0 667 944 815 778 667 778 722 630 667 815 0 981 704 0 -611 0 0 0 0 0 333 556 556 444 574 500 333 537 611 315 0 593 315 -889 611 500 574 0 444 463 389 611 537 778 537 537 481 ] -/Encoding /WinAnsiEncoding -/BaseFont /ADKHFG+Century -/FontDescriptor 7 0 R ->> -endobj -9 0 obj -[ -/CalRGB << /WhitePoint [ 0.9505 1 1.089 ] /Gamma [ 2.22221 2.22221 2.22221 ] -/Matrix [ 0.4124 0.2126 0.0193 0.3576 0.71519 0.1192 0.1805 0.0722 0.9505 ] >> - -] -endobj -10 0 obj -578 -endobj -11 0 obj -<< /Filter /FlateDecode /Length 10 0 R >> -stream -H??TQo?0~?????!?g;??XJ?2 -???J???????T#A??;?$??h?H???}??w?3??SX? x???Z/?`???W -???vgRn?l?&?^{?fU???t5$Z???????P?u????xf?????+??V???M4???q?????????????8qNf\F???????(??Y~1?NB3}*??0/~?????r?~??D?`?????t?????A?x&w?\?F??8>8?XwOC??????:h???????#????+? -&????6??????SF?????(<#i?$? -??t?)%Um+HBJiR? \J??s??CU??K???1Q?r?XJ v??$l????e-?0s?Z??9?&??M?|{W7?f?T?d??'???\{+D???UE????*"w??0?6?=aa?: <>O8???-????Pg?)z?????)Y??p?:??`6gD? -endstream -endobj -12 0 obj -484 -endobj -13 0 obj -<< /Filter /FlateDecode /Length 12 0 R >> -stream -H???Mo?@@???9?*F????`zh?Vu?????I?6?*F???;P ?N?]13??fv?x?2 9? (?P?Q\?YR?????=l???????????}??&K?f;?-55P???!??kC????k)?t??A??A????? ?8??k?Zh?z||Q?????.??:7???9d???r??w??{E[?'??? ?oW?B7>?rz>:?SW????t-W?r??????2r???L?0t?_P'6? -endstream -endobj -14 0 obj -646 -endobj -15 0 obj -<< /Filter /FlateDecode /Length 14 0 R >> -stream -H??TMo?0 ??W??fp???mi????????[???r ?[?_?J??f?R,AZ|?#)A?? Bc???4!iNS????9??h??+?65t+X???Z ??h????M)?a???_\??`?M????NCJ?C??p?Oo?{?|=?W??k??YuC??fIF?p?nQ -K.??ej -?k?b:(YS? -36?,?Og???'?d+?????W??%???B`???C?_?0.?3?6????R???NU??pV?^qS???????hKU??N??q????o]r?????%?vCb??{>]n?Nm?i`?????{;|aG'??I?^?<7L??????b~=?pc????4l?2_??6\?:?2Y?}?jn?????#?$&Q??(?.??N??6??a??}C@???Op???!?a|=????>`??z?*(?pd9???@&??3x(K?HDBlm??> -stream -H?|??N?0 ??>?g?c????gCb at g`@L\Hp^?4 A??P????????%,? ?????????&?|?U?*w??2&????*????zvZ?????x?? ??-?'}?_w?> -stream -H?t??n?0 ?w?? o???y? C??$?}???e???????;a?j??A???f??????o?0???i?????P Y?K?&?????O??s1?T??^?)?????#3?o?3r??Aj?!???????F???_?X?FPuwS????>??X?0?|f??!yz??p?)? ?3??]?bu???/???J????YU?=?P?ID?e??j????u??)VF[???gqA]?.Y}?/???D?1?[???:??1????Y?Q.??qk??U???m%C??W@???44_?m_;??????e??t??A?X{'??,?K?xK1?C??K?M??i????p??O?x???x??$??M??S?S4i&N? ???'??l7?C?>?0?;?k??????2?r ??C???KD???^? bl2gz a????`?q? -endstream -endobj -20 0 obj -<< -/Type /FontDescriptor -/Ascent 859 -/CapHeight 0 -/Descent -140 -/Flags 32 -/FontBBox [ -121 -137 996 859 ] -/FontName /ADKHNA+MS-PGothic -/ItalicAngle 0 -/StemV 0 -/FontFile2 29 0 R ->> -endobj -21 0 obj -<< -/Type /Font -/Subtype /TrueType -/FirstChar 32 -/LastChar 87 -/Widths [ 305 0 0 0 0 0 0 0 0 0 0 0 0 500 0 0 500 500 500 500 500 500 500 500 -500 500 0 0 0 0 0 0 0 633 637 664 648 566 0 680 0 246 0 0 0 742 -641 0 0 707 625 602 590 0 0 742 ] -/Encoding /WinAnsiEncoding -/BaseFont /ADKHNA +MS-PGothic -/FontDescriptor 20 0 R ->> -endobj -22 0 obj -503 -endobj -23 0 obj -<< /Filter /FlateDecode /Length 22 0 R >> -stream -H???=o?0 ?w? -?v??(???:(z@ \"?C???E??????l??sY?}??)E+2,M6C??S?????[}???I,????$???&@ ?X?F?da?E??:???kK$?i.|???fa%\ -?? ? ?hx???A?N??A?Y?<~??? ?f??9 +asfCMD"???&|^t@?#G5???F?w?I#???X>$?&??????p???)?\??M?th?? -??S??w?:?[fX??#?S?? ^???vJ???_?O????i`?S-?"?R*?????|( Y?,s??2??iu??ul?????%*Y????8???$?????jhA?A(??UK? -ew{??H?Y?????0?.???iJ ?et}??DB??+?:$?v??e????'??w?? ?KfC=?9?G???W????Z?'?q?n&??&N5?8t??'o{?(`;o?`{????C?????o?@???|?-??.??F???5?2?a;??? ??? -endstream -endobj -24 0 obj -410 -endobj -25 0 obj -<< /Filter /FlateDecode /Length 24 0 R >> -stream -H?|?MN?0 ??=??HX???m??Yp? Xp}?v?6e??????}q;0$?_?2ccNUA??j ????t???y?r? ??Y??? [???D?? ?#/???J?? RB?0g@?)F????-*|? ????b?1?w?h????s?W?`?????\_1??1??????1??cr at 9???+f0tL?(r???+f08Fb?xP?;f4tL??M??b?c?6?}??3?6d`??????e&???W!????k???c?}?\?G)???mh84,4?y?l?<$=|??0??g?#JT)????r?b??Gm?Z?cP???#???d?T?I?C???????0??,vq?h9-?k?[????[uUN?!??r!;> -r???9??_?=?}?\?\6?? ? -endstream -endobj -26 0 obj -431 -endobj -27 0 obj -<< /Filter /FlateDecode /Length 26 0 R >> -stream -H?t???? ??<?L?X????f??T?+???????????/? d0???!???l?k?'???+0?W?B?] y??:A??QC8??I?$r?? ??BV?N???c'Q2?????????c'??\e????????????n????4???T????P~???? ?Q???ya???D????Wz?%??x?Q???_???c??U??"???v???u?r?? -????3E[?fy?wi?n?Z?????-?'?^??v=7K?bN???M -?9?????????#?????\{?J???=]?[>V?$???r????H?dj??/????? -endstream -endobj -28 0 obj -<< /Filter /FlateDecode /Length 21406 /Length1 30692 >> -stream -H?|V -pT?????m $???y?#AHB4D???n `???H?n? ?1I#??????P?X????(????0t*C+??heD?j??y??&a???????{?=?|???? $? -e?????(?/?Gpufe]?aB??????M??????o??V??`???????V>?tEM????????Hmu???l?H?q??Z.x[z????F??TL??W??9?5?)?q~?8x??*T??>w?W0?#??M- ??t??r??8??R?N??B?? -??w??V~?@V?M~O>??= -K? ??u?$.ie?0g???9????b&??/???9?]d??????Fg??#??"?G??x%???1???p?+F?Z? 6???r?!s?j?jS?Q??9L\??-?]??%?D'???f?5???"Q??"?7????Wy? 3n)L????-M???29_6? ??T?6C????.?H???j_?+???B?coe%L?X?`l??1??????????Y?#??9,#}?9?g ?cPZ??)??O???O???m? ??{??????Y?(l?a[?0?M?ve3???M a??R??6????Z????, :- nX -?1?????i?g???.??????!???g?x-#&$R??????? -[???]?Tk?~????/4 ??????E?9??l????"???@~T?G"??KL?.6?n?JD????`???????lQXiV?0???3c&(?c{ -???1?"Z?h? ?????pfB?YY?U$????iO5???G/?dg???9A?ga????Q?8???f??????0??f?TeR?hY? {gy?f??? -??4;?tV????@?????!?S??? ?5f'?j3???vOs?Yk-?X-?V?^XRp?y%??4}??T3??E?????Pq?Q|?&;+?M??t???]LB??L? -]??????N?p#2??"?Qi0??i??1?O?X?ch?'$??E?_?????????a}6?y??[W"]+?t?pY?]n??????i??vJ\!K??&??{????R??k??L?????a?}>??-???`7?;e?/? '3d???9??I??j??57??M??a??l?v??????j?m?????;??>#???VY0#b??f???KS??hYE?Qd??H??\a^????Z -?p7?v?DK?]??L?=?3v???J??NN?*r??????A#`?? -??2&&?/FF?AG??z3????=???~?#?{????.Z?#j??e?ym6y??"??=?%?Y?&???c?v????S?{????&] ?I??????6???&???6?G?????z??"A??|???i??E??????|-c ?)?N?)??zA?z a|s(?S.???=yz?`??m?a???h?<????$?o??U?*???k1???1???????-4???Z=??m!2??X????F_D{??X??;I??U -h?6??S???l@?u9????????I?gT$ow??K~?x?b??m??6?0???y?_e?c?m??A?=??G?j?"???????E??|w9??V?? !V?0~?-??(? ?? -???N??:??t???l??????@ ??i??????e[??9?8vr????p?????M? ?? ???i??l?v??y?W>???}??wShS???Lc?z?~?m?u?w??7?^gk?????r`????? x?1?s>??!???4O -????????9?~+-?5??????lm??5.?T?%?98??0f?? -?W?Y]i?\?????O5Z/?<?Mu?????+?W8k?W=??A??U?3M>?u?I?N\7??<-?M??ap1?1??k^?m(?J??3??!-?|>??CL< ?QP??????Qe?????????s?o?????I<?0??u??/????H?????i??+p? ???K???????"??uA??\B=1|K=!?u??????^???y??m?????,\?????{????t??w??B????? -??p?3 -????6P????M???%9??^?4?=?_z??Sk??????????[?]}`????/?^|S??=?????W.0?K??/?R -??,?M?????~T?g&@?_??[L??1??Al??????_d???>???????????g?}fhZR nP -??=?????l??:;???3 - LZ2_ZF?  N?~p4???P??a??????Q ??ph#? ?R?c??{??=?s?????Pg????;c?U?*??V?]???`?`??u?>;?QC?!?`5? -???BU?*?????bU????/-?5?{]??Vw? |?Z??_Z}uhn??b???}554.???p?JDc??!???P7???o?h??AS?????i??P?????_OL??G?????#???>mPy??:W???909Q??3????????????yg$?3????|k& ???p????|k???l???H?I?1?TXx?We??J+^)??D|??????:??? ???Id4"$???????9W?m???1???a???"xy??[2M??"????M?p?8?y?`C??2?>s???W??3??E??????GG7??M?.C???.?gv/enU? ????v??,a:?N?????%?2????)?4y?9??h?Y???K?D8?MX?:?A??? )???bVI?,??`h?0????????&]???5sP????l????#?g????? -?1L??-???$-HX???=?0{?? -?c?ev?<<$?)h?z?3???g???#h ??????`?]???O?p~?U?I??e5??ot?oV????td??[??sW?q??%?????3???I???.??/ OJ[??5Q???I???????;V???m"???????|g??'6???Y??K???Rvz??Q=m??2ATW?}?5_r?B?O??}??]??t?A???c???zE??n*R?X$??&?SB'???D1 5J?,?dY?DD?m:? -?????, ?2'?g????????X?(?????I?K1???h??2 ??Q???O???@ -I?V???D\?!&?qqV?DM,v -?E??t???a|-??|o??GU?*???????6?????e??/3l?a?Df?e,?o@?x-? -??Y?? -?7"sLJ~J????f??jY?N ?CE0?r???irR?y????)mq?)??????r-???e??y????? \^oh???c?[BM!?m-???????I4h??- ??+????>U?????+? 2????Q???. -z?E~???????w???? -???@8)W]?n?7?oR~`)????c????????uLm??`]?????V+??/=]?????}]???A8? 5?S?c4^@?4???j:B??!?,[?c???:?Z??????]??t?+9wrMaL>5? ?)v=\G4iv???^?UcIBmn??J????"(}V??Y??g?d?????O?2>~?%T5?:L?(??e9~VU??})B?HL?qZWU#A$9?????:?????6j#???G???2???1??;y??y?*?`}?,??????a??0? ??N??'??Q?E?????FR=???~????N\?3?Z?R??????5/io8??;?M????r????_l;7???u~^q???kC?V??????????M?]]/okB>????F[r?xK~6??????(??W?I+<???FOmz??` [G??H????M33??> -???u??h"???N??7????? M?:G??icx??l????????7?(w???[???Y???B?rR???(]g[????>W?U??o?? -?????????k8?za??> ~?l?/_fB!|??#t?L\?5???G?"? ?/ ???????T?y16?(??2;?uEM???@?Qw?????R?M?????YE???????M8?V???QW???,0(?K??T??? -2??rN?Tn-????T?h?v??E?<]???5?b@,IY?#??0Q ?qk?#\?!%#?????qhb??s????9Q??h??.??W????7M???LB?9@?8@???C3??????-D?n'??,T ?BT?ha*2?7i@? -?[T????]Y0??jC?A% -i"????1^rJ???]?????4L< -\???)s?????x??O?k^????????!???@?Y?G^?a?y?z?|??????n-?P?FFa?d? -f%????iuw?:???)k????s????d?[k?~J???J!%4 -?N N? X \Q?n???4U?S?n?}Q??.M?^?????&o?w????<,ho7?I'pi ?{E??Nc??m??%??W?H???A?2T&<:????B?PW? -??K?^W?W??e"? ??1???@3?[M???h? D4'???e?2XK??o?0????2????????l?s?]}????@?oc[_???????=?hE??? -????,;>e???????+4?}????G? )?s$???g?-8?(u].{?}??r;m??????qV???W??m?YZ?????%>?????9p?a??ZiMY?$y5?Vd??1-?^?? z??????DH??????^om????beg?3V??????R?=??`k??<_????I$hn%C?L?&?U?8?????Pnb???W4???H}?v?+Vh???K.~?????Hl?!?H!]SKii???? ?|?p?*?(?8?Z?O????? P?$?7y?:????S?????`?D???){??~?Qa????Q??Q:&v????0G7?b?l?O??@3s? G1?????>?tXO1??@@rd????R???R???n?M??|\?'?tS?Gq?#??'j??E?(N?I???AV?z0U]?H??3????p4?/7vS\.E ]72??n*1??(u?z$?PT?(?D?V??e?Mb????{u?e????sm???{?]?W??\?0?<Q?????????Zn?A?L?????p -5?+?6?l?|P!O -6??O#W????r???x2?9??e?????%^?)2?(?I?s()??QF?)?3P???FM???d?b?_ ??|??????S)?Db????tf??5???2DK$V|????????p;???$??,??=??"??Y??p?SM?g?%Kz -?Y)?gCK7??J?yj!?`MTQ?.????>??%`?.???V????t??LYs??Z ??+????I??q??I~?eD???s?'?n??>??Z?F??uh????d!???Hc????x R}+???V?Gjoa??'??[?????&G?,??D??v???dP?*x75*/\g????q??,75?6???????~o?j?? ??4??lChR[???xsD?#?"!m????i???vx????E,????.C0v -?[?j?????m?????*?A?!????????????k??>)??z?Dt?0???[?o?,????7??l?O&?K?????"V6?5??,?q?r>?7DtdE?4??Q7/??F????v?m????aL??? -F??q ???4C?? ???|:??C?v????@?| -?????P?)C????1,+??0-?`??r??J??????CA?mT??;3Zj?:???@X$?3?B?LM?? -/???/?TT`??h?? -?@{???h?M?Qt }???|????u????(|?\??????H?f?'??!%\9?9V???|z?}??m?4??_?G?H??h?~?S???u???Y????????????`1E&???R??@0????@B'?)???B??'6??qi???C?Ii???LM???? -$@??}?????Cow??fg???.r?????s`??????g?3???:??? z? ?J)?????jVyM????N?4)???rBmuI???????J?1#]0?gw -?:? S?%H??m?MdRAV?L???D??]n?d ??[?m< -?5">,?q&?G???????W?Xi??Od??>?7???????O?= -???/?}??7?w?%&n?:??M?D-v?(n?m1??82???*\?`?Kr/q"?C? ???J??]fm?=?/?????:n??C????U_????j4??u?1?? ?Q"?E`?+??`(*?QF???$?x??~??????iAH???qR" r\?????P??E(?O'~?5???V??-??K+?fG?5?.?X???8????W"???????O?P?)j?" -U??fBZz?^?TF$!???Ih?????1??????j%?bMi#V??6????h?`s!?t?,?]???2&?q??qEX?@>?4??G?"?????7|~? ???\??)?Z`?]??ie?y??7Z???O/??c??????\?????????@?+?????u???????? =??,????,???'^?Y? *^?}z?dh>HI??n??Vj?1H??\N4?:?U?U???z??K?K????????N?(tv??T?8???}? -:Qe???3(m??/?F?4???b^`x^?????5?~/???????>?W?8?k????p???b?~??k??a :?70??( ?I_?dn7????q???hv? ?`???g???K??LcP5'!???????6?GLk;B????!??????G<^ ??i#PcZ?S?@??W??= -Z$C??[3?V -PT%??!s>7??? s??U??? -6?eU=u??w?K[?O??????????a?7|`????/??????????[&??Y3_(?:?sQ~x`7Z1%?9??fM]QY???s? ?e????siA ? ??[???"??mr??r??5?x9[?l?X??c.?Ur -\??;?M?V??n??T??C?2d?(?`?$ -???1? H?1?+??N??? ?0G?KB?2w??'!?????P*?d?????? d?Q?W?_?:M??o??? ??e?p??%'r?? ????????U0??????f -??? -?t???? ?fEUR -FQa2???Ps????&???v/?~,):??#?"??G??????C? -I ?1??B9zQ???}q?'?x2???_S?qmK??H??v?S?Sj|v@?O(V??H????P@`??T?*?[????Ud??????FK?kg??????0+c(??aB5??????w??* ?????c?8????w>??#g_????]b; ?8??'?/KB Z?ihH? ? ?Z? ?6U???E???????I ?-0T?J7?UK --cZ%@??:5M51?_?{???I????'Y~??}~????Xk'???!???}q??ja?2s??d#r?!?u ?\?(8??e)z????? ??[6??8??`?$VK?????2??O???O??Z)???t??/?l????Nv?????????_?`??]I|???????wct??0bq;???%????i /Dr?s????P???n?_?' ?&????Z??Q5J?Im?veH!?#???(? L?10 ??-? ??U9??s?)??[jOE{e?\%?????V?VN?f?ci?{??<,?????e#?5???g?Hg?2??PI??U51?X4 I[?,??a ?m??i????[?3? -???B"?}?NG5 m?x?e;??a7????pr~P?R?tp????B G?a??=????j}????{t??Q???=[??*??>o?????6?\e??M?????3??g?fVw}?i?S??I9?fGH.??`U?9???U??u???????e??fO???????"8?MM?5??????g?B?k ??6??f*???%Q??V?mDB??Z?o????h?vO?????^?I?4,?J?"?H??^?????4%]????6?5 -?u ?P:??????py?}?tZJ??B?L? -1?D 56??bE?%?y{q)?]??+[7|b?L?x? %?oF???h?????@?"%?3?/??$.????:??0??????????T????^D?>4?m??????U????????o^?????????L?????z??????9?+????v???Ni?)?]o?`Dw?cF?n?_?'?Hc??4'E??T?.\??,# -???x???1??~????Qn?;???????q -W??s9?;??/?i?[T????PM??(?Y^Y/*?a ?^?3?P?nH?$Y )??D ????b??u?????????n??ZQj[??'?9??-?*?o`r?l?ki??%K*????'?_?8 ?? ?? -??Q?\K?b???Z??K???Y?#_??X????????0b?d?<"??y????a?? w)??PIJ?AElITI?8&???? f?a?M?#?W???????A?b?? ?????/:{k??4?o7??b???]?? ????:_?J?J?A??K?cN??2d6?xaw????g??????/???????]???veS?5?>?mMc??=?k?u? =?Q????Kh6ok?6???%?u?u?$???s?)???h?&?Z?"???%k6?7w???>uDSg?9?(?h? [?????_??>?????{??|??????????]???$???YM??BB?LJC?R?$ ?v??G?i?j -???h????0D????It???G????????:M?????d,J??}????}?h]?RG???????2,?6?ML?b14?:???Q%Q??1?C?KQ)??;???/???%??????^??!????*?]?U{?*????4?#???5 -u2????P??J??=JP???WVo+4o?MK?????p -? -?????m?=?B??j?????zCb?hh????N ???W??D????R? ?9y???}?W#?T*,(????6?B}? ??*EB???W?*N????`???2`.3.?f?sZ2?????(]??X?H8?d?1? ?d5r??P!l"?2|?2X???X?(?????j w??|G?4A[???>\?O*?v????p???Y???ku?T? ?;??Q??y?? -??z??}???AF??? ??0???&8)t,;I*L$???jV?S??2_?+X?VT?=???k????2?^aV?h?l??W^.?L???u?t??dZ1)? d?y8|mR??S??C$[?`?I{f=????8??T???????????n?i?k?W8??f??E?p?| z~of?xB????:???????????V(?8? -?????J??z?????x???(A -??n?????25=?E"??_1:???vgDdB?(??BZ?c????nM??b -?J?t:?d??S??[?R???Ec??G&"&?Pd?? ?"?iM?D?|%???A??0???? <`????nBo???????a?7???????z?F}@1????~? Tw??D -m?Z|???????Hj=U?????_Q?R?0?????????g?[?@&-I??B?$-??? -9?}?N?q??3?,1+?4???0C? ?dH??D??j8???]?>??c?I??47?Q~/???y/? ~????????L?C?O???G?"K???BqEz"C???2???$?K)a?j?u\?K?G&?c????I??a3??4?uRE'?p?????W???M????????@??d???|e?b?*????q??Io?????8????_???uo?;)?????bPhG??a?z^*?A???>?it??b ?wP? -??9?#??????? ???R?????tJ*'?????*??/*?&,??,?7????P???d'!??uy???"|p???? +???,'t????k/???? ^Xu?U6?Z?P????mv???+ ?8?jF?d???j%???Zs?k]??*~?RmP??d?&?}>sb;k/V ??????y!?V???m[D??q??????x??????k?{?}??6>X2??? \? -p???8# ?HmC?5? ?????2%Qc?,u????(??=I-?]??SD*{?N?++G???)?pdS?L*?0????? -?NW;??8L??X??a?/??=??p??,?dQ???H)U??q>?p?????B????Lv??????????@????????????}?lKqZ? ?R??J?;%?? "?iH:?S?k?N??Xe9?I?????:y????7\??lxnk^??a_`)????????(?+|?????>fvwfgf???;??5?u??'??????ckRA!?k???j?!?&???ELT?)Q[?i??Xj??-N_TQ+P??j+ --?b?g?-??????:?x??l?'?"???%)??b????@Y?@???j???Z????????z?{?;_???r????\n?N???S?????&/s???/??|<:?u???2??f?%?j????~???????|d??*?={?Y?#?K9???\T>Pn(S??0????~?w?Fj???a??3k:??N? ?{gm??hG???.???F? ?6???y.????q??????(?90G???)2W?? ?????F??"t0{??x???zN%?{??o???\^7]Qa??`???K????U??Rr@ -?t????T???4?}????? -?d?L&??+??"? -?]3V|r?c?+k=???Z????,\.?????@??G?L?jh??????\c??{??$??O??M -fv??_'????h???z?????au?u2?G?8?.|???L???NVt:?2??O?Yv??}?}?}??)?{??{?u????f)? -??M????y}Z???u;?=??/??n?X?B@????t?;???"!*??M?? w????<?%??????O?$?E -W?(>??? -O???? ????Amh?h$?? ????B??V>????GJh??9h7?? ????Y??Y2?,4h!???????????'0 1????q???Q|xU??????Q1?y??X?????q???&????????69?zi??C??)??g@t?????m?s?D?NG??????? -8??C?7$?????T ?B? -??????????j???M91Ct`^?t??D?#?2e?s?;????#bL-? ??1?6??i-?jjJ?g"?:2??0?@?8S?aYeYJ$?????Pd??`???HI??DF_Cw -????????016G????-?????? -:???3?n? ???b>?/?zKJ?uF?u?v8V!??$&P????eh?"??x?w??4n?Y?l?????d2????G?~???o?Q?4Q?o?7??U????!b??!(D?? ????L??2?L(??W? -?e?Zc??????Sn??n?????:???F?r -??{??9?96N??m?t??O at tf??? ???1(1H? ?? Dc?5?CD??????1?ZT??s??^??HT???????~+?C??_Hu?>??7?:qCR'L????QJH{??P???????.?#???Rj?|f?=.??Z?XAa?M?9?8`f????dy???x???????u???7??W??,]K????x.?w9????????{??D????y?\????`???]\?=????4????p?o??1 ???K?T7????t??p??? -?t???e??/??d'X~?????I[??6i???y'???ou??O??o?)???m??n??? -endstream -endobj -29 0 obj -<< /Filter /FlateDecode /Length 22522 /Length1 168840 >> -stream -H??WIo\??7?p?????)?g?s,R%.?$kId!R ?"??b?,%']r ??o?}?!??0???K?\??HnF?J????J/?J? ?u?????????"J?C -?????6????2??]???}u???)??:Q?????????W{???????8??+D?C???w~z?????19?D}W?????????????w??????D???????|=??{?P??c?}???[???s?????????+??7??L? -?m??f????_?U??[??c???u??Z??4Q`}d??f??~p?`??N ???? s' f??aF??3???0???????Lp?f??%a??3f??Uaf??3???0s?????~^??f?)?[?b??>nuJMRn:??H=?1?q??R?q???o??5??o?I:?-?Yq?n?_??zg`?S?=???L>z? -??4???,?:C?F?3???????E`???07?7?:7?7????F???r?????7?qnR???s?9?Mv??\??|???7?inJ3??g????f`???7???T??|?5V? -Q????$?,?*?D????Q???rLTYU??*'D?UQeMTYU6D??????rJT9-??U?U??*?D????Q?;? -u????'n????9?-3nt???cHv??F?2??a??AK??F?????4#?????X3{???4?1?^?????^iP?> ??a?????r???????9??_?????)F?1d???`??{?????0y~cQ?yt??>?x??9??????????I??vJ???Fnr?w -?A?????6i?'17?}?@?;P????3;??????oK?w??????Q/jc?R???.i?????????w?O?'$??c?3?2?/???G?????Qc? y?0D^ ?? /gd? _???I?uF ?(v?5??i??}s???c?=????S??~$/?1W}Ec"?}t??#I^???5?3f??<]225G -8?????8?uKd -???S????92_?`??eL?? ??MF?q???i????????'?=??????L??? ??????g?<~rV ?? -=???9m?;?????+?o?F??w@?? /6??Q?;C??????~???`W????_?`G??iN?uc????#G?nc5??[??/????5??}??e?????5i????R???<_?r?fo??" ???|??9?|N?z?}? ??8?7??? -??\?????o??\? -?????v??g????~??-??7"??? ??4?:!?%Z???i???D??_/??V????}/?cl#?+??&n??2|?o;????v3?????_?[?Z?w???o??????????W??G|}}oF?n -??V_??o r5???{???[?W???si?wD??0????~???@?v?????I????????? ??,?}???o'?qf?? jl?k?`?%??g??-y]?&o?qPy;m:n?^?q????1.?????x -?? -?3??????;I?[??????????}(?y+???}??d?S?+:7?= -? ???@?+?b???3?h??%??@?A??&???E?e???Y??>??'???0?;??W??>S?u?M??#8????w??;?}?????o ?????7?(?S??-? --Cv?u??o?1?M??9X?sZX7:L???3???????????/A??? [??????.ZpWu?X????? ?????sh??Y?|???E ???W?? -d?A j'8^]]u?????f????C??S??jzj>?|???S?]?????????{??f?&??????[???|Bo????????????f?M????r??>??e???jr??{??c??|??p?y??}?????M??%?}?m? ????H?7?kL\?|??ZL?O[L s??)??f?|?k='???????H?.??????o???n??4??? -????^d_????????C}?/p?????F???t??6>???Soo??????X?]??"y?!???S?:??????m8??Y?ct?l?????[????)??b??C"?{??p]?o??{r13?^t??zI~??Z:???!?1 -???Fx\????!???a?|??/z?OAwW????<}?A??E??u????x????a?3?I?l?C??\?S?a?+/i???w????W:?u????????on???<{?|]???????E?w\"????o8?o?????6? ?S??/??|6?????C??????&???'>V??&>???^]?/??T?d&%???I???d?^????????~=?s?S???s??????q??0S????????<{[dy?]]G???`8cO???K??{L??sj???9z=?????,???wS??#??;^???E?]t~?????E??Xh?'??QxL?,Z?c???????1?q??/o?{K?[?{????~????j?eaU???????UO?b?X?Y_?|??5?6.??v??????????t???W??*/u{\?????/??}??-???*x????l?s?X????p'|?!? ??C?e?Q????????7?{/?? Z???j?zpO?c,????sr0? ?;????M????7????<7??Q?Q???????{????cgxh??v??Q?Yj!z???k??k?k~t?>OA??WtK?!g???S??k?s???C?w????3< ?g6j1??d????k??mu???1??8?R+n???????'jt?[???U?\?????^?T??u3??^??ceO?!???y?2??Qp?g;?s????I????~I.?????D???At?S??k???s)?a?$?>F??b?=???;??????=????'?|?????????V???Q??E??Y???b?S?MrW??^????`+ltO?? ? -}??.5??ou???????? ?I????6??Q??t??p^??????/1??C?????v -????_?a=O?p???)?<;,???????????Q??V?_?????C.l{?? ?6B????????1???.>???|?????>&?L??Q??qb????}??o????59???Hf???#>??3?qX.??N?S???J??.??7??D?t?r_?|s;?_??????Z??O?jM???Exp???%?s?:???c???|?S{0??u?)g??g??K???-?]???A?We??a?<??!{?%??z?f??f?\?7?(3d????i??dY+B;y?????9n?p???(?#3+?7?G??Rklc?K??X? ???^4????3????I????h???}xR??3??s?{?B??y???????`?/??4b??Zrq5?Z?????h????I@??k??F???????????)^?k????m-???u???i???VK#??k??s????H0????"43r?y?5?8p???:?????I?]???Wd??7????G]5?5?s???4~???]S????????K?3?4F??q?k"????????o1?3?4?go?5?Y?Wlb??????}?X???7&???{lB?? 5???????Q?????C?;&O??6?/?9??c?Y?-?3??_}???a+9?????^??????c?????????,??????? ?22?Z???^t?$????9??????'o?=?????l?N??c??v???~?!????'?;v9{??????x?-???k??9t_K??xd?y???]y?K=??w?_??\??v?e????G???q?;?;km??1??d??????.????L?{??b?s?uq -^??i??(?e? tk??}???????p??????\??}??;m3b?6%?o /??E4?;?^?}?>??:????vmx]???}t??A????????'?;??Nrg??)? ? ? -??y???U?y???J??O?X'??kmG????y?6?????)?{??,?;??>??}?ZK?k?Q? :??u?8to??H???????^{?7????V???m?w???}???vK??????o?7?|s?::??? -?i,?r?%Z???h8??????P?m????c???????s???[^?{?????^?C???v?-?y??7??}?4??{?g????>????}??W??L{N5??????????? ?????8c?????????>?:?c????g o]%?-h????????Y??t.9?g?\E???|?z? c-=??dma??????2?I/?i??p3??z?%6&?~??n{???]p%?@?c???I???cZ?)c??O,?|??5?{?I~?y?{????y??>?/?????{?????cY??u?w^Dc?F?6?Rf?`nr?f??????N|^j?0??????v?????;??V?H???l??^4?3=?????/?dt -???????o?'??^{|??????t??,?]z?|???? t?~??????Z?:??N#??N????:x???k)=v?}????e!F]m???]??6y C??????O????????gO??|?c????^????g??N???l?|b???? -y????/{b-???'?I???}????o??=p?}???}???F??8????U?.????F????????x?K?1uf7??????s? ?;k??=j????N??nN?E/?p??9ba??C?e2?Qrea??? ?"?I4??s?D???c??t??+?????'?k?g/:?}?Z~?Qg?/?f=]??E?????|??s???j????}??D?f???N??6??}????S???^|??9??????g??kmg????????|?????w?v?????!O??7?6??yo#?{?3?tn3???>6e?P ??N???o/???f]???>?G?????????a?}???s]??]g?f??$?{????yh?????????'????????Z???????^)C????zMZ-???????k??????w????1?)s????n?y???*??=??^?>???????wq}9wC???5??y??I^?;w??7?????wv???}-?:s?k -6???u26???4w?g???O???????=?k??>??j?i?Z?!x?:?qg?????t?%???????\???@x????Q????????}?8???`\?x??'C_??c?'??:E?_????r??/?D?^ NC?V???O???c?:?zg???3?????U?OO?8f:????????????~???e?c\???=?s??.?~??????x4s?X?????????o??K??????????]?? :?n???s??L???Ez??]?d??X??>???7????N??l?X?X??e?j?Q?????{O??s??I Q?t??$?GA ? ?????>???????????>,????Pk^????)w{??^gO?)s????MR????ko??or?;\??y?2???g??:????~1{?V?????????=?????:'G???Z??x?I6:????????????.h^????w.???;?}b???K?2?c???wj??E8W??;?A????p?{?B?wm???+??? -?s??'??-??qy??}??y|?a??????y?r???."????????;?? ~??U|,???^|??l7t?}6?p?w(?????>?[?C??vr,???j??p-?8W?fzn?1???????1?~?yz??2??k???&s?Uo??f??":???k/?r_???g??O????'???3?mt,??????a????Y????ZG?-??.??csnB?????8?t?:???_?y????}?W??}?9'?????=?{b???AS?????-?m??K?????l{??%??6??kM???2?O???p ?????i???qs?????E4_??v????D?????=??5?&=?ZO?jW?M?2?]?}?g??;?&?R#6e^?-w? ????M?Y??7y?7?k]???Gb?????NLa????????JQ??S??xg)?r????????X] -??????g???????????????? -???^?n?tb?_??4??!~???W:?J?ZI????????p?A/y'???_??N??u]?z????;????g????8?????d?z??]?O???}[????)s[?Y???V>?Eo?G[:4?m???m???Od_??????????@???2????G????6?????5K ????s?H???u?zz??H?????w??????S/v????????a?W?pW???,??z?zA??9??W?\???]?w??y???>?}?.???yt?;?K?+?????L???S]????zf???S|???????Q?????:?e?!#?s??/???Y?]?G?v??~??w????C?o?}??C??~_n{o?p?????>?\??Z?I?a?? ?e?W4=??c$???tI????=c?_?????qoi[Q???????:^Z???>?~^?MF?+S??n??we?'n*?B{#?I8??k??2? ??h<'_ Z4V??O????Y'???z?????,m???|???*?g????n?=E?????-[????vZ??????g??4[w?q????>?6 {?D?????e??????|fj??????s????_[?]???\ ?]-??d?v?~??xn?9?????r?bM??~}????3???m??g^???q? -??n?'????m?]?[??b??o??U???N???d,?5?=????G?0?m??2??Cy?I????Fx??_+??\?? ??:?? -??u?8g??????%??? ??? ?Q??o????????=4??W???? }?{???\H?7???2??N?=????:?2?w??G????A3??????;???~l??^t??^???(?N?????3?ca-?????W?[??}c????s?":?f???}??#??g?xd=?N?2??i>%g?????k??_????e? ?l b`-?????gZb?;?+;7?3?]#G??">Bb#G(?!|$??=?????p?wTw?[??n????? _R2C?&??~J???h|??2??O -??vB O??)??F??5?&}Z?CAzr???7Jq?/??K?7iO??????e?C?) ?B?????q??????!U>?????B?#?!c?n?^??_ -{h?j?y s?4?se?? -v???L??_????y??l?O?O,????E??b2??%???5??&?3??L???X??!?? -?C'??ew???????'?B???%;_??Q?,?9?|:?;??y?9??????c???J?????cdt??>+_??g?C?}r??}{qf{????C???? ??B???_?n?s?P??4?;R???EJ[???????}&77 e??????????n??`L -D??????v???_??_?p~?????A?%????w?5?? c??}??$??;B?kH? -?E?????BD??|???J?u??4??J??=p4ct-?z?????w??????/?N?~u????>?[cw?1?????w??2v>T???/?,7o?svm?6??tp??YC???/???5?@??n6?c~K??????x?pvq????????Tp?8?5[m?0???n?w?d4dy?{?????m?8??g7?VB?.? ??+ at f?S???A?0?7?g?????t????{m4[3??? ?m???'"k??7 ??'???s ?)? }?Y.????B^<#??h?????????????'????=???I???d?7??jY??k?]o -?e1??3\?O???^??????w2?Y ????iuxof^???????3???}?????????V???L??!???Cl2~2???5)?????{?.????f???????q???2????Y???K`?????????g?X?E??7N??? -?m?W???A??}???Q/???A??T??!eu???J???@???kp?G???|c2????|???? -????)???Z;]4,??????2?e?gO??I??? -?K?????]]??k????6.?~M?????WM???h??X;M????]u???|?P-7???xL?x}???@4VegV4????R ?'???4%?vj????v"?OV?x?{?xw??jmt}?/j_?m?'?)cQ -??????@????& |/&?]?H ? -?{?U???8???K???uz3??@?j?Z?'_???k????????x?=O??????Z?@???B??O???n??n!??~???wT?j]G??? ???????A???)??a??????soXA???????e ??9????oFI?q?s??????I?s^_????1??c??1???"?????M??o?l#&???Z7V? ????e? ?=yg+?`??????~?????a???"??<????h?????+z?y??????`H?Ix??p)?`???B?R???&(???y?gx'f+>???????[?s ?[??[?]?o?A2??A?Z???S?3??-o?>??y??/?^ -??????????v???7?????U????^???G?WQ??03??0?O???f?C?;??C???t??a?k?? ?????]??N?? -?k? xAp???~9[?>???b??]?p??g???z?a? -????w -?(?*b??u???Q???`9???@?0??.??????_?}?&Y%???g?_g????z`G?Q?9?c????8?????A?e??M?C????m?Z????E????????}???Q?W?b?q?h??? -???F??Y? -??E?5??#??G+}?7j1G??q?????????q?e??? -?c[? -??^??BNf?k??r/???????x;@/??e2???????????8?????? ???+?p?????????#?C???\?>)?}?Q??(?????V??!??/???f??6??|?.U?xW?????E96?r}?5? ????(l?zs??tJ?2?x????O??-??o????L???,??7? R?X?k?v???Vgv????"??[n??????#????A???v?? ?-??T?/ -????i??l?i?T?`???j?q?????&?q`5??h??A6}<4'[???I?????@:r?.???>???{?a????????y?????(|??G?????$?????x????k~^?@c?U??l??w ?z-6???-?]|?-?M?&lnu??W??N:???h?2?@?=?+??/?~?qu|/?b1}Y??P???9??#g?s?t`??@Nb?UD??R4]?,??Vw:0o?n?#??D?2??S?????a????!? ?????f????o????P?K;3???*?\?????5????^??6???Af at K?s?#???W?F*4???????.?????g??W???N?Q`xh?]?? -????`{J?&tr?6?4?j?f?oE{???P??gwPA?;??????????????~(?%?{??>????d?j]??S?3i??v??v?? -i?,?2j?tX????o?x??5X?q?lW?xs?r??J ?0??lp?t??G????????????Q?d???_^2??????CVVq?8???q? -?OM?%_k?!?7;_??W??c?ct???7?t?????W?,??W"???0?z????n?Qh2?~HZ???Xk?rq0F???58??F?|?1i?\?}?}???&D?]?Z??!?](Zl???v??0;?eg?O?? ?w?m????7??????Z?@>??{??Abz4V?H???_S??~??????vpc*?????hB????sM???E???x?=?^x? n??~K????3F3F??]??=?,Ys,V??????????}v&3?&O???{???T?!_H?'myk????`?yh??N??ql???V?7U??????????'?|GcT?LA{eI?@'?p????.????????c ??g?y?B6v?????M???f??U???d?o?q??_*?WK???X??X;??g?}?B????{@??|hm?c????!??a??5?? u????&e????Wm;?'jx?|??a?????a???:???bo?|?D????4? ????[?o?Y????]?H}???{?U???8???|o{ug?n?F??O?P{/?Z?S?????x??p;?'e?'?{??????;??a=ju??'????A?5s???:-^??#???6???W??????0FT??V!?????:a???& -????q???w!x??j}p??h?~??XK??? -?W??~???j??;?6???????*y?u5?:???h?(k?'#.G?_K??????'&k/?5?????[??\?K???V| ??Q??f???y?;?1????x??~?c??S?_????[????Uwa?(?"?? -??? ????? ?o@?5?} -rD??a??????????w???/????;}??K~g????:'u/B????'_?v?rl?(+BY-?e,???s| 5?wa?Sd-???x>?????k??K?s ?K??%???N-B2??Am?G?y?Z?zG????z?E????[??rj~= -??A?Y??/???w1?"r?]??&???}??,{I?????0??9?,??{?_? ????????d? y?O?[1_r? ??b??{?T?B?(???3?i?= -z -9s? g7????|???Q???????R#?????@;??_?}8???7@}x8?/??3?=~??? -???G?C??Oa?/0?8????????L???w???=@?(??_#????????oF???\ =?A??????_? 9g??!?.?&9{k?U+?}??>?????)?=???U?IY?`?J -??ZK?????'1a??M?_b?1*w?$i???}???R??2e]????8?????sn?>???f[?T?S?$???(????V?????????_0??Rj?J?R??c]?tK?:?????NuBd?C}?b{?"H?W?/??"? -S???d,$_>?5#??????.??s~??JmZ?0*5N ?(g|?Q>'???(??U??8}? ??{??????^s??)????O???T/??R???????m????gj?"L????D;???xHNw??W:+=_??z|)?I???????hg{9???B:F{?W]????ou???_???R?)sw?~?(??5e#eKm??Km?K???????????-W???)|;????V??}j?S?????r?P????i??=???T????,_?Oo>K???h??????f|T?+?I5??????7??Z??L?MT+?N????w???E?O????j?ZF~P -???jX -?????????l?????l?g?(>k???z>#%Ql?Q% -? ??U????j -? -j?%??6?1???n5A~???6?????????v??>g???i?W!??????????R???j???&???P??4?)X???? -_W3*????JC???@.?h?-????1\?L4r???Rq?1??Q??L?K??}???????vd_o?????!=?m?-W?l!m?-:??j?>?"*#??V?jB!?[??X??vE???0?3?\S???E_8??X?B???i???I?S????5?@a?_DK?e[-3?????????m[5[>??? ? ?f?Ps?u?Tm2?m;??$????c?f??Of?}?*??\[?????????g?T?????k?G?1?YQ?J??T?u"????g???F????_?O??r|4??????kQ2?N?2????ck??dj????Q+?!?7?k??n/???d?~??A???O??????R????[:???f???8?\q??w????^???(????z?;D=?W??????G}3$i?W??$??44???Lrx`?7?&I?2?????4??????b?2&?hLt???qD????H? Z????|?Y??c???H<???@3?L??gM`?[Y????l? ??l????[? ??d??8???? -??r5??SI^?r????l???????????=??=W???? ?Z}P?V?GN6\???g??i?z5?7&LM?'?_???????N?F??vY???&???m^H?N???-?|jO?????{I?+?????V???.??G?3\???????????|???;??m????????N?a5hB'\??.??c-G??/ ???,???~E???????k4???r???i?O]?????l6?i?^,??s????tdb?2???(???Q?}?;o??Oo???q.??G?\??????/MgX?N????w????u????%?[??????H?+"?@]Uzn}_?/?xY?)????????>q????>??6??{?E?[S????=? ?????&???,?b?[e???Q??{^?1:n?,?(~T?*?,~\?U?????s??/?_?*???o?????????/?P???3*o=r??????????h?a9!??)yZ?(???re{[?????????r??-???L&??mp?????$??? --'U???L?? -OkRY??u????????\?Z?nU??????.??????'??~????}????srA?k ???v??|Y?!??/~Y?*????'d]?????A?&?? -??'???b|?_29??????y?????d[>???????? -r -endstream -endobj -30 0 obj -<< -/Type /ExtGState -/SA false -/SM 0.02 -/TR /Identity ->> -endobj -1 0 obj -<< -/Type /Pages -/Kids [ 5 0 R ] -/Count 1 ->> -endobj -2 0 obj -<< -/CreationDate (D:20061105011133) -/Producer (Acrobat Distiller 4.0 for Windows) -/ModDate (D:20061105011215+09'00') ->> -endobj -xref -0 3 -0000000000 65535 f -0000051809 00000 n -0000051873 00000 n -trailer -<< -/Size 3 -/ID[<21b37df8f836949f6a724722f5ba950d><21b37df8f836949f6a724722f5ba950d>] ->> -startxref -173 -%%EOF Copied: box/trunk/qdbm/misc/benchmark.pdf (from rev 2716, box/trunk/qdbm/misc/benchmark.pdf) =================================================================== --- box/trunk/qdbm/misc/benchmark.pdf (rev 0) +++ box/trunk/qdbm/misc/benchmark.pdf 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,588 @@ +%PDF-1.2 +%???? +3 0 obj +<< +/Linearized 1 +/O 5 +/H [ 997 194 ] +/L 52196 +/E 51873 +/N 1 +/T 52019 +>> +endobj + xref +3 30 +0000000016 00000 n +0000000944 00000 n +0000001191 00000 n +0000001395 00000 n +0000001539 00000 n +0000001745 00000 n +0000002240 00000 n +0000002419 00000 n +0000002440 00000 n +0000003096 00000 n +0000003117 00000 n +0000003679 00000 n +0000003700 00000 n +0000004424 00000 n +0000004445 00000 n +0000004888 00000 n +0000004909 00000 n +0000005424 00000 n +0000005632 00000 n +0000005979 00000 n +0000006000 00000 n +0000006581 00000 n +0000006602 00000 n +0000007090 00000 n +0000007111 00000 n +0000007620 00000 n +0000029117 00000 n +0000051731 00000 n +0000000997 00000 n +0000001171 00000 n +trailer +<< +/Size 33 +/Info 2 0 R +/Root 4 0 R +/Prev 52010 +/ID[<21b37df8f836949f6a724722f5ba950d><21b37df8f836949f6a724722f5ba950d>] +>> +startxref +0 +%%EOF + +4 0 obj +<< +/Type /Catalog +/Pages 1 0 R +>> +endobj +31 0 obj +<< /S 36 /Filter /FlateDecode /Length 32 0 R >> +stream +H?b``?a``~?Gw1`PZ?????A???1?? +? ??mX????L00|g????? ???`????%???&?' }??V +endstream +endobj +32 0 obj +90 +endobj +5 0 obj +<< +/Type /Page +/Parent 1 0 R +/Resources 6 0 R +/Contents [ 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R 23 0 R 25 0 R 27 0 R ] +/MediaBox [ 0 0 595 842 ] +/CropBox [ 0 0 595 842 ] +/Rotate 0 +>> +endobj +6 0 obj +<< +/ProcSet [ /PDF /Text ] +/Font << /TT2 8 0 R /TT4 21 0 R >> +/ExtGState << /GS1 30 0 R >> +/ColorSpace << /Cs5 9 0 R >> +>> +endobj +7 0 obj +<< +/Type /FontDescriptor +/Ascent 985 +/CapHeight 0 +/Descent -216 +/Flags 34 +/FontBBox [ -165 -307 1246 1201 ] +/FontName /ADKHFG+Century +/ItalicAngle 0 +/StemV 0 +/FontFile2 28 0 R +>> +endobj +8 0 obj +<< +/Type /Font +/Subtype /TrueType +/FirstChar 32 +/LastChar 122 +/Widths [ 278 0 0 0 0 0 0 204 333 333 0 606 278 333 278 0 556 556 556 556 556 +556 556 556 556 556 278 0 0 0 0 0 0 722 722 722 778 722 667 778 +833 407 0 0 667 944 815 778 667 778 722 630 667 815 0 981 704 0 +611 0 0 0 0 0 333 556 556 444 574 500 333 537 611 315 0 593 315 +889 611 500 574 0 444 463 389 611 537 778 537 537 481 ] +/Encoding /WinAnsiEncoding +/BaseFont /ADKHFG+Century +/FontDescriptor 7 0 R +>> +endobj +9 0 obj +[ +/CalRGB << /WhitePoint [ 0.9505 1 1.089 ] /Gamma [ 2.22221 2.22221 2.22221 ] +/Matrix [ 0.4124 0.2126 0.0193 0.3576 0.71519 0.1192 0.1805 0.0722 0.9505 ] >> + +] +endobj +10 0 obj +578 +endobj +11 0 obj +<< /Filter /FlateDecode /Length 10 0 R >> +stream +H??TQo?0~?????!?g;??XJ?2 +???J???????T#A??;?$??h?H???}??w?3??SX? x???Z/?`???W +???vgRn?l?&?^{?fU???t5$Z???????P?u????xf?????+??V???M4???q?????????????8qNf\F???????(??Y~1?NB3}*??0/~?????r?~??D?`?????t?????A?x&w?\?F??8>8?XwOC??????:h???????#????+? +&????6??????SF?????(<#i?$? +??t?)%Um+HBJiR? \J??s??CU??K???1Q?r?XJ v??$l????e-?0s?Z??9?&??M?|{W7?f?T?d??'???\{+D???UE????*"w??0?6?=aa?: <>O8???-????Pg?)z?????)Y??p?:??`6gD? +endstream +endobj +12 0 obj +484 +endobj +13 0 obj +<< /Filter /FlateDecode /Length 12 0 R >> +stream +H???Mo?@@???9?*F????`zh?Vu?????I?6?*F???;P ?N?]13??fv?x?2 9? (?P?Q\?YR?????=l???????????}??&K?f;?-55P???!??kC????k)?t??A??A????? ?8??k?Zh?z||Q?????.??:7???9d???r??w??{E[?'??? ?oW?B7>?rz>:?SW????t-W?r??????2r???L?0t?_P'6? +endstream +endobj +14 0 obj +646 +endobj +15 0 obj +<< /Filter /FlateDecode /Length 14 0 R >> +stream +H??TMo?0 ??W??fp???mi????????[???r ?[?_?J??f?R,AZ|?#)A?? Bc???4!iNS????9??h??+?65t+X???Z ??h????M)?a???_\??`?M????NCJ?C??p?Oo?{?|=?W??k??YuC??fIF?p?nQ +K.??ej +?k?b:(YS? +36?,?Og???'?d+?????W??%???B`???C?_?0.?3?6????R???NU??pV?^qS???????hKU??N??q????o]r?????%?vCb??{>]n?Nm?i`?????{;|aG'??I?^?<7L??????b~=?pc????4l?2_??6\?:?2Y?}?jn?????#?$&Q??(?.??N??6??a??}C@???Op???!?a|=????>`??z?*(?pd9???@&??3x(K?HDBlm??> +stream +H?|??N?0 ??>?g?c????gCb at g`@L\Hp^?4 A??P????????%,? ?????????&?|?U?*w??2&????*????zvZ?????x?? ??-?'}?_w?> +stream +H?t??n?0 ?w?? o???y? C??$?}???e???????;a?j??A???f??????o?0???i?????P Y?K?&?????O??s1?T??^?)?????#3?o?3r??Aj?!???????F???_?X?FPuwS????>??X?0?|f??!yz??p?)? ?3??]?bu???/???J????YU?=?P?ID?e??j????u??)VF[???gqA]?.Y}?/???D?1?[???:??1????Y?Q.??qk??U???m%C??W@???44_?m_;??????e??t??A?X{'??,?K?xK1?C??K?M??i????p??O?x???x??$??M??S?S4i&N? ???'??l7?C?>?0?;?k??????2?r ??C???KD???^? bl2gz a????`?q? +endstream +endobj +20 0 obj +<< +/Type /FontDescriptor +/Ascent 859 +/CapHeight 0 +/Descent -140 +/Flags 32 +/FontBBox [ -121 -137 996 859 ] +/FontName /ADKHNA+MS-PGothic +/ItalicAngle 0 +/StemV 0 +/FontFile2 29 0 R +>> +endobj +21 0 obj +<< +/Type /Font +/Subtype /TrueType +/FirstChar 32 +/LastChar 87 +/Widths [ 305 0 0 0 0 0 0 0 0 0 0 0 0 500 0 0 500 500 500 500 500 500 500 500 +500 500 0 0 0 0 0 0 0 633 637 664 648 566 0 680 0 246 0 0 0 742 +641 0 0 707 625 602 590 0 0 742 ] +/Encoding /WinAnsiEncoding +/BaseFont /ADKHNA +MS-PGothic +/FontDescriptor 20 0 R +>> +endobj +22 0 obj +503 +endobj +23 0 obj +<< /Filter /FlateDecode /Length 22 0 R >> +stream +H???=o?0 ?w? +?v??(???:(z@ \"?C???E??????l??sY?}??)E+2,M6C??S?????[}???I,????$???&@ ?X?F?da?E??:???kK$?i.|???fa%\ +?? ? ?hx???A?N??A?Y?<~??? ?f??9 +asfCMD"???&|^t@?#G5???F?w?I#???X>$?&??????p???)?\??M?th?? +??S??w?:?[fX??#?S?? ^???vJ???_?O????i`?S-?"?R*?????|( Y?,s??2??iu??ul?????%*Y????8???$?????jhA?A(??UK? +ew{??H?Y?????0?.???iJ ?et}??DB??+?:$?v??e????'??w?? ?KfC=?9?G???W????Z?'?q?n&??&N5?8t??'o{?(`;o?`{????C?????o?@???|?-??.??F???5?2?a;??? ??? +endstream +endobj +24 0 obj +410 +endobj +25 0 obj +<< /Filter /FlateDecode /Length 24 0 R >> +stream +H?|?MN?0 ??=??HX???m??Yp? Xp}?v?6e??????}q;0$?_?2ccNUA??j ????t???y?r? ??Y??? [???D?? ?#/???J?? RB?0g@?)F????-*|? ????b?1?w?h????s?W?`?????\_1??1??????1??cr at 9???+f0tL?(r???+f08Fb?xP?;f4tL??M??b?c?6?}??3?6d`??????e&???W!????k???c?}?\?G)???mh84,4?y?l?<$=|??0??g?#JT)????r?b??Gm?Z?cP???#???d?T?I?C???????0??,vq?h9-?k?[????[uUN?!??r!;> +r???9??_?=?}?\?\6?? ? +endstream +endobj +26 0 obj +431 +endobj +27 0 obj +<< /Filter /FlateDecode /Length 26 0 R >> +stream +H?t???? ??<?L?X????f??T?+???????????/? d0???!???l?k?'???+0?W?B?] y??:A??QC8??I?$r?? ??BV?N???c'Q2?????????c'??\e????????????n????4???T????P~???? ?Q???ya???D????Wz?%??x?Q???_???c??U??"???v???u?r?? +????3E[?fy?wi?n?Z?????-?'?^??v=7K?bN???M +?9?????????#?????\{?J???=]?[>V?$???r????H?dj??/????? +endstream +endobj +28 0 obj +<< /Filter /FlateDecode /Length 21406 /Length1 30692 >> +stream +H?|V +pT?????m $???y?#AHB4D???n `???H?n? ?1I#??????P?X????(????0t*C+??heD?j??y??&a???????{?=?|???? $? +e?????(?/?Gpufe]?aB??????M??????o??V??`???????V>?tEM????????Hmu???l?H?q??Z.x[z????F??TL??W??9?5?)?q~?8x??*T??>w?W0?#??M- ??t??r??8??R?N??B?? +??w??V~?@V?M~O>??= +K? ??u?$.ie?0g???9????b&??/???9?]d??????Fg??#??"?G??x%???1???p?+F?Z? 6???r?!s?j?jS?Q??9L\??-?]??%?D'???f?5???"Q??"?7????Wy? 3n)L????-M???29_6? ??T?6C????.?H???j_?+???B?coe%L?X?`l??1??????????Y?#??9,#}?9?g ?cPZ??)??O???O???m? ??{??????Y?(l?a[?0?M?ve3???M a??R??6????Z????, :- nX +?1?????i?g???.??????!???g?x-#&$R??????? +[???]?Tk?~????/4 ??????E?9??l????"???@~T?G"??KL?.6?n?JD????`???????lQXiV?0???3c&(?c{ +???1?"Z?h? ?????pfB?YY?U$????iO5???G/?dg???9A?ga????Q?8???f??????0??f?TeR?hY? {gy?f??? +??4;?tV????@?????!?S??? ?5f'?j3???vOs?Yk-?X-?V?^XRp?y%??4}??T3??E?????Pq?Q|?&;+?M??t???]LB??L? +]??????N?p#2??"?Qi0??i??1?O?X?ch?'$??E?_?????????a}6?y??[W"]+?t?pY?]n??????i??vJ\!K??&??{????R??k??L?????a?}>??-???`7?;e?/? '3d???9??I??j??57??M??a??l?v??????j?m?????;??>#???VY0#b??f???KS??hYE?Qd??H??\a^????Z +?p7?v?DK?]??L?=?3v???J??NN?*r??????A#`?? +??2&&?/FF?AG??z3????=???~?#?{????.Z?#j??e?ym6y??"??=?%?Y?&???c?v????S?{????&] ?I??????6???&???6?G?????z??"A??|???i??E??????|-c ?)?N?)??zA?z a|s(?S.???=yz?`??m?a???h?<????$?o??U?*???k1???1???????-4???Z=??m!2??X????F_D{??X??;I??U +h?6??S???l@?u9????????I?gT$ow??K~?x?b??m??6?0???y?_e?c?m??A?=??G?j?"???????E??|w9??V?? !V?0~?-??(? ?? +???N??:??t???l??????@ ??i??????e[??9?8vr????p?????M? ?? ???i??l?v??y?W>???}??wShS???Lc?z?~?m?u?w??7?^gk?????r`????? x?1?s>??!???4O +????????9?~+-?5??????lm??5.?T?%?98??0f?? +?W?Y]i?\?????O5Z/?<?Mu?????+?W8k?W=??A??U?3M>?u?I?N\7??<-?M??ap1?1??k^?m(?J??3??!-?|>??CL< ?QP??????Qe?????????s?o?????I<?0??u??/????H?????i??+p? ???K???????"??uA??\B=1|K=!?u??????^???y??m?????,\?????{????t??w??B????? +??p?3 +????6P????M???%9??^?4?=?_z??Sk??????????[?]}`????/?^|S??=?????W.0?K??/?R +??,?M?????~T?g&@?_??[L??1??Al??????_d???>???????????g?}fhZR nP +??=?????l??:;???3 + LZ2_ZF?  N?~p4???P??a??????Q ??ph#? ?R?c??{??=?s?????Pg????;c?U?*??V?]???`?`??u?>;?QC?!?`5? +???BU?*?????bU????/-?5?{]??Vw? |?Z??_Z}uhn??b???}554.???p?JDc??!???P7???o?h??AS?????i??P?????_OL??G?????#???>mPy??:W???909Q??3????????????yg$?3????|k& ???p????|k???l???H?I?1?TXx?We??J+^)??D|??????:??? ???Id4"$???????9W?m???1???a???"xy??[2M??"????M?p?8?y?`C??2?>s???W??3??E??????GG7??M?.C???.?gv/enU? ????v??,a:?N?????%?2????)?4y?9??h?Y???K?D8?MX?:?A??? )???bVI?,??`h?0????????&]???5sP????l????#?g????? +?1L??-???$-HX???=?0{?? +?c?ev?<<$?)h?z?3???g???#h ??????`?]???O?p~?U?I??e5??ot?oV????td??[??sW?q??%?????3???I???.??/ OJ[??5Q???I???????;V???m"???????|g??'6???Y??K???Rvz??Q=m??2ATW?}?5_r?B?O??}??]??t?A???c???zE??n*R?X$??&?SB'???D1 5J?,?dY?DD?m:? +?????, ?2'?g????????X?(?????I?K1???h??2 ??Q???O???@ +I?V???D\?!&?qqV?DM,v +?E??t???a|-??|o??GU?*???????6?????e??/3l?a?Df?e,?o@?x-? +??Y?? +?7"sLJ~J????f??jY?N ?CE0?r???irR?y????)mq?)??????r-???e??y????? \^oh???c?[BM!?m-???????I4h??- ??+????>U?????+? 2????Q???. +z?E~???????w???? +???@8)W]?n?7?oR~`)????c????????uLm??`]?????V+??/=]?????}]???A8? 5?S?c4^@?4???j:B??!?,[?c???:?Z??????]??t?+9wrMaL>5? ?)v=\G4iv???^?UcIBmn??J????"(}V??Y??g?d?????O?2>~?%T5?:L?(??e9~VU??})B?HL?qZWU#A$9?????:?????6j#???G???2???1??;y??y?*?`}?,??????a??0? ??N??'??Q?E?????FR=???~????N\?3?Z?R??????5/io8??;?M????r????_l;7???u~^q???kC?V??????????M?]]/okB>????F[r?xK~6??????(??W?I+<???FOmz??` [G??H????M33??> +???u??h"???N??7????? M?:G??icx??l????????7?(w???[???Y???B?rR???(]g[????>W?U??o?? +?????????k8?za??> ~?l?/_fB!|??#t?L\?5???G?"? ?/ ???????T?y16?(??2;?uEM???@?Qw?????R?M?????YE???????M8?V???QW???,0(?K??T??? +2??rN?Tn-????T?h?v??E?<]???5?b@,IY?#??0Q ?qk?#\?!%#?????qhb??s????9Q??h??.??W????7M???LB?9@?8@???C3??????-D?n'??,T ?BT?ha*2?7i@? +?[T????]Y0??jC?A% +i"????1^rJ???]?????4L< +\???)s?????x??O?k^????????!???@?Y?G^?a?y?z?|??????n-?P?FFa?d? +f%????iuw?:???)k????s????d?[k?~J???J!%4 +?N N? X \Q?n???4U?S?n?}Q??.M?^?????&o?w????<,ho7?I'pi ?{E??Nc??m??%??W?H???A?2T&<:????B?PW? +??K?^W?W??e"? ??1???@3?[M???h? D4'???e?2XK??o?0????2????????l?s?]}????@?oc[_???????=?hE??? +????,;>e???????+4?}????G? )?s$???g?-8?(u].{?}??r;m??????qV???W??m?YZ?????%>?????9p?a??ZiMY?$y5?Vd??1-?^?? z??????DH??????^om????beg?3V??????R?=??`k??<_????I$hn%C?L?&?U?8?????Pnb???W4???H}?v?+Vh???K.~?????Hl?!?H!]SKii???? ?|?p?*?(?8?Z?O????? P?$?7y?:????S?????`?D???){??~?Qa????Q??Q:&v????0G7?b?l?O??@3s? G1?????>?tXO1??@@rd????R???R???n?M??|\?'?tS?Gq?#??'j??E?(N?I???AV?z0U]?H??3????p4?/7vS\.E ]72??n*1??(u?z$?PT?(?D?V??e?Mb????{u?e????sm???{?]?W??\?0?<Q?????????Zn?A?L?????p +5?+?6?l?|P!O +6??O#W????r???x2?9??e?????%^?)2?(?I?s()??QF?)?3P???FM???d?b?_ ??|??????S)?Db????tf??5???2DK$V|????????p;???$??,??=??"??Y??p?SM?g?%Kz +?Y)?gCK7??J?yj!?`MTQ?.????>??%`?.???V????t??LYs??Z ??+????I??q??I~?eD???s?'?n??>??Z?F??uh????d!???Hc????x R}+???V?Gjoa??'??[?????&G?,??D??v???dP?*x75*/\g????q??,75?6???????~o?j?? ??4??lChR[???xsD?#?"!m????i???vx????E,????.C0v +?[?j?????m?????*?A?!????????????k??>)??z?Dt?0???[?o?,????7??l?O&?K?????"V6?5??,?q?r>?7DtdE?4??Q7/??F????v?m????aL??? +F??q ???4C?? ???|:??C?v????@?| +?????P?)C????1,+??0-?`??r??J??????CA?mT??;3Zj?:???@X$?3?B?LM?? +/???/?TT`??h?? +?@{???h?M?Qt }???|????u????(|?\??????H?f?'??!%\9?9V???|z?}??m?4??_?G?H??h?~?S???u???Y????????????`1E&???R??@0????@B'?)???B??'6??qi???C?Ii???LM???? +$@??}?????Cow??fg???.r?????s`??????g?3???:??? z? ?J)?????jVyM????N?4)???rBmuI???????J?1#]0?gw +?:? S?%H??m?MdRAV?L???D??]n?d ??[?m< +?5">,?q&?G???????W?Xi??Od??>?7???????O?= +???/?}??7?w?%&n?:??M?D-v?(n?m1??82???*\?`?Kr/q"?C? ???J??]fm?=?/?????:n??C????U_????j4??u?1?? ?Q"?E`?+??`(*?QF???$?x??~??????iAH???qR" r\?????P??E(?O'~?5???V??-??K+?fG?5?.?X???8????W"???????O?P?)j?" +U??fBZz?^?TF$!???Ih?????1??????j%?bMi#V??6????h?`s!?t?,?]???2&?q??qEX?@>?4??G?"?????7|~? ???\??)?Z`?]??ie?y??7Z???O/??c??????\?????????@?+?????u???????? =??,????,???'^?Y? *^?}z?dh>HI??n??Vj?1H??\N4?:?U?U???z??K?K????????N?(tv??T?8???}? +:Qe???3(m??/?F?4???b^`x^?????5?~/???????>?W?8?k????p???b?~??k??a :?70??( ?I_?dn7????q???hv? ?`???g???K??LcP5'!???????6?GLk;B????!??????G<^ ??i#PcZ?S?@??W??= +Z$C??[3?V +PT%??!s>7??? s??U??? +6?eU=u??w?K[?O??????????a?7|`????/??????????[&??Y3_(?:?sQ~x`7Z1%?9??fM]QY???s? ?e????siA ? ??[???"??mr??r??5?x9[?l?X??c.?Ur +\??;?M?V??n??T??C?2d?(?`?$ +???1? H?1?+??N??? ?0G?KB?2w??'!?????P*?d?????? d?Q?W?_?:M??o??? ??e?p??%'r?? ????????U0??????f +??? +?t???? ?fEUR +FQa2???Ps????&???v/?~,):??#?"??G??????C? +I ?1??B9zQ???}q?'?x2???_S?qmK??H??v?S?Sj|v@?O(V??H????P@`??T?*?[????Ud??????FK?kg??????0+c(??aB5??????w??* ?????c?8????w>??#g_????]b; ?8??'?/KB Z?ihH? ? ?Z? ?6U???E???????I ?-0T?J7?UK +-cZ%@??:5M51?_?{???I????'Y~??}~????Xk'???!???}q??ja?2s??d#r?!?u ?\?(8??e)z????? ??[6??8??`?$VK?????2??O???O??Z)???t??/?l????Nv?????????_?`??]I|???????wct??0bq;???%????i /Dr?s????P???n?_?' ?&????Z??Q5J?Im?veH!?#???(? L?10 ??-? ??U9??s?)??[jOE{e?\%?????V?VN?f?ci?{??<,?????e#?5???g?Hg?2??PI??U51?X4 I[?,??a ?m??i????[?3? +???B"?}?NG5 m?x?e;??a7????pr~P?R?tp????B G?a??=????j}????{t??Q???=[??*??>o?????6?\e??M?????3??g?fVw}?i?S??I9?fGH.??`U?9???U??u???????e??fO???????"8?MM?5??????g?B?k ??6??f*???%Q??V?mDB??Z?o????h?vO?????^?I?4,?J?"?H??^?????4%]????6?5 +?u ?P:??????py?}?tZJ??B?L? +1?D 56??bE?%?y{q)?]??+[7|b?L?x? %?oF???h?????@?"%?3?/??$.????:??0??????????T????^D?>4?m??????U????????o^?????????L?????z??????9?+????v???Ni?)?]o?`Dw?cF?n?_?'?Hc??4'E??T?.\??,# +???x???1??~????Qn?;???????q +W??s9?;??/?i?[T????PM??(?Y^Y/*?a ?^?3?P?nH?$Y )??D ????b??u?????????n??ZQj[??'?9??-?*?o`r?l?ki??%K*????'?_?8 ?? ?? +??Q?\K?b???Z??K???Y?#_??X????????0b?d?<"??y????a?? w)??PIJ?AElITI?8&???? f?a?M?#?W???????A?b?? ?????/:{k??4?o7??b???]?? ????:_?J?J?A??K?cN??2d6?xaw????g??????/???????]???veS?5?>?mMc??=?k?u? =?Q????Kh6ok?6???%?u?u?$???s?)???h?&?Z?"???%k6?7w???>uDSg?9?(?h? [?????_??>?????{??|??????????]???$???YM??BB?LJC?R?$ ?v??G?i?j +???h????0D????It???G????????:M?????d,J??}????}?h]?RG???????2,?6?ML?b14?:???Q%Q??1?C?KQ)??;???/???%??????^??!????*?]?U{?*????4?#???5 +u2????P??J??=JP???WVo+4o?MK?????p +? +?????m?=?B??j?????zCb?hh????N ???W??D????R? ?9y???}?W#?T*,(????6?B}? ??*EB???W?*N????`???2`.3.?f?sZ2?????(]??X?H8?d?1? ?d5r??P!l"?2|?2X???X?(?????j w??|G?4A[???>\?O*?v????p???Y???ku?T? ?;??Q??y?? +??z??}???AF??? ??0???&8)t,;I*L$???jV?S??2_?+X?VT?=???k????2?^aV?h?l??W^.?L???u?t??dZ1)? d?y8|mR??S??C$[?`?I{f=????8??T???????????n?i?k?W8??f??E?p?| z~of?xB????:???????????V(?8? +?????J??z?????x???(A +??n?????25=?E"??_1:???vgDdB?(??BZ?c????nM??b +?J?t:?d??S??[?R???Ec??G&"&?Pd?? ?"?iM?D?|%???A??0???? <`????nBo???????a?7???????z?F}@1????~? Tw??D +m?Z|???????Hj=U?????_Q?R?0?????????g?[?@&-I??B?$-??? +9?}?N?q??3?,1+?4???0C? ?dH??D??j8???]?>??c?I??47?Q~/???y/? ~????????L?C?O???G?"K???BqEz"C???2???$?K)a?j?u\?K?G&?c????I??a3??4?uRE'?p?????W???M????????@??d???|e?b?*????q??Io?????8????_???uo?;)?????bPhG??a?z^*?A???>?it??b ?wP? +??9?#??????? ???R?????tJ*'?????*??/*?&,??,?7????P???d'!??uy???"|p???? +???,'t????k/???? ^Xu?U6?Z?P????mv???+ ?8?jF?d???j%???Zs?k]??*~?RmP??d?&?}>sb;k/V ??????y!?V???m[D??q??????x??????k?{?}??6>X2??? \? +p???8# ?HmC?5? ?????2%Qc?,u????(??=I-?]??SD*{?N?++G???)?pdS?L*?0????? +?NW;??8L??X??a?/??=??p??,?dQ???H)U??q>?p?????B????Lv??????????@????????????}?lKqZ? ?R??J?;%?? "?iH:?S?k?N??Xe9?I?????:y????7\??lxnk^??a_`)????????(?+|?????>fvwfgf???;??5?u??'??????ckRA!?k???j?!?&???ELT?)Q[?i??Xj??-N_TQ+P??j+ +-?b?g?-??????:?x??l?'?"???%)??b????@Y?@???j???Z????????z?{?;_???r????\n?N???S?????&/s???/??|<:?u???2??f?%?j????~???????|d??*?={?Y?#?K9???\T>Pn(S??0????~?w?Fj???a??3k:??N? ?{gm??hG???.???F? ?6???y.????q??????(?90G???)2W?? ?????F??"t0{??x???zN%?{??o???\^7]Qa??`???K????U??Rr@ +?t????T???4?}????? +?d?L&??+??"? +?]3V|r?c?+k=???Z????,\.?????@??G?L?jh??????\c??{??$??O??M +fv??_'????h???z?????au?u2?G?8?.|???L???NVt:?2??O?Yv??}?}?}??)?{??{?u????f)? +??M????y}Z???u;?=??/??n?X?B@????t?;???"!*??M?? w????<?%??????O?$?E +W?(>??? +O???? ????Amh?h$?? ????B??V>????GJh??9h7?? ????Y??Y2?,4h!???????????'0 1????q???Q|xU??????Q1?y??X?????q???&????????69?zi??C??)??g@t?????m?s?D?NG??????? +8??C?7$?????T ?B? +??????????j???M91Ct`^?t??D?#?2e?s?;????#bL-? ??1?6??i-?jjJ?g"?:2??0?@?8S?aYeYJ$?????Pd??`???HI??DF_Cw +????????016G????-?????? +:???3?n? ???b>?/?zKJ?uF?u?v8V!??$&P????eh?"??x?w??4n?Y?l?????d2????G?~???o?Q?4Q?o?7??U????!b??!(D?? ????L??2?L(??W? +?e?Zc??????Sn??n?????:???F?r +??{??9?96N??m?t??O at tf??? ???1(1H? ?? Dc?5?CD??????1?ZT??s??^??HT???????~+?C??_Hu?>??7?:qCR'L????QJH{??P???????.?#???Rj?|f?=.??Z?XAa?M?9?8`f????dy???x???????u???7??W??,]K????x.?w9????????{??D????y?\????`???]\?=????4????p?o??1 ???K?T7????t??p??? +?t???e??/??d'X~?????I[??6i???y'???ou??O??o?)???m??n??? +endstream +endobj +29 0 obj +<< /Filter /FlateDecode /Length 22522 /Length1 168840 >> +stream +H??WIo\??7?p?????)?g?s,R%.?$kId!R ?"??b?,%']r ??o?}?!??0???K?\??HnF?J????J/?J? ?u?????????"J?C +?????6????2??]???}u???)??:Q?????????W{???????8??+D?C???w~z?????19?D}W?????????????w??????D???????|=??{?P??c?}???[???s?????????+??7??L? +?m??f????_?U??[??c???u??Z??4Q`}d??f??~p?`??N ???? s' f??aF??3???0???????Lp?f??%a??3f??Uaf??3???0s?????~^??f?)?[?b??>nuJMRn:??H=?1?q??R?q???o??5??o?I:?-?Yq?n?_??zg`?S?=???L>z? +??4???,?:C?F?3???????E`???07?7?:7?7????F???r?????7?qnR???s?9?Mv??\??|???7?inJ3??g????f`???7???T??|?5V? +Q????$?,?*?D????Q???rLTYU??*'D?UQeMTYU6D??????rJT9-??U?U??*?D????Q?;? +u????'n????9?-3nt???cHv??F?2??a??AK??F?????4#?????X3{???4?1?^?????^iP?> ??a?????r???????9??_?????)F?1d???`??{?????0y~cQ?yt??>?x??9??????????I??vJ???Fnr?w +?A?????6i?'17?}?@?;P????3;??????oK?w??????Q/jc?R???.i?????????w?O?'$??c?3?2?/???G?????Qc? y?0D^ ?? /gd? _???I?uF ?(v?5??i??}s???c?=????S??~$/?1W}Ec"?}t??#I^???5?3f??<]225G +8?????8?uKd +???S????92_?`??eL?? ??MF?q???i????????'?=??????L??? ??????g?<~rV ?? +=???9m?;?????+?o?F??w@?? /6??Q?;C??????~???`W????_?`G??iN?uc????#G?nc5??[??/????5??}??e?????5i????R???<_?r?fo??" ???|??9?|N?z?}? ??8?7??? +??\?????o??\? +?????v??g????~??-??7"??? ??4?:!?%Z???i???D??_/??V????}/?cl#?+??&n??2|?o;????v3?????_?[?Z?w???o??????????W??G|}}oF?n +??V_??o r5???{???[?W???si?wD??0????~???@?v?????I????????? ??,?}???o'?qf?? jl?k?`?%??g??-y]?&o?qPy;m:n?^?q????1.?????x +?? +?3??????;I?[??????????}(?y+???}??d?S?+:7?= +? ???@?+?b???3?h??%??@?A??&???E?e???Y??>??'???0?;??W??>S?u?M??#8????w??;?}?????o ?????7?(?S??-? +-Cv?u??o?1?M??9X?sZX7:L???3???????????/A??? [??????.ZpWu?X????? ?????sh??Y?|???E ???W?? +d?A j'8^]]u?????f????C??S??jzj>?|???S?]?????????{??f?&??????[???|Bo????????????f?M????r??>??e???jr??{??c??|??p?y??}?????M??%?}?m? ????H?7?kL\?|??ZL?O[L s??)??f?|?k='???????H?.??????o???n??4??? +????^d_????????C}?/p?????F???t??6>???Soo??????X?]??"y?!???S?:??????m8??Y?ct?l?????[????)??b??C"?{??p]?o??{r13?^t??zI~??Z:???!?1 +???Fx\????!???a?|??/z?OAwW????<}?A??E??u????x????a?3?I?l?C??\?S?a?+/i???w????W:?u????????on???<{?|]???????E?w\"????o8?o?????6? ?S??/??|6?????C??????&???'>V??&>???^]?/??T?d&%???I???d?^????????~=?s?S???s??????q??0S????????<{[dy?]]G???`8cO???K??{L??sj???9z=?????,???wS??#??;^???E?]t~?????E??Xh?'??QxL?,Z?c???????1?q??/o?{K?[?{????~????j?eaU???????UO?b?X?Y_?|??5?6.??v??????????t???W??*/u{\?????/??}??-???*x????l?s?X????p'|?!? ??C?e?Q????????7?{/?? Z???j?zpO?c,????sr0? ?;????M????7????<7??Q?Q???????{????cgxh??v??Q?Yj!z???k??k?k~t?>OA??WtK?!g???S??k?s???C?w????3< ?g6j1??d????k??mu???1??8?R+n???????'jt?[???U?\?????^?T??u3??^??ceO?!???y?2??Qp?g;?s????I????~I.?????D???At?S??k???s)?a?$?>F??b?=???;??????=????'?|?????????V???Q??E??Y???b?S?MrW??^????`+ltO?? ? +}??.5??ou???????? ?I????6??Q??t??p^??????/1??C?????v +????_?a=O?p???)?<;,???????????Q??V?_?????C.l{?? ?6B????????1???.>???|?????>&?L??Q??qb????}??o????59???Hf???#>??3?qX.??N?S???J??.??7??D?t?r_?|s;?_??????Z??O?jM???Exp???%?s?:???c???|?S{0??u?)g??g??K???-?]???A?We??a?<??!{?%??z?f??f?\?7?(3d????i??dY+B;y?????9n?p???(?#3+?7?G??Rklc?K??X? ???^4????3????I????h???}xR??3??s?{?B??y???????`?/??4b??Zrq5?Z?????h????I@??k??F???????????)^?k????m-???u???i???VK#??k??s????H0????"43r?y?5?8p???:?????I?]???Wd??7????G]5?5?s???4~???]S????????K?3?4F??q?k"????????o1?3?4?go?5?Y?Wlb??????}?X???7&???{lB?? 5???????Q?????C?;&O??6?/?9??c?Y?-?3??_}???a+9?????^??????c?????????,??????? ?22?Z???^t?$????9??????'o?=?????l?N??c??v???~?!????'?;v9{??????x?-???k??9t_K??xd?y???]y?K=??w?_??\??v?e????G???q?;?;km??1??d??????.????L?{??b?s?uq +^??i??(?e? tk??}???????p??????\??}??;m3b?6%?o /??E4?;?^?}?>??:????vmx]???}t??A????????'?;??Nrg??)? ? ? +??y???U?y???J??O?X'??kmG????y?6?????)?{??,?;??>??}?ZK?k?Q? :??u?8to??H???????^{?7????V???m?w???}???vK??????o?7?|s?::??? +?i,?r?%Z???h8??????P?m????c???????s???[^?{?????^?C???v?-?y??7??}?4??{?g????>????}??W??L{N5??????????? ?????8c?????????>?:?c????g o]%?-h????????Y??t.9?g?\E???|?z? c-=??dma??????2?I/?i??p3??z?%6&?~??n{???]p%?@?c???I???cZ?)c??O,?|??5?{?I~?y?{????y??>?/?????{?????cY??u?w^Dc?F?6?Rf?`nr?f??????N|^j?0??????v?????;??V?H???l??^4?3=?????/?dt +???????o?'??^{|??????t??,?]z?|???? t?~??????Z?:??N#??N????:x???k)=v?}????e!F]m???]??6y C??????O????????gO??|?c????^????g??N???l?|b???? +y????/{b-???'?I???}????o??=p?}???}???F??8????U?.????F????????x?K?1uf7??????s? ?;k??=j????N??nN?E/?p??9ba??C?e2?Qrea??? ?"?I4??s?D???c??t??+?????'?k?g/:?}?Z~?Qg?/?f=]??E?????|??s???j????}??D?f???N??6??}????S???^|??9??????g??kmg????????|?????w?v?????!O??7?6??yo#?{?3?tn3???>6e?P ??N???o/???f]???>?G?????????a?}???s]??]g?f??$?{????yh?????????'????????Z???????^)C????zMZ-???????k??????w????1?)s????n?y???*??=??^?>???????wq}9wC???5??y??I^?;w??7?????wv???}-?:s?k +6???u26???4w?g???O???????=?k??>??j?i?Z?!x?:?qg?????t?%???????\???@x????Q????????}?8???`\?x??'C_??c?'??:E?_????r??/?D?^ NC?V???O???c?:?zg???3?????U?OO?8f:????????????~???e?c\???=?s??.?~??????x4s?X?????????o??K??????????]?? :?n???s??L???Ez??]?d??X??>???7????N??l?X?X??e?j?Q?????{O??s??I Q?t??$?GA ? ?????>???????????>,????Pk^????)w{??^gO?)s????MR????ko??or?;\??y?2???g??:????~1{?V?????????=?????:'G???Z??x?I6:????????????.h^????w.???;?}b???K?2?c???wj??E8W??;?A????p?{?B?wm???+??? +?s??'??-??qy??}??y|?a??????y?r???."????????;?? ~??U|,???^|??l7t?}6?p?w(?????>?[?C??vr,???j??p-?8W?fzn?1???????1?~?yz??2??k???&s?Uo??f??":???k/?r_???g??O????'???3?mt,??????a????Y????ZG?-??.??csnB?????8?t?:???_?y????}?W??}?9'?????=?{b???AS?????-?m??K?????l{??%??6??kM???2?O???p ?????i???qs?????E4_??v????D?????=??5?&=?ZO?jW?M?2?]?}?g??;?&?R#6e^?-w? ????M?Y??7y?7?k]???Gb?????NLa????????JQ??S??xg)?r????????X] +??????g???????????????? +???^?n?tb?_??4??!~???W:?J?ZI????????p?A/y'???_??N??u]?z????;????g????8?????d?z??]?O???}[????)s[?Y???V>?Eo?G[:4?m???m???Od_??????????@???2????G????6?????5K ????s?H???u?zz??H?????w??????S/v????????a?W?pW???,??z?zA??9??W?\???]?w??y???>?}?.???yt?;?K?+?????L???S]????zf???S|???????Q?????:?e?!#?s??/???Y?]?G?v??~??w????C?o?}??C??~_n{o?p?????>?\??Z?I?a?? ?e?W4=??c$???tI????=c?_?????qoi[Q???????:^Z???>?~^?MF?+S??n??we?'n*?B{#?I8??k??2? ??h<'_ Z4V??O????Y'???z?????,m???|???*?g????n?=E?????-[????vZ??????g??4[w?q????>?6 {?D?????e??????|fj??????s????_[?]???\ ?]-??d?v?~??xn?9?????r?bM??~}????3???m??g^???q? +??n?'????m?]?[??b??o??U???N???d,?5?=????G?0?m??2??Cy?I????Fx??_+??\?? ??:?? +??u?8g??????%??? ??? ?Q??o????????=4??W???? }?{???\H?7???2??N?=????:?2?w??G????A3??????;???~l??^t??^???(?N?????3?ca-?????W?[??}c????s?":?f???}??#??g?xd=?N?2??i>%g?????k??_????e? ?l b`-?????gZb?;?+;7?3?]#G??">Bb#G(?!|$??=?????p?wTw?[??n????? _R2C?&??~J???h|??2??O +??vB O??)??F??5?&}Z?CAzr???7Jq?/??K?7iO??????e?C?) ?B?????q??????!U>?????B?#?!c?n?^??_ +{h?j?y s?4?se?? +v???L??_????y??l?O?O,????E??b2??%???5??&?3??L???X??!?? +?C'??ew???????'?B???%;_??Q?,?9?|:?;??y?9??????c???J?????cdt??>+_??g?C?}r??}{qf{????C???? ??B???_?n?s?P??4?;R???EJ[???????}&77 e??????????n??`L +D??????v???_??_?p~?????A?%????w?5?? c??}??$??;B?kH? +?E?????BD??|???J?u??4??J??=p4ct-?z?????w??????/?N?~u????>?[cw?1?????w??2v>T???/?,7o?svm?6??tp??YC???/???5?@??n6?c~K??????x?pvq????????Tp?8?5[m?0???n?w?d4dy?{?????m?8??g7?VB?.? ??+ at f?S???A?0?7?g?????t????{m4[3??? ?m???'"k??7 ??'???s ?)? }?Y.????B^<#??h?????????????'????=???I???d?7??jY??k?]o +?e1??3\?O???^??????w2?Y ????iuxof^???????3???}?????????V???L??!???Cl2~2???5)?????{?.????f???????q???2????Y???K`?????????g?X?E??7N??? +?m?W???A??}???Q/???A??T??!eu???J???@???kp?G???|c2????|???? +????)???Z;]4,??????2?e?gO??I??? +?K?????]]??k????6.?~M?????WM???h??X;M????]u???|?P-7???xL?x}???@4VegV4????R ?'???4%?vj????v"?OV?x?{?xw??jmt}?/j_?m?'?)cQ +??????@????& |/&?]?H ? +?{?U???8???K???uz3??@?j?Z?'_???k????????x?=O??????Z?@???B??O???n??n!??~???wT?j]G??? ???????A???)??a??????soXA???????e ??9????oFI?q?s??????I?s^_????1??c??1???"?????M??o?l#&???Z7V? ????e? ?=yg+?`??????~?????a???"??<????h?????+z?y??????`H?Ix??p)?`???B?R???&(???y?gx'f+>???????[?s ?[??[?]?o?A2??A?Z???S?3??-o?>??y??/?^ +??????????v???7?????U????^???G?WQ??03??0?O???f?C?;??C???t??a?k?? ?????]??N?? +?k? xAp???~9[?>???b??]?p??g???z?a? +????w +?(?*b??u???Q???`9???@?0??.??????_?}?&Y%???g?_g????z`G?Q?9?c????8?????A?e??M?C????m?Z????E????????}???Q?W?b?q?h??? +???F??Y? +??E?5??#??G+}?7j1G??q?????????q?e??? +?c[? +??^??BNf?k??r/???????x;@/??e2???????????8?????? ???+?p?????????#?C???\?>)?}?Q??(?????V??!??/???f??6??|?.U?xW?????E96?r}?5? ????(l?zs??tJ?2?x????O??-??o????L???,??7? R?X?k?v???Vgv????"??[n??????#????A???v?? ?-??T?/ +????i??l?i?T?`???j?q?????&?q`5??h??A6}<4'[???I?????@:r?.???>???{?a????????y?????(|??G?????$?????x????k~^?@c?U??l??w ?z-6???-?]|?-?M?&lnu??W??N:???h?2?@?=?+??/?~?qu|/?b1}Y??P???9??#g?s?t`??@Nb?UD??R4]?,??Vw:0o?n?#??D?2??S?????a????!? ?????f????o????P?K;3???*?\?????5????^??6???Af at K?s?#???W?F*4???????.?????g??W???N?Q`xh?]?? +????`{J?&tr?6?4?j?f?oE{???P??gwPA?;??????????????~(?%?{??>????d?j]??S?3i??v??v?? +i?,?2j?tX????o?x??5X?q?lW?xs?r??J ?0??lp?t??G????????????Q?d???_^2??????CVVq?8???q? +?OM?%_k?!?7;_??W??c?ct???7?t?????W?,??W"???0?z????n?Qh2?~HZ???Xk?rq0F???58??F?|?1i?\?}?}???&D?]?Z??!?](Zl???v??0;?eg?O?? ?w?m????7??????Z?@>??{??Abz4V?H???_S??~??????vpc*?????hB????sM???E???x?=?^x? n??~K????3F3F??]??=?,Ys,V??????????}v&3?&O???{???T?!_H?'myk????`?yh??N??ql???V?7U??????????'?|GcT?LA{eI?@'?p????.????????c ??g?y?B6v?????M???f??U???d?o?q??_*?WK???X??X;??g?}?B????{@??|hm?c????!??a??5?? u????&e????Wm;?'jx?|??a?????a???:???bo?|?D????4? ????[?o?Y????]?H}???{?U???8???|o{ug?n?F??O?P{/?Z?S?????x??p;?'e?'?{??????;??a=ju??'????A?5s???:-^??#???6???W??????0FT??V!?????:a???& +????q???w!x??j}p??h?~??XK??? +?W??~???j??;?6???????*y?u5?:???h?(k?'#.G?_K??????'&k/?5?????[??\?K???V| ??Q??f???y?;?1????x??~?c??S?_????[????Uwa?(?"?? +??? ????? ?o@?5?} +rD??a??????????w???/????;}??K~g????:'u/B????'_?v?rl?(+BY-?e,???s| 5?wa?Sd-???x>?????k??K?s ?K??%???N-B2??Am?G?y?Z?zG????z?E????[??rj~= +??A?Y??/???w1?"r?]??&???}??,{I?????0??9?,??{?_? ????????d? y?O?[1_r? ??b??{?T?B?(???3?i?= +z +9s? g7????|???Q???????R#?????@;??_?}8???7@}x8?/??3?=~??? +???G?C??Oa?/0?8????????L???w???=@?(??_#????????oF???\ =?A??????_? 9g??!?.?&9{k?U+?}??>?????)?=???U?IY?`?J +??ZK?????'1a??M?_b?1*w?$i???}???R??2e]????8?????sn?>???f[?T?S?$???(????V?????????_0??Rj?J?R??c]?tK?:?????NuBd?C}?b{?"H?W?/??"? +S???d,$_>?5#??????.??s~??JmZ?0*5N ?(g|?Q>'???(??U??8}? ??{??????^s??)????O???T/??R???????m????gj?"L????D;???xHNw??W:+=_??z|)?I???????hg{9???B:F{?W]????ou???_???R?)sw?~?(??5e#eKm??Km?K???????????-W???)|;????V??}j?S?????r?P????i??=???T????,_?Oo>K???h??????f|T?+?I5??????7??Z??L?MT+?N????w???E?O????j?ZF~P +???jX +?????????l?????l?g?(>k???z>#%Ql?Q% +? ??U????j +? +j?%??6?1???n5A~???6?????????v??>g???i?W!??????????R???j???&???P??4?)X???? +_W3*????JC???@.?h?-????1\?L4r???Rq?1??Q??L?K??}???????vd_o?????!=?m?-W?l!m?-:??j?>?"*#??V?jB!?[??X??vE???0?3?\S???E_8??X?B???i???I?S????5?@a?_DK?e[-3?????????m[5[>??? ? ?f?Ps?u?Tm2?m;??$????c?f??Of?}?*??\[?????????g?T?????k?G?1?YQ?J??T?u"????g???F????_?O??r|4??????kQ2?N?2????ck??dj????Q+?!?7?k??n/???d?~??A???O??????R????[:???f???8?\q??w????^???(????z?;D=?W??????G}3$i?W??$??44???Lrx`?7?&I?2?????4??????b?2&?hLt???qD????H? Z????|?Y??c???H<???@3?L??gM`?[Y????l? ??l????[? ??d??8???? +??r5??SI^?r????l???????????=??=W???? ?Z}P?V?GN6\???g??i?z5?7&LM?'?_???????N?F??vY???&???m^H?N???-?|jO?????{I?+?????V???.??G?3\???????????|???;??m????????N?a5hB'\??.??c-G??/ ???,???~E???????k4???r???i?O]?????l6?i?^,??s????tdb?2???(???Q?}?;o??Oo???q.??G?\??????/MgX?N????w????u????%?[??????H?+"?@]Uzn}_?/?xY?)????????>q????>??6??{?E?[S????=? ?????&???,?b?[e???Q??{^?1:n?,?(~T?*?,~\?U?????s??/?_?*???o?????????/?P???3*o=r??????????h?a9!??)yZ?(???re{[?????????r??-???L&??mp?????$??? +-'U???L?? +OkRY??u????????\?Z?nU??????.??????'??~????}????srA?k ???v??|Y?!??/~Y?*????'d]?????A?&?? +??'???b|?_29??????y?????d[>???????? +r +endstream +endobj +30 0 obj +<< +/Type /ExtGState +/SA false +/SM 0.02 +/TR /Identity +>> +endobj +1 0 obj +<< +/Type /Pages +/Kids [ 5 0 R ] +/Count 1 +>> +endobj +2 0 obj +<< +/CreationDate (D:20061105011133) +/Producer (Acrobat Distiller 4.0 for Windows) +/ModDate (D:20061105011215+09'00') +>> +endobj +xref +0 3 +0000000000 65535 f +0000051809 00000 n +0000051873 00000 n +trailer +<< +/Size 3 +/ID[<21b37df8f836949f6a724722f5ba950d><21b37df8f836949f6a724722f5ba950d>] +>> +startxref +173 +%%EOF Deleted: box/trunk/qdbm/misc/icon16.png =================================================================== (Binary files differ) Copied: box/trunk/qdbm/misc/icon16.png (from rev 2716, box/trunk/qdbm/misc/icon16.png) =================================================================== (Binary files differ) Deleted: box/trunk/qdbm/misc/icon20.png =================================================================== (Binary files differ) Copied: box/trunk/qdbm/misc/icon20.png (from rev 2716, box/trunk/qdbm/misc/icon20.png) =================================================================== (Binary files differ) Deleted: box/trunk/qdbm/misc/index.html =================================================================== --- box/trunk/qdbm/misc/index.html 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/misc/index.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - -QDBM: Quick Database Manager - - - - - - -

QDBM: Quick Database Manager

- -
Copyright (C) 2000-2007 Mikio Hirabayashi
-
Last Update: Thu, 26 Oct 2006 15:00:20 +0900
- - - - -
- -

Overview

- -

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organized in hash table or B+ tree.

- -

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers: NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

- -

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting, and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

- -

QDBM is written in C, and provided as APIs of C, C++, Java, Perl, and Ruby. QDBM is available on platforms which have API conforming to POSIX. QDBM is a free software licensed under the GNU Lesser General Public License.

- -
- -

Documents

- -

The following are documents of QDBM. They are contained also in the source package.

- - - -
- -

Packages

- -

The following are packages of QDBM. The Linux binary package contains APIs for C, C++, and Java. It contains CGI scripts also. The Windows binary package contains APIs for C and Java. It contains CGI scripts also.

- - - - - - - -
- -

Applications

- -

The following are links to applications of QDBM. If you run or find a project using QDBM, please tell it, and it will added to this list.

- -
    -
  • Hyper Estraier : Full-text Search System for Communities written by Mikio Hirabayashi
  • -
  • Estraier : Personal Full-text Search System written by Mikio Hirabayashi
  • -
  • Diqt : Multilingual Dictionary Searcher written by Mikio Hirabayashi
  • -
  • RBBS : WWW-based Bulletin Board System written by Mikio Hirabayashi
  • -
  • Harvest : Distributed Search System written by Kang-Jin Lee et al
  • -
  • Bogofilter : Bayesian Spam Mail Filter written by Eric S. Raymond et al
  • -
  • MQS : Minimalist Queue Services written by Alexandre Dulaunoy
  • -
  • Ruby/Odeum : Ruby Binding to the Inverted API written by Zed A. Shaw
  • -
  • Surfulater : Utility to Save and Organize Web Pages written by Soft As it Gets Pty Ltd
  • -
  • Mutt-NG : Text Based Mail Client written by Andreas Krennmair et al
  • -
  • SMFS : Smart Sendmail Filters written by Eugene Kurmanin
  • -
  • Dixit : Romanian Dictionary Searcher written by Octavian Procopiuc
  • -
- -
- -

Brothers

- -

There are many followers of UNIX DBM. Select the best suited one for your products. NDBM is ancient and you should not use it. SDBM is maintained by Apache Project, and GDBM is maintained by GNU Project. They are most popular and time-tested. TDB is maintained by Samba Team. It allows multiple simultaneous writers. While CDB does not support updating at a runtime, it is the fastest. Berkeley DB is very multifunctional and ACID compliant. It is used in many commercial products. Finally, QDBM is balanced of performance, functionality, portability, and usability.

- -
    -
  • NDBM : New DBM written by BSD
  • -
  • SDBM : Substitute DBM written by Ozan S. Yigit
  • -
  • GDBM : GNU Database Manager written by Philip A. Nelson et al
  • -
  • TDB : Trivial Database written by Andrew Tridgell et al
  • -
  • TinyCDB : Constant Database written by Michael Tokarev
  • -
  • Berkeley DB : Berkeley DB written by Sleepycat Software
  • -
- - - -
- -

Information

- -

QDBM was written by Mikio Hirabayashi. You can contact the author by e-mail to `mikio at users.sourceforge.net'. However, as for topics which can be shared among other users, pleae send it to the mailing list. To join the mailing list, refer to `http://lists.sourceforge.net/lists/listinfo/qdbm-users'.

- -

The project page on SourceForge.net is `http://sourceforge.net/projects/qdbm/'.

- -

Update of this project is announced on Freshmeat.net at `http://freshmeat.net/projects/qdbm/'.

- -
- - - - - - Copied: box/trunk/qdbm/misc/index.html (from rev 2716, box/trunk/qdbm/misc/index.html) =================================================================== --- box/trunk/qdbm/misc/index.html (rev 0) +++ box/trunk/qdbm/misc/index.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + +QDBM: Quick Database Manager + + + + + + +

QDBM: Quick Database Manager

+ +
Copyright (C) 2000-2007 Mikio Hirabayashi
+
Last Update: Thu, 26 Oct 2006 15:00:20 +0900
+ + + + +
+ +

Overview

+ +

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organized in hash table or B+ tree.

+ +

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers: NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

+ +

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting, and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

+ +

QDBM is written in C, and provided as APIs of C, C++, Java, Perl, and Ruby. QDBM is available on platforms which have API conforming to POSIX. QDBM is a free software licensed under the GNU Lesser General Public License.

+ +
+ +

Documents

+ +

The following are documents of QDBM. They are contained also in the source package.

+ + + +
+ +

Packages

+ +

The following are packages of QDBM. The Linux binary package contains APIs for C, C++, and Java. It contains CGI scripts also. The Windows binary package contains APIs for C and Java. It contains CGI scripts also.

+ + + + + + + +
+ +

Applications

+ +

The following are links to applications of QDBM. If you run or find a project using QDBM, please tell it, and it will added to this list.

+ +
    +
  • Hyper Estraier : Full-text Search System for Communities written by Mikio Hirabayashi
  • +
  • Estraier : Personal Full-text Search System written by Mikio Hirabayashi
  • +
  • Diqt : Multilingual Dictionary Searcher written by Mikio Hirabayashi
  • +
  • RBBS : WWW-based Bulletin Board System written by Mikio Hirabayashi
  • +
  • Harvest : Distributed Search System written by Kang-Jin Lee et al
  • +
  • Bogofilter : Bayesian Spam Mail Filter written by Eric S. Raymond et al
  • +
  • MQS : Minimalist Queue Services written by Alexandre Dulaunoy
  • +
  • Ruby/Odeum : Ruby Binding to the Inverted API written by Zed A. Shaw
  • +
  • Surfulater : Utility to Save and Organize Web Pages written by Soft As it Gets Pty Ltd
  • +
  • Mutt-NG : Text Based Mail Client written by Andreas Krennmair et al
  • +
  • SMFS : Smart Sendmail Filters written by Eugene Kurmanin
  • +
  • Dixit : Romanian Dictionary Searcher written by Octavian Procopiuc
  • +
+ +
+ +

Brothers

+ +

There are many followers of UNIX DBM. Select the best suited one for your products. NDBM is ancient and you should not use it. SDBM is maintained by Apache Project, and GDBM is maintained by GNU Project. They are most popular and time-tested. TDB is maintained by Samba Team. It allows multiple simultaneous writers. While CDB does not support updating at a runtime, it is the fastest. Berkeley DB is very multifunctional and ACID compliant. It is used in many commercial products. Finally, QDBM is balanced of performance, functionality, portability, and usability.

+ +
    +
  • NDBM : New DBM written by BSD
  • +
  • SDBM : Substitute DBM written by Ozan S. Yigit
  • +
  • GDBM : GNU Database Manager written by Philip A. Nelson et al
  • +
  • TDB : Trivial Database written by Andrew Tridgell et al
  • +
  • TinyCDB : Constant Database written by Michael Tokarev
  • +
  • Berkeley DB : Berkeley DB written by Sleepycat Software
  • +
+ + + +
+ +

Information

+ +

QDBM was written by Mikio Hirabayashi. You can contact the author by e-mail to `mikio at users.sourceforge.net'. However, as for topics which can be shared among other users, pleae send it to the mailing list. To join the mailing list, refer to `http://lists.sourceforge.net/lists/listinfo/qdbm-users'.

+ +

The project page on SourceForge.net is `http://sourceforge.net/projects/qdbm/'.

+ +

Update of this project is announced on Freshmeat.net at `http://freshmeat.net/projects/qdbm/'.

+ +
+ + + + + + Deleted: box/trunk/qdbm/misc/index.ja.html =================================================================== --- box/trunk/qdbm/misc/index.ja.html 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/misc/index.ja.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,209 +0,0 @@ - - - - - - - - - - - - - - -????????????????????????????????? QDBM - - - - - - -

QDBM: Quick Database Manager

- -
Copyright (C) 2000-2007 Mikio Hirabayashi
-
Last Update: Thu, 26 Oct 2006 15:00:20 +0900
- - - - -
- -

??????

- -

QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+???????????????????????????

- -

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????UNIX??????????????????????????????DBM?????????????????????????????????????????????NDBM???GDBM???????????????????????????QDBM???DBM??????????????????????????????????????????????????????????????????

- -

B+??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+??????????????????????????????????????????????????????????????????????????????

- -

QDBM???C??????????????????C???C++???Java???Perl?????????Ruby???API??????????????????????????????QDBM???POSIX?????????API????????????????????????????????????????????????????????????QDBM???GNU Lesser General Public License????????????????????????????????????????????????

- -
- -

??????

- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????

- - - -
- -

??????????????????

- -

??????????????????????????????????????????????????????????????????Linux????????????????????????????????????C???C++???Java???API??????CGI???????????????????????????????????????Windows????????????????????????????????????C???Java???API??????CGI???????????????????????????????????????

- - - - - - - -
- -

????????????????????????

- -

QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????????????????????????????????????????

- -
    -
  • Hyper Estraier : ?????????????????????????????????????????????????????????
  • -
  • Estraier : ??????????????????????????????????????????????????????
  • -
  • Diqt : ??????????????????????????????????????????????????????
  • -
  • RBBS : ?????????????????????Web?????????????????????
  • -
  • Harvest : Kang-Jin Lee??????????????????????????????????????????
  • -
  • Bogofilter : Eric S. Raymond??????????????????????????????????????????????????????
  • -
  • MQS : Alexandre Dulaunoy????????????????????????????????????
  • -
  • Ruby/Odeum : Zed A. Shaw???????????????API???Ruby???????????????????????????
  • -
  • Surfulater : Soft As it Gets Pty????????????Web?????????????????????????????????
  • -
  • Mutt-NG : Andreas Krennmair??????????????????????????????????????????????????????
  • -
  • SMFS : Eugene Kurmanin?????????Sendmail???????????????????????????
  • -
  • Dixit : Octavian Procopiuc???????????????????????????????????????????????????
  • -
- -
- -

??????

- -

UNIX?????????DBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????NDBM???????????????????????????????????????????????????????????????SDBM???Apache Project??????????????????GDBM???GNU Project??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????TDB???Samba Team????????????????????????????????????????????????????????????????????????TinyCDB???????????????????????????????????????????????????????????????????????????Berkeley DB???????????????????????????ACID????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????????????????????????????

- -
    -
  • NDBM : BSD?????????New DBM
  • -
  • SDBM : Ozan S. Yigit?????????Substitute DBM
  • -
  • GDBM : Philip A. Nelson????????????GNU Database Manager
  • -
  • TDB : Andrew Tridgell????????????Trivial Database
  • -
  • TinyCDB : Michael Tokarev?????????Constant Database
  • -
  • Berkeley DB : Sleepycat Software????????????Berkeley DB
  • -
- - - -
- -

??????????????????

- -

QDBM????????????????????????????????????????????????????????????????????????`mikio at users.sourceforge.net' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`http://lists.sourceforge.net/lists/listinfo/qdbm-users' ??????????????????????????????

- -

SourceForge.net?????????????????????????????????????????? `http://sourceforge.net/projects/qdbm/' ??????????????????Freshmeat??????????????????????????? `http://freshmeat.net/projects/qdbm/' ???????????????????????????

- -
- - - - - - Copied: box/trunk/qdbm/misc/index.ja.html (from rev 2716, box/trunk/qdbm/misc/index.ja.html) =================================================================== --- box/trunk/qdbm/misc/index.ja.html (rev 0) +++ box/trunk/qdbm/misc/index.ja.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + +????????????????????????????????? QDBM + + + + + + +

QDBM: Quick Database Manager

+ +
Copyright (C) 2000-2007 Mikio Hirabayashi
+
Last Update: Thu, 26 Oct 2006 15:00:20 +0900
+ + + + +
+ +

??????

+ +

QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+???????????????????????????

+ +

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????UNIX??????????????????????????????DBM?????????????????????????????????????????????NDBM???GDBM???????????????????????????QDBM???DBM??????????????????????????????????????????????????????????????????

+ +

B+??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+??????????????????????????????????????????????????????????????????????????????

+ +

QDBM???C??????????????????C???C++???Java???Perl?????????Ruby???API??????????????????????????????QDBM???POSIX?????????API????????????????????????????????????????????????????????????QDBM???GNU Lesser General Public License????????????????????????????????????????????????

+ +
+ +

??????

+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ + + +
+ +

??????????????????

+ +

??????????????????????????????????????????????????????????????????Linux????????????????????????????????????C???C++???Java???API??????CGI???????????????????????????????????????Windows????????????????????????????????????C???Java???API??????CGI???????????????????????????????????????

+ + + + + + + +
+ +

????????????????????????

+ +

QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????????????????????????????????????????

+ +
    +
  • Hyper Estraier : ?????????????????????????????????????????????????????????
  • +
  • Estraier : ??????????????????????????????????????????????????????
  • +
  • Diqt : ??????????????????????????????????????????????????????
  • +
  • RBBS : ?????????????????????Web?????????????????????
  • +
  • Harvest : Kang-Jin Lee??????????????????????????????????????????
  • +
  • Bogofilter : Eric S. Raymond??????????????????????????????????????????????????????
  • +
  • MQS : Alexandre Dulaunoy????????????????????????????????????
  • +
  • Ruby/Odeum : Zed A. Shaw???????????????API???Ruby???????????????????????????
  • +
  • Surfulater : Soft As it Gets Pty????????????Web?????????????????????????????????
  • +
  • Mutt-NG : Andreas Krennmair??????????????????????????????????????????????????????
  • +
  • SMFS : Eugene Kurmanin?????????Sendmail???????????????????????????
  • +
  • Dixit : Octavian Procopiuc???????????????????????????????????????????????????
  • +
+ +
+ +

??????

+ +

UNIX?????????DBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????NDBM???????????????????????????????????????????????????????????????SDBM???Apache Project??????????????????GDBM???GNU Project??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????TDB???Samba Team????????????????????????????????????????????????????????????????????????TinyCDB???????????????????????????????????????????????????????????????????????????Berkeley DB???????????????????????????ACID????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????????????????????????????

+ +
    +
  • NDBM : BSD?????????New DBM
  • +
  • SDBM : Ozan S. Yigit?????????Substitute DBM
  • +
  • GDBM : Philip A. Nelson????????????GNU Database Manager
  • +
  • TDB : Andrew Tridgell????????????Trivial Database
  • +
  • TinyCDB : Michael Tokarev?????????Constant Database
  • +
  • Berkeley DB : Sleepycat Software????????????Berkeley DB
  • +
+ + + +
+ +

??????????????????

+ +

QDBM????????????????????????????????????????????????????????????????????????`mikio at users.sourceforge.net' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`http://lists.sourceforge.net/lists/listinfo/qdbm-users' ??????????????????????????????

+ +

SourceForge.net?????????????????????????????????????????? `http://sourceforge.net/projects/qdbm/' ??????????????????Freshmeat??????????????????????????? `http://freshmeat.net/projects/qdbm/' ???????????????????????????

+ +
+ + + + + + Deleted: box/trunk/qdbm/misc/logo.png =================================================================== (Binary files differ) Copied: box/trunk/qdbm/misc/logo.png (from rev 2716, box/trunk/qdbm/misc/logo.png) =================================================================== (Binary files differ) Deleted: box/trunk/qdbm/misc/makevcdef =================================================================== --- box/trunk/qdbm/misc/makevcdef 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/misc/makevcdef 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,48 +0,0 @@ -#! /bin/sh - -#================================================================ -# makevcdef -# Generator of module definition file for Visual C++ -#================================================================ - - -# check arguments -file="$1" -if [ -f "$file" ] -then - true -else - printf 'usage: makevcdef library\n' 1>&2 - exit 1 -fi - - -# show headers -name=`echo $file | sed -e 's/^lib//' -e 's/\..*//'` -printf 'EXPORTS\r\n' - - -# show variables -nm -g "$file" | grep ' [BDR] ' | sed 's/.* [BDR] //' | grep -v '^_' | sort | uniq | -while read name -do - num=$((num + 1)) - printf ' %s = %s DATA\r\n' "$name" "$name" -done - - -# show functions -nm -g "$file" | grep ' T ' | sed 's/.* T //' | grep -v '^_' | sort | uniq | -while read name -do - num=$((num + 1)) - printf ' %s = %s\r\n' "$name" "$name" -done - - -# exit normally -exit 0 - - - -# END OF FILE Copied: box/trunk/qdbm/misc/makevcdef (from rev 2716, box/trunk/qdbm/misc/makevcdef) =================================================================== --- box/trunk/qdbm/misc/makevcdef (rev 0) +++ box/trunk/qdbm/misc/makevcdef 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,48 @@ +#! /bin/sh + +#================================================================ +# makevcdef +# Generator of module definition file for Visual C++ +#================================================================ + + +# check arguments +file="$1" +if [ -f "$file" ] +then + true +else + printf 'usage: makevcdef library\n' 1>&2 + exit 1 +fi + + +# show headers +name=`echo $file | sed -e 's/^lib//' -e 's/\..*//'` +printf 'EXPORTS\r\n' + + +# show variables +nm -g "$file" | grep ' [BDR] ' | sed 's/.* [BDR] //' | grep -v '^_' | sort | uniq | +while read name +do + num=$((num + 1)) + printf ' %s = %s DATA\r\n' "$name" "$name" +done + + +# show functions +nm -g "$file" | grep ' T ' | sed 's/.* T //' | grep -v '^_' | sort | uniq | +while read name +do + num=$((num + 1)) + printf ' %s = %s\r\n' "$name" "$name" +done + + +# exit normally +exit 0 + + + +# END OF FILE Deleted: box/trunk/qdbm/misc/mymemo-ja.html =================================================================== --- box/trunk/qdbm/misc/mymemo-ja.html 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/misc/mymemo-ja.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,34 +0,0 @@ - - - - - - - - - - -My Private Memo for QDBM - - - - -

QDBM????????????????????????

- -
- -

cygwin+mingw????????????????????????????????????

- -
    -
  • Cygwin??????????????????????????????mingw???gcc???mingw???zlib??????????????????
  • -
  • mingw???libiconv???mingw????????????????????????????????????????????????*.h ??? /usr/include/mingw ????????????*.dll.a ??? /lib/mingw ????????????*.dll ??? /bin???????????????????????????
  • -
  • QDBM?????????????????????????????? ./configure --enable-zlib --enable-iconv ??????????????????????????????????????? make win32pkg ????????????
  • -
- -
- - - - - - Copied: box/trunk/qdbm/misc/mymemo-ja.html (from rev 2716, box/trunk/qdbm/misc/mymemo-ja.html) =================================================================== --- box/trunk/qdbm/misc/mymemo-ja.html (rev 0) +++ box/trunk/qdbm/misc/mymemo-ja.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,34 @@ + + + + + + + + + + +My Private Memo for QDBM + + + + +

QDBM????????????????????????

+ +
+ +

cygwin+mingw????????????????????????????????????

+ +
    +
  • Cygwin??????????????????????????????mingw???gcc???mingw???zlib??????????????????
  • +
  • mingw???libiconv???mingw????????????????????????????????????????????????*.h ??? /usr/include/mingw ????????????*.dll.a ??? /lib/mingw ????????????*.dll ??? /bin???????????????????????????
  • +
  • QDBM?????????????????????????????? ./configure --enable-zlib --enable-iconv ??????????????????????????????????????? make win32pkg ????????????
  • +
+ +
+ + + + + + Deleted: box/trunk/qdbm/misc/tutorial-ja.html =================================================================== --- box/trunk/qdbm/misc/tutorial-ja.html 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/misc/tutorial-ja.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,622 +0,0 @@ - - - - - - - - - - - - - - -Tutorial of QDBM Version 1 (Japanese) - - - - - -

QDBM????????????????????????

- -
Copyright (C) 2000-2007 Mikio Hirabayashi
-
Last Update: Thu, 26 Oct 2006 15:00:20 +0900
- - -
- -

??????

- -
    -
  1. ???????????????????????????
  2. -
  3. Depot: ??????API
  4. -
  5. Curia: ??????API
  6. -
  7. Relic: NDBM??????API
  8. -
  9. Hovel: GDBM??????API
  10. -
  11. Cabin: ?????????????????????API
  12. -
  13. Villa: ??????API
  14. -
  15. Odeum: ??????API
  16. -
- -
- -

???????????????????????????

- -

QDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????SQL????????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

QDBM???C????????????????????????????????????????????????API????????????????????????QDBM?????????????????????????????????????????????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????C???????????????????????????????????????????????????????????????????????????C++???Java???Perl???Ruby???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????QDBM????????????????????????C??????????????????????????????Perl?????????????????????????????????????????????????????????????????????UNIX??????Windows??????Mac OS X????????????????????????????????????????????????????????????????????????????????????????????????

- -

?????????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????B+?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????MIME???CSV???XML???????????????????????????????????????????????????????????????????????????????????????????????????

- -

?????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????B+????????????????????????????????????????????????????????????????????????????????????????????????Web?????????????????????????????????????????????

- -
- -

Depot: ??????API

- -

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

?????????QDBM????????????????????????????????????????????????????????????????????????????????????CSV??????????????????????????????????????????????????????????????????????????????????????????????????????

- -
00001,8-902-1234
-00002,7-938-834
-00008,4-214-491
-
- -

?????????????????????????????? `putphonenumber' ??????????????????????????????????????? `getphonenumber' ?????????????????????

- -
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define PHONEFILE    "phone"
-#define LINEBUFSIZ   256
-
-int putphonenumber(const char *id, const char *phone){
-  FILE *OUT;
-  /* ??????????????????????????????????????? */
-  if(!(OUT = fopen(PHONEFILE, "a"))) return -1;
-  /* ??????????????????????????? */
-  fprintf(OUT, "%s,%s\n", id, phone);
-  /* ???????????????????????? */
-  if(fclose(OUT) != 0) return -1;
-  return 0;
-}
-
-char *getphonenumber(const char *id){
-  FILE *IN;
-  char line[LINEBUFSIZ], *pivot, *phone;
-  int len;
-  /* ????????????????????????????????????????????? */
-  if(!(IN = fopen(PHONEFILE, "r"))) return NULL;
-  /* ????????????????????? */
-  while(fscanf(IN, "%s", line) == 1){
-    /* ?????????????????????????????? */
-    if(!(pivot = strchr(line, ','))) continue;
-    *pivot = '\0';
-    pivot++;
-    /* ????????????????????? */
-    if(strcmp(line, id) == 0){
-      /* ???????????????????????? */
-      if(fclose(IN) != 0) return NULL;
-      /* ???????????????????????????????????????????????? */
-      len = strlen(pivot);
-      if(!(phone = malloc(len + 1))) return NULL;
-      memcpy(phone, pivot, len + 1);
-      return phone;
-    }
-  }
-  /* ???????????????????????? */
-  fclose(IN);
-  return NULL;
-}
-
- -

`fscanf' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????255????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <stdlib.h>
-
-#define PHONEFILE    "phone"
-
-int putphonenumber(const char *id, const char *phone){
-  DEPOT *depot;
-  /* ????????????????????????????????????????????? */
-  if(!(depot = dpopen(PHONEFILE, DP_OWRITER | DP_OCREAT, -1))) return -1;
-  /* ??????????????????????????? */
-  dpput(depot, id, -1, phone, -1, DP_DOVER);
-  /* ?????????????????????????????? */
-  if(!dpclose(depot)) return -1;
-  return 0;
-}
-
-char *getphonenumber(const char *id){
-  DEPOT *depot;
-  char *phone;
-  /* ??????????????????????????????????????????????????? */
-  if(!(depot = dpopen(PHONEFILE, DP_OREADER, -1))) return NULL;
-  /* ??????????????????????????????????????????????????? */
-  phone = dpget(depot, id, -1, 0, -1, NULL);
-  /* ?????????????????????????????? */
-  dpclose(depot);
-  return phone;
-}
-
- -

??????????????????????????????CSV?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????

- -

??????????????????QDBM?????????API?????????Depot????????????????????????????????????`DEPOT' ???????????????????????????????????????????????????????????????????????? `FILE' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`dpopen'???`dpclose'???`dpput' ????????? `dpget' ??????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????

- -
DEPOT *dpopen(const char *name, int omode, int bnum);
- -

`dpopen' ????????????????????????Depot?????????????????????????????????????????????????????????????????? `DEPOT' ?????????????????????????????????????????????????????????1??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????2???????????????????????????????????????????????????????????????????????????????????????????????? `DP_OWRITER' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `DP_OCREAT' ????????????OR???????????????????????????????????????????????????????????????????????????`fopen' ??? `a+' ?????????????????????????????????????????????????????? `DP_OTRUNC' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `fopen' ??? `w+' ?????????????????????????????????????????????????????????????? ??????????????????????`DP_OREADER' ?????????????????????????????? `fopen' ??? `r' ??????????????????????????????????????????3??????????????????????????????????????????????????????????????????????????????????????????????????????????????? `-1' ?????????????????????????????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
int dpclose(DEPOT *depot);
- -

`dpclose' ???????????????????????????????????????????????????1???????????? `dpopen' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????????QDBM???????????????????????????????????????????????????????????? `fprintf' ????????????????????????????????????????????????`fprintf' ???????????????????????? `fclose' ????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????????????????????????? `dpclose' ???????????????????????????????????????????????????????????????????????????????????????????????????

- -
int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
- -

`dpput' ?????????????????????????????????????????????????????????????????????1???????????? `dpopen' ?????????????????????????????????????????????2????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3??????????????????????????????????????????????????????????????????????????????????????????2???????????????????????????????????????`strlen' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4????????????5???????????????????????????????????????????????????????????????????????????????????????????????????6????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`DP_DOVER' ???????? ??????????????????????????????????????????????????????????????????????????????????`DP_DKEEP' ???????????????????????????????????????????????????????????????????????????????????????`DP_EKEEP' ?????????????????????????????????????????? `dpecode' ???????????????????????????

- -

`dpput' ?????????????????????????????????`DP_DCAT' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????DBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????[10,11,12] ????????????????????????????????????????????????????????????????????????????????? [10,11,12,13] ????????????????????????????????????????????????DBM???????????????????????????????????????????????????[10,11,12] ????????????????????????????????? [10,11,12,13] ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????? [13] ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp);
- -

`dpget' ?????????????????????????????????????????????????????????????????????????????????1????????????????????????????????????2????????????3????????? `dpput' ???????????????????????????????????????????????????????????????????????????4????????????5???????????????????????? `0' ??? '-1' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`-1' ?????????????????????????????????????????????????????????????????? `abcdef' ???????????????????????????????????? `1'??????????????? `3' ??????????????????`bcd' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ????????????????????????????????????????????????????????????????????????????????? `free' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????6????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????`DP_ENOITEM' ?????????????????????????????????????????? `dpecode' ???????????????????????????

- -

Depot????????????????????????????????????????????????`dpout'???`dpiterinit'???`dpiternext' ?????????????????????????????????????????????????????????????????????

- -
int dpout(DEPOT *depot, const char *kbuf, int ksiz);
- -

`dpout' ???????????????????????????????????????????????????????????????????????????????????????????????? `dpget' ?????????????????????????????????????????????????????????????????????????????????????????????`DP_ENOITEM' ?????????????????????????????????????????? `dpecode' ???????????????????????????

- -

`dpiterinit' ??? `dpiternext' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define PHONEFILE    "phone"
-
-int printphonenumbers(void){
-  DEPOT *depot;
-  char *kbuf, *vbuf;
-  /* ??????????????????????????????????????????????????? */
-  if(!(depot = dpopen(PHONEFILE, DP_OREADER, -1))) return -1;
-  /* ????????????????????????????????? */
-  dpiterinit(depot);
-  /* ??????????????????????????????????????? */
-  while((kbuf = dpiternext(depot, NULL)) != NULL){
-    /* ???????????????????????????????????? */
-    if((vbuf = dpget(depot, kbuf, -1, 0, -1, NULL)) != NULL){
-      printf("%s: %s\n", kbuf, vbuf);
-      /* ??????????????????????????? */
-      free(vbuf);
-    }
-    /* ?????????????????????????????? */
-    free(kbuf);
-  }
-  /* ?????????????????????????????? */
-  return dpclose(depot) ? 0 : -1;
-}
-
- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
int dpiterinit(DEPOT *depot);
- -

`dpiterinit' ?????????????????????????????????????????????????????????????????????????????????????????????

- -
char *dpiternext(DEPOT *depot, int *sp);
- -

`dpiternext' ????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ????????????????????????????????????????????????????????????????????? `free' ?????????????????????????????????????????????????????????????????????2?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????`DP_ENOITEM' ?????????????????????????????????????????? `dpecode' ???????????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????????Depot??????????????????????????????????????????????????????QDBM??????????????????API???Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
- -

Curia: ??????API

- -

Curia??????Depot???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API????????????????????????????????????????????????????????????????????????????????????Curia?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Depot?????????????????????2GB???????????????????????????????????????????????????????????????Depot????????????????????? `DEPOT' ??????????????????????????????????????????Curia?????? `CURIA' ????????????????????????????????????????????????Depot?????? `dp' ????????????????????????????????????Curia?????? `cr' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cropen' ????????????????????????????????????????????????????????????????????????????????????????????????

- -
CURIA *cropen(const char *name, int omode, int bnum, int dnum);
- -

???1??????2??????3????????? `dpopen' ????????????????????????????????????4??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Curia???????????????????????????????????????????????????

- -

Curia???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
- -

Relic: NDBM??????API

- -

Relic??????NDBM?????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????API???????????????????????????????????????????????????NDBM????????????????????????NDBM????????????????????????????????????????????????????????????Perl??????????????????????????????????????????????????????????????????????????????????????????Relic?????????????????????????????????????????????QDBM???????????????????????????????????????????????????

- -

??????????????????????????????????????????????????????????????? `ndbm.h' ?????????????????????????????????????????? `relic.h' ???????????????????????????????????? `ndbm' ?????? `qdbm' ??????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????Relic?????????Depot?????????????????????????????????????????????

- -
- -

Hovel: GDBM??????API

- -

Hovel??????GDBM?????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????API???????????????????????????????????????????????????GDBM????????????????????????GDBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

??????????????????????????????????????????????????????????????? `gdbm.h' ?????????????????????????????????????????? `hovel.h' ???????????????????????????????????? `gdbm' ?????? `qdbm' ??????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????Hovel?????????Depot?????????????????????????????????????????????

- -

?????????Hovel????????????????????????????????????????????????Depot???????????????????????????????????????????????????????????????????????????????????????Curia??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `gdbm_open' ??????`gdbm_open2' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????2GB???????????????????????????????????????????????????????????????`gdbm_open2' ????????????????????????????????????????????????????????????`gdbm_open' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align);
- -

???1???????????????????????????????????????????????????????????????????????????2????????????3????????? `gdbm_open' ??????3????????????4????????????????????????????????????????????????4?????????????????????????????????????????????5???????????????????????????????????????????????????????????????6????????????????????????????????????????????????????????????????????? `gdbm_open' ???????????????????????????????????????????????????

- -
- -

Cabin: ?????????????????????API

- -

Cabin????????????????????????????????????????????????????????????????????????????????????API??????????????????QDBM???API?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????CSV???XML??????????????????????????????????????????????????????????????????????????????????????????????????????XML???????????????????????????????????????

- -

????????????????????????????????????????????????????????????Cabin???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`first'???`second'???`third' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <cabin.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-void listtest(void){
-  CBLIST *list;
-  int i;
-  /* ?????????????????? */
-  list = cblistopen();
-  /* ????????????????????????????????? */
-  cblistpush(list, "first", -1);
-  cblistpush(list, "second", -1);
-  cblistpush(list, "third", -1);
-  /* ?????????????????????????????????????????? */
-  for(i = 0; i < cblistnum(list); i++){
-    printf("%s\n", cblistval(list, i, NULL));
-  }
-  /* ????????????????????? */
-  cblistclose(list);
-}
-
- -

`CBLIST' ???????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ?????????????????????????????????????????????????????????????????????????????????????????????`cblistclose' ????????????????????????`cblistpush' ???????????????????????????????????????`cblistnum' ??????????????????????????????????????????`cblistval' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

????????????????????????????????????????????????????????????????????????Cabin????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `one' ?????? `first'????????? `two' ?????? `second'????????? `three' ?????? `third' ????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <cabin.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-void maptest(void){
-  CBMAP *map;
-  /* ?????????????????? */
-  map = cbmapopen();
-  /* ??????????????????????????? */
-  cbmapput(map, "one", -1, "first", -1, 1);
-  cbmapput(map, "two", -1, "second", -1, 1);
-  cbmapput(map, "three", -1, "third", -1, 1);
-  /* ???????????????????????????????????????????????? */
-  printf("one: %s\n", cbmapget(map, "one", -1, NULL));
-  printf("two: %s\n", cbmapget(map, "two", -1, NULL));
-  printf("three: %s\n", cbmapget(map, "three", -1, NULL));
-  /* ????????????????????? */
-  cbmapclose(map);
-}
-
- -

`CBMAP' ???????????????????????????????????????????????????????????????????????????????????????????????? `cbmapopen' ?????????????????????????????????????????????????????????????????????????????????????????????`cbmapclose' ????????????????????????`cbmapput' ????????????????????????????????????`cbmapget' ?????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

XML????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????HTML???SGML??????????????????????????????????????????????????????????????????XML?????????????????????????????????DOM???SAX????????????API??????????????????????????????????????????????????????XML?????????????????? `id' ?????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <cabin.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-void showtextbyid(const char *xml, const char *id){
-  CBLIST *elems;
-  CBMAP *attrs;
-  const char *elem, *attr;
-  char *orig;
-  int i;
-  /* ???????????????????????????????????????????????? */
-  elems = cbxmlbreak(xml, 1);
-  /* ????????????????????????????????? */
-  for(i = 0; i < cblistnum(elems); i++){
-    /* ????????????????????? */
-    elem = cblistval(elems, i, NULL);
-    /* ??????????????????????????????????????? */
-    if(elem[0] != '<' || elem[1] == '?' || elem[1] == '!' || elem[1] == '/') continue;
-    /* ????????????????????????????????? */
-    attrs = cbxmlattrs(elem);
-    /* ID??????????????????????????????????????????????????? */
-    attr = cbmapget(attrs, "id", -1, NULL);
-    if(attr && !strcmp(attr, id)){
-      /* ??????????????????????????? */
-      elem = cblistval(elems, i + 1, NULL);
-      if(elem){
-        /* ??????????????????????????????????????? */
-        orig = cbxmlunescape(elem);
-        printf("%s\n", orig);
-        free(orig);
-      }
-    }
-    /* ??????????????????????????? */
-    cbmapclose(attrs);
-  }
-  /* ??????????????????????????? */
-  cblistclose(elems);
-}
-
- -

???????????????XML???????????????????????? `cbxmlbreak' ?????????????????????????????? `<body><p id="nuts">NUTS&amp;MILK</p></body>' ?????????????????????`<body>'???`<p id="nuts">'???`NUTS&amp;MILK'???`</p>'???`</body>' ???????????????????????????????????????????????????????????????1???????????? '<' ??????????????????????????????????????????????????????2???????????? '?'???`!'???`/' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbxmlattrs' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbxmlunescape' ??????????????????

- -

GTK+???????????????GLib???Apache???????????????APR?????????????????????????????????????????????????????????????????????????????????Cabin?????????????????????????????????????????????????????????????????????GLib???APR??????????????????????????????????????????????????????????????????????????????????????????????????????Cabin??????????????????????????????????????????????????????

- -
- -

Villa: ??????API

- -

Villa??????B+?????????????????????????????????API?????????B+???????????????????????????????????????????????????????????????????????????????????????????????????????????????Depot???Curia??????????????????????????????????????????????????????????????????Villa??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ABC????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????????????????????????????????Depot??????????????????Depot??????????????????????????????Villa?????????????????????????????????????????????

- -
#include <depot.h>
-#include <cabin.h>
-#include <villa.h>
-#include <stdlib.h>
-
-#define PHONEFILE    "phone"
-
-int putphonenumber(const char *id, const char *phone){
-  VILLA *villa;
-  /* ????????????????????????????????????????????? */
-  if(!(villa = vlopen(PHONEFILE, VL_OWRITER | VL_OCREAT, VL_CMPLEX))) return -1;
-  /* ??????????????????????????? */
-  vlput(villa, id, -1, phone, -1, VL_DOVER);
-  /* ?????????????????????????????? */
-  if(!vlclose(villa)) return -1;
-  return 0;
-}
-
-char *getphonenumber(const char *id){
-  VILLA *villa;
-  char *phone;
-  /* ??????????????????????????????????????????????????? */
-  if(!(villa = vlopen(PHONEFILE, VL_OREADER, VL_CMPLEX))) return NULL;
-  /* ??????????????????????????????????????????????????? */
-  phone = vlget(villa, id, -1, NULL);
-  /* ?????????????????????????????? */
-  vlclose(villa);
-  return phone;
-}
-
- -

`VILLA' ???????????????????????????????????????????????????????????????????????????`vlopen' ???????????????????????????????????????????????????3????????? `VL_CMPLEX' ????????????????????????????????????????????????????????????????????? `vlclose' ??????????????????`vlput' ??????????????????????????????????????????`vlget' ?????????????????????????????????????????????

- -

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+????????????????????????????????????????????????????????????????????????????????????????????????????????? `one'???`two'???`three'???`four' ???????????????????????????????????????????????????????????? `four'???`one'???`three'???`two' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`one' ????????????????????????????????????????????????????????????????????????`one' ?????????????????????`one' ???????????? `three' ?????????????????????????????????????????????????????????`one' ?????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`one' ?????? `three' ??????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <cabin.h>
-#include <villa.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define WORDFILE     "word"
-#define TOPWORD      "one"
-#define BOTTOMWORD   "three"
-
-void printwords(void){
-  VILLA *villa;
-  char *kbuf, *vbuf;
-  int ksiz;
-  /* ??????????????????????????????????????????????????? */
-  if(!(villa = vlopen(WORDFILE, VL_OREADER, VL_CMPLEX))) return;
-  /* ?????????????????????????????????????????? */
-  vlcurjump(villa, TOPWORD, -1, VL_JFORWARD);
-  /* ???????????????????????? */
-  do {
-    /* ???????????????????????????????????? */
-    kbuf = vlcurkey(villa, &ksiz);
-    /* ??????????????????????????????????????? */
-    if(!kbuf || VL_CMPLEX(kbuf, ksiz, BOTTOMWORD, sizeof(BOTTOMWORD) - 1) > 0){
-      free(kbuf);
-      break;
-    }
-    /* ???????????????????????????????????????????????? */
-    vbuf = vlcurval(villa, NULL);
-    if(kbuf && vbuf) printf("%s: %s\n", kbuf, vbuf);
-    /* ???????????????????????????????????? */
-    free(vbuf);
-    free(kbuf);
-    /* ?????????????????????????????? */
-  } while(vlcurnext(villa));
-  /* ?????????????????????????????? */
-  vlclose(villa);
-}
-
- -

`vlcurjump' ????????????????????????????????????????????????????????????`VL_JFORWARD' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `VL_JBACKWARD' ????????????????????????do-while???????????????????????? `vlcurnext' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`vlcurkey' ??? `vlcurval' ??????????????????????????????????????????????????????????????????`VL_CMPLEX' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

??????????????????????????????????????????????????????Villa??????????????????int??????????????????????????? `VL_CMPINT' ??????10????????????????????????????????? `VL_CMPDEC' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Villa??????????????????FIFO??????????????????????????????????????????????????????`VL_CMPINT' ???????????????????????????????????????????????????????????????????????????????????????int??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`qopen'???`qclose'???`qappend'???`qconsume' ?????????????????????????????????????????????????????????

- -
- -

Odeum: ??????API

- -

Odeum?????????????????????????????????????????????????????????API??????????????????????????????????????????????????????????????????HTML???MS-Word???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????GDBM?????????????????????????????????????????????????????????????????????????????????QDBM?????????Curia?????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `penguin.txt' ?????????flightless marine birds??????????????????????????????????????????????????????????????? `ostrich.txt' ????????????flightless birds in africa???????????????????????????????????????????????????????????????????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????

- - - - - - - -
flightless1,2
marine1
birds1,2
in2
africa2
- -

???????????????????????????????????????birds??????????????????????????????????????????????????????`birds' ????????? [1,2,3] ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Depot???Curia?????????????????????????????????????????????????????????????????????

- -

????????????????????????????????????????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Depot???Curia??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????????????????URI???????????????????????????????????????URI??????????????????????????????????????????????????????????????????????????????????????????

- -

Odeum??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????HTML????????????????????????????????????????????????????????????????????????????????????????????????PDF???MS-Word???????????????????????????????????????????????????Web????????????????????????????????????????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum???????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

??????????????????????????????????????????????????????????????????????????????????????????????????????/?????????????????????go/went??????child/children??????????????????????????????Odeum????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????child???????????????????????????children??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????children?????????????????????child???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????

- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID???????????????????????????????????????????????????????????????

- -
????????? = (????????????????????? * 10000) / log(?????????????????????) ^ 3
- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????10%??????????????????????????????????????????????????????????????????????????????????????????????????????????????????10000?????????15000???????????????????????????

- -

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????the beatles??????????????????????????????the?????????????????????beatles????????????????????????????????????beatles?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum??????????????????????????????????????????????????????????????????????????????????????????????????????

- -
????????????????????? = ???????????????????????? / log(???????????????????????????) ^ 2
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????TF-IDF???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Odeum??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????32??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????32????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????0??????1??????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????OR????????????????????????????????????????????????????????????????????????????????????????????????

- -

????????????????????????????????????Odeum??????????????????????????????????????????????????????URI??? `http://tako.ika/uni.txt' ???????????????????????????????????????????????????The sun is driven by the Grateful Dead.??????????????????????????????????????????/??????????????????the/The??????sun/sun??????be/is??????drive/driven??????by/by??????the/the??????grateful/Grateful??????die/dead???????????????????????????/.??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `index' ????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <cabin.h>
-#include <odeum.h>
-#include <stdlib.h>
-
-int docregistertest(void){
-  ODEUM *odeum;
-  ODDOC *doc;
-  /* ??????????????????????????? */
-  if(!(odeum = odopen("index", OD_OWRITER | OD_OCREAT))) return -1;
-  /* ????????????????????? */
-  doc = oddocopen("http://tako.ika/uni.txt");
-  oddocaddword(doc, "the", "the");
-  oddocaddword(doc, "sun", "sun");
-  oddocaddword(doc, "be", "is");
-  oddocaddword(doc, "drive", "driven");
-  oddocaddword(doc, "by", "by");
-  oddocaddword(doc, "the", "the");
-  oddocaddword(doc, "grateful", "Grateful");
-  oddocaddword(doc, "die", "Dead");
-  oddocaddword(doc, "", ".");
-  /* ????????????????????? */
-  odput(odeum, doc, -1, 1);
-  /* ?????????????????????????????? */
-  oddocclose(doc);
-  /* ?????????????????????????????? */
-  if(!odclose(odeum)) return -1;
-  return 0;
-}
-
- -

`ODEUM' ???????????????????????????????????????????????????????????????????????????`odopen' ?????????????????????????????????????????????????????????????????? `odclose' ??????????????????`ODDOC' ??????????????????????????????????????????????????????????????????????????????????????????????????????`oddocopen' ????????????????????????????????????????????????1??????????????????URI??????????????????????????????????????????????????????????????? `oddocclose' ??????????????????????????????????????????????????????????????????????????????`oddocaddword' ???????????????????????????2????????????????????????????????????3??????????????????????????????????????????????????????????????? `odput' ?????????????????????????????????????????????3??????????????????????????????????????????????????????????????????????????????`-1' ???????????????????????????????????????????????????4??????????????????URI??????????????????????????????????????????????????????????????????????????????????????????

- -

`odput' ??????3????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

?????????????????????`grateful' ??????????????????????????????????????????????????????URI?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID????????????????????????????????????????????????????????????????????????ID???????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <cabin.h>
-#include <odeum.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-void docsearchtest(void){
-  ODEUM *odeum;
-  ODPAIR *pairs;
-  ODDOC *doc;
-  int i, pnum;
-  /* ??????????????????????????????????????????????????? */
-  if(!(odeum = odopen("index", OD_OREADER))) return;
-  /* ??????????????????????????????????????? */
-  pairs = odsearch(odeum, "grateful", -1, &pnum);
-  if(pairs && pnum > 0){
-    /* ????????????????????????????????? */
-    for(i = 0; i < pnum; i++){
-      /* ??????????????????????????????????????????????????? */
-      if(!(doc = odgetbyid(odeum, pairs[i].id))) continue;
-      /* ?????????????????????????????? */
-      printf("URI: %s\n", oddocuri(doc));
-      printf("SCORE: %d\n", pairs[i].score);
-      /* ?????????????????????????????? */
-      oddocclose(doc);
-    }
-  }
-  /* ???????????????????????????????????? */
-  free(pairs);
-  /* ?????????????????????????????? */
-  odclose(odeum);
-}
-
- -

????????????????????????????????????????????? `odsearch' ???????????????????????????2?????????????????????????????????????????????????????????3???????????????????????????????????????????????????????????????????????????????????????????????? `-1' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`odgetbyid' ?????????ID?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`odgetbyid' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????`oddocuri' ????????????URI???????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Odeum??????????????????????????????????????????AND??????????????????????????????????????????OR????????????????????????????????????????????????NOTAND????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum???API?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
- - - - - - Copied: box/trunk/qdbm/misc/tutorial-ja.html (from rev 2716, box/trunk/qdbm/misc/tutorial-ja.html) =================================================================== --- box/trunk/qdbm/misc/tutorial-ja.html (rev 0) +++ box/trunk/qdbm/misc/tutorial-ja.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,622 @@ + + + + + + + + + + + + + + +Tutorial of QDBM Version 1 (Japanese) + + + + + +

QDBM????????????????????????

+ +
Copyright (C) 2000-2007 Mikio Hirabayashi
+
Last Update: Thu, 26 Oct 2006 15:00:20 +0900
+ + +
+ +

??????

+ +
    +
  1. ???????????????????????????
  2. +
  3. Depot: ??????API
  4. +
  5. Curia: ??????API
  6. +
  7. Relic: NDBM??????API
  8. +
  9. Hovel: GDBM??????API
  10. +
  11. Cabin: ?????????????????????API
  12. +
  13. Villa: ??????API
  14. +
  15. Odeum: ??????API
  16. +
+ +
+ +

???????????????????????????

+ +

QDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????SQL????????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

QDBM???C????????????????????????????????????????????????API????????????????????????QDBM?????????????????????????????????????????????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????C???????????????????????????????????????????????????????????????????????????C++???Java???Perl???Ruby???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????QDBM????????????????????????C??????????????????????????????Perl?????????????????????????????????????????????????????????????????????UNIX??????Windows??????Mac OS X????????????????????????????????????????????????????????????????????????????????????????????????

+ +

?????????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????B+?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????MIME???CSV???XML???????????????????????????????????????????????????????????????????????????????????????????????????

+ +

?????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????B+????????????????????????????????????????????????????????????????????????????????????????????????Web?????????????????????????????????????????????

+ +
+ +

Depot: ??????API

+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

?????????QDBM????????????????????????????????????????????????????????????????????????????????????CSV??????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
00001,8-902-1234
+00002,7-938-834
+00008,4-214-491
+
+ +

?????????????????????????????? `putphonenumber' ??????????????????????????????????????? `getphonenumber' ?????????????????????

+ +
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define PHONEFILE    "phone"
+#define LINEBUFSIZ   256
+
+int putphonenumber(const char *id, const char *phone){
+  FILE *OUT;
+  /* ??????????????????????????????????????? */
+  if(!(OUT = fopen(PHONEFILE, "a"))) return -1;
+  /* ??????????????????????????? */
+  fprintf(OUT, "%s,%s\n", id, phone);
+  /* ???????????????????????? */
+  if(fclose(OUT) != 0) return -1;
+  return 0;
+}
+
+char *getphonenumber(const char *id){
+  FILE *IN;
+  char line[LINEBUFSIZ], *pivot, *phone;
+  int len;
+  /* ????????????????????????????????????????????? */
+  if(!(IN = fopen(PHONEFILE, "r"))) return NULL;
+  /* ????????????????????? */
+  while(fscanf(IN, "%s", line) == 1){
+    /* ?????????????????????????????? */
+    if(!(pivot = strchr(line, ','))) continue;
+    *pivot = '\0';
+    pivot++;
+    /* ????????????????????? */
+    if(strcmp(line, id) == 0){
+      /* ???????????????????????? */
+      if(fclose(IN) != 0) return NULL;
+      /* ???????????????????????????????????????????????? */
+      len = strlen(pivot);
+      if(!(phone = malloc(len + 1))) return NULL;
+      memcpy(phone, pivot, len + 1);
+      return phone;
+    }
+  }
+  /* ???????????????????????? */
+  fclose(IN);
+  return NULL;
+}
+
+ +

`fscanf' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????255????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <stdlib.h>
+
+#define PHONEFILE    "phone"
+
+int putphonenumber(const char *id, const char *phone){
+  DEPOT *depot;
+  /* ????????????????????????????????????????????? */
+  if(!(depot = dpopen(PHONEFILE, DP_OWRITER | DP_OCREAT, -1))) return -1;
+  /* ??????????????????????????? */
+  dpput(depot, id, -1, phone, -1, DP_DOVER);
+  /* ?????????????????????????????? */
+  if(!dpclose(depot)) return -1;
+  return 0;
+}
+
+char *getphonenumber(const char *id){
+  DEPOT *depot;
+  char *phone;
+  /* ??????????????????????????????????????????????????? */
+  if(!(depot = dpopen(PHONEFILE, DP_OREADER, -1))) return NULL;
+  /* ??????????????????????????????????????????????????? */
+  phone = dpget(depot, id, -1, 0, -1, NULL);
+  /* ?????????????????????????????? */
+  dpclose(depot);
+  return phone;
+}
+
+ +

??????????????????????????????CSV?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????

+ +

??????????????????QDBM?????????API?????????Depot????????????????????????????????????`DEPOT' ???????????????????????????????????????????????????????????????????????? `FILE' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`dpopen'???`dpclose'???`dpput' ????????? `dpget' ??????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????

+ +
DEPOT *dpopen(const char *name, int omode, int bnum);
+ +

`dpopen' ????????????????????????Depot?????????????????????????????????????????????????????????????????? `DEPOT' ?????????????????????????????????????????????????????????1??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????2???????????????????????????????????????????????????????????????????????????????????????????????? `DP_OWRITER' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `DP_OCREAT' ????????????OR???????????????????????????????????????????????????????????????????????????`fopen' ??? `a+' ?????????????????????????????????????????????????????? `DP_OTRUNC' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `fopen' ??? `w+' ?????????????????????????????????????????????????????????????? ??????????????????????`DP_OREADER' ?????????????????????????????? `fopen' ??? `r' ??????????????????????????????????????????3??????????????????????????????????????????????????????????????????????????????????????????????????????????????? `-1' ?????????????????????????????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
int dpclose(DEPOT *depot);
+ +

`dpclose' ???????????????????????????????????????????????????1???????????? `dpopen' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????????QDBM???????????????????????????????????????????????????????????? `fprintf' ????????????????????????????????????????????????`fprintf' ???????????????????????? `fclose' ????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????????????????????????? `dpclose' ???????????????????????????????????????????????????????????????????????????????????????????????????

+ +
int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+ +

`dpput' ?????????????????????????????????????????????????????????????????????1???????????? `dpopen' ?????????????????????????????????????????????2????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3??????????????????????????????????????????????????????????????????????????????????????????2???????????????????????????????????????`strlen' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4????????????5???????????????????????????????????????????????????????????????????????????????????????????????????6????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`DP_DOVER' ???????? ??????????????????????????????????????????????????????????????????????????????????`DP_DKEEP' ???????????????????????????????????????????????????????????????????????????????????????`DP_EKEEP' ?????????????????????????????????????????? `dpecode' ???????????????????????????

+ +

`dpput' ?????????????????????????????????`DP_DCAT' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????DBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????[10,11,12] ????????????????????????????????????????????????????????????????????????????????? [10,11,12,13] ????????????????????????????????????????????????DBM???????????????????????????????????????????????????[10,11,12] ????????????????????????????????? [10,11,12,13] ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????? [13] ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp);
+ +

`dpget' ?????????????????????????????????????????????????????????????????????????????????1????????????????????????????????????2????????????3????????? `dpput' ???????????????????????????????????????????????????????????????????????????4????????????5???????????????????????? `0' ??? '-1' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`-1' ?????????????????????????????????????????????????????????????????? `abcdef' ???????????????????????????????????? `1'??????????????? `3' ??????????????????`bcd' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ????????????????????????????????????????????????????????????????????????????????? `free' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????6????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????`DP_ENOITEM' ?????????????????????????????????????????? `dpecode' ???????????????????????????

+ +

Depot????????????????????????????????????????????????`dpout'???`dpiterinit'???`dpiternext' ?????????????????????????????????????????????????????????????????????

+ +
int dpout(DEPOT *depot, const char *kbuf, int ksiz);
+ +

`dpout' ???????????????????????????????????????????????????????????????????????????????????????????????? `dpget' ?????????????????????????????????????????????????????????????????????????????????????????????`DP_ENOITEM' ?????????????????????????????????????????? `dpecode' ???????????????????????????

+ +

`dpiterinit' ??? `dpiternext' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define PHONEFILE    "phone"
+
+int printphonenumbers(void){
+  DEPOT *depot;
+  char *kbuf, *vbuf;
+  /* ??????????????????????????????????????????????????? */
+  if(!(depot = dpopen(PHONEFILE, DP_OREADER, -1))) return -1;
+  /* ????????????????????????????????? */
+  dpiterinit(depot);
+  /* ??????????????????????????????????????? */
+  while((kbuf = dpiternext(depot, NULL)) != NULL){
+    /* ???????????????????????????????????? */
+    if((vbuf = dpget(depot, kbuf, -1, 0, -1, NULL)) != NULL){
+      printf("%s: %s\n", kbuf, vbuf);
+      /* ??????????????????????????? */
+      free(vbuf);
+    }
+    /* ?????????????????????????????? */
+    free(kbuf);
+  }
+  /* ?????????????????????????????? */
+  return dpclose(depot) ? 0 : -1;
+}
+
+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
int dpiterinit(DEPOT *depot);
+ +

`dpiterinit' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +
char *dpiternext(DEPOT *depot, int *sp);
+ +

`dpiternext' ????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ????????????????????????????????????????????????????????????????????? `free' ?????????????????????????????????????????????????????????????????????2?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????`DP_ENOITEM' ?????????????????????????????????????????? `dpecode' ???????????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????????Depot??????????????????????????????????????????????????????QDBM??????????????????API???Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+ +

Curia: ??????API

+ +

Curia??????Depot???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API????????????????????????????????????????????????????????????????????????????????????Curia?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Depot?????????????????????2GB???????????????????????????????????????????????????????????????Depot????????????????????? `DEPOT' ??????????????????????????????????????????Curia?????? `CURIA' ????????????????????????????????????????????????Depot?????? `dp' ????????????????????????????????????Curia?????? `cr' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cropen' ????????????????????????????????????????????????????????????????????????????????????????????????

+ +
CURIA *cropen(const char *name, int omode, int bnum, int dnum);
+ +

???1??????2??????3????????? `dpopen' ????????????????????????????????????4??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????3??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Curia???????????????????????????????????????????????????

+ +

Curia???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+ +

Relic: NDBM??????API

+ +

Relic??????NDBM?????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????API???????????????????????????????????????????????????NDBM????????????????????????NDBM????????????????????????????????????????????????????????????Perl??????????????????????????????????????????????????????????????????????????????????????????Relic?????????????????????????????????????????????QDBM???????????????????????????????????????????????????

+ +

??????????????????????????????????????????????????????????????? `ndbm.h' ?????????????????????????????????????????? `relic.h' ???????????????????????????????????? `ndbm' ?????? `qdbm' ??????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????Relic?????????Depot?????????????????????????????????????????????

+ +
+ +

Hovel: GDBM??????API

+ +

Hovel??????GDBM?????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????API???????????????????????????????????????????????????GDBM????????????????????????GDBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

??????????????????????????????????????????????????????????????? `gdbm.h' ?????????????????????????????????????????? `hovel.h' ???????????????????????????????????? `gdbm' ?????? `qdbm' ??????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????Hovel?????????Depot?????????????????????????????????????????????

+ +

?????????Hovel????????????????????????????????????????????????Depot???????????????????????????????????????????????????????????????????????????????????????Curia??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `gdbm_open' ??????`gdbm_open2' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????2GB???????????????????????????????????????????????????????????????`gdbm_open2' ????????????????????????????????????????????????????????????`gdbm_open' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align);
+ +

???1???????????????????????????????????????????????????????????????????????????2????????????3????????? `gdbm_open' ??????3????????????4????????????????????????????????????????????????4?????????????????????????????????????????????5???????????????????????????????????????????????????????????????6????????????????????????????????????????????????????????????????????? `gdbm_open' ???????????????????????????????????????????????????

+ +
+ +

Cabin: ?????????????????????API

+ +

Cabin????????????????????????????????????????????????????????????????????????????????????API??????????????????QDBM???API?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????CSV???XML??????????????????????????????????????????????????????????????????????????????????????????????????????XML???????????????????????????????????????

+ +

????????????????????????????????????????????????????????????Cabin???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`first'???`second'???`third' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <cabin.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void listtest(void){
+  CBLIST *list;
+  int i;
+  /* ?????????????????? */
+  list = cblistopen();
+  /* ????????????????????????????????? */
+  cblistpush(list, "first", -1);
+  cblistpush(list, "second", -1);
+  cblistpush(list, "third", -1);
+  /* ?????????????????????????????????????????? */
+  for(i = 0; i < cblistnum(list); i++){
+    printf("%s\n", cblistval(list, i, NULL));
+  }
+  /* ????????????????????? */
+  cblistclose(list);
+}
+
+ +

`CBLIST' ???????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ?????????????????????????????????????????????????????????????????????????????????????????????`cblistclose' ????????????????????????`cblistpush' ???????????????????????????????????????`cblistnum' ??????????????????????????????????????????`cblistval' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

????????????????????????????????????????????????????????????????????????Cabin????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `one' ?????? `first'????????? `two' ?????? `second'????????? `three' ?????? `third' ????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <cabin.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void maptest(void){
+  CBMAP *map;
+  /* ?????????????????? */
+  map = cbmapopen();
+  /* ??????????????????????????? */
+  cbmapput(map, "one", -1, "first", -1, 1);
+  cbmapput(map, "two", -1, "second", -1, 1);
+  cbmapput(map, "three", -1, "third", -1, 1);
+  /* ???????????????????????????????????????????????? */
+  printf("one: %s\n", cbmapget(map, "one", -1, NULL));
+  printf("two: %s\n", cbmapget(map, "two", -1, NULL));
+  printf("three: %s\n", cbmapget(map, "three", -1, NULL));
+  /* ????????????????????? */
+  cbmapclose(map);
+}
+
+ +

`CBMAP' ???????????????????????????????????????????????????????????????????????????????????????????????? `cbmapopen' ?????????????????????????????????????????????????????????????????????????????????????????????`cbmapclose' ????????????????????????`cbmapput' ????????????????????????????????????`cbmapget' ?????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

XML????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????HTML???SGML??????????????????????????????????????????????????????????????????XML?????????????????????????????????DOM???SAX????????????API??????????????????????????????????????????????????????XML?????????????????? `id' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <cabin.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+void showtextbyid(const char *xml, const char *id){
+  CBLIST *elems;
+  CBMAP *attrs;
+  const char *elem, *attr;
+  char *orig;
+  int i;
+  /* ???????????????????????????????????????????????? */
+  elems = cbxmlbreak(xml, 1);
+  /* ????????????????????????????????? */
+  for(i = 0; i < cblistnum(elems); i++){
+    /* ????????????????????? */
+    elem = cblistval(elems, i, NULL);
+    /* ??????????????????????????????????????? */
+    if(elem[0] != '<' || elem[1] == '?' || elem[1] == '!' || elem[1] == '/') continue;
+    /* ????????????????????????????????? */
+    attrs = cbxmlattrs(elem);
+    /* ID??????????????????????????????????????????????????? */
+    attr = cbmapget(attrs, "id", -1, NULL);
+    if(attr && !strcmp(attr, id)){
+      /* ??????????????????????????? */
+      elem = cblistval(elems, i + 1, NULL);
+      if(elem){
+        /* ??????????????????????????????????????? */
+        orig = cbxmlunescape(elem);
+        printf("%s\n", orig);
+        free(orig);
+      }
+    }
+    /* ??????????????????????????? */
+    cbmapclose(attrs);
+  }
+  /* ??????????????????????????? */
+  cblistclose(elems);
+}
+
+ +

???????????????XML???????????????????????? `cbxmlbreak' ?????????????????????????????? `<body><p id="nuts">NUTS&amp;MILK</p></body>' ?????????????????????`<body>'???`<p id="nuts">'???`NUTS&amp;MILK'???`</p>'???`</body>' ???????????????????????????????????????????????????????????????1???????????? '<' ??????????????????????????????????????????????????????2???????????? '?'???`!'???`/' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbxmlattrs' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbxmlunescape' ??????????????????

+ +

GTK+???????????????GLib???Apache???????????????APR?????????????????????????????????????????????????????????????????????????????????Cabin?????????????????????????????????????????????????????????????????????GLib???APR??????????????????????????????????????????????????????????????????????????????????????????????????????Cabin??????????????????????????????????????????????????????

+ +
+ +

Villa: ??????API

+ +

Villa??????B+?????????????????????????????????API?????????B+???????????????????????????????????????????????????????????????????????????????????????????????????????????????Depot???Curia??????????????????????????????????????????????????????????????????Villa??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ABC????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????????????????????????????????Depot??????????????????Depot??????????????????????????????Villa?????????????????????????????????????????????

+ +
#include <depot.h>
+#include <cabin.h>
+#include <villa.h>
+#include <stdlib.h>
+
+#define PHONEFILE    "phone"
+
+int putphonenumber(const char *id, const char *phone){
+  VILLA *villa;
+  /* ????????????????????????????????????????????? */
+  if(!(villa = vlopen(PHONEFILE, VL_OWRITER | VL_OCREAT, VL_CMPLEX))) return -1;
+  /* ??????????????????????????? */
+  vlput(villa, id, -1, phone, -1, VL_DOVER);
+  /* ?????????????????????????????? */
+  if(!vlclose(villa)) return -1;
+  return 0;
+}
+
+char *getphonenumber(const char *id){
+  VILLA *villa;
+  char *phone;
+  /* ??????????????????????????????????????????????????? */
+  if(!(villa = vlopen(PHONEFILE, VL_OREADER, VL_CMPLEX))) return NULL;
+  /* ??????????????????????????????????????????????????? */
+  phone = vlget(villa, id, -1, NULL);
+  /* ?????????????????????????????? */
+  vlclose(villa);
+  return phone;
+}
+
+ +

`VILLA' ???????????????????????????????????????????????????????????????????????????`vlopen' ???????????????????????????????????????????????????3????????? `VL_CMPLEX' ????????????????????????????????????????????????????????????????????? `vlclose' ??????????????????`vlput' ??????????????????????????????????????????`vlget' ?????????????????????????????????????????????

+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+????????????????????????????????????????????????????????????????????????????????????????????????????????? `one'???`two'???`three'???`four' ???????????????????????????????????????????????????????????? `four'???`one'???`three'???`two' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`one' ????????????????????????????????????????????????????????????????????????`one' ?????????????????????`one' ???????????? `three' ?????????????????????????????????????????????????????????`one' ?????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`one' ?????? `three' ??????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <cabin.h>
+#include <villa.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define WORDFILE     "word"
+#define TOPWORD      "one"
+#define BOTTOMWORD   "three"
+
+void printwords(void){
+  VILLA *villa;
+  char *kbuf, *vbuf;
+  int ksiz;
+  /* ??????????????????????????????????????????????????? */
+  if(!(villa = vlopen(WORDFILE, VL_OREADER, VL_CMPLEX))) return;
+  /* ?????????????????????????????????????????? */
+  vlcurjump(villa, TOPWORD, -1, VL_JFORWARD);
+  /* ???????????????????????? */
+  do {
+    /* ???????????????????????????????????? */
+    kbuf = vlcurkey(villa, &ksiz);
+    /* ??????????????????????????????????????? */
+    if(!kbuf || VL_CMPLEX(kbuf, ksiz, BOTTOMWORD, sizeof(BOTTOMWORD) - 1) > 0){
+      free(kbuf);
+      break;
+    }
+    /* ???????????????????????????????????????????????? */
+    vbuf = vlcurval(villa, NULL);
+    if(kbuf && vbuf) printf("%s: %s\n", kbuf, vbuf);
+    /* ???????????????????????????????????? */
+    free(vbuf);
+    free(kbuf);
+    /* ?????????????????????????????? */
+  } while(vlcurnext(villa));
+  /* ?????????????????????????????? */
+  vlclose(villa);
+}
+
+ +

`vlcurjump' ????????????????????????????????????????????????????????????`VL_JFORWARD' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `VL_JBACKWARD' ????????????????????????do-while???????????????????????? `vlcurnext' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`vlcurkey' ??? `vlcurval' ??????????????????????????????????????????????????????????????????`VL_CMPLEX' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

??????????????????????????????????????????????????????Villa??????????????????int??????????????????????????? `VL_CMPINT' ??????10????????????????????????????????? `VL_CMPDEC' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Villa??????????????????FIFO??????????????????????????????????????????????????????`VL_CMPINT' ???????????????????????????????????????????????????????????????????????????????????????int??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`qopen'???`qclose'???`qappend'???`qconsume' ?????????????????????????????????????????????????????????

+ +
+ +

Odeum: ??????API

+ +

Odeum?????????????????????????????????????????????????????????API??????????????????????????????????????????????????????????????????HTML???MS-Word???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????GDBM?????????????????????????????????????????????????????????????????????????????????QDBM?????????Curia?????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `penguin.txt' ?????????flightless marine birds??????????????????????????????????????????????????????????????? `ostrich.txt' ????????????flightless birds in africa???????????????????????????????????????????????????????????????????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????

+ + + + + + + +
flightless1,2
marine1
birds1,2
in2
africa2
+ +

???????????????????????????????????????birds??????????????????????????????????????????????????????`birds' ????????? [1,2,3] ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Depot???Curia?????????????????????????????????????????????????????????????????????

+ +

????????????????????????????????????????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Depot???Curia??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????????????????URI???????????????????????????????????????URI??????????????????????????????????????????????????????????????????????????????????????????

+ +

Odeum??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????HTML????????????????????????????????????????????????????????????????????????????????????????????????PDF???MS-Word???????????????????????????????????????????????????Web????????????????????????????????????????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum???????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

??????????????????????????????????????????????????????????????????????????????????????????????????????/?????????????????????go/went??????child/children??????????????????????????????Odeum????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????child???????????????????????????children??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????children?????????????????????child???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????

+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID???????????????????????????????????????????????????????????????

+ +
????????? = (????????????????????? * 10000) / log(?????????????????????) ^ 3
+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????10%??????????????????????????????????????????????????????????????????????????????????????????????????????????????????10000?????????15000???????????????????????????

+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????the beatles??????????????????????????????the?????????????????????beatles????????????????????????????????????beatles?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum??????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
????????????????????? = ???????????????????????? / log(???????????????????????????) ^ 2
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????TF-IDF???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Odeum??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????32??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????32????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????0??????1??????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????OR????????????????????????????????????????????????????????????????????????????????????????????????

+ +

????????????????????????????????????Odeum??????????????????????????????????????????????????????URI??? `http://tako.ika/uni.txt' ???????????????????????????????????????????????????The sun is driven by the Grateful Dead.??????????????????????????????????????????/??????????????????the/The??????sun/sun??????be/is??????drive/driven??????by/by??????the/the??????grateful/Grateful??????die/dead???????????????????????????/.??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `index' ????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <cabin.h>
+#include <odeum.h>
+#include <stdlib.h>
+
+int docregistertest(void){
+  ODEUM *odeum;
+  ODDOC *doc;
+  /* ??????????????????????????? */
+  if(!(odeum = odopen("index", OD_OWRITER | OD_OCREAT))) return -1;
+  /* ????????????????????? */
+  doc = oddocopen("http://tako.ika/uni.txt");
+  oddocaddword(doc, "the", "the");
+  oddocaddword(doc, "sun", "sun");
+  oddocaddword(doc, "be", "is");
+  oddocaddword(doc, "drive", "driven");
+  oddocaddword(doc, "by", "by");
+  oddocaddword(doc, "the", "the");
+  oddocaddword(doc, "grateful", "Grateful");
+  oddocaddword(doc, "die", "Dead");
+  oddocaddword(doc, "", ".");
+  /* ????????????????????? */
+  odput(odeum, doc, -1, 1);
+  /* ?????????????????????????????? */
+  oddocclose(doc);
+  /* ?????????????????????????????? */
+  if(!odclose(odeum)) return -1;
+  return 0;
+}
+
+ +

`ODEUM' ???????????????????????????????????????????????????????????????????????????`odopen' ?????????????????????????????????????????????????????????????????? `odclose' ??????????????????`ODDOC' ??????????????????????????????????????????????????????????????????????????????????????????????????????`oddocopen' ????????????????????????????????????????????????1??????????????????URI??????????????????????????????????????????????????????????????? `oddocclose' ??????????????????????????????????????????????????????????????????????????????`oddocaddword' ???????????????????????????2????????????????????????????????????3??????????????????????????????????????????????????????????????? `odput' ?????????????????????????????????????????????3??????????????????????????????????????????????????????????????????????????????`-1' ???????????????????????????????????????????????????4??????????????????URI??????????????????????????????????????????????????????????????????????????????????????????

+ +

`odput' ??????3????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

?????????????????????`grateful' ??????????????????????????????????????????????????????URI?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID????????????????????????????????????????????????????????????????????????ID???????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <cabin.h>
+#include <odeum.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void docsearchtest(void){
+  ODEUM *odeum;
+  ODPAIR *pairs;
+  ODDOC *doc;
+  int i, pnum;
+  /* ??????????????????????????????????????????????????? */
+  if(!(odeum = odopen("index", OD_OREADER))) return;
+  /* ??????????????????????????????????????? */
+  pairs = odsearch(odeum, "grateful", -1, &pnum);
+  if(pairs && pnum > 0){
+    /* ????????????????????????????????? */
+    for(i = 0; i < pnum; i++){
+      /* ??????????????????????????????????????????????????? */
+      if(!(doc = odgetbyid(odeum, pairs[i].id))) continue;
+      /* ?????????????????????????????? */
+      printf("URI: %s\n", oddocuri(doc));
+      printf("SCORE: %d\n", pairs[i].score);
+      /* ?????????????????????????????? */
+      oddocclose(doc);
+    }
+  }
+  /* ???????????????????????????????????? */
+  free(pairs);
+  /* ?????????????????????????????? */
+  odclose(odeum);
+}
+
+ +

????????????????????????????????????????????? `odsearch' ???????????????????????????2?????????????????????????????????????????????????????????3???????????????????????????????????????????????????????????????????????????????????????????????? `-1' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`odgetbyid' ?????????ID?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`odgetbyid' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????`oddocuri' ????????????URI???????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Odeum??????????????????????????????????????????AND??????????????????????????????????????????OR????????????????????????????????????????????????NOTAND????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum???API?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+ + + + + + Deleted: box/trunk/qdbm/misc/win32check.bat =================================================================== --- box/trunk/qdbm/misc/win32check.bat 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/misc/win32check.bat 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,111 +0,0 @@ -dptest write casket 50000 5000 -if errorlevel 1 goto error -dptest read casket -if errorlevel 1 goto error -dptest read -wb casket -if errorlevel 1 goto error -dptest rcat casket 50000 50 500 32 32 -if errorlevel 1 goto error -dptest combo casket -if errorlevel 1 goto error -dptest wicked casket 5000 -if errorlevel 1 goto error -del /Q casket - -crtest write casket 50000 500 10 -if errorlevel 1 goto error -crtest read casket -if errorlevel 1 goto error -crtest read -wb casket -if errorlevel 1 goto error -crtest rcat casket 50000 5 10 500 32 32 -if errorlevel 1 goto error -crtest combo casket -if errorlevel 1 goto error -crtest wicked casket 5000 -if errorlevel 1 goto error -rd /S /Q casket - -crtest write -lob casket 1000 50 10 -if errorlevel 1 goto error -crtest read -lob casket -if errorlevel 1 goto error -rd /S /Q casket - -rltest write casket 50000 -if errorlevel 1 goto error -rltest read casket 50000 -if errorlevel 1 goto error -del /Q casket* - -hvtest write casket 50000 -if errorlevel 1 goto error -hvtest read casket 50000 -if errorlevel 1 goto error -del /Q casket - -hvtest write -qdbm casket 50000 -if errorlevel 1 goto error -hvtest read -qdbm casket 50000 -if errorlevel 1 goto error -rd /S /Q casket - -cbtest sort 5000 -if errorlevel 1 goto error -cbtest strstr 500 -if errorlevel 1 goto error -cbtest list 50000 -if errorlevel 1 goto error -cbtest map 50000 -if errorlevel 1 goto error -cbtest wicked 5000 -if errorlevel 1 goto error -cbtest misc -if errorlevel 1 goto error - -vltest write -tune 25 64 32 32 casket 50000 -if errorlevel 1 goto error -vltest read casket -if errorlevel 1 goto error -vltest rdup -tune 25 64 256 256 casket 50000 50000 -if errorlevel 1 goto error -vltest combo casket -if errorlevel 1 goto error -vltest wicked casket 5000 -if errorlevel 1 goto error -del /Q casket - -vltest write -int -cz -tune 25 64 32 32 casket 50000 -if errorlevel 1 goto error -vltest read -int casket -if errorlevel 1 goto error -vltest rdup -int -cz -tune 25 64 256 256 casket 50000 50000 -if errorlevel 1 goto error -vltest combo -cz casket -if errorlevel 1 goto error -vltest wicked -cz casket 5000 -if errorlevel 1 goto error -del /Q casket - -odtest write casket 500 50 5000 -if errorlevel 1 goto error -odtest read casket -if errorlevel 1 goto error -odtest combo casket -if errorlevel 1 goto error -odtest wicked casket 500 -if errorlevel 1 goto error -rd /S /Q casket - - at echo off -echo #================================ -echo # SUCCESS -echo #================================ -goto :EOF - -:error - at echo off -echo #================================ -echo # ERROR -echo #================================ -goto :EOF Copied: box/trunk/qdbm/misc/win32check.bat (from rev 2716, box/trunk/qdbm/misc/win32check.bat) =================================================================== --- box/trunk/qdbm/misc/win32check.bat (rev 0) +++ box/trunk/qdbm/misc/win32check.bat 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,111 @@ +dptest write casket 50000 5000 +if errorlevel 1 goto error +dptest read casket +if errorlevel 1 goto error +dptest read -wb casket +if errorlevel 1 goto error +dptest rcat casket 50000 50 500 32 32 +if errorlevel 1 goto error +dptest combo casket +if errorlevel 1 goto error +dptest wicked casket 5000 +if errorlevel 1 goto error +del /Q casket + +crtest write casket 50000 500 10 +if errorlevel 1 goto error +crtest read casket +if errorlevel 1 goto error +crtest read -wb casket +if errorlevel 1 goto error +crtest rcat casket 50000 5 10 500 32 32 +if errorlevel 1 goto error +crtest combo casket +if errorlevel 1 goto error +crtest wicked casket 5000 +if errorlevel 1 goto error +rd /S /Q casket + +crtest write -lob casket 1000 50 10 +if errorlevel 1 goto error +crtest read -lob casket +if errorlevel 1 goto error +rd /S /Q casket + +rltest write casket 50000 +if errorlevel 1 goto error +rltest read casket 50000 +if errorlevel 1 goto error +del /Q casket* + +hvtest write casket 50000 +if errorlevel 1 goto error +hvtest read casket 50000 +if errorlevel 1 goto error +del /Q casket + +hvtest write -qdbm casket 50000 +if errorlevel 1 goto error +hvtest read -qdbm casket 50000 +if errorlevel 1 goto error +rd /S /Q casket + +cbtest sort 5000 +if errorlevel 1 goto error +cbtest strstr 500 +if errorlevel 1 goto error +cbtest list 50000 +if errorlevel 1 goto error +cbtest map 50000 +if errorlevel 1 goto error +cbtest wicked 5000 +if errorlevel 1 goto error +cbtest misc +if errorlevel 1 goto error + +vltest write -tune 25 64 32 32 casket 50000 +if errorlevel 1 goto error +vltest read casket +if errorlevel 1 goto error +vltest rdup -tune 25 64 256 256 casket 50000 50000 +if errorlevel 1 goto error +vltest combo casket +if errorlevel 1 goto error +vltest wicked casket 5000 +if errorlevel 1 goto error +del /Q casket + +vltest write -int -cz -tune 25 64 32 32 casket 50000 +if errorlevel 1 goto error +vltest read -int casket +if errorlevel 1 goto error +vltest rdup -int -cz -tune 25 64 256 256 casket 50000 50000 +if errorlevel 1 goto error +vltest combo -cz casket +if errorlevel 1 goto error +vltest wicked -cz casket 5000 +if errorlevel 1 goto error +del /Q casket + +odtest write casket 500 50 5000 +if errorlevel 1 goto error +odtest read casket +if errorlevel 1 goto error +odtest combo casket +if errorlevel 1 goto error +odtest wicked casket 500 +if errorlevel 1 goto error +rd /S /Q casket + + at echo off +echo #================================ +echo # SUCCESS +echo #================================ +goto :EOF + +:error + at echo off +echo #================================ +echo # ERROR +echo #================================ +goto :EOF Deleted: box/trunk/qdbm/myconf.c =================================================================== --- box/trunk/qdbm/myconf.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/myconf.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,1113 +0,0 @@ -/************************************************************************************************* - * 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 */ Copied: box/trunk/qdbm/myconf.c (from rev 2716, box/trunk/qdbm/myconf.c) =================================================================== --- box/trunk/qdbm/myconf.c (rev 0) +++ box/trunk/qdbm/myconf.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -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 */ Deleted: box/trunk/qdbm/myconf.h =================================================================== --- box/trunk/qdbm/myconf.h 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/myconf.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,593 +0,0 @@ -/************************************************************************************************* - * System configurations for QDBM - * 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. - *************************************************************************************************/ - - -#ifndef _MYCONF_H /* duplication check */ -#define _MYCONF_H - -#if defined(__cplusplus) /* export for C++ */ -extern "C" { -#endif - - - -/************************************************************************************************* - * system discrimination - *************************************************************************************************/ - - -#if defined(__linux__) - -#define _SYS_LINUX_ -#define _QDBM_SYSNAME "Linux" - -#elif defined(__FreeBSD__) - -#define _SYS_FREEBSD_ -#define _QDBM_SYSNAME "FreeBSD" - -#elif defined(__NetBSD__) - -#define _SYS_NETBSD_ -#define _QDBM_SYSNAME "NetBSD" - -#elif defined(__OpenBSD__) - -#define _SYS_OPENBSD_ -#define _QDBM_SYSNAME "OpenBSD" - -#elif defined(__sun__) - -#define _SYS_SUNOS_ -#define _QDBM_SYSNAME "SunOS" - -#elif defined(__hpux) - -#define _SYS_HPUX_ -#define _QDBM_SYSNAME "HP-UX" - -#elif defined(__osf) - -#define _SYS_TRU64_ -#define _QDBM_SYSNAME "Tru64" - -#elif defined(_AIX) - -#define _SYS_AIX_ -#define _QDBM_SYSNAME "AIX" - -#elif defined(__APPLE__) && defined(__MACH__) - -#define _SYS_MACOSX_ -#define _QDBM_SYSNAME "Mac OS X" - -#elif defined(_MSC_VER) - -#define _SYS_MSVC_ -#define _QDBM_SYSNAME "Windows (VC++)" - -#elif defined(_WIN32) - -#define _SYS_MINGW_ -#define _QDBM_SYSNAME "Windows (MinGW)" - -#elif defined(__CYGWIN__) - -#define _SYS_CYGWIN_ -#define _QDBM_SYSNAME "Windows (Cygwin)" - -#elif defined(__riscos__) || defined(__riscos) - -#define _SYS_RISCOS_ -#define _QDBM_SYSNAME "RISC OS" - -#else - -#define _SYS_GENERIC_ -#define _QDBM_SYSNAME "Generic" - -#endif - - - -/************************************************************************************************* - * general headers - *************************************************************************************************/ - - -#if defined(_SYS_MSVC_) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#elif defined(_SYS_MINGW_) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#elif defined(_SYS_CYGWIN_) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#else - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif - - - -/************************************************************************************************* - * notation of filesystems - *************************************************************************************************/ - - -#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) - -#define MYPATHCHR '\\' -#define MYPATHSTR "\\" -#define MYEXTCHR '.' -#define MYEXTSTR "." -#define MYCDIRSTR "." -#define MYPDIRSTR ".." - -#elif defined(_SYS_RISCOS_) - -#define MYPATHCHR '.' -#define MYPATHSTR "." -#define MYEXTCHR '/' -#define MYEXTSTR "/" -#define MYCDIRSTR "@" -#define MYPDIRSTR "^" - -#else - -#define MYPATHCHR '/' -#define MYPATHSTR "/" -#define MYEXTCHR '.' -#define MYEXTSTR "." -#define MYCDIRSTR "." -#define MYPDIRSTR ".." - -#endif - - - -/************************************************************************************************* - * for dosish filesystems - *************************************************************************************************/ - - -#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || defined(_SYS_CYGWIN_) - -#undef UNICODE -#undef open - -#define \ - open(pathname, flags, mode) \ - open(pathname, flags | O_BINARY, mode) - -#define \ - lstat(pathname, buf) \ - _qdbm_win32_lstat(pathname, buf) - -int _qdbm_win32_lstat(const char *pathname, struct stat *buf); - -#else - -#undef O_BINARY -#undef O_TEXT -#undef setmode - -#define O_BINARY 0 -#define O_TEXT 1 - -#define \ - setmode(fd, mode) \ - (O_BINARY) - -#endif - - - -/************************************************************************************************* - * for POSIX thread - *************************************************************************************************/ - - -#if defined(MYPTHREAD) - -#define _qdbm_ptsafe TRUE - -void *_qdbm_settsd(void *ptr, int size, const void *initval); - -#else - -#define _qdbm_ptsafe FALSE - -#define \ - _qdbm_settsd(ptr, size, initval) \ - (NULL) - -#endif - - - -/************************************************************************************************* - * for systems without file locking - *************************************************************************************************/ - - -#if defined(_SYS_RISCOS_) || defined(MYNOLOCK) - -#undef fcntl - -#define \ - fcntl(fd, cmd, lock) \ - (0) - -#endif - - - -/************************************************************************************************* - * for systems without mmap - *************************************************************************************************/ - - -#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || \ - defined(_SYS_FREEBSD_) || defined(_SYS_NETBSD_) || defined(_SYS_OPENBSD_) || \ - defined(_SYS_AIX_) || defined(_SYS_RISCOS_) || defined(MYNOMMAP) - -#undef PROT_EXEC -#undef PROT_READ -#undef PROT_WRITE -#undef PROT_NONE -#undef MAP_FIXED -#undef MAP_SHARED -#undef MAP_PRIVATE -#undef MAP_FAILED -#undef MS_ASYNC -#undef MS_SYNC -#undef MS_INVALIDATE -#undef mmap -#undef munmap -#undef msync -#undef mflush - -#define PROT_EXEC (1 << 0) -#define PROT_READ (1 << 1) -#define PROT_WRITE (1 << 2) -#define PROT_NONE (1 << 3) -#define MAP_FIXED 1 -#define MAP_SHARED 2 -#define MAP_PRIVATE 3 -#define MAP_FAILED ((void *)-1) -#define MS_ASYNC (1 << 0) -#define MS_SYNC (1 << 1) -#define MS_INVALIDATE (1 << 2) - -#define \ - mmap(start, length, prot, flags, fd, offset) \ - _qdbm_mmap(start, length, prot, flags, fd, offset) - -#define \ - munmap(start, length) \ - _qdbm_munmap(start, length) - -#define \ - msync(start, length, flags) \ - _qdbm_msync(start, length, flags) - -#define \ - mflush(start, length, flags) \ - _qdbm_msync(start, length, flags) - -void *_qdbm_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); -int _qdbm_munmap(void *start, size_t length); -int _qdbm_msync(const void *start, size_t length, int flags); - -#else - -#undef mflush -#define \ - mflush(start, length, flags) \ - (0) - -#endif - - - -/************************************************************************************************* - * for reentrant time routines - *************************************************************************************************/ - - -struct tm *_qdbm_gmtime(const time_t *timep, struct tm *result); -struct tm *_qdbm_localtime(const time_t *timep, struct tm *result); - - - -/************************************************************************************************* - * for systems without times - *************************************************************************************************/ - - -#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) - -#undef times -#undef sysconf - -struct tms { - clock_t tms_utime; - clock_t tms_stime; - clock_t tms_cutime; - clock_t tms_cstime; -}; - -#define \ - times(buf) \ - _qdbm_times(buf) - -#define \ - sysconf(name) \ - (CLOCKS_PER_SEC) - -clock_t _qdbm_times(struct tms *buf); - -#endif - - - -/************************************************************************************************* - * for Win32 - *************************************************************************************************/ - - -#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) - -#undef F_WRLCK -#undef F_RDLCK -#undef F_SETLK -#undef F_SETLKW -#undef fcntl -#undef ftruncate -#undef fsync -#undef mkdir -#undef rename - -#define F_WRLCK 0 -#define F_RDLCK 1 -#define F_SETLK 0 -#define F_SETLKW 1 - -struct flock { - int l_type; - int l_whence; - int l_start; - int l_len; - int l_pid; -}; - -#define \ - fcntl(fd, cmd, lock) \ - _qdbm_win32_fcntl(fd, cmd, lock) - -#define \ - ftruncate(fd, length) \ - _chsize(fd, length) - -#define \ - fsync(fd) \ - (0) - -#define \ - mkdir(pathname, mode) \ - mkdir(pathname) - -#define \ - rename(oldpath, newpath) \ - (unlink(newpath), rename(oldpath, newpath)) - -int _qdbm_win32_fcntl(int fd, int cmd, struct flock *lock); - -#endif - - -#if defined(_SYS_MSVC_) - -#undef S_ISDIR -#undef S_ISREG -#undef opendir -#undef closedir -#undef readdir - -#define S_ISDIR(x) (x & _S_IFDIR) -#define S_ISREG(x) (x & _S_IFREG) - -struct dirent { - char d_name[1024]; -}; - -typedef struct { - HANDLE fh; - WIN32_FIND_DATA data; - struct dirent de; - int first; -} DIR; - -#define \ - opendir(name) \ - _qdbm_win32_opendir(name) - -#define \ - closedir(dir) \ - _qdbm_win32_closedir(dir) - -#define \ - readdir(dir) \ - _qdbm_win32_readdir(dir) - -DIR *_qdbm_win32_opendir(const char *name); - -int _qdbm_win32_closedir(DIR *dir); - -struct dirent *_qdbm_win32_readdir(DIR *dir); - -#endif - - - -/************************************************************************************************* - * for checking information of the system - *************************************************************************************************/ - - -int _qdbm_vmemavail(size_t size); - - - -/************************************************************************************************* - * for ZLIB - *************************************************************************************************/ - - -enum { - _QDBM_ZMZLIB, - _QDBM_ZMRAW, - _QDBM_ZMGZIP -}; - - -extern char *(*_qdbm_deflate)(const char *, int, int *, int); - -extern char *(*_qdbm_inflate)(const char *, int, int *, int); - -extern unsigned int (*_qdbm_getcrc)(const char *, int); - - - -/************************************************************************************************* - * for LZO - *************************************************************************************************/ - - -extern char *(*_qdbm_lzoencode)(const char *, int, int *); - -extern char *(*_qdbm_lzodecode)(const char *, int, int *); - - - -/************************************************************************************************* - * for BZIP2 - *************************************************************************************************/ - - -extern char *(*_qdbm_bzencode)(const char *, int, int *); - -extern char *(*_qdbm_bzdecode)(const char *, int, int *); - - - -/************************************************************************************************* - * for ICONV - *************************************************************************************************/ - - -extern char *(*_qdbm_iconv)(const char *, int, const char *, const char *, int *, int *); - -extern const char *(*_qdbm_encname)(const char *, int); - - - -/************************************************************************************************* - * common settings - *************************************************************************************************/ - - -#undef TRUE -#define TRUE 1 -#undef FALSE -#define FALSE 0 - -#define sizeof(a) ((int)sizeof(a)) - -int _qdbm_dummyfunc(void); - - - -#if defined(__cplusplus) /* export for C++ */ -} -#endif - -#endif /* duplication check */ - - -/* END OF FILE */ Copied: box/trunk/qdbm/myconf.h (from rev 2716, box/trunk/qdbm/myconf.h) =================================================================== --- box/trunk/qdbm/myconf.h (rev 0) +++ box/trunk/qdbm/myconf.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,593 @@ +/************************************************************************************************* + * System configurations for QDBM + * 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. + *************************************************************************************************/ + + +#ifndef _MYCONF_H /* duplication check */ +#define _MYCONF_H + +#if defined(__cplusplus) /* export for C++ */ +extern "C" { +#endif + + + +/************************************************************************************************* + * system discrimination + *************************************************************************************************/ + + +#if defined(__linux__) + +#define _SYS_LINUX_ +#define _QDBM_SYSNAME "Linux" + +#elif defined(__FreeBSD__) + +#define _SYS_FREEBSD_ +#define _QDBM_SYSNAME "FreeBSD" + +#elif defined(__NetBSD__) + +#define _SYS_NETBSD_ +#define _QDBM_SYSNAME "NetBSD" + +#elif defined(__OpenBSD__) + +#define _SYS_OPENBSD_ +#define _QDBM_SYSNAME "OpenBSD" + +#elif defined(__sun__) + +#define _SYS_SUNOS_ +#define _QDBM_SYSNAME "SunOS" + +#elif defined(__hpux) + +#define _SYS_HPUX_ +#define _QDBM_SYSNAME "HP-UX" + +#elif defined(__osf) + +#define _SYS_TRU64_ +#define _QDBM_SYSNAME "Tru64" + +#elif defined(_AIX) + +#define _SYS_AIX_ +#define _QDBM_SYSNAME "AIX" + +#elif defined(__APPLE__) && defined(__MACH__) + +#define _SYS_MACOSX_ +#define _QDBM_SYSNAME "Mac OS X" + +#elif defined(_MSC_VER) + +#define _SYS_MSVC_ +#define _QDBM_SYSNAME "Windows (VC++)" + +#elif defined(_WIN32) + +#define _SYS_MINGW_ +#define _QDBM_SYSNAME "Windows (MinGW)" + +#elif defined(__CYGWIN__) + +#define _SYS_CYGWIN_ +#define _QDBM_SYSNAME "Windows (Cygwin)" + +#elif defined(__riscos__) || defined(__riscos) + +#define _SYS_RISCOS_ +#define _QDBM_SYSNAME "RISC OS" + +#else + +#define _SYS_GENERIC_ +#define _QDBM_SYSNAME "Generic" + +#endif + + + +/************************************************************************************************* + * general headers + *************************************************************************************************/ + + +#if defined(_SYS_MSVC_) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#elif defined(_SYS_MINGW_) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#elif defined(_SYS_CYGWIN_) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif + + + +/************************************************************************************************* + * notation of filesystems + *************************************************************************************************/ + + +#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) + +#define MYPATHCHR '\\' +#define MYPATHSTR "\\" +#define MYEXTCHR '.' +#define MYEXTSTR "." +#define MYCDIRSTR "." +#define MYPDIRSTR ".." + +#elif defined(_SYS_RISCOS_) + +#define MYPATHCHR '.' +#define MYPATHSTR "." +#define MYEXTCHR '/' +#define MYEXTSTR "/" +#define MYCDIRSTR "@" +#define MYPDIRSTR "^" + +#else + +#define MYPATHCHR '/' +#define MYPATHSTR "/" +#define MYEXTCHR '.' +#define MYEXTSTR "." +#define MYCDIRSTR "." +#define MYPDIRSTR ".." + +#endif + + + +/************************************************************************************************* + * for dosish filesystems + *************************************************************************************************/ + + +#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || defined(_SYS_CYGWIN_) + +#undef UNICODE +#undef open + +#define \ + open(pathname, flags, mode) \ + open(pathname, flags | O_BINARY, mode) + +#define \ + lstat(pathname, buf) \ + _qdbm_win32_lstat(pathname, buf) + +int _qdbm_win32_lstat(const char *pathname, struct stat *buf); + +#else + +#undef O_BINARY +#undef O_TEXT +#undef setmode + +#define O_BINARY 0 +#define O_TEXT 1 + +#define \ + setmode(fd, mode) \ + (O_BINARY) + +#endif + + + +/************************************************************************************************* + * for POSIX thread + *************************************************************************************************/ + + +#if defined(MYPTHREAD) + +#define _qdbm_ptsafe TRUE + +void *_qdbm_settsd(void *ptr, int size, const void *initval); + +#else + +#define _qdbm_ptsafe FALSE + +#define \ + _qdbm_settsd(ptr, size, initval) \ + (NULL) + +#endif + + + +/************************************************************************************************* + * for systems without file locking + *************************************************************************************************/ + + +#if defined(_SYS_RISCOS_) || defined(MYNOLOCK) + +#undef fcntl + +#define \ + fcntl(fd, cmd, lock) \ + (0) + +#endif + + + +/************************************************************************************************* + * for systems without mmap + *************************************************************************************************/ + + +#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || \ + defined(_SYS_FREEBSD_) || defined(_SYS_NETBSD_) || defined(_SYS_OPENBSD_) || \ + defined(_SYS_AIX_) || defined(_SYS_RISCOS_) || defined(MYNOMMAP) + +#undef PROT_EXEC +#undef PROT_READ +#undef PROT_WRITE +#undef PROT_NONE +#undef MAP_FIXED +#undef MAP_SHARED +#undef MAP_PRIVATE +#undef MAP_FAILED +#undef MS_ASYNC +#undef MS_SYNC +#undef MS_INVALIDATE +#undef mmap +#undef munmap +#undef msync +#undef mflush + +#define PROT_EXEC (1 << 0) +#define PROT_READ (1 << 1) +#define PROT_WRITE (1 << 2) +#define PROT_NONE (1 << 3) +#define MAP_FIXED 1 +#define MAP_SHARED 2 +#define MAP_PRIVATE 3 +#define MAP_FAILED ((void *)-1) +#define MS_ASYNC (1 << 0) +#define MS_SYNC (1 << 1) +#define MS_INVALIDATE (1 << 2) + +#define \ + mmap(start, length, prot, flags, fd, offset) \ + _qdbm_mmap(start, length, prot, flags, fd, offset) + +#define \ + munmap(start, length) \ + _qdbm_munmap(start, length) + +#define \ + msync(start, length, flags) \ + _qdbm_msync(start, length, flags) + +#define \ + mflush(start, length, flags) \ + _qdbm_msync(start, length, flags) + +void *_qdbm_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); +int _qdbm_munmap(void *start, size_t length); +int _qdbm_msync(const void *start, size_t length, int flags); + +#else + +#undef mflush +#define \ + mflush(start, length, flags) \ + (0) + +#endif + + + +/************************************************************************************************* + * for reentrant time routines + *************************************************************************************************/ + + +struct tm *_qdbm_gmtime(const time_t *timep, struct tm *result); +struct tm *_qdbm_localtime(const time_t *timep, struct tm *result); + + + +/************************************************************************************************* + * for systems without times + *************************************************************************************************/ + + +#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) + +#undef times +#undef sysconf + +struct tms { + clock_t tms_utime; + clock_t tms_stime; + clock_t tms_cutime; + clock_t tms_cstime; +}; + +#define \ + times(buf) \ + _qdbm_times(buf) + +#define \ + sysconf(name) \ + (CLOCKS_PER_SEC) + +clock_t _qdbm_times(struct tms *buf); + +#endif + + + +/************************************************************************************************* + * for Win32 + *************************************************************************************************/ + + +#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) + +#undef F_WRLCK +#undef F_RDLCK +#undef F_SETLK +#undef F_SETLKW +#undef fcntl +#undef ftruncate +#undef fsync +#undef mkdir +#undef rename + +#define F_WRLCK 0 +#define F_RDLCK 1 +#define F_SETLK 0 +#define F_SETLKW 1 + +struct flock { + int l_type; + int l_whence; + int l_start; + int l_len; + int l_pid; +}; + +#define \ + fcntl(fd, cmd, lock) \ + _qdbm_win32_fcntl(fd, cmd, lock) + +#define \ + ftruncate(fd, length) \ + _chsize(fd, length) + +#define \ + fsync(fd) \ + (0) + +#define \ + mkdir(pathname, mode) \ + mkdir(pathname) + +#define \ + rename(oldpath, newpath) \ + (unlink(newpath), rename(oldpath, newpath)) + +int _qdbm_win32_fcntl(int fd, int cmd, struct flock *lock); + +#endif + + +#if defined(_SYS_MSVC_) + +#undef S_ISDIR +#undef S_ISREG +#undef opendir +#undef closedir +#undef readdir + +#define S_ISDIR(x) (x & _S_IFDIR) +#define S_ISREG(x) (x & _S_IFREG) + +struct dirent { + char d_name[1024]; +}; + +typedef struct { + HANDLE fh; + WIN32_FIND_DATA data; + struct dirent de; + int first; +} DIR; + +#define \ + opendir(name) \ + _qdbm_win32_opendir(name) + +#define \ + closedir(dir) \ + _qdbm_win32_closedir(dir) + +#define \ + readdir(dir) \ + _qdbm_win32_readdir(dir) + +DIR *_qdbm_win32_opendir(const char *name); + +int _qdbm_win32_closedir(DIR *dir); + +struct dirent *_qdbm_win32_readdir(DIR *dir); + +#endif + + + +/************************************************************************************************* + * for checking information of the system + *************************************************************************************************/ + + +int _qdbm_vmemavail(size_t size); + + + +/************************************************************************************************* + * for ZLIB + *************************************************************************************************/ + + +enum { + _QDBM_ZMZLIB, + _QDBM_ZMRAW, + _QDBM_ZMGZIP +}; + + +extern char *(*_qdbm_deflate)(const char *, int, int *, int); + +extern char *(*_qdbm_inflate)(const char *, int, int *, int); + +extern unsigned int (*_qdbm_getcrc)(const char *, int); + + + +/************************************************************************************************* + * for LZO + *************************************************************************************************/ + + +extern char *(*_qdbm_lzoencode)(const char *, int, int *); + +extern char *(*_qdbm_lzodecode)(const char *, int, int *); + + + +/************************************************************************************************* + * for BZIP2 + *************************************************************************************************/ + + +extern char *(*_qdbm_bzencode)(const char *, int, int *); + +extern char *(*_qdbm_bzdecode)(const char *, int, int *); + + + +/************************************************************************************************* + * for ICONV + *************************************************************************************************/ + + +extern char *(*_qdbm_iconv)(const char *, int, const char *, const char *, int *, int *); + +extern const char *(*_qdbm_encname)(const char *, int); + + + +/************************************************************************************************* + * common settings + *************************************************************************************************/ + + +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +#define sizeof(a) ((int)sizeof(a)) + +int _qdbm_dummyfunc(void); + + + +#if defined(__cplusplus) /* export for C++ */ +} +#endif + +#endif /* duplication check */ + + +/* END OF FILE */ Deleted: box/trunk/qdbm/odeum.c =================================================================== --- box/trunk/qdbm/odeum.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/odeum.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,2090 +0,0 @@ -/************************************************************************************************* - * Implementation of Odeum - * 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. - *************************************************************************************************/ - - -#define QDBM_INTERNAL 1 - -#include "odeum.h" -#include "myconf.h" - -#define OD_NAMEMAX 256 /* max size of a database name */ -#define OD_DIRMODE 00755 /* permission of a creating directory */ -#define OD_PATHBUFSIZ 1024 /* size of a path buffer */ -#define OD_NUMBUFSIZ 32 /* size of a buffer for a number */ -#define OD_MAPPBNUM 127 /* bucket size of a petit map handle */ -#define OD_DOCSNAME "docs" /* name of the database for documents */ -#define OD_INDEXNAME "index" /* name of the database for inverted index */ -#define OD_RDOCSNAME "rdocs" /* name of the database for reverse dictionary */ -#define OD_DOCSBNUM 2039 /* initial bucket number of document database */ -#define OD_DOCSDNUM 17 /* division number of document database */ -#define OD_DOCSALIGN -4 /* alignment of document database */ -#define OD_DOCSFBP 32 /* size of free block pool of document database */ -#define OD_INDEXBNUM 32749 /* initial bucket number of inverted index */ -#define OD_INDEXDNUM 7 /* division number of inverted index */ -#define OD_INDEXALIGN -2 /* alignment of inverted index */ -#define OD_INDEXFBP 32 /* size of free block pool of inverted index */ -#define OD_RDOCSLRM 81 /* records in a leaf node of reverse dictionary */ -#define OD_RDOCSNIM 192 /* records in a non-leaf node of reverse dictionary */ -#define OD_RDOCSLCN 128 /* number of leaf cache of reverse dictionary */ -#define OD_RDOCSNCN 32 /* number of non-leaf cache of reverse dictionary */ -#define OD_CACHEBNUM 262139 /* number of buckets for dirty buffers */ -#define OD_CACHESIZ 8388608 /* max bytes to use memory for dirty buffers */ -#define OD_CFLIVERAT 0.8 /* ratio of usable cache region */ -#define OD_CFBEGSIZ 2048 /* beginning size of flushing frequent words */ -#define OD_CFENDSIZ 64 /* lower limit of flushing frequent words */ -#define OD_CFRFRAT 0.2 /* ratio of flushing rare words a time */ -#define OD_OTCBBUFSIZ 1024 /* size of a buffer for call back functions */ -#define OD_OTPERWORDS 10000 /* frequency of call back in merging index */ -#define OD_OTPERDOCS 1000 /* frequency of call back in merging docs */ -#define OD_MDBRATIO 2.5 /* ratio of bucket number and document number */ -#define OD_MIBRATIO 1.5 /* ratio of bucket number and word number */ -#define OD_MIARATIO 0.75 /* ratio of alignment to the first words */ -#define OD_MIWUNIT 32 /* writing unit of merging inverted index */ -#define OD_DMAXEXPR "dmax" /* key of max number of the document ID */ -#define OD_DNUMEXPR "dnum" /* key of number of the documents */ -#define OD_URIEXPR "1" /* map key of URI */ -#define OD_ATTRSEXPR "2" /* map key of attributes */ -#define OD_NWORDSEXPR "3" /* map key of normal words */ -#define OD_AWORDSEXPR "4" /* map key of as-is words */ -#define OD_WTOPRATE 0.1 /* ratio of top words */ -#define OD_WTOPBONUS 5000 /* bonus points of top words */ -#define OD_KEYCRATIO 1.75 /* ratio of number to max of keyword candidates */ -#define OD_WOCCRPOINT 10000 /* points per occurence */ -#define OD_SPACECHARS "\t\n\v\f\r " /* space characters */ -#define OD_DELIMCHARS "!\"#$%&'()*/<=>?[\\]^`{|}~" /* delimiter characters */ -#define OD_GLUECHARS "+,-.:;@" /* glueing characters */ -#define OD_MAXWORDLEN 48 /* max length of a word */ - -typedef struct { /* type of structure for word counting */ - const char *word; /* pointer to the word */ - int num; /* frequency of the word */ -} ODWORD; - -enum { /* enumeration for events binded to each character */ - OD_EVWORD, /* word */ - OD_EVSPACE, /* space */ - OD_EVDELIM, /* delimiter */ - OD_EVGLUE /* glue */ -}; - - -/* private global variables */ -int odindexbnum = OD_INDEXBNUM; -int odindexdnum = OD_INDEXDNUM; -int odcachebnum = OD_CACHEBNUM; -int odcachesiz = OD_CACHESIZ; -void (*odotcb)(const char *, ODEUM *, const char *) = NULL; - - -/* private function prototypes */ -static ODEUM *odopendb(const char *name, int omode, int docsbnum, int indexbnum, - const char *fname); -static int odcacheflush(ODEUM *odeum, const char *fname); -static int odcacheflushfreq(ODEUM *odeum, const char *fname, int min); -static int odcacheflushrare(ODEUM *odeum, const char *fname, double ratio); -static int odsortindex(ODEUM *odeum, const char *fname); -static int odsortcompare(const void *a, const void *b); -static int odpurgeindex(ODEUM *odeum, const char *fname); -static CBMAP *odpairsmap(const ODPAIR *pairs, int num); -static int odwordcompare(const void *a, const void *b); -static int odmatchoperator(ODEUM *odeum, CBLIST *tokens); -static ODPAIR *odparsesubexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, - CBLIST *errors); -static ODPAIR *odparseexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, - CBLIST *errors); -static void odfixtokens(ODEUM *odeum, CBLIST *tokens); -static void odcleannormalized(ODEUM *odeum, CBLIST *nwords); - - - -/************************************************************************************************* - * public objects - *************************************************************************************************/ - - -/* Get a database handle. */ -ODEUM *odopen(const char *name, int omode){ - assert(name); - return odopendb(name, omode, OD_DOCSBNUM, odindexbnum, "odopen"); -} - - -/* Close a database handle. */ -int odclose(ODEUM *odeum){ - char numbuf[OD_NUMBUFSIZ]; - int err; - assert(odeum); - err = FALSE; - if(odotcb) odotcb("odclose", odeum, "closing the connection"); - if(odeum->wmode){ - if(odotcb) odotcb("odclose", odeum, "writing meta information"); - sprintf(numbuf, "%d", odeum->dmax); - if(!vlput(odeum->rdocsdb, OD_DMAXEXPR, sizeof(OD_DMAXEXPR), numbuf, -1, VL_DOVER)) err = TRUE; - sprintf(numbuf, "%d", odeum->dnum); - if(!vlput(odeum->rdocsdb, OD_DNUMEXPR, sizeof(OD_DNUMEXPR), numbuf, -1, VL_DOVER)) err = TRUE; - if(!odcacheflushfreq(odeum, "odclose", OD_CFENDSIZ)) err = TRUE; - if(!odcacheflushrare(odeum, "odclose", OD_CFRFRAT)) err = TRUE; - if(!odcacheflush(odeum, "odclose")) err = TRUE; - if(!odsortindex(odeum, "odclose")) err = TRUE; - cbmapclose(odeum->cachemap); - cbmapclose(odeum->sortmap); - } - if(!vlclose(odeum->rdocsdb)) err = TRUE; - if(!crclose(odeum->indexdb)) err = TRUE; - if(!crclose(odeum->docsdb)) err = TRUE; - free(odeum->name); - free(odeum); - return err ? FALSE : TRUE; -} - - -/* Store a document. */ -int odput(ODEUM *odeum, ODDOC *doc, int wmax, int over){ - char *tmp, *zbuf; - const char *word, *ctmp; - int i, docid, tsiz, wsiz, wnum, tmax, num, zsiz; - double ival; - ODPAIR pair; - CBMAP *map; - CBLIST *tlist; - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!odeum->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if((tmp = vlget(odeum->rdocsdb, doc->uri, -1, &tsiz)) != NULL){ - if(!over){ - free(tmp); - dpecodeset(DP_EKEEP, __FILE__, __LINE__); - return FALSE; - } - if(tsiz != sizeof(int) || !odoutbyid(odeum, *(int *)tmp)){ - free(tmp); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - odeum->fatal = TRUE; - return FALSE; - } - free(tmp); - } - odeum->dmax++; - odeum->dnum++; - docid = odeum->dmax; - map = cbmapopen(); - cbmapput(map, OD_URIEXPR, sizeof(OD_URIEXPR), doc->uri, -1, TRUE); - tmp = cbmapdump(doc->attrs, &tsiz); - cbmapput(map, OD_ATTRSEXPR, sizeof(OD_ATTRSEXPR), tmp, tsiz, TRUE); - free(tmp); - if(wmax < 0 || wmax > cblistnum(doc->nwords)) wmax = cblistnum(doc->nwords); - tlist = cblistopen(); - for(i = 0; i < wmax; i++){ - ctmp = cblistval(doc->nwords, i, &wsiz); - cblistpush(tlist, ctmp, wsiz); - } - tmp = cblistdump(tlist, &tsiz); - cbmapput(map, OD_NWORDSEXPR, sizeof(OD_NWORDSEXPR), tmp, tsiz, TRUE); - free(tmp); - cblistclose(tlist); - tlist = cblistopen(); - for(i = 0; i < wmax; i++){ - ctmp = cblistval(doc->awords, i, &wsiz); - if(strcmp(ctmp, cblistval(doc->nwords, i, NULL))){ - cblistpush(tlist, ctmp, wsiz); - } else { - cblistpush(tlist, "\0", 1); - } - } - tmp = cblistdump(tlist, &tsiz); - cbmapput(map, OD_AWORDSEXPR, sizeof(OD_AWORDSEXPR), tmp, tsiz, TRUE); - free(tmp); - cblistclose(tlist); - tmp = cbmapdump(map, &tsiz); - cbmapclose(map); - if(_qdbm_deflate){ - if(!(zbuf = _qdbm_deflate(tmp, tsiz, &zsiz, _QDBM_ZMRAW))){ - free(tmp); - dpecodeset(DP_EMISC, __FILE__, __LINE__); - odeum->fatal = TRUE; - return FALSE; - } - free(tmp); - tmp = zbuf; - tsiz = zsiz; - } - if(!crput(odeum->docsdb, (char *)&docid, sizeof(int), tmp, tsiz, CR_DKEEP)){ - free(tmp); - if(dpecode == DP_EKEEP) dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - odeum->fatal = TRUE; - return FALSE; - } - free(tmp); - if(!vlput(odeum->rdocsdb, doc->uri, -1, (char *)&docid, sizeof(int), VL_DOVER)){ - odeum->fatal = TRUE; - return FALSE; - } - map = cbmapopen(); - wnum = cblistnum(doc->nwords); - tmax = (int)(wnum * OD_WTOPRATE); - for(i = 0; i < wnum; i++){ - word = cblistval(doc->nwords, i, &wsiz); - if(wsiz < 1) continue; - if((ctmp = cbmapget(map, word, wsiz, NULL)) != NULL){ - num = *(int *)ctmp + OD_WOCCRPOINT; - } else { - num = i <= tmax ? OD_WTOPBONUS + OD_WOCCRPOINT : OD_WOCCRPOINT; - } - cbmapput(map, word, wsiz, (char *)&num, sizeof(int), TRUE); - } - ival = odlogarithm(wnum); - ival = (ival * ival * ival) / 8.0; - if(ival < 8.0) ival = 8.0; - cbmapiterinit(map); - while((word = cbmapiternext(map, &wsiz)) != NULL){ - pair.id = docid; - pair.score = (int)(*(int *)cbmapget(map, word, wsiz, NULL) / ival); - cbmapputcat(odeum->cachemap, word, wsiz, (char *)&pair, sizeof(pair)); - cbmapmove(odeum->cachemap, word, wsiz, FALSE); - odeum->cacheasiz += sizeof(pair); - cbmapput(odeum->sortmap, word, wsiz, "", 0, FALSE); - } - cbmapclose(map); - if(odeum->cacheasiz > odcachesiz){ - for(i = OD_CFBEGSIZ; odeum->cacheasiz > odcachesiz * OD_CFLIVERAT && i >= OD_CFENDSIZ; - i /= 2){ - if(!odcacheflushfreq(odeum, "odput", i)) return FALSE; - } - while(odeum->cacheasiz > odcachesiz * OD_CFLIVERAT){ - if(!odcacheflushrare(odeum, "odput", OD_CFRFRAT)) return FALSE; - } - } - doc->id = docid; - odeum->ldid = docid; - return TRUE; -} - - -/* Delete a document by a URL. */ -int odout(ODEUM *odeum, const char *uri){ - char *tmp; - int tsiz, docid; - assert(odeum && uri); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!odeum->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(!(tmp = vlget(odeum->rdocsdb, uri, -1, &tsiz))){ - if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; - return FALSE; - } - if(tsiz != sizeof(int)){ - free(tmp); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - odeum->fatal = TRUE; - return FALSE; - } - docid = *(int *)tmp; - free(tmp); - return odoutbyid(odeum, docid); -} - - -/* Delete a document specified by an ID number. */ -int odoutbyid(ODEUM *odeum, int id){ - char *tmp, *zbuf; - const char *uritmp; - int tsiz, uritsiz, zsiz; - CBMAP *map; - assert(odeum && id > 0); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!odeum->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(!(tmp = crget(odeum->docsdb, (char *)&id, sizeof(int), 0, -1, &tsiz))){ - if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; - return FALSE; - } - if(_qdbm_inflate){ - if(!(zbuf = _qdbm_inflate(tmp, tsiz, &zsiz, _QDBM_ZMRAW))){ - free(tmp); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - odeum->fatal = TRUE; - return FALSE; - } - free(tmp); - tmp = zbuf; - tsiz = zsiz; - } - map = cbmapload(tmp, tsiz); - free(tmp); - uritmp = cbmapget(map, OD_URIEXPR, sizeof(OD_URIEXPR), &uritsiz); - if(!uritmp || !vlout(odeum->rdocsdb, uritmp, uritsiz)){ - cbmapclose(map); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - odeum->fatal = TRUE; - return FALSE; - } - cbmapclose(map); - if(!crout(odeum->docsdb, (char *)&id, sizeof(int))){ - odeum->fatal = TRUE; - return FALSE; - } - odeum->dnum--; - return TRUE; -} - - -/* Retrieve a document by a URI. */ -ODDOC *odget(ODEUM *odeum, const char *uri){ - char *tmp; - int tsiz, docid; - assert(odeum && uri); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return NULL; - } - if(!(tmp = vlget(odeum->rdocsdb, uri, -1, &tsiz))){ - if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; - return NULL; - } - if(tsiz != sizeof(int)){ - free(tmp); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - odeum->fatal = TRUE; - return NULL; - } - docid = *(int *)tmp; - free(tmp); - return odgetbyid(odeum, docid); -} - - -/* Retrieve a document by an ID number. */ -ODDOC *odgetbyid(ODEUM *odeum, int id){ - char *tmp, *zbuf; - const char *uritmp, *attrstmp, *nwordstmp, *awordstmp, *asis, *normal; - int i, tsiz, uritsiz, attrstsiz, nwordstsiz, awordstsiz, zsiz, asiz, nsiz; - ODDOC *doc; - CBMAP *map; - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return NULL; - } - if(id < 1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return NULL; - } - if(!(tmp = crget(odeum->docsdb, (char *)&id, sizeof(int), 0, -1, &tsiz))){ - if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; - return NULL; - } - if(_qdbm_inflate){ - if(!(zbuf = _qdbm_inflate(tmp, tsiz, &zsiz, _QDBM_ZMRAW))){ - free(tmp); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - odeum->fatal = TRUE; - return NULL; - } - free(tmp); - tmp = zbuf; - tsiz = zsiz; - } - map = cbmapload(tmp, tsiz); - free(tmp); - uritmp = cbmapget(map, OD_URIEXPR, sizeof(OD_URIEXPR), &uritsiz); - attrstmp = cbmapget(map, OD_ATTRSEXPR, sizeof(OD_ATTRSEXPR), &attrstsiz); - nwordstmp = cbmapget(map, OD_NWORDSEXPR, sizeof(OD_NWORDSEXPR), &nwordstsiz); - awordstmp = cbmapget(map, OD_AWORDSEXPR, sizeof(OD_AWORDSEXPR), &awordstsiz); - if(!uritmp || !attrstmp || !nwordstmp || !awordstmp){ - cbmapclose(map); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - odeum->fatal = TRUE; - return NULL; - } - doc = cbmalloc(sizeof(ODDOC)); - doc->id = id; - doc->uri = cbmemdup(uritmp, uritsiz); - doc->attrs = cbmapload(attrstmp, attrstsiz); - doc->nwords = cblistload(nwordstmp, nwordstsiz); - doc->awords = cblistload(awordstmp, awordstsiz); - cbmapclose(map); - for(i = 0; i < cblistnum(doc->awords); i++){ - asis = cblistval(doc->awords, i, &asiz); - if(asiz == 1 && asis[0] == '\0'){ - normal = cblistval(doc->nwords, i, &nsiz); - cblistover(doc->awords, i, normal, nsiz); - } - } - return doc; -} - - -/* Retrieve the ID of the document specified by a URI. */ -int odgetidbyuri(ODEUM *odeum, const char *uri){ - char *tmp; - int tsiz, docid; - assert(odeum && uri); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - if(!(tmp = vlget(odeum->rdocsdb, uri, -1, &tsiz))){ - if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; - return -1; - } - if(tsiz != sizeof(int)){ - free(tmp); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - odeum->fatal = TRUE; - return -1; - } - docid = *(int *)tmp; - free(tmp); - return docid; -} - - -/* Check whether the document specified by an ID number exists. */ -int odcheck(ODEUM *odeum, int id){ - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(id < 1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - return crvsiz(odeum->docsdb, (char *)&id, sizeof(int)) != -1; -} - - -/* Search the inverted index for documents including a word. */ -ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np){ - char *tmp; - int tsiz; - assert(odeum && word && np); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return NULL; - } - if(odeum->wmode && cbmaprnum(odeum->sortmap) > 0 && - (!odcacheflush(odeum, "odsearch") || !odsortindex(odeum, "odsearch"))){ - odeum->fatal = TRUE; - return NULL; - } - max = max < 0 ? -1 : max * sizeof(ODPAIR); - if(!(tmp = crget(odeum->indexdb, word, -1, 0, max, &tsiz))){ - if(dpecode != DP_ENOITEM){ - odeum->fatal = TRUE; - return NULL; - } - *np = 0; - return cbmalloc(1); - } - *np = tsiz / sizeof(ODPAIR); - return (ODPAIR *)tmp; -} - - -/* Get the number of documents including a word. */ -int odsearchdnum(ODEUM *odeum, const char *word){ - int rv; - assert(odeum && word); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - rv = crvsiz(odeum->indexdb, word, -1); - return rv < 0 ? -1 : rv / sizeof(ODPAIR); -} - - -/* Initialize the iterator of a database handle. */ -int oditerinit(ODEUM *odeum){ - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - return criterinit(odeum->docsdb); -} - - -/* Get the next key of the iterator. */ -ODDOC *oditernext(ODEUM *odeum){ - char *tmp; - int tsiz, docsid; - ODDOC *doc; - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return NULL; - } - doc = NULL; - while(TRUE){ - if(!(tmp = criternext(odeum->docsdb, &tsiz))){ - if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; - return NULL; - } - if(tsiz != sizeof(int)){ - free(tmp); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - odeum->fatal = TRUE; - return NULL; - } - docsid = *(int *)tmp; - free(tmp); - if((doc = odgetbyid(odeum, docsid)) != NULL) break; - if(dpecode != DP_ENOITEM){ - odeum->fatal = TRUE; - return NULL; - } - } - return doc; -} - - -/* Synchronize updating contents with the files and the devices. */ -int odsync(ODEUM *odeum){ - char numbuf[OD_NUMBUFSIZ]; - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!odeum->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(odotcb) odotcb("odsync", odeum, "writing meta information"); - sprintf(numbuf, "%d", odeum->dmax); - if(!vlput(odeum->rdocsdb, OD_DMAXEXPR, sizeof(OD_DMAXEXPR), numbuf, -1, VL_DOVER)){ - odeum->fatal = TRUE; - return FALSE; - } - sprintf(numbuf, "%d", odeum->dnum); - if(!vlput(odeum->rdocsdb, OD_DNUMEXPR, sizeof(OD_DNUMEXPR), numbuf, -1, VL_DOVER)){ - odeum->fatal = TRUE; - return FALSE; - } - if(!odcacheflush(odeum, "odsync")){ - odeum->fatal = TRUE; - return FALSE; - } - if(!odsortindex(odeum, "odsync")){ - odeum->fatal = TRUE; - return FALSE; - } - if(odotcb) odotcb("odsync", odeum, "synchronizing the document database"); - if(!crsync(odeum->docsdb)){ - odeum->fatal = TRUE; - return FALSE; - } - if(odotcb) odotcb("odsync", odeum, "synchronizing the inverted index"); - if(!crsync(odeum->indexdb)){ - odeum->fatal = TRUE; - return FALSE; - } - if(odotcb) odotcb("odsync", odeum, "synchronizing the reverse dictionary"); - if(!vlsync(odeum->rdocsdb)){ - odeum->fatal = TRUE; - return FALSE; - } - return TRUE; -} - - -/* Optimize a database. */ -int odoptimize(ODEUM *odeum){ - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return FALSE; - } - if(!odeum->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(!odcacheflush(odeum, "odoptimize")){ - odeum->fatal = TRUE; - return FALSE; - } - if(odeum->ldid < 1 || odeum->ldid != odeum->dnum){ - if(!odpurgeindex(odeum, "odoptimize")){ - odeum->fatal = TRUE; - return FALSE; - } - } - if(odeum->ldid > 0){ - if(!odsortindex(odeum, "odoptimize")){ - odeum->fatal = TRUE; - return FALSE; - } - } - if(odotcb) odotcb("odoptimize", odeum, "optimizing the document database"); - if(!croptimize(odeum->docsdb, -1)){ - odeum->fatal = TRUE; - return FALSE; - } - if(odotcb) odotcb("odoptimize", odeum, "optimizing the inverted index"); - if(!croptimize(odeum->indexdb, -1)){ - odeum->fatal = TRUE; - return FALSE; - } - if(odotcb) odotcb("odoptimize", odeum, "optimizing the reverse dictionary"); - if(!vloptimize(odeum->rdocsdb)){ - odeum->fatal = TRUE; - return FALSE; - } - return TRUE; -} - - -/* Get the name of a database. */ -char *odname(ODEUM *odeum){ - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return NULL; - } - return cbmemdup(odeum->name, -1); -} - - -/* Get the total size of database files. */ -double odfsiz(ODEUM *odeum){ - double fsiz, rv; - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - fsiz = 0; - if((rv = crfsizd(odeum->docsdb)) < 0) return -1.0; - fsiz += rv; - if((rv = crfsizd(odeum->indexdb)) < 0) return -1.0; - fsiz += rv; - if((rv = vlfsiz(odeum->rdocsdb)) == -1) return -1.0; - fsiz += rv; - return fsiz; -} - - -/* Get the total number of the elements of the bucket arrays for the inverted index. */ -int odbnum(ODEUM *odeum){ - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - return crbnum(odeum->indexdb); -} - - -/* Get the total number of the used elements of the bucket arrays in the inverted index. */ -int odbusenum(ODEUM *odeum){ - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - return crbusenum(odeum->indexdb); -} - - -/* Get the number of the documents stored in a database. */ -int oddnum(ODEUM *odeum){ - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - return odeum->dnum; -} - - -/* Get the number of the words stored in a database. */ -int odwnum(ODEUM *odeum){ - assert(odeum); - if(odeum->fatal){ - dpecodeset(DP_EFATAL, __FILE__, __LINE__); - return -1; - } - return crrnum(odeum->indexdb); -} - - -/* Check whether a database handle is a writer or not. */ -int odwritable(ODEUM *odeum){ - assert(odeum); - return odeum->wmode; -} - - -/* Check whether a database has a fatal error or not. */ -int odfatalerror(ODEUM *odeum){ - assert(odeum); - return odeum->fatal; -} - - -/* Get the inode number of a database directory. */ -int odinode(ODEUM *odeum){ - assert(odeum); - return odeum->inode; -} - - -/* Get the last modified time of a database. */ -time_t odmtime(ODEUM *odeum){ - assert(odeum); - return crmtime(odeum->indexdb); -} - - -/* Merge plural database directories. */ -int odmerge(const char *name, const CBLIST *elemnames){ - ODEUM *odeum, **elems; - CURIA *curia, *ecuria; - VILLA *villa, *evilla; - ODPAIR *pairs; - char *word, *kbuf, *vbuf, *dbuf, otmsg[OD_OTCBBUFSIZ]; - char *wpunit[OD_MIWUNIT], *vpunit[OD_MIWUNIT]; - int i, j, k, num, dnum, wnum, dbnum, ibnum, tnum, wsunit[OD_MIWUNIT], vsunit[OD_MIWUNIT]; - int err, *bases, sum, max, wsiz, ksiz, vsiz, uend, unum, pnum, align, id, nid, dsiz; - assert(name && elemnames); - num = cblistnum(elemnames); - elems = cbmalloc(num * sizeof(ODEUM *) + 1); - dnum = 0; - wnum = 0; - for(i = 0; i < num; i++){ - if(!(elems[i] = odopen(cblistval(elemnames, i, NULL), OD_OREADER))){ - for(i -= 1; i >= 0; i--){ - odclose(elems[i]); - } - free(elems); - return FALSE; - } - dnum += oddnum(elems[i]); - wnum += odwnum(elems[i]); - } - dbnum = (int)(dnum * OD_MDBRATIO / OD_DOCSDNUM); - ibnum = (int)(wnum * OD_MIBRATIO / odindexdnum); - if(!(odeum = odopendb(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC, dbnum, ibnum, "odmerge"))){ - for(i = 0; i < num; i++){ - odclose(elems[i]); - } - free(elems); - return FALSE; - } - err = FALSE; - if(odotcb) odotcb("odmerge", odeum, "calculating the base ID numbers"); - bases = cbmalloc(num * sizeof(int) + 1); - sum = 0; - for(i = 0; i < num; i++){ - ecuria = elems[i]->docsdb; - max = 0; - if(!criterinit(ecuria) && dpecode != DP_ENOITEM) err = TRUE; - while((kbuf = criternext(ecuria, &ksiz)) != NULL){ - if(ksiz == sizeof(int)){ - if(*(int *)kbuf > max) max = *(int *)kbuf; - } - free(kbuf); - } - bases[i] = sum; - sum += max; - } - curia = odeum->indexdb; - for(i = 0; i < num; i++){ - if(odotcb){ - sprintf(otmsg, "merging the inverted index (%d/%d)", i + 1, num); - odotcb("odmerge", odeum, otmsg); - } - ecuria = elems[i]->indexdb; - tnum = 0; - uend = FALSE; - if(!criterinit(ecuria) && dpecode != DP_ENOITEM) err = TRUE; - while(!uend){ - for(unum = 0; unum < OD_MIWUNIT; unum++){ - if(!(word = criternext(ecuria, &wsiz))){ - uend = TRUE; - break; - } - if(!(vbuf = crget(ecuria, word, wsiz, 0, -1, &vsiz))){ - err = TRUE; - free(word); - break; - } - wpunit[unum] = word; - wsunit[unum] = wsiz; - vpunit[unum] = vbuf; - vsunit[unum] = vsiz; - } - for(j = 0; j < unum; j++){ - word = wpunit[j]; - wsiz = wsunit[j]; - vbuf = vpunit[j]; - vsiz = vsunit[j]; - pairs = (ODPAIR *)vbuf; - pnum = vsiz / sizeof(ODPAIR); - for(k = 0; k < pnum; k++){ - pairs[k].id += bases[i]; - } - align = (int)(i < num - 1 ? vsiz * (num - i) * OD_MIARATIO : OD_INDEXALIGN); - if(!crsetalign(curia, align)) err = TRUE; - if(!crput(curia, word, wsiz, vbuf, vsiz, CR_DCAT)) err = TRUE; - free(vbuf); - free(word); - if(odotcb && (tnum + 1) % OD_OTPERWORDS == 0){ - sprintf(otmsg, "... (%d/%d)", tnum + 1, crrnum(ecuria)); - odotcb("odmerge", odeum, otmsg); - } - tnum++; - } - } - } - if(odotcb) odotcb("odmerge", odeum, "sorting the inverted index"); - tnum = 0; - if(!criterinit(curia) && dpecode != DP_ENOITEM) err = TRUE; - while((word = criternext(curia, &wsiz)) != NULL){ - if((vbuf = crget(curia, word, wsiz, 0, -1, &vsiz)) != NULL){ - if(vsiz > sizeof(ODPAIR)){ - pairs = (ODPAIR *)vbuf; - pnum = vsiz / sizeof(ODPAIR); - qsort(pairs, pnum, sizeof(ODPAIR), odsortcompare); - if(!crput(curia, word, wsiz, vbuf, vsiz, CR_DOVER)) err = TRUE; - } - free(vbuf); - } - free(word); - if(odotcb && (tnum + 1) % OD_OTPERWORDS == 0){ - sprintf(otmsg, "... (%d/%d)", tnum + 1, crrnum(curia)); - odotcb("odmerge", odeum, otmsg); - } - tnum++; - } - if(odotcb) odotcb("odmerge", odeum, "synchronizing the inverted index"); - if(!crsync(curia)) err = TRUE; - dnum = 0; - curia = odeum->docsdb; - villa = odeum->rdocsdb; - for(i = 0; i < num; i++){ - if(odotcb){ - sprintf(otmsg, "merging the document database (%d/%d)", i + 1, num); - odotcb("odmerge", odeum, otmsg); - } - evilla = elems[i]->rdocsdb; - ecuria = elems[i]->docsdb; - tnum = 0; - if(!vlcurfirst(evilla) && dpecode != DP_ENOITEM) err = TRUE; - while(TRUE){ - if(!(kbuf = vlcurkey(evilla, &ksiz))) break; - if((ksiz == sizeof(OD_DMAXEXPR) && !memcmp(kbuf, OD_DMAXEXPR, ksiz)) || - (ksiz == sizeof(OD_DNUMEXPR) && !memcmp(kbuf, OD_DNUMEXPR, ksiz))){ - free(kbuf); - if(!vlcurnext(evilla)) break; - continue; - } - if(!(vbuf = vlcurval(evilla, &vsiz))){ - free(kbuf); - if(!vlcurnext(evilla)) break; - continue; - } - if(vsiz != sizeof(int)){ - free(vbuf); - free(kbuf); - if(!vlcurnext(evilla)) break; - continue; - } - id = *(int *)vbuf; - nid = id + bases[i]; - if(vlput(villa, kbuf, ksiz, (char *)&nid, sizeof(int), VL_DKEEP)){ - if((dbuf = crget(ecuria, (char *)&id, sizeof(int), 0, -1, &dsiz)) != NULL){ - if(crput(curia, (char *)&nid, sizeof(int), dbuf, dsiz, CR_DKEEP)){ - dnum++; - } else { - err = TRUE; - } - free(dbuf); - } else { - err = TRUE; - } - } else if(dpecode != DP_EKEEP){ - err = TRUE; - } - free(vbuf); - free(kbuf); - odeum->dnum++; - if(odotcb && (tnum + 1) % OD_OTPERDOCS == 0){ - sprintf(otmsg, "... (%d/%d)", tnum + 1, crrnum(ecuria)); - odotcb("odmerge", odeum, otmsg); - } - tnum++; - if(!vlcurnext(evilla)) break; - } - } - odeum->dnum = dnum; - odeum->dmax = dnum; - free(bases); - if(odotcb) odotcb("odmerge", odeum, "synchronizing the document index"); - if(!crsync(curia)) err = TRUE; - if(!odclose(odeum)) err = TRUE; - for(i = 0; i < num; i++){ - if(!odclose(elems[i])) err = TRUE; - } - free(elems); - return err ? FALSE : TRUE; -} - - -/* Remove a database directory. */ -int odremove(const char *name){ - char docsname[OD_PATHBUFSIZ], indexname[OD_PATHBUFSIZ], rdocsname[OD_PATHBUFSIZ]; - char path[OD_PATHBUFSIZ]; - const char *file; - struct stat sbuf; - CBLIST *list; - int i; - assert(name); - sprintf(docsname, "%s%c%s", name, MYPATHCHR, OD_DOCSNAME); - sprintf(indexname, "%s%c%s", name, MYPATHCHR, OD_INDEXNAME); - sprintf(rdocsname, "%s%c%s", name, MYPATHCHR, OD_RDOCSNAME); - if(lstat(name, &sbuf) == -1){ - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - return FALSE; - } - if(lstat(docsname, &sbuf) != -1 && !crremove(docsname)) return FALSE; - if(lstat(indexname, &sbuf) != -1 && !crremove(indexname)) return FALSE; - if(lstat(rdocsname, &sbuf) != -1 && !vlremove(rdocsname)) return FALSE; - if((list = cbdirlist(name)) != NULL){ - for(i = 0; i < cblistnum(list); i++){ - file = cblistval(list, i, NULL); - if(!strcmp(file, MYCDIRSTR) || !strcmp(file, MYPDIRSTR)) continue; - sprintf(path, "%s%c%s", name, MYPATHCHR, file); - if(lstat(path, &sbuf) == -1) continue; - if(S_ISDIR(sbuf.st_mode)){ - if(!crremove(path)) return FALSE; - } else { - if(!dpremove(path)) return FALSE; - } - } - cblistclose(list); - } - if(rmdir(name) == -1){ - dpecodeset(DP_ERMDIR, __FILE__, __LINE__); - return FALSE; - } - return TRUE; -} - - -/* Get a document handle. */ -ODDOC *oddocopen(const char *uri){ - ODDOC *doc; - assert(uri); - doc = cbmalloc(sizeof(ODDOC)); - doc->id = -1; - doc->uri = cbmemdup(uri, -1); - doc->attrs = cbmapopenex(OD_MAPPBNUM); - doc->nwords = cblistopen(); - doc->awords = cblistopen(); - return doc; -} - - -/* Close a document handle. */ -void oddocclose(ODDOC *doc){ - assert(doc); - cblistclose(doc->awords); - cblistclose(doc->nwords); - cbmapclose(doc->attrs); - free(doc->uri); - free(doc); -} - - -/* Add an attribute to a document. */ -void oddocaddattr(ODDOC *doc, const char *name, const char *value){ - assert(doc && name && value); - cbmapput(doc->attrs, name, -1, value, -1, TRUE); -} - - -/* Add a word to a document. */ -void oddocaddword(ODDOC *doc, const char *normal, const char *asis){ - assert(doc && normal && asis); - cblistpush(doc->nwords, normal, -1); - cblistpush(doc->awords, asis, -1); -} - - -/* Get the ID number of a document. */ -int oddocid(const ODDOC *doc){ - assert(doc); - return doc->id; -} - - -/* Get the URI of a document. */ -const char *oddocuri(const ODDOC *doc){ - assert(doc); - return doc->uri; -} - - -/* Get the value of an attribute of a document. */ -const char *oddocgetattr(const ODDOC *doc, const char *name){ - assert(doc && name); - return cbmapget(doc->attrs, name, -1, NULL); -} - - -/* Get the list handle contains words in normalized form of a document. */ -const CBLIST *oddocnwords(const ODDOC *doc){ - assert(doc); - return doc->nwords; -} - - -/* Get the list handle contains words in appearance form of a document. */ -const CBLIST *oddocawords(const ODDOC *doc){ - assert(doc); - return doc->awords; -} - - -/* Get the map handle contains keywords in normalized form and their scores. */ -CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum){ - const CBLIST *nwords; - CBMAP *map, *kwmap; - const char *word, *ctmp; - char numbuf[OD_NUMBUFSIZ]; - ODWORD *owords; - int i, wsiz, wnum, hnum, mnum, nbsiz; - double ival; - assert(doc && max >= 0); - map = cbmapopen(); - nwords = oddocnwords(doc); - for(i = 0; i < cblistnum(nwords); i++){ - word = cblistval(nwords, i, &wsiz); - if(wsiz < 1) continue; - if((ctmp = cbmapget(map, word, wsiz, NULL)) != NULL){ - wnum = *(int *)ctmp + OD_WOCCRPOINT; - } else { - wnum = OD_WOCCRPOINT; - } - cbmapput(map, word, wsiz, (char *)&wnum, sizeof(int), TRUE); - } - mnum = cbmaprnum(map); - owords = cbmalloc(mnum * sizeof(ODWORD) + 1); - cbmapiterinit(map); - for(i = 0; (word = cbmapiternext(map, &wsiz)) != NULL; i++){ - owords[i].word = word; - owords[i].num = *(int *)cbmapget(map, word, wsiz, NULL); - } - qsort(owords, mnum, sizeof(ODWORD), odwordcompare); - if(odeum){ - if(mnum > max * OD_KEYCRATIO) mnum = (int)(max * OD_KEYCRATIO); - for(i = 0; i < mnum; i++){ - if((hnum = odsearchdnum(odeum, owords[i].word)) < 0) hnum = 0; - ival = odlogarithm(hnum); - ival = (ival * ival * ival) / 8.0; - if(ival < 8.0) ival = 8.0; - owords[i].num = (int)(owords[i].num / ival); - } - qsort(owords, mnum, sizeof(ODWORD), odwordcompare); - } - if(mnum > max) mnum = max; - kwmap = cbmapopenex(OD_MAPPBNUM); - for(i = 0; i < mnum; i++){ - nbsiz = sprintf(numbuf, "%d", owords[i].num); - cbmapput(kwmap, owords[i].word, -1, numbuf, nbsiz, TRUE); - } - free(owords); - cbmapclose(map); - return kwmap; -} - - -/* Break a text into words in appearance form. */ -CBLIST *odbreaktext(const char *text){ - const char *word; - CBLIST *elems, *words; - int i, j, dif, wsiz, pv, delim; - assert(text); - words = cblistopen(); - elems = cbsplit(text, -1, OD_SPACECHARS); - for(i = 0; i < cblistnum(elems); i++){ - word = cblistval(elems, i, &wsiz); - delim = FALSE; - j = 0; - pv = 0; - while(TRUE){ - dif = j - pv; - if(j >= wsiz){ - if(dif > 0 && dif <= OD_MAXWORDLEN) cblistpush(words, word + pv, j - pv); - break; - } - if(delim){ - if(!strchr(OD_DELIMCHARS, word[j])){ - if(dif > 0 && dif <= OD_MAXWORDLEN) cblistpush(words, word + pv, j - pv); - pv = j; - delim = FALSE; - } - } else { - if(strchr(OD_DELIMCHARS, word[j])){ - if(dif > 0 && dif <= OD_MAXWORDLEN) cblistpush(words, word + pv, j - pv); - pv = j; - delim = TRUE; - } - } - j++; - } - } - cblistclose(elems); - return words; -} - - -/* Make the normalized form of a word. */ -char *odnormalizeword(const char *asis){ - char *nword; - int i; - assert(asis); - for(i = 0; asis[i] != '\0'; i++){ - if(!strchr(OD_DELIMCHARS, asis[i])) break; - } - if(asis[i] == '\0') return cbmemdup("", 0); - nword = cbmemdup(asis, -1); - for(i = 0; nword[i] != '\0'; i++){ - if(nword[i] >= 'A' && nword[i] <= 'Z') nword[i] += 'a' - 'A'; - } - while(i >= 0){ - if(strchr(OD_GLUECHARS, nword[i])){ - nword[i] = '\0'; - } else { - break; - } - i--; - } - return nword; -} - - -/* Get the common elements of two sets of documents. */ -ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np){ - CBMAP *map; - ODPAIR *result; - const char *tmp; - int i, rnum; - assert(apairs && anum >= 0 && bpairs && bnum >= 0); - map = odpairsmap(bpairs, bnum); - result = cbmalloc(sizeof(ODPAIR) * anum + 1); - rnum = 0; - for(i = 0; i < anum; i++){ - if(!(tmp = cbmapget(map, (char *)&(apairs[i].id), sizeof(int), NULL))) continue; - result[rnum].id = apairs[i].id; - result[rnum].score = apairs[i].score + *(int *)tmp; - rnum++; - } - cbmapclose(map); - qsort(result, rnum, sizeof(ODPAIR), odsortcompare); - *np = rnum; - return result; -} - - -/* Get the sum of elements of two sets of documents. */ -ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np){ - CBMAP *map; - ODPAIR *result; - const char *tmp; - int i, score, rnum; - assert(apairs && anum >= 0 && bpairs && bnum >= 0); - map = odpairsmap(bpairs, bnum); - for(i = 0; i < anum; i++){ - score = 0; - if((tmp = cbmapget(map, (char *)&(apairs[i].id), sizeof(int), NULL)) != NULL) - score = *(int *)tmp; - score += apairs[i].score; - cbmapput(map, (char *)&(apairs[i].id), sizeof(int), - (char *)&score, sizeof(int), TRUE); - } - rnum = cbmaprnum(map); - result = cbmalloc(rnum * sizeof(ODPAIR) + 1); - cbmapiterinit(map); - for(i = 0; (tmp = cbmapiternext(map, NULL)) != NULL; i++){ - result[i].id = *(int *)tmp; - result[i].score = *(int *)cbmapget(map, tmp, sizeof(int), NULL); - } - cbmapclose(map); - qsort(result, rnum, sizeof(ODPAIR), odsortcompare); - *np = rnum; - return result; -} - - -/* Get the difference set of documents. */ -ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np){ - CBMAP *map; - ODPAIR *result; - const char *tmp; - int i, rnum; - assert(apairs && anum >= 0 && bpairs && bnum >= 0); - map = odpairsmap(bpairs, bnum); - result = cbmalloc(sizeof(ODPAIR) * anum + 1); - rnum = 0; - for(i = 0; i < anum; i++){ - if((tmp = cbmapget(map, (char *)&(apairs[i].id), sizeof(int), NULL)) != NULL) continue; - result[rnum].id = apairs[i].id; - result[rnum].score = apairs[i].score; - rnum++; - } - cbmapclose(map); - qsort(result, rnum, sizeof(ODPAIR), odsortcompare); - *np = rnum; - return result; -} - - -/* Sort a set of documents in descending order of scores. */ -void odpairssort(ODPAIR *pairs, int pnum){ - assert(pairs && pnum >= 0); - qsort(pairs, pnum, sizeof(ODPAIR), odsortcompare); -} - - -/* Get the natural logarithm of a number. */ -double odlogarithm(double x){ - int i; - if(x <= 1.0) return 0.0; - x = x * x * x * x * x * x * x * x * x * x; - for(i = 0; x > 1.0; i++){ - x /= 2.718281828459; - } - return (double)i / 10.0; -} - - -/* Get the cosine of the angle of two vectors. */ -double odvectorcosine(const int *avec, const int *bvec, int vnum){ - double rv; - assert(avec && bvec && vnum >= 0); - rv = odvecinnerproduct(avec, bvec, vnum) / - ((odvecabsolute(avec, vnum) * odvecabsolute(bvec, vnum))); - return rv > 0.0 ? rv : 0.0; -} - - -/* Set the global tuning parameters. */ -void odsettuning(int ibnum, int idnum, int cbnum, int csiz){ - if(ibnum > 0) odindexbnum = ibnum; - if(idnum > 0) odindexdnum = idnum; - if(cbnum > 0) odcachebnum = dpprimenum(cbnum); - if(csiz > 0) odcachesiz = csiz; -} - - -/* Break a text into words and store appearance forms and normalized form into lists. */ -void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords){ - char aword[OD_MAXWORDLEN+1], *wp; - int lev, wsiz; - assert(odeum && text && awords); - lev = OD_EVSPACE; - wsiz = 0; - for(; *text != '\0'; text++){ - switch(odeum->statechars[*(unsigned char *)text]){ - case OD_EVWORD: - if(wsiz > 0 && lev == OD_EVDELIM){ - cblistpush(awords, aword, wsiz); - if(nwords) cblistpush(nwords, "", 0); - wsiz = 0; - } - if(wsiz <= OD_MAXWORDLEN){ - aword[wsiz++] = *text; - } - lev = OD_EVWORD; - break; - case OD_EVGLUE: - if(wsiz > 0 && lev == OD_EVDELIM){ - cblistpush(awords, aword, wsiz); - if(nwords) cblistpush(nwords, "", 0); - wsiz = 0; - } - if(wsiz <= OD_MAXWORDLEN){ - aword[wsiz++] = *text; - } - lev = OD_EVGLUE; - break; - case OD_EVDELIM: - if(wsiz > 0 && lev != OD_EVDELIM){ - cblistpush(awords, aword, wsiz); - if(nwords){ - wp = aword; - aword[wsiz] = '\0'; - while(*wp != '\0'){ - if(*wp >= 'A' && *wp <= 'Z') *wp += 'a' - 'A'; - wp++; - } - wp--; - while(wp >= aword && odeum->statechars[*(unsigned char *)wp] == OD_EVGLUE){ - wsiz--; - wp--; - } - cblistpush(nwords, aword, wsiz); - } - wsiz = 0; - } - if(wsiz <= OD_MAXWORDLEN){ - aword[wsiz++] = *text; - } - lev = OD_EVDELIM; - break; - default: - if(wsiz > 0){ - cblistpush(awords, aword, wsiz); - if(nwords){ - if(lev == OD_EVDELIM){ - cblistpush(nwords, "", 0); - } else { - wp = aword; - aword[wsiz] = '\0'; - while(*wp != '\0'){ - if(*wp >= 'A' && *wp <= 'Z') *wp += 'a' - 'A'; - wp++; - } - wp--; - while(wp >= aword && odeum->statechars[*(unsigned char *)wp] == OD_EVGLUE){ - wsiz--; - wp--; - } - cblistpush(nwords, aword, wsiz); - } - } - wsiz = 0; - } - lev = OD_EVSPACE; - break; - } - } - if(wsiz > 0){ - cblistpush(awords, aword, wsiz); - if(nwords){ - if(lev == OD_EVDELIM){ - cblistpush(nwords, "", 0); - } else { - wp = aword; - aword[wsiz] = '\0'; - while(*wp != '\0'){ - if(*wp >= 'A' && *wp <= 'Z') *wp += 'a' - 'A'; - wp++; - } - wp--; - while(wp >= aword && odeum->statechars[*(unsigned char *)wp] == OD_EVGLUE){ - wsiz--; - wp--; - } - cblistpush(nwords, aword, wsiz); - } - } - wsiz = 0; - } -} - - -/* Set the classes of characters used by `odanalyzetext'. */ -void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, - const char *gluechars){ - assert(odeum && spacechars && delimchars && gluechars); - memset(odeum->statechars, OD_EVWORD, sizeof(odeum->statechars)); - for(; *spacechars != '\0'; spacechars++){ - odeum->statechars[*(unsigned char *)spacechars] = OD_EVSPACE; - } - for(; *delimchars != '\0'; delimchars++){ - odeum->statechars[*(unsigned char *)delimchars] = OD_EVDELIM; - } - for(; *gluechars != '\0'; gluechars++){ - odeum->statechars[*(unsigned char *)gluechars] = OD_EVGLUE; - } -} - - -/* Query a database using a small boolean query language. */ -ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors){ - CBLIST *tokens = cblistopen(); - CBLIST *nwords = cblistopen(); - ODPAIR *results = NULL; - assert(odeum && query && np); - odanalyzetext(odeum, query, tokens, nwords); - odcleannormalized(odeum, nwords); - odfixtokens(odeum, tokens); - results = odparseexpr(odeum, tokens, nwords, np, errors); - cblistclose(tokens); - cblistclose(nwords); - return results; -} - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Get the internal database handle for documents. */ -CURIA *odidbdocs(ODEUM *odeum){ - assert(odeum); - return odeum->docsdb; -} - - -/* Get the internal database handle for the inverted index. */ -CURIA *odidbindex(ODEUM *odeum){ - assert(odeum); - return odeum->indexdb; -} - - -/* Get the internal database handle for the reverse dictionary. */ -VILLA *odidbrdocs(ODEUM *odeum){ - assert(odeum); - return odeum->rdocsdb; -} - - -/* Set the call back function called in merging. */ -void odsetotcb(void (*otcb)(const char *, ODEUM *, const char *)){ - odotcb = otcb; -} - - -/* Get the positive one of square roots of a number. */ -double odsquareroot(double x){ - double c, rv; - if(x <= 0.0) return 0.0; - c = x > 1.0 ? x : 1; - do { - rv = c; - c = (x / c + c) * 0.5; - } while(c < rv); - return rv; -} - - -/* Get the absolute of a vector. */ -double odvecabsolute(const int *vec, int vnum){ - double rv; - int i; - assert(vec && vnum >= 0); - rv = 0; - for(i = 0; i < vnum; i++){ - rv += (double)vec[i] * (double)vec[i]; - } - return odsquareroot(rv); -} - - -/* Get the inner product of two vectors. */ -double odvecinnerproduct(const int *avec, const int *bvec, int vnum){ - double rv; - int i; - assert(avec && bvec && vnum >= 0); - rv = 0; - for(i = 0; i < vnum; i++){ - rv += (double)avec[i] * (double)bvec[i]; - } - return rv; -} - - - -/************************************************************************************************* - * private objects - *************************************************************************************************/ - - -/* Get a database handle. - `name' specifies the name of a database directory. - `omode' specifies the connection mode. - `docsbnum` specifies the number of buckets of the document database. - `indexbnum` specifies the number of buckets of the index database. - `fname' specifies the name of caller function. - The return value is the database handle or `NULL' if it is not successful. */ -static ODEUM *odopendb(const char *name, int omode, int docsbnum, int indexbnum, - const char *fname){ - int cromode, vlomode, inode, dmax, dnum; - char docsname[OD_PATHBUFSIZ], indexname[OD_PATHBUFSIZ], rdocsname[OD_PATHBUFSIZ], *tmp; - struct stat sbuf; - CURIA *docsdb, *indexdb; - VILLA *rdocsdb; - CBMAP *cachemap; - CBMAP *sortmap; - ODEUM *odeum; - assert(name); - if(strlen(name) > OD_NAMEMAX){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return NULL; - } - cromode = CR_OREADER; - vlomode = VL_OREADER; - if(omode & OD_OWRITER){ - cromode = CR_OWRITER; - vlomode = VL_OWRITER | VL_OZCOMP | VL_OYCOMP; - if(omode & OD_OCREAT){ - cromode |= CR_OCREAT; - vlomode |= VL_OCREAT; - } - if(omode & OD_OTRUNC){ - cromode |= CR_OTRUNC; - vlomode |= VL_OTRUNC; - } - } - if(omode & OD_ONOLCK){ - cromode |= CR_ONOLCK; - vlomode |= VL_ONOLCK; - } - if(omode & OD_OLCKNB){ - cromode |= CR_OLCKNB; - vlomode |= VL_OLCKNB; - } - sprintf(docsname, "%s%c%s", name, MYPATHCHR, OD_DOCSNAME); - sprintf(indexname, "%s%c%s", name, MYPATHCHR, OD_INDEXNAME); - sprintf(rdocsname, "%s%c%s", name, MYPATHCHR, OD_RDOCSNAME); - docsdb = NULL; - indexdb = NULL; - rdocsdb = NULL; - if((omode & OD_OWRITER) && (omode & OD_OCREAT)){ - if(mkdir(name, OD_DIRMODE) == -1 && errno != EEXIST){ - dpecodeset(DP_EMKDIR, __FILE__, __LINE__); - return NULL; - } - } - if(lstat(name, &sbuf) == -1){ - dpecodeset(DP_ESTAT, __FILE__, __LINE__); - return NULL; - } - inode = sbuf.st_ino; - if(!(docsdb = cropen(docsname, cromode, docsbnum, OD_DOCSDNUM))) return NULL; - if(!(indexdb = cropen(indexname, cromode, indexbnum, odindexdnum))){ - crclose(docsdb); - return NULL; - } - if(omode & OD_OWRITER){ - if(!crsetalign(docsdb, OD_DOCSALIGN) || !crsetfbpsiz(docsdb, OD_DOCSFBP) || - !crsetalign(indexdb, OD_INDEXALIGN) || !crsetfbpsiz(indexdb, OD_INDEXFBP)){ - crclose(indexdb); - crclose(docsdb); - return NULL; - } - } - if(!(rdocsdb = vlopen(rdocsname, vlomode, VL_CMPLEX))){ - crclose(indexdb); - crclose(docsdb); - return NULL; - } - vlsettuning(rdocsdb, OD_RDOCSLRM, OD_RDOCSNIM, OD_RDOCSLCN, OD_RDOCSNCN); - if(omode & OD_OWRITER){ - cachemap = cbmapopenex(odcachebnum); - sortmap = cbmapopenex(odcachebnum); - } else { - cachemap = NULL; - sortmap = NULL; - } - if(vlrnum(rdocsdb) > 0){ - dmax = -1; - dnum = -1; - if((tmp = vlget(rdocsdb, OD_DMAXEXPR, sizeof(OD_DMAXEXPR), NULL)) != NULL){ - dmax = atoi(tmp); - free(tmp); - } - if((tmp = vlget(rdocsdb, OD_DNUMEXPR, sizeof(OD_DNUMEXPR), NULL)) != NULL){ - dnum = atoi(tmp); - free(tmp); - } - if(dmax < 0 || dnum < 0){ - if(sortmap) cbmapclose(sortmap); - if(cachemap) cbmapclose(cachemap); - vlclose(rdocsdb); - crclose(indexdb); - crclose(docsdb); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - } else { - dmax = 0; - dnum = 0; - } - odeum = cbmalloc(sizeof(ODEUM)); - odeum->name = cbmemdup(name, -1); - odeum->wmode = omode & OD_OWRITER; - odeum->fatal = FALSE; - odeum->inode = inode; - odeum->docsdb = docsdb; - odeum->indexdb = indexdb; - odeum->rdocsdb = rdocsdb; - odeum->cachemap = cachemap; - odeum->cacheasiz = 0; - odeum->sortmap = sortmap; - odeum->dmax = dmax; - odeum->dnum = dnum; - odeum->ldid = -1; - odsetcharclass(odeum, OD_SPACECHARS, OD_DELIMCHARS, OD_GLUECHARS); - if(odotcb) odotcb(fname, odeum, "the connection was established"); - return odeum; -} - - -/* Flush the cache for dirty buffer of words. - `odeum' specifies a database handle. - `fname' specifies the name of caller function. - If successful, the return value is true, else, it is false. */ -static int odcacheflush(ODEUM *odeum, const char *fname){ - const char *kbuf, *vbuf; - char otmsg[OD_OTCBBUFSIZ]; - int i, rnum, ksiz, vsiz; - assert(odeum); - if((rnum = cbmaprnum(odeum->cachemap)) < 1) return TRUE; - if(odotcb) odotcb(fname, odeum, "flushing caches"); - cbmapiterinit(odeum->cachemap); - for(i = 0; (kbuf = cbmapiternext(odeum->cachemap, &ksiz)) != NULL; i++){ - vbuf = cbmapget(odeum->cachemap, kbuf, ksiz, &vsiz); - if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, vsiz, CR_DCAT)){ - odeum->fatal = TRUE; - return FALSE; - } - if(odotcb && (i + 1) % OD_OTPERWORDS == 0){ - sprintf(otmsg, "... (%d/%d)", i + 1, rnum); - odotcb(fname, odeum, otmsg); - } - } - cbmapclose(odeum->cachemap); - odeum->cachemap = cbmapopenex(odcachebnum); - odeum->cacheasiz = 0; - return TRUE; -} - - -/* Flush all frequent words in the cache for dirty buffer of words. - `odeum' specifies a database handle. - `fname' specifies the name of caller function. - `min' specifies the minimum size of frequent words. - If successful, the return value is true, else, it is false. */ -static int odcacheflushfreq(ODEUM *odeum, const char *fname, int min){ - const char *kbuf, *vbuf; - char otmsg[OD_OTCBBUFSIZ]; - int rnum, ksiz, vsiz; - assert(odeum); - if((rnum = cbmaprnum(odeum->cachemap)) < 1) return TRUE; - if(odotcb){ - sprintf(otmsg, "flushing frequent words: min=%d asiz=%d rnum=%d)", - min, odeum->cacheasiz, rnum); - odotcb(fname, odeum, otmsg); - } - cbmapiterinit(odeum->cachemap); - while((kbuf = cbmapiternext(odeum->cachemap, &ksiz)) != NULL){ - vbuf = cbmapget(odeum->cachemap, kbuf, ksiz, &vsiz); - if(vsiz >= sizeof(ODPAIR) * min){ - if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, vsiz, CR_DCAT)){ - odeum->fatal = TRUE; - return FALSE; - } - cbmapout(odeum->cachemap, kbuf, ksiz); - odeum->cacheasiz -= vsiz; - } - } - if(odotcb){ - sprintf(otmsg, "... (done): min=%d asiz=%d rnum=%d)", - min, odeum->cacheasiz, cbmaprnum(odeum->cachemap)); - odotcb(fname, odeum, otmsg); - } - return TRUE; -} - - -/* Flush the half of rare words in the cache for dirty buffer of words. - `odeum' specifies a database handle. - `fname' specifies the name of caller function. - `ratio' specifies the ratio of rare words. - If successful, the return value is true, else, it is false. */ -static int odcacheflushrare(ODEUM *odeum, const char *fname, double ratio){ - const char *kbuf, *vbuf; - char otmsg[OD_OTCBBUFSIZ]; - int i, rnum, limit, ksiz, vsiz; - assert(odeum); - if((rnum = cbmaprnum(odeum->cachemap)) < 1) return TRUE; - if(odotcb){ - sprintf(otmsg, "flushing rare words: ratio=%.2f asiz=%d rnum=%d)", - ratio, odeum->cacheasiz, rnum); - odotcb(fname, odeum, otmsg); - } - cbmapiterinit(odeum->cachemap); - limit = (int)(rnum * ratio); - for(i = 0; i < limit && (kbuf = cbmapiternext(odeum->cachemap, &ksiz)) != NULL; i++){ - vbuf = cbmapget(odeum->cachemap, kbuf, ksiz, &vsiz); - if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, vsiz, CR_DCAT)){ - odeum->fatal = TRUE; - return FALSE; - } - cbmapout(odeum->cachemap, kbuf, ksiz); - odeum->cacheasiz -= vsiz; - } - if(odotcb){ - sprintf(otmsg, "... (done): ratio=%.2f asiz=%d rnum=%d)", - ratio, odeum->cacheasiz, cbmaprnum(odeum->cachemap)); - odotcb(fname, odeum, otmsg); - } - return TRUE; -} - - -/* Sort the records of inverted index. - `odeum' specifies a database handle. - `fname' specifies the name of caller function. - If successful, the return value is true, else, it is false. */ -static int odsortindex(ODEUM *odeum, const char *fname){ - const char *word; - char *tmp, otmsg[OD_OTCBBUFSIZ]; - int i, rnum, wsiz, tsiz; - ODPAIR *pairs; - assert(odeum); - if((rnum = cbmaprnum(odeum->sortmap)) < 1) return TRUE; - if(odotcb) odotcb(fname, odeum, "sorting the inverted index"); - cbmapiterinit(odeum->sortmap); - for(i = 0; (word = cbmapiternext(odeum->sortmap, &wsiz)) != NULL; i++){ - if((tmp = crget(odeum->indexdb, word, wsiz, 0, -1, &tsiz)) != NULL){ - if(tsiz > sizeof(ODPAIR)){ - pairs = (ODPAIR *)tmp; - qsort(pairs, tsiz / sizeof(ODPAIR), sizeof(ODPAIR), odsortcompare); - if(!crput(odeum->indexdb, word, wsiz, tmp, tsiz, CR_DOVER)){ - free(tmp); - return FALSE; - } - } - free(tmp); - } else if(dpecode != DP_ENOITEM){ - return FALSE; - } - if(odotcb && (i + 1) % OD_OTPERWORDS == 0){ - sprintf(otmsg, "... (%d/%d)", i + 1, rnum); - odotcb(fname, odeum, otmsg); - } - } - cbmapclose(odeum->sortmap); - odeum->sortmap = cbmapopenex(odcachebnum); - return TRUE; -} - - -/* Compare two pairs of structures of a search result. - `a' specifies the pointer to the region of one pair. - `b' specifies the pointer to the region of the other pair. - The return value is positive if the former is big, negative if the latter is big, 0 if both - are equivalent. */ -static int odsortcompare(const void *a, const void *b){ - ODPAIR *ap, *bp; - int rv; - assert(a && b); - ap = (ODPAIR *)a; - bp = (ODPAIR *)b; - rv = bp->score - ap->score; - if(rv != 0) return rv; - return ap->id - bp->id; -} - - -/* Purge the elements of the deleted documents from the inverted index. - `odeum' specifies a database handle. - `fname' specifies the name of caller function. - If successful, the return value is true, else, it is false. */ -static int odpurgeindex(ODEUM *odeum, const char *fname){ - ODPAIR *pairs; - char *kbuf, *vbuf, otmsg[OD_OTCBBUFSIZ]; - int i, rnum, tnum, ksiz, vsiz, pnum, wi; - assert(odeum); - if((rnum = crrnum(odeum->indexdb)) < 1) return TRUE; - if(odotcb) odotcb(fname, odeum, "purging dispensable regions"); - if(!criterinit(odeum->indexdb)) return FALSE; - tnum = 0; - while(TRUE){ - if(!(kbuf = criternext(odeum->indexdb, &ksiz))){ - if(dpecode != DP_ENOITEM) return FALSE; - break; - } - if(!(vbuf = crget(odeum->indexdb, kbuf, ksiz, 0, -1, &vsiz))){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - free(kbuf); - return FALSE; - } - pairs = (ODPAIR *)vbuf; - pnum = vsiz / sizeof(ODPAIR); - wi = 0; - for(i = 0; i < pnum; i++){ - if(crvsiz(odeum->docsdb, (char *)&(pairs[i].id), sizeof(int)) != -1){ - pairs[wi++] = pairs[i]; - } - } - if(wi > 0){ - if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, wi * sizeof(ODPAIR), CR_DOVER)){ - free(vbuf); - free(kbuf); - return FALSE; - } - } else { - if(!crout(odeum->indexdb, kbuf, ksiz)){ - free(vbuf); - free(kbuf); - return FALSE; - } - } - free(vbuf); - free(kbuf); - if(odotcb && (tnum + 1) % OD_OTPERWORDS == 0){ - sprintf(otmsg, "... (%d/%d)", tnum + 1, rnum); - odotcb(fname, odeum, otmsg); - } - tnum++; - } - return TRUE; -} - - -/* Create a map of a document array. - `pairs' specifies the pointer to a document array. - `num' specifies the number of elements of the array. - The return value is a map of the document array. */ -static CBMAP *odpairsmap(const ODPAIR *pairs, int num){ - CBMAP *map; - int i; - assert(pairs && num >= 0); - map = cbmapopen(); - for(i = 0; i < num; i++){ - cbmapput(map, (char *)&(pairs[i].id), sizeof(int), - (char *)&(pairs[i].score), sizeof(int), TRUE); - } - return map; -} - - -/* compare two pairs of structures of words in a document. - `a' specifies the pointer to the region of one word. - `b' specifies the pointer to the region of the other word. - The return value is positive if the former is big, negative if the latter is big, 0 if both - are equivalent. */ -static int odwordcompare(const void *a, const void *b){ - ODWORD *ap, *bp; - int rv; - assert(a && b); - ap = (ODWORD *)a; - bp = (ODWORD *)b; - if((rv = bp->num - ap->num) != 0) return rv; - if((rv = strlen(bp->word) - strlen(ap->word)) != 0) return rv; - return strcmp(ap->word, bp->word); -} - - -/* Match an operator without taking it off the token list. - `odeum' specifies a database handle. - `tokens' specifies a list handle of tokens. - The return value is whether the next token is an operator. */ -static int odmatchoperator(ODEUM *odeum, CBLIST *tokens){ - const char *tk = NULL; - int tk_len = 0; - tk = cblistval(tokens, 0, &tk_len); - if(tk && (tk[0] == '&' || tk[0] == '|' || tk[0] == '!')) return 1; - return 0; -} - - -/* Implements the subexpr part of the grammar. - `odeum' specifies a database handle. - `tokens' specifies a list handle of tokens. - `nwords' specifies a list handle of normalized words. - `np' specifies the pointer to a variable to which the number of the elements of the return - value is assigned. - `errors' specifies a list handle into which error messages are stored. - The return value is the pointer to an array of document IDs. */ -static ODPAIR *odparsesubexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, - CBLIST *errors){ - char *tk = NULL; - int tk_len = 0; - char *nword = NULL; /* used to do the actual search, should match with tokens */ - ODPAIR *result = NULL; - int result_num = 0; - int i; - double ival; - if((tk = cblistshift(tokens, &tk_len)) != NULL){ - assert(tk != NULL); - if(tk[0] == '('){ - free(tk); - /* recurse into expr */ - result = odparseexpr(odeum, tokens, nwords, &result_num, errors); - /* match right token RPAREN */ - tk = cblistshift(tokens, &tk_len); - /* print an error if either we didn't get anything or we didn't get a ) */ - if(tk == NULL){ - if(errors) cblistpush(errors, "Expression ended without closing ')'", -1); - } else if(tk[0] != ')'){ - if(errors) cblistpush(errors, "Un-balanced parenthesis.", -1); - } - } else if(odeum->statechars[*(unsigned char *)tk] == 0){ - /* Perform odsearch with the next norm word that isn't an operator. */ - nword = cblistshift(nwords, NULL); - assert(nword != NULL); - if((result = odsearch(odeum, nword, -1, &result_num)) != NULL){ - /* TF-IDF tuning */ - ival = odlogarithm(result_num); - ival = (ival * ival) / 4.0; - if(ival < 4.0) ival = 4.0; - for(i = 0; i < result_num; i++){ - result[i].score = (int)(result[i].score / ival); - } - } - free(nword); - } else { - if(errors) cblistpush(errors, "Invalid sub-expression. Expected '(' or WORD.", -1); - result = cbmalloc(1); - result_num = 0; - } - /* done with the token */ - free(tk); - } - *np = result_num; - return result; -} - - -/* Implements the actual recursive decent parser for the mini query language. - `odeum' specifies a database handle. - `tokens' specifies a list handle of tokens. - `nwords' specifies a list handle of normalized words. - `np' specifies the pointer to a variable to which the number of the elements of the return - value is assigned. - `errors' specifies a list handle into which error messages are stored. - The return value is the pointer to an array of document IDs. - It simply parses an initial subexpr, and then loops over as many (operator subexpr) - sequences as it can find. The odmatchoperator function handles injecting a default & - between consecutive words. */ -static ODPAIR *odparseexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, - CBLIST *errors){ - ODPAIR *left = NULL; - ODPAIR *right = NULL; - ODPAIR *temp = NULL; - int left_num = 0; - int right_num = 0; - int temp_num = 0; - char *op = NULL; - int op_len = 0; - if(!(left = odparsesubexpr(odeum, tokens, nwords, &left_num, errors))) return NULL; - /* expr ::= subexpr ( op subexpr )* */ - while(odmatchoperator(odeum, tokens)){ - op = cblistshift(tokens, &op_len); - if(!(right = odparsesubexpr(odeum, tokens, nwords, &right_num, errors))){ - free(op); - free(left); - return NULL; - } - switch(op[0]){ - case '&': - temp = odpairsand(left, left_num, right, right_num, &temp_num); - break; - case '|': - temp = odpairsor(left, left_num, right, right_num, &temp_num); - break; - case '!': - temp = odpairsnotand(left, left_num, right, right_num, &temp_num); - break; - default: - if(errors) cblistpush(errors, "Invalid operator. Expected '&', '|', or '!'.", -1); - break; - } - if(temp){ - /* an operator was done so we must swap it with the left */ - free(left); left = NULL; - left = temp; - left_num = temp_num; - } - free(op); - if(right) free(right); - } - *np = left_num; - return left; -} - - -/* Processes the tokens in order to break them up further. - `odeum' specifies a database handle. - `tokens' specifies a list handle of tokens. */ -static void odfixtokens(ODEUM *odeum, CBLIST *tokens){ - const char *tk = NULL; - int tk_len = 0; - int i = 0; - int lastword = 0; - for(i = 0; i < cblistnum(tokens); i++){ - tk = cblistval(tokens, i, &tk_len); - assert(tk); - if(tk[0] == '&' || tk[0] == '|' || tk[0] == '!' || tk[0] == '(' || tk[0] == ')'){ - lastword = 0; - if(tk_len > 1){ - /* need to break it up for the next loop around */ - tk = cblistremove(tokens, i, &tk_len); - cblistinsert(tokens, i, tk, 1); - cblistinsert(tokens, i+1, tk+1, tk_len-1); - free((char *)tk); - } - } else if(odeum->statechars[*(unsigned char *)tk] == 0){ - /* if the last one was a word and this is a word then we need a default & between them */ - if(lastword){ - cblistinsert(tokens, i, "&", 1); - i++; - } - lastword = 1; - } - } -} - - -/* Cleans out the parts of the normalized word list that are not considered words. - `odeum' specifies a database handle. - `tokens' specifies a list handle of tokens. */ -static void odcleannormalized(ODEUM *odeum, CBLIST *nwords){ - char *tk = NULL; - int tk_len = 0; - int i = 0; - for(i = 0; i < cblistnum(nwords); i++){ - tk = (char *)cblistval(nwords, i, &tk_len); - if(tk_len == 0 || (!odeum->statechars[*(unsigned char *)tk] == 0)){ - /* not a word so delete it */ - tk = cblistremove(nwords, i, &tk_len); - free(tk); - i--; - } - } -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/odeum.c (from rev 2716, box/trunk/qdbm/odeum.c) =================================================================== --- box/trunk/qdbm/odeum.c (rev 0) +++ box/trunk/qdbm/odeum.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,2090 @@ +/************************************************************************************************* + * Implementation of Odeum + * 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. + *************************************************************************************************/ + + +#define QDBM_INTERNAL 1 + +#include "odeum.h" +#include "myconf.h" + +#define OD_NAMEMAX 256 /* max size of a database name */ +#define OD_DIRMODE 00755 /* permission of a creating directory */ +#define OD_PATHBUFSIZ 1024 /* size of a path buffer */ +#define OD_NUMBUFSIZ 32 /* size of a buffer for a number */ +#define OD_MAPPBNUM 127 /* bucket size of a petit map handle */ +#define OD_DOCSNAME "docs" /* name of the database for documents */ +#define OD_INDEXNAME "index" /* name of the database for inverted index */ +#define OD_RDOCSNAME "rdocs" /* name of the database for reverse dictionary */ +#define OD_DOCSBNUM 2039 /* initial bucket number of document database */ +#define OD_DOCSDNUM 17 /* division number of document database */ +#define OD_DOCSALIGN -4 /* alignment of document database */ +#define OD_DOCSFBP 32 /* size of free block pool of document database */ +#define OD_INDEXBNUM 32749 /* initial bucket number of inverted index */ +#define OD_INDEXDNUM 7 /* division number of inverted index */ +#define OD_INDEXALIGN -2 /* alignment of inverted index */ +#define OD_INDEXFBP 32 /* size of free block pool of inverted index */ +#define OD_RDOCSLRM 81 /* records in a leaf node of reverse dictionary */ +#define OD_RDOCSNIM 192 /* records in a non-leaf node of reverse dictionary */ +#define OD_RDOCSLCN 128 /* number of leaf cache of reverse dictionary */ +#define OD_RDOCSNCN 32 /* number of non-leaf cache of reverse dictionary */ +#define OD_CACHEBNUM 262139 /* number of buckets for dirty buffers */ +#define OD_CACHESIZ 8388608 /* max bytes to use memory for dirty buffers */ +#define OD_CFLIVERAT 0.8 /* ratio of usable cache region */ +#define OD_CFBEGSIZ 2048 /* beginning size of flushing frequent words */ +#define OD_CFENDSIZ 64 /* lower limit of flushing frequent words */ +#define OD_CFRFRAT 0.2 /* ratio of flushing rare words a time */ +#define OD_OTCBBUFSIZ 1024 /* size of a buffer for call back functions */ +#define OD_OTPERWORDS 10000 /* frequency of call back in merging index */ +#define OD_OTPERDOCS 1000 /* frequency of call back in merging docs */ +#define OD_MDBRATIO 2.5 /* ratio of bucket number and document number */ +#define OD_MIBRATIO 1.5 /* ratio of bucket number and word number */ +#define OD_MIARATIO 0.75 /* ratio of alignment to the first words */ +#define OD_MIWUNIT 32 /* writing unit of merging inverted index */ +#define OD_DMAXEXPR "dmax" /* key of max number of the document ID */ +#define OD_DNUMEXPR "dnum" /* key of number of the documents */ +#define OD_URIEXPR "1" /* map key of URI */ +#define OD_ATTRSEXPR "2" /* map key of attributes */ +#define OD_NWORDSEXPR "3" /* map key of normal words */ +#define OD_AWORDSEXPR "4" /* map key of as-is words */ +#define OD_WTOPRATE 0.1 /* ratio of top words */ +#define OD_WTOPBONUS 5000 /* bonus points of top words */ +#define OD_KEYCRATIO 1.75 /* ratio of number to max of keyword candidates */ +#define OD_WOCCRPOINT 10000 /* points per occurence */ +#define OD_SPACECHARS "\t\n\v\f\r " /* space characters */ +#define OD_DELIMCHARS "!\"#$%&'()*/<=>?[\\]^`{|}~" /* delimiter characters */ +#define OD_GLUECHARS "+,-.:;@" /* glueing characters */ +#define OD_MAXWORDLEN 48 /* max length of a word */ + +typedef struct { /* type of structure for word counting */ + const char *word; /* pointer to the word */ + int num; /* frequency of the word */ +} ODWORD; + +enum { /* enumeration for events binded to each character */ + OD_EVWORD, /* word */ + OD_EVSPACE, /* space */ + OD_EVDELIM, /* delimiter */ + OD_EVGLUE /* glue */ +}; + + +/* private global variables */ +int odindexbnum = OD_INDEXBNUM; +int odindexdnum = OD_INDEXDNUM; +int odcachebnum = OD_CACHEBNUM; +int odcachesiz = OD_CACHESIZ; +void (*odotcb)(const char *, ODEUM *, const char *) = NULL; + + +/* private function prototypes */ +static ODEUM *odopendb(const char *name, int omode, int docsbnum, int indexbnum, + const char *fname); +static int odcacheflush(ODEUM *odeum, const char *fname); +static int odcacheflushfreq(ODEUM *odeum, const char *fname, int min); +static int odcacheflushrare(ODEUM *odeum, const char *fname, double ratio); +static int odsortindex(ODEUM *odeum, const char *fname); +static int odsortcompare(const void *a, const void *b); +static int odpurgeindex(ODEUM *odeum, const char *fname); +static CBMAP *odpairsmap(const ODPAIR *pairs, int num); +static int odwordcompare(const void *a, const void *b); +static int odmatchoperator(ODEUM *odeum, CBLIST *tokens); +static ODPAIR *odparsesubexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, + CBLIST *errors); +static ODPAIR *odparseexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, + CBLIST *errors); +static void odfixtokens(ODEUM *odeum, CBLIST *tokens); +static void odcleannormalized(ODEUM *odeum, CBLIST *nwords); + + + +/************************************************************************************************* + * public objects + *************************************************************************************************/ + + +/* Get a database handle. */ +ODEUM *odopen(const char *name, int omode){ + assert(name); + return odopendb(name, omode, OD_DOCSBNUM, odindexbnum, "odopen"); +} + + +/* Close a database handle. */ +int odclose(ODEUM *odeum){ + char numbuf[OD_NUMBUFSIZ]; + int err; + assert(odeum); + err = FALSE; + if(odotcb) odotcb("odclose", odeum, "closing the connection"); + if(odeum->wmode){ + if(odotcb) odotcb("odclose", odeum, "writing meta information"); + sprintf(numbuf, "%d", odeum->dmax); + if(!vlput(odeum->rdocsdb, OD_DMAXEXPR, sizeof(OD_DMAXEXPR), numbuf, -1, VL_DOVER)) err = TRUE; + sprintf(numbuf, "%d", odeum->dnum); + if(!vlput(odeum->rdocsdb, OD_DNUMEXPR, sizeof(OD_DNUMEXPR), numbuf, -1, VL_DOVER)) err = TRUE; + if(!odcacheflushfreq(odeum, "odclose", OD_CFENDSIZ)) err = TRUE; + if(!odcacheflushrare(odeum, "odclose", OD_CFRFRAT)) err = TRUE; + if(!odcacheflush(odeum, "odclose")) err = TRUE; + if(!odsortindex(odeum, "odclose")) err = TRUE; + cbmapclose(odeum->cachemap); + cbmapclose(odeum->sortmap); + } + if(!vlclose(odeum->rdocsdb)) err = TRUE; + if(!crclose(odeum->indexdb)) err = TRUE; + if(!crclose(odeum->docsdb)) err = TRUE; + free(odeum->name); + free(odeum); + return err ? FALSE : TRUE; +} + + +/* Store a document. */ +int odput(ODEUM *odeum, ODDOC *doc, int wmax, int over){ + char *tmp, *zbuf; + const char *word, *ctmp; + int i, docid, tsiz, wsiz, wnum, tmax, num, zsiz; + double ival; + ODPAIR pair; + CBMAP *map; + CBLIST *tlist; + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!odeum->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if((tmp = vlget(odeum->rdocsdb, doc->uri, -1, &tsiz)) != NULL){ + if(!over){ + free(tmp); + dpecodeset(DP_EKEEP, __FILE__, __LINE__); + return FALSE; + } + if(tsiz != sizeof(int) || !odoutbyid(odeum, *(int *)tmp)){ + free(tmp); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + odeum->fatal = TRUE; + return FALSE; + } + free(tmp); + } + odeum->dmax++; + odeum->dnum++; + docid = odeum->dmax; + map = cbmapopen(); + cbmapput(map, OD_URIEXPR, sizeof(OD_URIEXPR), doc->uri, -1, TRUE); + tmp = cbmapdump(doc->attrs, &tsiz); + cbmapput(map, OD_ATTRSEXPR, sizeof(OD_ATTRSEXPR), tmp, tsiz, TRUE); + free(tmp); + if(wmax < 0 || wmax > cblistnum(doc->nwords)) wmax = cblistnum(doc->nwords); + tlist = cblistopen(); + for(i = 0; i < wmax; i++){ + ctmp = cblistval(doc->nwords, i, &wsiz); + cblistpush(tlist, ctmp, wsiz); + } + tmp = cblistdump(tlist, &tsiz); + cbmapput(map, OD_NWORDSEXPR, sizeof(OD_NWORDSEXPR), tmp, tsiz, TRUE); + free(tmp); + cblistclose(tlist); + tlist = cblistopen(); + for(i = 0; i < wmax; i++){ + ctmp = cblistval(doc->awords, i, &wsiz); + if(strcmp(ctmp, cblistval(doc->nwords, i, NULL))){ + cblistpush(tlist, ctmp, wsiz); + } else { + cblistpush(tlist, "\0", 1); + } + } + tmp = cblistdump(tlist, &tsiz); + cbmapput(map, OD_AWORDSEXPR, sizeof(OD_AWORDSEXPR), tmp, tsiz, TRUE); + free(tmp); + cblistclose(tlist); + tmp = cbmapdump(map, &tsiz); + cbmapclose(map); + if(_qdbm_deflate){ + if(!(zbuf = _qdbm_deflate(tmp, tsiz, &zsiz, _QDBM_ZMRAW))){ + free(tmp); + dpecodeset(DP_EMISC, __FILE__, __LINE__); + odeum->fatal = TRUE; + return FALSE; + } + free(tmp); + tmp = zbuf; + tsiz = zsiz; + } + if(!crput(odeum->docsdb, (char *)&docid, sizeof(int), tmp, tsiz, CR_DKEEP)){ + free(tmp); + if(dpecode == DP_EKEEP) dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + odeum->fatal = TRUE; + return FALSE; + } + free(tmp); + if(!vlput(odeum->rdocsdb, doc->uri, -1, (char *)&docid, sizeof(int), VL_DOVER)){ + odeum->fatal = TRUE; + return FALSE; + } + map = cbmapopen(); + wnum = cblistnum(doc->nwords); + tmax = (int)(wnum * OD_WTOPRATE); + for(i = 0; i < wnum; i++){ + word = cblistval(doc->nwords, i, &wsiz); + if(wsiz < 1) continue; + if((ctmp = cbmapget(map, word, wsiz, NULL)) != NULL){ + num = *(int *)ctmp + OD_WOCCRPOINT; + } else { + num = i <= tmax ? OD_WTOPBONUS + OD_WOCCRPOINT : OD_WOCCRPOINT; + } + cbmapput(map, word, wsiz, (char *)&num, sizeof(int), TRUE); + } + ival = odlogarithm(wnum); + ival = (ival * ival * ival) / 8.0; + if(ival < 8.0) ival = 8.0; + cbmapiterinit(map); + while((word = cbmapiternext(map, &wsiz)) != NULL){ + pair.id = docid; + pair.score = (int)(*(int *)cbmapget(map, word, wsiz, NULL) / ival); + cbmapputcat(odeum->cachemap, word, wsiz, (char *)&pair, sizeof(pair)); + cbmapmove(odeum->cachemap, word, wsiz, FALSE); + odeum->cacheasiz += sizeof(pair); + cbmapput(odeum->sortmap, word, wsiz, "", 0, FALSE); + } + cbmapclose(map); + if(odeum->cacheasiz > odcachesiz){ + for(i = OD_CFBEGSIZ; odeum->cacheasiz > odcachesiz * OD_CFLIVERAT && i >= OD_CFENDSIZ; + i /= 2){ + if(!odcacheflushfreq(odeum, "odput", i)) return FALSE; + } + while(odeum->cacheasiz > odcachesiz * OD_CFLIVERAT){ + if(!odcacheflushrare(odeum, "odput", OD_CFRFRAT)) return FALSE; + } + } + doc->id = docid; + odeum->ldid = docid; + return TRUE; +} + + +/* Delete a document by a URL. */ +int odout(ODEUM *odeum, const char *uri){ + char *tmp; + int tsiz, docid; + assert(odeum && uri); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!odeum->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(!(tmp = vlget(odeum->rdocsdb, uri, -1, &tsiz))){ + if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; + return FALSE; + } + if(tsiz != sizeof(int)){ + free(tmp); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + odeum->fatal = TRUE; + return FALSE; + } + docid = *(int *)tmp; + free(tmp); + return odoutbyid(odeum, docid); +} + + +/* Delete a document specified by an ID number. */ +int odoutbyid(ODEUM *odeum, int id){ + char *tmp, *zbuf; + const char *uritmp; + int tsiz, uritsiz, zsiz; + CBMAP *map; + assert(odeum && id > 0); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!odeum->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(!(tmp = crget(odeum->docsdb, (char *)&id, sizeof(int), 0, -1, &tsiz))){ + if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; + return FALSE; + } + if(_qdbm_inflate){ + if(!(zbuf = _qdbm_inflate(tmp, tsiz, &zsiz, _QDBM_ZMRAW))){ + free(tmp); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + odeum->fatal = TRUE; + return FALSE; + } + free(tmp); + tmp = zbuf; + tsiz = zsiz; + } + map = cbmapload(tmp, tsiz); + free(tmp); + uritmp = cbmapget(map, OD_URIEXPR, sizeof(OD_URIEXPR), &uritsiz); + if(!uritmp || !vlout(odeum->rdocsdb, uritmp, uritsiz)){ + cbmapclose(map); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + odeum->fatal = TRUE; + return FALSE; + } + cbmapclose(map); + if(!crout(odeum->docsdb, (char *)&id, sizeof(int))){ + odeum->fatal = TRUE; + return FALSE; + } + odeum->dnum--; + return TRUE; +} + + +/* Retrieve a document by a URI. */ +ODDOC *odget(ODEUM *odeum, const char *uri){ + char *tmp; + int tsiz, docid; + assert(odeum && uri); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return NULL; + } + if(!(tmp = vlget(odeum->rdocsdb, uri, -1, &tsiz))){ + if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; + return NULL; + } + if(tsiz != sizeof(int)){ + free(tmp); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + odeum->fatal = TRUE; + return NULL; + } + docid = *(int *)tmp; + free(tmp); + return odgetbyid(odeum, docid); +} + + +/* Retrieve a document by an ID number. */ +ODDOC *odgetbyid(ODEUM *odeum, int id){ + char *tmp, *zbuf; + const char *uritmp, *attrstmp, *nwordstmp, *awordstmp, *asis, *normal; + int i, tsiz, uritsiz, attrstsiz, nwordstsiz, awordstsiz, zsiz, asiz, nsiz; + ODDOC *doc; + CBMAP *map; + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return NULL; + } + if(id < 1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return NULL; + } + if(!(tmp = crget(odeum->docsdb, (char *)&id, sizeof(int), 0, -1, &tsiz))){ + if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; + return NULL; + } + if(_qdbm_inflate){ + if(!(zbuf = _qdbm_inflate(tmp, tsiz, &zsiz, _QDBM_ZMRAW))){ + free(tmp); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + odeum->fatal = TRUE; + return NULL; + } + free(tmp); + tmp = zbuf; + tsiz = zsiz; + } + map = cbmapload(tmp, tsiz); + free(tmp); + uritmp = cbmapget(map, OD_URIEXPR, sizeof(OD_URIEXPR), &uritsiz); + attrstmp = cbmapget(map, OD_ATTRSEXPR, sizeof(OD_ATTRSEXPR), &attrstsiz); + nwordstmp = cbmapget(map, OD_NWORDSEXPR, sizeof(OD_NWORDSEXPR), &nwordstsiz); + awordstmp = cbmapget(map, OD_AWORDSEXPR, sizeof(OD_AWORDSEXPR), &awordstsiz); + if(!uritmp || !attrstmp || !nwordstmp || !awordstmp){ + cbmapclose(map); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + odeum->fatal = TRUE; + return NULL; + } + doc = cbmalloc(sizeof(ODDOC)); + doc->id = id; + doc->uri = cbmemdup(uritmp, uritsiz); + doc->attrs = cbmapload(attrstmp, attrstsiz); + doc->nwords = cblistload(nwordstmp, nwordstsiz); + doc->awords = cblistload(awordstmp, awordstsiz); + cbmapclose(map); + for(i = 0; i < cblistnum(doc->awords); i++){ + asis = cblistval(doc->awords, i, &asiz); + if(asiz == 1 && asis[0] == '\0'){ + normal = cblistval(doc->nwords, i, &nsiz); + cblistover(doc->awords, i, normal, nsiz); + } + } + return doc; +} + + +/* Retrieve the ID of the document specified by a URI. */ +int odgetidbyuri(ODEUM *odeum, const char *uri){ + char *tmp; + int tsiz, docid; + assert(odeum && uri); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + if(!(tmp = vlget(odeum->rdocsdb, uri, -1, &tsiz))){ + if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; + return -1; + } + if(tsiz != sizeof(int)){ + free(tmp); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + odeum->fatal = TRUE; + return -1; + } + docid = *(int *)tmp; + free(tmp); + return docid; +} + + +/* Check whether the document specified by an ID number exists. */ +int odcheck(ODEUM *odeum, int id){ + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(id < 1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + return crvsiz(odeum->docsdb, (char *)&id, sizeof(int)) != -1; +} + + +/* Search the inverted index for documents including a word. */ +ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np){ + char *tmp; + int tsiz; + assert(odeum && word && np); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return NULL; + } + if(odeum->wmode && cbmaprnum(odeum->sortmap) > 0 && + (!odcacheflush(odeum, "odsearch") || !odsortindex(odeum, "odsearch"))){ + odeum->fatal = TRUE; + return NULL; + } + max = max < 0 ? -1 : max * sizeof(ODPAIR); + if(!(tmp = crget(odeum->indexdb, word, -1, 0, max, &tsiz))){ + if(dpecode != DP_ENOITEM){ + odeum->fatal = TRUE; + return NULL; + } + *np = 0; + return cbmalloc(1); + } + *np = tsiz / sizeof(ODPAIR); + return (ODPAIR *)tmp; +} + + +/* Get the number of documents including a word. */ +int odsearchdnum(ODEUM *odeum, const char *word){ + int rv; + assert(odeum && word); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + rv = crvsiz(odeum->indexdb, word, -1); + return rv < 0 ? -1 : rv / sizeof(ODPAIR); +} + + +/* Initialize the iterator of a database handle. */ +int oditerinit(ODEUM *odeum){ + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + return criterinit(odeum->docsdb); +} + + +/* Get the next key of the iterator. */ +ODDOC *oditernext(ODEUM *odeum){ + char *tmp; + int tsiz, docsid; + ODDOC *doc; + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return NULL; + } + doc = NULL; + while(TRUE){ + if(!(tmp = criternext(odeum->docsdb, &tsiz))){ + if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; + return NULL; + } + if(tsiz != sizeof(int)){ + free(tmp); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + odeum->fatal = TRUE; + return NULL; + } + docsid = *(int *)tmp; + free(tmp); + if((doc = odgetbyid(odeum, docsid)) != NULL) break; + if(dpecode != DP_ENOITEM){ + odeum->fatal = TRUE; + return NULL; + } + } + return doc; +} + + +/* Synchronize updating contents with the files and the devices. */ +int odsync(ODEUM *odeum){ + char numbuf[OD_NUMBUFSIZ]; + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!odeum->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(odotcb) odotcb("odsync", odeum, "writing meta information"); + sprintf(numbuf, "%d", odeum->dmax); + if(!vlput(odeum->rdocsdb, OD_DMAXEXPR, sizeof(OD_DMAXEXPR), numbuf, -1, VL_DOVER)){ + odeum->fatal = TRUE; + return FALSE; + } + sprintf(numbuf, "%d", odeum->dnum); + if(!vlput(odeum->rdocsdb, OD_DNUMEXPR, sizeof(OD_DNUMEXPR), numbuf, -1, VL_DOVER)){ + odeum->fatal = TRUE; + return FALSE; + } + if(!odcacheflush(odeum, "odsync")){ + odeum->fatal = TRUE; + return FALSE; + } + if(!odsortindex(odeum, "odsync")){ + odeum->fatal = TRUE; + return FALSE; + } + if(odotcb) odotcb("odsync", odeum, "synchronizing the document database"); + if(!crsync(odeum->docsdb)){ + odeum->fatal = TRUE; + return FALSE; + } + if(odotcb) odotcb("odsync", odeum, "synchronizing the inverted index"); + if(!crsync(odeum->indexdb)){ + odeum->fatal = TRUE; + return FALSE; + } + if(odotcb) odotcb("odsync", odeum, "synchronizing the reverse dictionary"); + if(!vlsync(odeum->rdocsdb)){ + odeum->fatal = TRUE; + return FALSE; + } + return TRUE; +} + + +/* Optimize a database. */ +int odoptimize(ODEUM *odeum){ + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return FALSE; + } + if(!odeum->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(!odcacheflush(odeum, "odoptimize")){ + odeum->fatal = TRUE; + return FALSE; + } + if(odeum->ldid < 1 || odeum->ldid != odeum->dnum){ + if(!odpurgeindex(odeum, "odoptimize")){ + odeum->fatal = TRUE; + return FALSE; + } + } + if(odeum->ldid > 0){ + if(!odsortindex(odeum, "odoptimize")){ + odeum->fatal = TRUE; + return FALSE; + } + } + if(odotcb) odotcb("odoptimize", odeum, "optimizing the document database"); + if(!croptimize(odeum->docsdb, -1)){ + odeum->fatal = TRUE; + return FALSE; + } + if(odotcb) odotcb("odoptimize", odeum, "optimizing the inverted index"); + if(!croptimize(odeum->indexdb, -1)){ + odeum->fatal = TRUE; + return FALSE; + } + if(odotcb) odotcb("odoptimize", odeum, "optimizing the reverse dictionary"); + if(!vloptimize(odeum->rdocsdb)){ + odeum->fatal = TRUE; + return FALSE; + } + return TRUE; +} + + +/* Get the name of a database. */ +char *odname(ODEUM *odeum){ + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return NULL; + } + return cbmemdup(odeum->name, -1); +} + + +/* Get the total size of database files. */ +double odfsiz(ODEUM *odeum){ + double fsiz, rv; + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + fsiz = 0; + if((rv = crfsizd(odeum->docsdb)) < 0) return -1.0; + fsiz += rv; + if((rv = crfsizd(odeum->indexdb)) < 0) return -1.0; + fsiz += rv; + if((rv = vlfsiz(odeum->rdocsdb)) == -1) return -1.0; + fsiz += rv; + return fsiz; +} + + +/* Get the total number of the elements of the bucket arrays for the inverted index. */ +int odbnum(ODEUM *odeum){ + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + return crbnum(odeum->indexdb); +} + + +/* Get the total number of the used elements of the bucket arrays in the inverted index. */ +int odbusenum(ODEUM *odeum){ + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + return crbusenum(odeum->indexdb); +} + + +/* Get the number of the documents stored in a database. */ +int oddnum(ODEUM *odeum){ + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + return odeum->dnum; +} + + +/* Get the number of the words stored in a database. */ +int odwnum(ODEUM *odeum){ + assert(odeum); + if(odeum->fatal){ + dpecodeset(DP_EFATAL, __FILE__, __LINE__); + return -1; + } + return crrnum(odeum->indexdb); +} + + +/* Check whether a database handle is a writer or not. */ +int odwritable(ODEUM *odeum){ + assert(odeum); + return odeum->wmode; +} + + +/* Check whether a database has a fatal error or not. */ +int odfatalerror(ODEUM *odeum){ + assert(odeum); + return odeum->fatal; +} + + +/* Get the inode number of a database directory. */ +int odinode(ODEUM *odeum){ + assert(odeum); + return odeum->inode; +} + + +/* Get the last modified time of a database. */ +time_t odmtime(ODEUM *odeum){ + assert(odeum); + return crmtime(odeum->indexdb); +} + + +/* Merge plural database directories. */ +int odmerge(const char *name, const CBLIST *elemnames){ + ODEUM *odeum, **elems; + CURIA *curia, *ecuria; + VILLA *villa, *evilla; + ODPAIR *pairs; + char *word, *kbuf, *vbuf, *dbuf, otmsg[OD_OTCBBUFSIZ]; + char *wpunit[OD_MIWUNIT], *vpunit[OD_MIWUNIT]; + int i, j, k, num, dnum, wnum, dbnum, ibnum, tnum, wsunit[OD_MIWUNIT], vsunit[OD_MIWUNIT]; + int err, *bases, sum, max, wsiz, ksiz, vsiz, uend, unum, pnum, align, id, nid, dsiz; + assert(name && elemnames); + num = cblistnum(elemnames); + elems = cbmalloc(num * sizeof(ODEUM *) + 1); + dnum = 0; + wnum = 0; + for(i = 0; i < num; i++){ + if(!(elems[i] = odopen(cblistval(elemnames, i, NULL), OD_OREADER))){ + for(i -= 1; i >= 0; i--){ + odclose(elems[i]); + } + free(elems); + return FALSE; + } + dnum += oddnum(elems[i]); + wnum += odwnum(elems[i]); + } + dbnum = (int)(dnum * OD_MDBRATIO / OD_DOCSDNUM); + ibnum = (int)(wnum * OD_MIBRATIO / odindexdnum); + if(!(odeum = odopendb(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC, dbnum, ibnum, "odmerge"))){ + for(i = 0; i < num; i++){ + odclose(elems[i]); + } + free(elems); + return FALSE; + } + err = FALSE; + if(odotcb) odotcb("odmerge", odeum, "calculating the base ID numbers"); + bases = cbmalloc(num * sizeof(int) + 1); + sum = 0; + for(i = 0; i < num; i++){ + ecuria = elems[i]->docsdb; + max = 0; + if(!criterinit(ecuria) && dpecode != DP_ENOITEM) err = TRUE; + while((kbuf = criternext(ecuria, &ksiz)) != NULL){ + if(ksiz == sizeof(int)){ + if(*(int *)kbuf > max) max = *(int *)kbuf; + } + free(kbuf); + } + bases[i] = sum; + sum += max; + } + curia = odeum->indexdb; + for(i = 0; i < num; i++){ + if(odotcb){ + sprintf(otmsg, "merging the inverted index (%d/%d)", i + 1, num); + odotcb("odmerge", odeum, otmsg); + } + ecuria = elems[i]->indexdb; + tnum = 0; + uend = FALSE; + if(!criterinit(ecuria) && dpecode != DP_ENOITEM) err = TRUE; + while(!uend){ + for(unum = 0; unum < OD_MIWUNIT; unum++){ + if(!(word = criternext(ecuria, &wsiz))){ + uend = TRUE; + break; + } + if(!(vbuf = crget(ecuria, word, wsiz, 0, -1, &vsiz))){ + err = TRUE; + free(word); + break; + } + wpunit[unum] = word; + wsunit[unum] = wsiz; + vpunit[unum] = vbuf; + vsunit[unum] = vsiz; + } + for(j = 0; j < unum; j++){ + word = wpunit[j]; + wsiz = wsunit[j]; + vbuf = vpunit[j]; + vsiz = vsunit[j]; + pairs = (ODPAIR *)vbuf; + pnum = vsiz / sizeof(ODPAIR); + for(k = 0; k < pnum; k++){ + pairs[k].id += bases[i]; + } + align = (int)(i < num - 1 ? vsiz * (num - i) * OD_MIARATIO : OD_INDEXALIGN); + if(!crsetalign(curia, align)) err = TRUE; + if(!crput(curia, word, wsiz, vbuf, vsiz, CR_DCAT)) err = TRUE; + free(vbuf); + free(word); + if(odotcb && (tnum + 1) % OD_OTPERWORDS == 0){ + sprintf(otmsg, "... (%d/%d)", tnum + 1, crrnum(ecuria)); + odotcb("odmerge", odeum, otmsg); + } + tnum++; + } + } + } + if(odotcb) odotcb("odmerge", odeum, "sorting the inverted index"); + tnum = 0; + if(!criterinit(curia) && dpecode != DP_ENOITEM) err = TRUE; + while((word = criternext(curia, &wsiz)) != NULL){ + if((vbuf = crget(curia, word, wsiz, 0, -1, &vsiz)) != NULL){ + if(vsiz > sizeof(ODPAIR)){ + pairs = (ODPAIR *)vbuf; + pnum = vsiz / sizeof(ODPAIR); + qsort(pairs, pnum, sizeof(ODPAIR), odsortcompare); + if(!crput(curia, word, wsiz, vbuf, vsiz, CR_DOVER)) err = TRUE; + } + free(vbuf); + } + free(word); + if(odotcb && (tnum + 1) % OD_OTPERWORDS == 0){ + sprintf(otmsg, "... (%d/%d)", tnum + 1, crrnum(curia)); + odotcb("odmerge", odeum, otmsg); + } + tnum++; + } + if(odotcb) odotcb("odmerge", odeum, "synchronizing the inverted index"); + if(!crsync(curia)) err = TRUE; + dnum = 0; + curia = odeum->docsdb; + villa = odeum->rdocsdb; + for(i = 0; i < num; i++){ + if(odotcb){ + sprintf(otmsg, "merging the document database (%d/%d)", i + 1, num); + odotcb("odmerge", odeum, otmsg); + } + evilla = elems[i]->rdocsdb; + ecuria = elems[i]->docsdb; + tnum = 0; + if(!vlcurfirst(evilla) && dpecode != DP_ENOITEM) err = TRUE; + while(TRUE){ + if(!(kbuf = vlcurkey(evilla, &ksiz))) break; + if((ksiz == sizeof(OD_DMAXEXPR) && !memcmp(kbuf, OD_DMAXEXPR, ksiz)) || + (ksiz == sizeof(OD_DNUMEXPR) && !memcmp(kbuf, OD_DNUMEXPR, ksiz))){ + free(kbuf); + if(!vlcurnext(evilla)) break; + continue; + } + if(!(vbuf = vlcurval(evilla, &vsiz))){ + free(kbuf); + if(!vlcurnext(evilla)) break; + continue; + } + if(vsiz != sizeof(int)){ + free(vbuf); + free(kbuf); + if(!vlcurnext(evilla)) break; + continue; + } + id = *(int *)vbuf; + nid = id + bases[i]; + if(vlput(villa, kbuf, ksiz, (char *)&nid, sizeof(int), VL_DKEEP)){ + if((dbuf = crget(ecuria, (char *)&id, sizeof(int), 0, -1, &dsiz)) != NULL){ + if(crput(curia, (char *)&nid, sizeof(int), dbuf, dsiz, CR_DKEEP)){ + dnum++; + } else { + err = TRUE; + } + free(dbuf); + } else { + err = TRUE; + } + } else if(dpecode != DP_EKEEP){ + err = TRUE; + } + free(vbuf); + free(kbuf); + odeum->dnum++; + if(odotcb && (tnum + 1) % OD_OTPERDOCS == 0){ + sprintf(otmsg, "... (%d/%d)", tnum + 1, crrnum(ecuria)); + odotcb("odmerge", odeum, otmsg); + } + tnum++; + if(!vlcurnext(evilla)) break; + } + } + odeum->dnum = dnum; + odeum->dmax = dnum; + free(bases); + if(odotcb) odotcb("odmerge", odeum, "synchronizing the document index"); + if(!crsync(curia)) err = TRUE; + if(!odclose(odeum)) err = TRUE; + for(i = 0; i < num; i++){ + if(!odclose(elems[i])) err = TRUE; + } + free(elems); + return err ? FALSE : TRUE; +} + + +/* Remove a database directory. */ +int odremove(const char *name){ + char docsname[OD_PATHBUFSIZ], indexname[OD_PATHBUFSIZ], rdocsname[OD_PATHBUFSIZ]; + char path[OD_PATHBUFSIZ]; + const char *file; + struct stat sbuf; + CBLIST *list; + int i; + assert(name); + sprintf(docsname, "%s%c%s", name, MYPATHCHR, OD_DOCSNAME); + sprintf(indexname, "%s%c%s", name, MYPATHCHR, OD_INDEXNAME); + sprintf(rdocsname, "%s%c%s", name, MYPATHCHR, OD_RDOCSNAME); + if(lstat(name, &sbuf) == -1){ + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + return FALSE; + } + if(lstat(docsname, &sbuf) != -1 && !crremove(docsname)) return FALSE; + if(lstat(indexname, &sbuf) != -1 && !crremove(indexname)) return FALSE; + if(lstat(rdocsname, &sbuf) != -1 && !vlremove(rdocsname)) return FALSE; + if((list = cbdirlist(name)) != NULL){ + for(i = 0; i < cblistnum(list); i++){ + file = cblistval(list, i, NULL); + if(!strcmp(file, MYCDIRSTR) || !strcmp(file, MYPDIRSTR)) continue; + sprintf(path, "%s%c%s", name, MYPATHCHR, file); + if(lstat(path, &sbuf) == -1) continue; + if(S_ISDIR(sbuf.st_mode)){ + if(!crremove(path)) return FALSE; + } else { + if(!dpremove(path)) return FALSE; + } + } + cblistclose(list); + } + if(rmdir(name) == -1){ + dpecodeset(DP_ERMDIR, __FILE__, __LINE__); + return FALSE; + } + return TRUE; +} + + +/* Get a document handle. */ +ODDOC *oddocopen(const char *uri){ + ODDOC *doc; + assert(uri); + doc = cbmalloc(sizeof(ODDOC)); + doc->id = -1; + doc->uri = cbmemdup(uri, -1); + doc->attrs = cbmapopenex(OD_MAPPBNUM); + doc->nwords = cblistopen(); + doc->awords = cblistopen(); + return doc; +} + + +/* Close a document handle. */ +void oddocclose(ODDOC *doc){ + assert(doc); + cblistclose(doc->awords); + cblistclose(doc->nwords); + cbmapclose(doc->attrs); + free(doc->uri); + free(doc); +} + + +/* Add an attribute to a document. */ +void oddocaddattr(ODDOC *doc, const char *name, const char *value){ + assert(doc && name && value); + cbmapput(doc->attrs, name, -1, value, -1, TRUE); +} + + +/* Add a word to a document. */ +void oddocaddword(ODDOC *doc, const char *normal, const char *asis){ + assert(doc && normal && asis); + cblistpush(doc->nwords, normal, -1); + cblistpush(doc->awords, asis, -1); +} + + +/* Get the ID number of a document. */ +int oddocid(const ODDOC *doc){ + assert(doc); + return doc->id; +} + + +/* Get the URI of a document. */ +const char *oddocuri(const ODDOC *doc){ + assert(doc); + return doc->uri; +} + + +/* Get the value of an attribute of a document. */ +const char *oddocgetattr(const ODDOC *doc, const char *name){ + assert(doc && name); + return cbmapget(doc->attrs, name, -1, NULL); +} + + +/* Get the list handle contains words in normalized form of a document. */ +const CBLIST *oddocnwords(const ODDOC *doc){ + assert(doc); + return doc->nwords; +} + + +/* Get the list handle contains words in appearance form of a document. */ +const CBLIST *oddocawords(const ODDOC *doc){ + assert(doc); + return doc->awords; +} + + +/* Get the map handle contains keywords in normalized form and their scores. */ +CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum){ + const CBLIST *nwords; + CBMAP *map, *kwmap; + const char *word, *ctmp; + char numbuf[OD_NUMBUFSIZ]; + ODWORD *owords; + int i, wsiz, wnum, hnum, mnum, nbsiz; + double ival; + assert(doc && max >= 0); + map = cbmapopen(); + nwords = oddocnwords(doc); + for(i = 0; i < cblistnum(nwords); i++){ + word = cblistval(nwords, i, &wsiz); + if(wsiz < 1) continue; + if((ctmp = cbmapget(map, word, wsiz, NULL)) != NULL){ + wnum = *(int *)ctmp + OD_WOCCRPOINT; + } else { + wnum = OD_WOCCRPOINT; + } + cbmapput(map, word, wsiz, (char *)&wnum, sizeof(int), TRUE); + } + mnum = cbmaprnum(map); + owords = cbmalloc(mnum * sizeof(ODWORD) + 1); + cbmapiterinit(map); + for(i = 0; (word = cbmapiternext(map, &wsiz)) != NULL; i++){ + owords[i].word = word; + owords[i].num = *(int *)cbmapget(map, word, wsiz, NULL); + } + qsort(owords, mnum, sizeof(ODWORD), odwordcompare); + if(odeum){ + if(mnum > max * OD_KEYCRATIO) mnum = (int)(max * OD_KEYCRATIO); + for(i = 0; i < mnum; i++){ + if((hnum = odsearchdnum(odeum, owords[i].word)) < 0) hnum = 0; + ival = odlogarithm(hnum); + ival = (ival * ival * ival) / 8.0; + if(ival < 8.0) ival = 8.0; + owords[i].num = (int)(owords[i].num / ival); + } + qsort(owords, mnum, sizeof(ODWORD), odwordcompare); + } + if(mnum > max) mnum = max; + kwmap = cbmapopenex(OD_MAPPBNUM); + for(i = 0; i < mnum; i++){ + nbsiz = sprintf(numbuf, "%d", owords[i].num); + cbmapput(kwmap, owords[i].word, -1, numbuf, nbsiz, TRUE); + } + free(owords); + cbmapclose(map); + return kwmap; +} + + +/* Break a text into words in appearance form. */ +CBLIST *odbreaktext(const char *text){ + const char *word; + CBLIST *elems, *words; + int i, j, dif, wsiz, pv, delim; + assert(text); + words = cblistopen(); + elems = cbsplit(text, -1, OD_SPACECHARS); + for(i = 0; i < cblistnum(elems); i++){ + word = cblistval(elems, i, &wsiz); + delim = FALSE; + j = 0; + pv = 0; + while(TRUE){ + dif = j - pv; + if(j >= wsiz){ + if(dif > 0 && dif <= OD_MAXWORDLEN) cblistpush(words, word + pv, j - pv); + break; + } + if(delim){ + if(!strchr(OD_DELIMCHARS, word[j])){ + if(dif > 0 && dif <= OD_MAXWORDLEN) cblistpush(words, word + pv, j - pv); + pv = j; + delim = FALSE; + } + } else { + if(strchr(OD_DELIMCHARS, word[j])){ + if(dif > 0 && dif <= OD_MAXWORDLEN) cblistpush(words, word + pv, j - pv); + pv = j; + delim = TRUE; + } + } + j++; + } + } + cblistclose(elems); + return words; +} + + +/* Make the normalized form of a word. */ +char *odnormalizeword(const char *asis){ + char *nword; + int i; + assert(asis); + for(i = 0; asis[i] != '\0'; i++){ + if(!strchr(OD_DELIMCHARS, asis[i])) break; + } + if(asis[i] == '\0') return cbmemdup("", 0); + nword = cbmemdup(asis, -1); + for(i = 0; nword[i] != '\0'; i++){ + if(nword[i] >= 'A' && nword[i] <= 'Z') nword[i] += 'a' - 'A'; + } + while(i >= 0){ + if(strchr(OD_GLUECHARS, nword[i])){ + nword[i] = '\0'; + } else { + break; + } + i--; + } + return nword; +} + + +/* Get the common elements of two sets of documents. */ +ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np){ + CBMAP *map; + ODPAIR *result; + const char *tmp; + int i, rnum; + assert(apairs && anum >= 0 && bpairs && bnum >= 0); + map = odpairsmap(bpairs, bnum); + result = cbmalloc(sizeof(ODPAIR) * anum + 1); + rnum = 0; + for(i = 0; i < anum; i++){ + if(!(tmp = cbmapget(map, (char *)&(apairs[i].id), sizeof(int), NULL))) continue; + result[rnum].id = apairs[i].id; + result[rnum].score = apairs[i].score + *(int *)tmp; + rnum++; + } + cbmapclose(map); + qsort(result, rnum, sizeof(ODPAIR), odsortcompare); + *np = rnum; + return result; +} + + +/* Get the sum of elements of two sets of documents. */ +ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np){ + CBMAP *map; + ODPAIR *result; + const char *tmp; + int i, score, rnum; + assert(apairs && anum >= 0 && bpairs && bnum >= 0); + map = odpairsmap(bpairs, bnum); + for(i = 0; i < anum; i++){ + score = 0; + if((tmp = cbmapget(map, (char *)&(apairs[i].id), sizeof(int), NULL)) != NULL) + score = *(int *)tmp; + score += apairs[i].score; + cbmapput(map, (char *)&(apairs[i].id), sizeof(int), + (char *)&score, sizeof(int), TRUE); + } + rnum = cbmaprnum(map); + result = cbmalloc(rnum * sizeof(ODPAIR) + 1); + cbmapiterinit(map); + for(i = 0; (tmp = cbmapiternext(map, NULL)) != NULL; i++){ + result[i].id = *(int *)tmp; + result[i].score = *(int *)cbmapget(map, tmp, sizeof(int), NULL); + } + cbmapclose(map); + qsort(result, rnum, sizeof(ODPAIR), odsortcompare); + *np = rnum; + return result; +} + + +/* Get the difference set of documents. */ +ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np){ + CBMAP *map; + ODPAIR *result; + const char *tmp; + int i, rnum; + assert(apairs && anum >= 0 && bpairs && bnum >= 0); + map = odpairsmap(bpairs, bnum); + result = cbmalloc(sizeof(ODPAIR) * anum + 1); + rnum = 0; + for(i = 0; i < anum; i++){ + if((tmp = cbmapget(map, (char *)&(apairs[i].id), sizeof(int), NULL)) != NULL) continue; + result[rnum].id = apairs[i].id; + result[rnum].score = apairs[i].score; + rnum++; + } + cbmapclose(map); + qsort(result, rnum, sizeof(ODPAIR), odsortcompare); + *np = rnum; + return result; +} + + +/* Sort a set of documents in descending order of scores. */ +void odpairssort(ODPAIR *pairs, int pnum){ + assert(pairs && pnum >= 0); + qsort(pairs, pnum, sizeof(ODPAIR), odsortcompare); +} + + +/* Get the natural logarithm of a number. */ +double odlogarithm(double x){ + int i; + if(x <= 1.0) return 0.0; + x = x * x * x * x * x * x * x * x * x * x; + for(i = 0; x > 1.0; i++){ + x /= 2.718281828459; + } + return (double)i / 10.0; +} + + +/* Get the cosine of the angle of two vectors. */ +double odvectorcosine(const int *avec, const int *bvec, int vnum){ + double rv; + assert(avec && bvec && vnum >= 0); + rv = odvecinnerproduct(avec, bvec, vnum) / + ((odvecabsolute(avec, vnum) * odvecabsolute(bvec, vnum))); + return rv > 0.0 ? rv : 0.0; +} + + +/* Set the global tuning parameters. */ +void odsettuning(int ibnum, int idnum, int cbnum, int csiz){ + if(ibnum > 0) odindexbnum = ibnum; + if(idnum > 0) odindexdnum = idnum; + if(cbnum > 0) odcachebnum = dpprimenum(cbnum); + if(csiz > 0) odcachesiz = csiz; +} + + +/* Break a text into words and store appearance forms and normalized form into lists. */ +void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords){ + char aword[OD_MAXWORDLEN+1], *wp; + int lev, wsiz; + assert(odeum && text && awords); + lev = OD_EVSPACE; + wsiz = 0; + for(; *text != '\0'; text++){ + switch(odeum->statechars[*(unsigned char *)text]){ + case OD_EVWORD: + if(wsiz > 0 && lev == OD_EVDELIM){ + cblistpush(awords, aword, wsiz); + if(nwords) cblistpush(nwords, "", 0); + wsiz = 0; + } + if(wsiz <= OD_MAXWORDLEN){ + aword[wsiz++] = *text; + } + lev = OD_EVWORD; + break; + case OD_EVGLUE: + if(wsiz > 0 && lev == OD_EVDELIM){ + cblistpush(awords, aword, wsiz); + if(nwords) cblistpush(nwords, "", 0); + wsiz = 0; + } + if(wsiz <= OD_MAXWORDLEN){ + aword[wsiz++] = *text; + } + lev = OD_EVGLUE; + break; + case OD_EVDELIM: + if(wsiz > 0 && lev != OD_EVDELIM){ + cblistpush(awords, aword, wsiz); + if(nwords){ + wp = aword; + aword[wsiz] = '\0'; + while(*wp != '\0'){ + if(*wp >= 'A' && *wp <= 'Z') *wp += 'a' - 'A'; + wp++; + } + wp--; + while(wp >= aword && odeum->statechars[*(unsigned char *)wp] == OD_EVGLUE){ + wsiz--; + wp--; + } + cblistpush(nwords, aword, wsiz); + } + wsiz = 0; + } + if(wsiz <= OD_MAXWORDLEN){ + aword[wsiz++] = *text; + } + lev = OD_EVDELIM; + break; + default: + if(wsiz > 0){ + cblistpush(awords, aword, wsiz); + if(nwords){ + if(lev == OD_EVDELIM){ + cblistpush(nwords, "", 0); + } else { + wp = aword; + aword[wsiz] = '\0'; + while(*wp != '\0'){ + if(*wp >= 'A' && *wp <= 'Z') *wp += 'a' - 'A'; + wp++; + } + wp--; + while(wp >= aword && odeum->statechars[*(unsigned char *)wp] == OD_EVGLUE){ + wsiz--; + wp--; + } + cblistpush(nwords, aword, wsiz); + } + } + wsiz = 0; + } + lev = OD_EVSPACE; + break; + } + } + if(wsiz > 0){ + cblistpush(awords, aword, wsiz); + if(nwords){ + if(lev == OD_EVDELIM){ + cblistpush(nwords, "", 0); + } else { + wp = aword; + aword[wsiz] = '\0'; + while(*wp != '\0'){ + if(*wp >= 'A' && *wp <= 'Z') *wp += 'a' - 'A'; + wp++; + } + wp--; + while(wp >= aword && odeum->statechars[*(unsigned char *)wp] == OD_EVGLUE){ + wsiz--; + wp--; + } + cblistpush(nwords, aword, wsiz); + } + } + wsiz = 0; + } +} + + +/* Set the classes of characters used by `odanalyzetext'. */ +void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, + const char *gluechars){ + assert(odeum && spacechars && delimchars && gluechars); + memset(odeum->statechars, OD_EVWORD, sizeof(odeum->statechars)); + for(; *spacechars != '\0'; spacechars++){ + odeum->statechars[*(unsigned char *)spacechars] = OD_EVSPACE; + } + for(; *delimchars != '\0'; delimchars++){ + odeum->statechars[*(unsigned char *)delimchars] = OD_EVDELIM; + } + for(; *gluechars != '\0'; gluechars++){ + odeum->statechars[*(unsigned char *)gluechars] = OD_EVGLUE; + } +} + + +/* Query a database using a small boolean query language. */ +ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors){ + CBLIST *tokens = cblistopen(); + CBLIST *nwords = cblistopen(); + ODPAIR *results = NULL; + assert(odeum && query && np); + odanalyzetext(odeum, query, tokens, nwords); + odcleannormalized(odeum, nwords); + odfixtokens(odeum, tokens); + results = odparseexpr(odeum, tokens, nwords, np, errors); + cblistclose(tokens); + cblistclose(nwords); + return results; +} + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Get the internal database handle for documents. */ +CURIA *odidbdocs(ODEUM *odeum){ + assert(odeum); + return odeum->docsdb; +} + + +/* Get the internal database handle for the inverted index. */ +CURIA *odidbindex(ODEUM *odeum){ + assert(odeum); + return odeum->indexdb; +} + + +/* Get the internal database handle for the reverse dictionary. */ +VILLA *odidbrdocs(ODEUM *odeum){ + assert(odeum); + return odeum->rdocsdb; +} + + +/* Set the call back function called in merging. */ +void odsetotcb(void (*otcb)(const char *, ODEUM *, const char *)){ + odotcb = otcb; +} + + +/* Get the positive one of square roots of a number. */ +double odsquareroot(double x){ + double c, rv; + if(x <= 0.0) return 0.0; + c = x > 1.0 ? x : 1; + do { + rv = c; + c = (x / c + c) * 0.5; + } while(c < rv); + return rv; +} + + +/* Get the absolute of a vector. */ +double odvecabsolute(const int *vec, int vnum){ + double rv; + int i; + assert(vec && vnum >= 0); + rv = 0; + for(i = 0; i < vnum; i++){ + rv += (double)vec[i] * (double)vec[i]; + } + return odsquareroot(rv); +} + + +/* Get the inner product of two vectors. */ +double odvecinnerproduct(const int *avec, const int *bvec, int vnum){ + double rv; + int i; + assert(avec && bvec && vnum >= 0); + rv = 0; + for(i = 0; i < vnum; i++){ + rv += (double)avec[i] * (double)bvec[i]; + } + return rv; +} + + + +/************************************************************************************************* + * private objects + *************************************************************************************************/ + + +/* Get a database handle. + `name' specifies the name of a database directory. + `omode' specifies the connection mode. + `docsbnum` specifies the number of buckets of the document database. + `indexbnum` specifies the number of buckets of the index database. + `fname' specifies the name of caller function. + The return value is the database handle or `NULL' if it is not successful. */ +static ODEUM *odopendb(const char *name, int omode, int docsbnum, int indexbnum, + const char *fname){ + int cromode, vlomode, inode, dmax, dnum; + char docsname[OD_PATHBUFSIZ], indexname[OD_PATHBUFSIZ], rdocsname[OD_PATHBUFSIZ], *tmp; + struct stat sbuf; + CURIA *docsdb, *indexdb; + VILLA *rdocsdb; + CBMAP *cachemap; + CBMAP *sortmap; + ODEUM *odeum; + assert(name); + if(strlen(name) > OD_NAMEMAX){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return NULL; + } + cromode = CR_OREADER; + vlomode = VL_OREADER; + if(omode & OD_OWRITER){ + cromode = CR_OWRITER; + vlomode = VL_OWRITER | VL_OZCOMP | VL_OYCOMP; + if(omode & OD_OCREAT){ + cromode |= CR_OCREAT; + vlomode |= VL_OCREAT; + } + if(omode & OD_OTRUNC){ + cromode |= CR_OTRUNC; + vlomode |= VL_OTRUNC; + } + } + if(omode & OD_ONOLCK){ + cromode |= CR_ONOLCK; + vlomode |= VL_ONOLCK; + } + if(omode & OD_OLCKNB){ + cromode |= CR_OLCKNB; + vlomode |= VL_OLCKNB; + } + sprintf(docsname, "%s%c%s", name, MYPATHCHR, OD_DOCSNAME); + sprintf(indexname, "%s%c%s", name, MYPATHCHR, OD_INDEXNAME); + sprintf(rdocsname, "%s%c%s", name, MYPATHCHR, OD_RDOCSNAME); + docsdb = NULL; + indexdb = NULL; + rdocsdb = NULL; + if((omode & OD_OWRITER) && (omode & OD_OCREAT)){ + if(mkdir(name, OD_DIRMODE) == -1 && errno != EEXIST){ + dpecodeset(DP_EMKDIR, __FILE__, __LINE__); + return NULL; + } + } + if(lstat(name, &sbuf) == -1){ + dpecodeset(DP_ESTAT, __FILE__, __LINE__); + return NULL; + } + inode = sbuf.st_ino; + if(!(docsdb = cropen(docsname, cromode, docsbnum, OD_DOCSDNUM))) return NULL; + if(!(indexdb = cropen(indexname, cromode, indexbnum, odindexdnum))){ + crclose(docsdb); + return NULL; + } + if(omode & OD_OWRITER){ + if(!crsetalign(docsdb, OD_DOCSALIGN) || !crsetfbpsiz(docsdb, OD_DOCSFBP) || + !crsetalign(indexdb, OD_INDEXALIGN) || !crsetfbpsiz(indexdb, OD_INDEXFBP)){ + crclose(indexdb); + crclose(docsdb); + return NULL; + } + } + if(!(rdocsdb = vlopen(rdocsname, vlomode, VL_CMPLEX))){ + crclose(indexdb); + crclose(docsdb); + return NULL; + } + vlsettuning(rdocsdb, OD_RDOCSLRM, OD_RDOCSNIM, OD_RDOCSLCN, OD_RDOCSNCN); + if(omode & OD_OWRITER){ + cachemap = cbmapopenex(odcachebnum); + sortmap = cbmapopenex(odcachebnum); + } else { + cachemap = NULL; + sortmap = NULL; + } + if(vlrnum(rdocsdb) > 0){ + dmax = -1; + dnum = -1; + if((tmp = vlget(rdocsdb, OD_DMAXEXPR, sizeof(OD_DMAXEXPR), NULL)) != NULL){ + dmax = atoi(tmp); + free(tmp); + } + if((tmp = vlget(rdocsdb, OD_DNUMEXPR, sizeof(OD_DNUMEXPR), NULL)) != NULL){ + dnum = atoi(tmp); + free(tmp); + } + if(dmax < 0 || dnum < 0){ + if(sortmap) cbmapclose(sortmap); + if(cachemap) cbmapclose(cachemap); + vlclose(rdocsdb); + crclose(indexdb); + crclose(docsdb); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + } else { + dmax = 0; + dnum = 0; + } + odeum = cbmalloc(sizeof(ODEUM)); + odeum->name = cbmemdup(name, -1); + odeum->wmode = omode & OD_OWRITER; + odeum->fatal = FALSE; + odeum->inode = inode; + odeum->docsdb = docsdb; + odeum->indexdb = indexdb; + odeum->rdocsdb = rdocsdb; + odeum->cachemap = cachemap; + odeum->cacheasiz = 0; + odeum->sortmap = sortmap; + odeum->dmax = dmax; + odeum->dnum = dnum; + odeum->ldid = -1; + odsetcharclass(odeum, OD_SPACECHARS, OD_DELIMCHARS, OD_GLUECHARS); + if(odotcb) odotcb(fname, odeum, "the connection was established"); + return odeum; +} + + +/* Flush the cache for dirty buffer of words. + `odeum' specifies a database handle. + `fname' specifies the name of caller function. + If successful, the return value is true, else, it is false. */ +static int odcacheflush(ODEUM *odeum, const char *fname){ + const char *kbuf, *vbuf; + char otmsg[OD_OTCBBUFSIZ]; + int i, rnum, ksiz, vsiz; + assert(odeum); + if((rnum = cbmaprnum(odeum->cachemap)) < 1) return TRUE; + if(odotcb) odotcb(fname, odeum, "flushing caches"); + cbmapiterinit(odeum->cachemap); + for(i = 0; (kbuf = cbmapiternext(odeum->cachemap, &ksiz)) != NULL; i++){ + vbuf = cbmapget(odeum->cachemap, kbuf, ksiz, &vsiz); + if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, vsiz, CR_DCAT)){ + odeum->fatal = TRUE; + return FALSE; + } + if(odotcb && (i + 1) % OD_OTPERWORDS == 0){ + sprintf(otmsg, "... (%d/%d)", i + 1, rnum); + odotcb(fname, odeum, otmsg); + } + } + cbmapclose(odeum->cachemap); + odeum->cachemap = cbmapopenex(odcachebnum); + odeum->cacheasiz = 0; + return TRUE; +} + + +/* Flush all frequent words in the cache for dirty buffer of words. + `odeum' specifies a database handle. + `fname' specifies the name of caller function. + `min' specifies the minimum size of frequent words. + If successful, the return value is true, else, it is false. */ +static int odcacheflushfreq(ODEUM *odeum, const char *fname, int min){ + const char *kbuf, *vbuf; + char otmsg[OD_OTCBBUFSIZ]; + int rnum, ksiz, vsiz; + assert(odeum); + if((rnum = cbmaprnum(odeum->cachemap)) < 1) return TRUE; + if(odotcb){ + sprintf(otmsg, "flushing frequent words: min=%d asiz=%d rnum=%d)", + min, odeum->cacheasiz, rnum); + odotcb(fname, odeum, otmsg); + } + cbmapiterinit(odeum->cachemap); + while((kbuf = cbmapiternext(odeum->cachemap, &ksiz)) != NULL){ + vbuf = cbmapget(odeum->cachemap, kbuf, ksiz, &vsiz); + if(vsiz >= sizeof(ODPAIR) * min){ + if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, vsiz, CR_DCAT)){ + odeum->fatal = TRUE; + return FALSE; + } + cbmapout(odeum->cachemap, kbuf, ksiz); + odeum->cacheasiz -= vsiz; + } + } + if(odotcb){ + sprintf(otmsg, "... (done): min=%d asiz=%d rnum=%d)", + min, odeum->cacheasiz, cbmaprnum(odeum->cachemap)); + odotcb(fname, odeum, otmsg); + } + return TRUE; +} + + +/* Flush the half of rare words in the cache for dirty buffer of words. + `odeum' specifies a database handle. + `fname' specifies the name of caller function. + `ratio' specifies the ratio of rare words. + If successful, the return value is true, else, it is false. */ +static int odcacheflushrare(ODEUM *odeum, const char *fname, double ratio){ + const char *kbuf, *vbuf; + char otmsg[OD_OTCBBUFSIZ]; + int i, rnum, limit, ksiz, vsiz; + assert(odeum); + if((rnum = cbmaprnum(odeum->cachemap)) < 1) return TRUE; + if(odotcb){ + sprintf(otmsg, "flushing rare words: ratio=%.2f asiz=%d rnum=%d)", + ratio, odeum->cacheasiz, rnum); + odotcb(fname, odeum, otmsg); + } + cbmapiterinit(odeum->cachemap); + limit = (int)(rnum * ratio); + for(i = 0; i < limit && (kbuf = cbmapiternext(odeum->cachemap, &ksiz)) != NULL; i++){ + vbuf = cbmapget(odeum->cachemap, kbuf, ksiz, &vsiz); + if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, vsiz, CR_DCAT)){ + odeum->fatal = TRUE; + return FALSE; + } + cbmapout(odeum->cachemap, kbuf, ksiz); + odeum->cacheasiz -= vsiz; + } + if(odotcb){ + sprintf(otmsg, "... (done): ratio=%.2f asiz=%d rnum=%d)", + ratio, odeum->cacheasiz, cbmaprnum(odeum->cachemap)); + odotcb(fname, odeum, otmsg); + } + return TRUE; +} + + +/* Sort the records of inverted index. + `odeum' specifies a database handle. + `fname' specifies the name of caller function. + If successful, the return value is true, else, it is false. */ +static int odsortindex(ODEUM *odeum, const char *fname){ + const char *word; + char *tmp, otmsg[OD_OTCBBUFSIZ]; + int i, rnum, wsiz, tsiz; + ODPAIR *pairs; + assert(odeum); + if((rnum = cbmaprnum(odeum->sortmap)) < 1) return TRUE; + if(odotcb) odotcb(fname, odeum, "sorting the inverted index"); + cbmapiterinit(odeum->sortmap); + for(i = 0; (word = cbmapiternext(odeum->sortmap, &wsiz)) != NULL; i++){ + if((tmp = crget(odeum->indexdb, word, wsiz, 0, -1, &tsiz)) != NULL){ + if(tsiz > sizeof(ODPAIR)){ + pairs = (ODPAIR *)tmp; + qsort(pairs, tsiz / sizeof(ODPAIR), sizeof(ODPAIR), odsortcompare); + if(!crput(odeum->indexdb, word, wsiz, tmp, tsiz, CR_DOVER)){ + free(tmp); + return FALSE; + } + } + free(tmp); + } else if(dpecode != DP_ENOITEM){ + return FALSE; + } + if(odotcb && (i + 1) % OD_OTPERWORDS == 0){ + sprintf(otmsg, "... (%d/%d)", i + 1, rnum); + odotcb(fname, odeum, otmsg); + } + } + cbmapclose(odeum->sortmap); + odeum->sortmap = cbmapopenex(odcachebnum); + return TRUE; +} + + +/* Compare two pairs of structures of a search result. + `a' specifies the pointer to the region of one pair. + `b' specifies the pointer to the region of the other pair. + The return value is positive if the former is big, negative if the latter is big, 0 if both + are equivalent. */ +static int odsortcompare(const void *a, const void *b){ + ODPAIR *ap, *bp; + int rv; + assert(a && b); + ap = (ODPAIR *)a; + bp = (ODPAIR *)b; + rv = bp->score - ap->score; + if(rv != 0) return rv; + return ap->id - bp->id; +} + + +/* Purge the elements of the deleted documents from the inverted index. + `odeum' specifies a database handle. + `fname' specifies the name of caller function. + If successful, the return value is true, else, it is false. */ +static int odpurgeindex(ODEUM *odeum, const char *fname){ + ODPAIR *pairs; + char *kbuf, *vbuf, otmsg[OD_OTCBBUFSIZ]; + int i, rnum, tnum, ksiz, vsiz, pnum, wi; + assert(odeum); + if((rnum = crrnum(odeum->indexdb)) < 1) return TRUE; + if(odotcb) odotcb(fname, odeum, "purging dispensable regions"); + if(!criterinit(odeum->indexdb)) return FALSE; + tnum = 0; + while(TRUE){ + if(!(kbuf = criternext(odeum->indexdb, &ksiz))){ + if(dpecode != DP_ENOITEM) return FALSE; + break; + } + if(!(vbuf = crget(odeum->indexdb, kbuf, ksiz, 0, -1, &vsiz))){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + free(kbuf); + return FALSE; + } + pairs = (ODPAIR *)vbuf; + pnum = vsiz / sizeof(ODPAIR); + wi = 0; + for(i = 0; i < pnum; i++){ + if(crvsiz(odeum->docsdb, (char *)&(pairs[i].id), sizeof(int)) != -1){ + pairs[wi++] = pairs[i]; + } + } + if(wi > 0){ + if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, wi * sizeof(ODPAIR), CR_DOVER)){ + free(vbuf); + free(kbuf); + return FALSE; + } + } else { + if(!crout(odeum->indexdb, kbuf, ksiz)){ + free(vbuf); + free(kbuf); + return FALSE; + } + } + free(vbuf); + free(kbuf); + if(odotcb && (tnum + 1) % OD_OTPERWORDS == 0){ + sprintf(otmsg, "... (%d/%d)", tnum + 1, rnum); + odotcb(fname, odeum, otmsg); + } + tnum++; + } + return TRUE; +} + + +/* Create a map of a document array. + `pairs' specifies the pointer to a document array. + `num' specifies the number of elements of the array. + The return value is a map of the document array. */ +static CBMAP *odpairsmap(const ODPAIR *pairs, int num){ + CBMAP *map; + int i; + assert(pairs && num >= 0); + map = cbmapopen(); + for(i = 0; i < num; i++){ + cbmapput(map, (char *)&(pairs[i].id), sizeof(int), + (char *)&(pairs[i].score), sizeof(int), TRUE); + } + return map; +} + + +/* compare two pairs of structures of words in a document. + `a' specifies the pointer to the region of one word. + `b' specifies the pointer to the region of the other word. + The return value is positive if the former is big, negative if the latter is big, 0 if both + are equivalent. */ +static int odwordcompare(const void *a, const void *b){ + ODWORD *ap, *bp; + int rv; + assert(a && b); + ap = (ODWORD *)a; + bp = (ODWORD *)b; + if((rv = bp->num - ap->num) != 0) return rv; + if((rv = strlen(bp->word) - strlen(ap->word)) != 0) return rv; + return strcmp(ap->word, bp->word); +} + + +/* Match an operator without taking it off the token list. + `odeum' specifies a database handle. + `tokens' specifies a list handle of tokens. + The return value is whether the next token is an operator. */ +static int odmatchoperator(ODEUM *odeum, CBLIST *tokens){ + const char *tk = NULL; + int tk_len = 0; + tk = cblistval(tokens, 0, &tk_len); + if(tk && (tk[0] == '&' || tk[0] == '|' || tk[0] == '!')) return 1; + return 0; +} + + +/* Implements the subexpr part of the grammar. + `odeum' specifies a database handle. + `tokens' specifies a list handle of tokens. + `nwords' specifies a list handle of normalized words. + `np' specifies the pointer to a variable to which the number of the elements of the return + value is assigned. + `errors' specifies a list handle into which error messages are stored. + The return value is the pointer to an array of document IDs. */ +static ODPAIR *odparsesubexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, + CBLIST *errors){ + char *tk = NULL; + int tk_len = 0; + char *nword = NULL; /* used to do the actual search, should match with tokens */ + ODPAIR *result = NULL; + int result_num = 0; + int i; + double ival; + if((tk = cblistshift(tokens, &tk_len)) != NULL){ + assert(tk != NULL); + if(tk[0] == '('){ + free(tk); + /* recurse into expr */ + result = odparseexpr(odeum, tokens, nwords, &result_num, errors); + /* match right token RPAREN */ + tk = cblistshift(tokens, &tk_len); + /* print an error if either we didn't get anything or we didn't get a ) */ + if(tk == NULL){ + if(errors) cblistpush(errors, "Expression ended without closing ')'", -1); + } else if(tk[0] != ')'){ + if(errors) cblistpush(errors, "Un-balanced parenthesis.", -1); + } + } else if(odeum->statechars[*(unsigned char *)tk] == 0){ + /* Perform odsearch with the next norm word that isn't an operator. */ + nword = cblistshift(nwords, NULL); + assert(nword != NULL); + if((result = odsearch(odeum, nword, -1, &result_num)) != NULL){ + /* TF-IDF tuning */ + ival = odlogarithm(result_num); + ival = (ival * ival) / 4.0; + if(ival < 4.0) ival = 4.0; + for(i = 0; i < result_num; i++){ + result[i].score = (int)(result[i].score / ival); + } + } + free(nword); + } else { + if(errors) cblistpush(errors, "Invalid sub-expression. Expected '(' or WORD.", -1); + result = cbmalloc(1); + result_num = 0; + } + /* done with the token */ + free(tk); + } + *np = result_num; + return result; +} + + +/* Implements the actual recursive decent parser for the mini query language. + `odeum' specifies a database handle. + `tokens' specifies a list handle of tokens. + `nwords' specifies a list handle of normalized words. + `np' specifies the pointer to a variable to which the number of the elements of the return + value is assigned. + `errors' specifies a list handle into which error messages are stored. + The return value is the pointer to an array of document IDs. + It simply parses an initial subexpr, and then loops over as many (operator subexpr) + sequences as it can find. The odmatchoperator function handles injecting a default & + between consecutive words. */ +static ODPAIR *odparseexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, + CBLIST *errors){ + ODPAIR *left = NULL; + ODPAIR *right = NULL; + ODPAIR *temp = NULL; + int left_num = 0; + int right_num = 0; + int temp_num = 0; + char *op = NULL; + int op_len = 0; + if(!(left = odparsesubexpr(odeum, tokens, nwords, &left_num, errors))) return NULL; + /* expr ::= subexpr ( op subexpr )* */ + while(odmatchoperator(odeum, tokens)){ + op = cblistshift(tokens, &op_len); + if(!(right = odparsesubexpr(odeum, tokens, nwords, &right_num, errors))){ + free(op); + free(left); + return NULL; + } + switch(op[0]){ + case '&': + temp = odpairsand(left, left_num, right, right_num, &temp_num); + break; + case '|': + temp = odpairsor(left, left_num, right, right_num, &temp_num); + break; + case '!': + temp = odpairsnotand(left, left_num, right, right_num, &temp_num); + break; + default: + if(errors) cblistpush(errors, "Invalid operator. Expected '&', '|', or '!'.", -1); + break; + } + if(temp){ + /* an operator was done so we must swap it with the left */ + free(left); left = NULL; + left = temp; + left_num = temp_num; + } + free(op); + if(right) free(right); + } + *np = left_num; + return left; +} + + +/* Processes the tokens in order to break them up further. + `odeum' specifies a database handle. + `tokens' specifies a list handle of tokens. */ +static void odfixtokens(ODEUM *odeum, CBLIST *tokens){ + const char *tk = NULL; + int tk_len = 0; + int i = 0; + int lastword = 0; + for(i = 0; i < cblistnum(tokens); i++){ + tk = cblistval(tokens, i, &tk_len); + assert(tk); + if(tk[0] == '&' || tk[0] == '|' || tk[0] == '!' || tk[0] == '(' || tk[0] == ')'){ + lastword = 0; + if(tk_len > 1){ + /* need to break it up for the next loop around */ + tk = cblistremove(tokens, i, &tk_len); + cblistinsert(tokens, i, tk, 1); + cblistinsert(tokens, i+1, tk+1, tk_len-1); + free((char *)tk); + } + } else if(odeum->statechars[*(unsigned char *)tk] == 0){ + /* if the last one was a word and this is a word then we need a default & between them */ + if(lastword){ + cblistinsert(tokens, i, "&", 1); + i++; + } + lastword = 1; + } + } +} + + +/* Cleans out the parts of the normalized word list that are not considered words. + `odeum' specifies a database handle. + `tokens' specifies a list handle of tokens. */ +static void odcleannormalized(ODEUM *odeum, CBLIST *nwords){ + char *tk = NULL; + int tk_len = 0; + int i = 0; + for(i = 0; i < cblistnum(nwords); i++){ + tk = (char *)cblistval(nwords, i, &tk_len); + if(tk_len == 0 || (!odeum->statechars[*(unsigned char *)tk] == 0)){ + /* not a word so delete it */ + tk = cblistremove(nwords, i, &tk_len); + free(tk); + i--; + } + } +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/odeum.h =================================================================== --- box/trunk/qdbm/odeum.h 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/odeum.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,590 +0,0 @@ -/************************************************************************************************* - * The inverted API of QDBM - * 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. - *************************************************************************************************/ - - -#ifndef _ODEUM_H /* duplication check */ -#define _ODEUM_H - -#if defined(__cplusplus) /* export for C++ */ -extern "C" { -#endif - - -#include -#include -#include -#include -#include -#include - - -#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) -#define MYEXTERN extern __declspec(dllimport) -#else -#define MYEXTERN extern -#endif - - - -/************************************************************************************************* - * API - *************************************************************************************************/ - - -typedef struct { /* type of structure for a database handle */ - char *name; /* name of the database directory */ - int wmode; /* whether to be writable */ - int fatal; /* whether a fatal error occured */ - int inode; /* inode of the database directory */ - CURIA *docsdb; /* database handle for documents */ - CURIA *indexdb; /* database handle for the inverted index */ - VILLA *rdocsdb; /* database handle for the reverse dictionary */ - CBMAP *cachemap; /* cache for dirty buffers of words */ - int cacheasiz; /* total allocated size of dirty buffers */ - CBMAP *sortmap; /* map handle for candidates of sorting */ - int dmax; /* max number of the document ID */ - int dnum; /* number of the documents */ - int ldid; /* ID number of the last registered document */ - char statechars[256]; /* state of single byte characters */ -} ODEUM; - -typedef struct { /* type of structure for a document handle */ - int id; /* ID number */ - char *uri; /* uniform resource identifier */ - CBMAP *attrs; /* map handle for attrubutes */ - CBLIST *nwords; /* list handle for words in normalized form */ - CBLIST *awords; /* list handle for words in appearance form */ -} ODDOC; - -typedef struct { /* type of structure for an element of search result */ - int id; /* ID number of the document */ - int score; /* score of the document */ -} ODPAIR; - -enum { /* enumeration for open modes */ - OD_OREADER = 1 << 0, /* open as a reader */ - OD_OWRITER = 1 << 1, /* open as a writer */ - OD_OCREAT = 1 << 2, /* a writer creating */ - OD_OTRUNC = 1 << 3, /* a writer truncating */ - OD_ONOLCK = 1 << 4, /* open without locking */ - OD_OLCKNB = 1 << 5 /* lock without blocking */ -}; - - -/* Get a database handle. - `name' specifies the name of a database directory. - `omode' specifies the connection mode: `OD_OWRITER' as a writer, `OD_OREADER' as a reader. - If the mode is `OD_OWRITER', the following may be added by bitwise or: `OD_OCREAT', which - means it creates a new database if not exist, `OD_OTRUNC', which means it creates a new - database regardless if one exists. Both of `OD_OREADER' and `OD_OWRITER' can be added to by - bitwise or: `OD_ONOLCK', which means it opens a database directory without file locking, or - `OD_OLCKNB', which means locking is performed without blocking. - The return value is the database handle or `NULL' if it is not successful. - While connecting as a writer, an exclusive lock is invoked to the database directory. - While connecting as a reader, a shared lock is invoked to the database directory. - The thread blocks until the lock is achieved. If `OD_ONOLCK' is used, the application is - responsible for exclusion control. */ -ODEUM *odopen(const char *name, int omode); - - -/* Close a database handle. - `odeum' specifies a database handle. - If successful, the return value is true, else, it is false. - Because the region of a closed handle is released, it becomes impossible to use the handle. - Updating a database is assured to be written when the handle is closed. If a writer opens - a database but does not close it appropriately, the database will be broken. */ -int odclose(ODEUM *odeum); - - -/* Store a document. - `odeum' specifies a database handle connected as a writer. - `doc' specifies a document handle. - `wmax' specifies the max number of words to be stored in the document database. If it is - negative, the number is unlimited. - `over' specifies whether the data of the duplicated document is overwritten or not. If it - is false and the URI of the document is duplicated, the function returns as an error. - If successful, the return value is true, else, it is false. */ -int odput(ODEUM *odeum, ODDOC *doc, int wmax, int over); - - -/* Delete a document specified by a URI. - `odeum' specifies a database handle connected as a writer. - `uri' specifies the string of the URI of a document. - If successful, the return value is true, else, it is false. False is returned when no - document corresponds to the specified URI. */ -int odout(ODEUM *odeum, const char *uri); - - -/* Delete a document specified by an ID number. - `odeum' specifies a database handle connected as a writer. - `id' specifies the ID number of a document. - If successful, the return value is true, else, it is false. False is returned when no - document corresponds to the specified ID number. */ -int odoutbyid(ODEUM *odeum, int id); - - -/* Retrieve a document specified by a URI. - `odeum' specifies a database handle. - `uri' specifies the string the URI of a document. - If successful, the return value is the handle of the corresponding document, else, it is - `NULL'. `NULL' is returned when no document corresponds to the specified URI. - Because the handle of the return value is opened with the function `oddocopen', it should - be closed with the function `oddocclose'. */ -ODDOC *odget(ODEUM *odeum, const char *uri); - - -/* Retrieve a document by an ID number. - `odeum' specifies a database handle. - `id' specifies the ID number of a document. - If successful, the return value is the handle of the corresponding document, else, it is - `NULL'. `NULL' is returned when no document corresponds to the specified ID number. - Because the handle of the return value is opened with the function `oddocopen', it should - be closed with the function `oddocclose'. */ -ODDOC *odgetbyid(ODEUM *odeum, int id); - - -/* Retrieve the ID of the document specified by a URI. - `odeum' specifies a database handle. - `uri' specifies the string the URI of a document. - If successful, the return value is the ID number of the document, else, it is -1. -1 is - returned when no document corresponds to the specified URI. */ -int odgetidbyuri(ODEUM *odeum, const char *uri); - - -/* Check whether the document specified by an ID number exists. - `odeum' specifies a database handle. - `id' specifies the ID number of a document. - The return value is true if the document exists, else, it is false. */ -int odcheck(ODEUM *odeum, int id); - - -/* Search the inverted index for documents including a particular word. - `odeum' specifies a database handle. - `word' specifies a searching word. - `max' specifies the max number of documents to be retrieve. - `np' specifies the pointer to a variable to which the number of the elements of the return - value is assigned. - If successful, the return value is the pointer to an array, else, it is `NULL'. Each - element of the array is a pair of the ID number and the score of a document, and sorted in - descending order of their scores. Even if no document corresponds to the specified word, - it is not error but returns an dummy array. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. Note that each element of the array - of the return value can be data of a deleted document. */ -ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np); - - -/* Get the number of documents including a word. - `odeum' specifies a database handle. - `word' specifies a searching word. - If successful, the return value is the number of documents including the word, else, it is -1. - Because this function does not read the entity of the inverted index, it is faster than - `odsearch'. */ -int odsearchdnum(ODEUM *odeum, const char *word); - - -/* Initialize the iterator of a database handle. - `odeum' specifies a database handle. - If successful, the return value is true, else, it is false. - The iterator is used in order to access every document stored in a database. */ -int oditerinit(ODEUM *odeum); - - -/* Get the next key of the iterator. - `odeum' specifies a database handle. - If successful, the return value is the handle of the next document, else, it is `NULL'. - `NULL' is returned when no document is to be get out of the iterator. - It is possible to access every document by iteration of calling this function. However, - it is not assured if updating the database is occurred while the iteration. Besides, the - order of this traversal access method is arbitrary, so it is not assured that the order of - string matches the one of the traversal access. Because the handle of the return value is - opened with the function `oddocopen', it should be closed with the function `oddocclose'. */ -ODDOC *oditernext(ODEUM *odeum); - - -/* Synchronize updating contents with the files and the devices. - `odeum' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. - This function is useful when another process uses the connected database directory. */ -int odsync(ODEUM *odeum); - - -/* Optimize a database. - `odeum' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. - Elements of the deleted documents in the inverted index are purged. */ -int odoptimize(ODEUM *odeum); - - -/* Get the name of a database. - `odeum' specifies a database handle. - If successful, the return value is the pointer to the region of the name of the database, - else, it is `NULL'. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *odname(ODEUM *odeum); - - -/* Get the total size of database files. - `odeum' specifies a database handle. - If successful, the return value is the total size of the database files, else, it is -1.0. */ -double odfsiz(ODEUM *odeum); - - -/* Get the total number of the elements of the bucket arrays in the inverted index. - `odeum' specifies a database handle. - If successful, the return value is the total number of the elements of the bucket arrays, - else, it is -1. */ -int odbnum(ODEUM *odeum); - - -/* Get the total number of the used elements of the bucket arrays in the inverted index. - `odeum' specifies a database handle. - If successful, the return value is the total number of the used elements of the bucket - arrays, else, it is -1. */ -int odbusenum(ODEUM *odeum); - - -/* Get the number of the documents stored in a database. - `odeum' specifies a database handle. - If successful, the return value is the number of the documents stored in the database, else, - it is -1. */ -int oddnum(ODEUM *odeum); - - -/* Get the number of the words stored in a database. - `odeum' specifies a database handle. - If successful, the return value is the number of the words stored in the database, else, - it is -1. - Because of the I/O buffer, the return value may be less than the hard number. */ -int odwnum(ODEUM *odeum); - - -/* Check whether a database handle is a writer or not. - `odeum' specifies a database handle. - The return value is true if the handle is a writer, false if not. */ -int odwritable(ODEUM *odeum); - - -/* Check whether a database has a fatal error or not. - `odeum' specifies a database handle. - The return value is true if the database has a fatal error, false if not. */ -int odfatalerror(ODEUM *odeum); - - -/* Get the inode number of a database directory. - `odeum' specifies a database handle. - The return value is the inode number of the database directory. */ -int odinode(ODEUM *odeum); - - -/* Get the last modified time of a database. - `odeum' specifies a database handle. - The return value is the last modified time of the database. */ -time_t odmtime(ODEUM *odeum); - - -/* Merge plural database directories. - `name' specifies the name of a database directory to create. - `elemnames' specifies a list of names of element databases. - If successful, the return value is true, else, it is false. - If two or more documents which have the same URL come in, the first one is adopted and the - others are ignored. */ -int odmerge(const char *name, const CBLIST *elemnames); - - -/* Remove a database directory. - `name' specifies the name of a database directory. - If successful, the return value is true, else, it is false. - A database directory can contain databases of other APIs of QDBM, they are also removed by - this function. */ -int odremove(const char *name); - - -/* Get a document handle. - `uri' specifies the URI of a document. - The return value is a document handle. - The ID number of a new document is not defined. It is defined when the document is stored - in a database. */ -ODDOC *oddocopen(const char *uri); - - -/* Close a document handle. - `doc' specifies a document handle. - Because the region of a closed handle is released, it becomes impossible to use the handle. */ -void oddocclose(ODDOC *doc); - - -/* Add an attribute to a document. - `doc' specifies a document handle. - `name' specifies the string of the name of an attribute. - `value' specifies the string of the value of the attribute. */ -void oddocaddattr(ODDOC *doc, const char *name, const char *value); - - -/* Add a word to a document. - `doc' specifies a document handle. - `normal' specifies the string of the normalized form of a word. Normalized forms are - treated as keys of the inverted index. If the normalized form of a word is an empty - string, the word is not reflected in the inverted index. - `asis' specifies the string of the appearance form of the word. Appearance forms are used - after the document is retrieved by an application. */ -void oddocaddword(ODDOC *doc, const char *normal, const char *asis); - - -/* Get the ID number of a document. - `doc' specifies a document handle. - The return value is the ID number of a document. */ -int oddocid(const ODDOC *doc); - - -/* Get the URI of a document. - `doc' specifies a document handle. - The return value is the string of the URI of a document. */ -const char *oddocuri(const ODDOC *doc); - - -/* Get the value of an attribute of a document. - `doc' specifies a document handle. - `name' specifies the string of the name of an attribute. - The return value is the string of the value of the attribute, or `NULL' if no attribute - corresponds. */ -const char *oddocgetattr(const ODDOC *doc, const char *name); - - -/* Get the list handle contains words in normalized form of a document. - `doc' specifies a document handle. - The return value is the list handle contains words in normalized form. */ -const CBLIST *oddocnwords(const ODDOC *doc); - - -/* Get the list handle contains words in appearance form of a document. - `doc' specifies a document handle. - The return value is the list handle contains words in appearance form. */ -const CBLIST *oddocawords(const ODDOC *doc); - - -/* Get the map handle contains keywords in normalized form and their scores. - `doc' specifies a document handle. - `max' specifies the max number of keywords to get. - `odeum' specifies a database handle with which the IDF for weighting is calculate. - If it is `NULL', it is not used. - The return value is the map handle contains keywords and their scores. Scores are expressed - as decimal strings. - Because the handle of the return value is opened with the function `cbmapopen', it should - be closed with the function `cbmapclose' if it is no longer in use. */ -CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum); - - -/* Break a text into words in appearance form. - `text' specifies the string of a text. - The return value is the list handle contains words in appearance form. - Words are separated with space characters and such delimiters as period, comma and so on. - Because the handle of the return value is opened with the function `cblistopen', it should - be closed with the function `cblistclose' if it is no longer in use. */ -CBLIST *odbreaktext(const char *text); - - -/* Make the normalized form of a word. - `asis' specifies the string of the appearance form of a word. - The return value is is the string of the normalized form of the word. - Alphabets of the ASCII code are unified into lower cases. Words composed of only delimiters - are treated as empty strings. Because the region of the return value is allocated with the - `malloc' call, it should be released with the `free' call if it is no longer in use. */ -char *odnormalizeword(const char *asis); - - -/* Get the common elements of two sets of documents. - `apairs' specifies the pointer to the former document array. - `anum' specifies the number of the elements of the former document array. - `bpairs' specifies the pointer to the latter document array. - `bnum' specifies the number of the elements of the latter document array. - `np' specifies the pointer to a variable to which the number of the elements of the return - value is assigned. - The return value is the pointer to a new document array whose elements commonly belong to - the specified two sets. - Elements of the array are sorted in descending order of their scores. Because the region of - the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); - - -/* Get the sum of elements of two sets of documents. - `apairs' specifies the pointer to the former document array. - `anum' specifies the number of the elements of the former document array. - `bpairs' specifies the pointer to the latter document array. - `bnum' specifies the number of the elements of the latter document array. - `np' specifies the pointer to a variable to which the number of the elements of the return - value is assigned. - The return value is the pointer to a new document array whose elements belong to both or - either of the specified two sets. - Elements of the array are sorted in descending order of their scores. Because the region of - the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); - - -/* Get the difference set of documents. - `apairs' specifies the pointer to the former document array. - `anum' specifies the number of the elements of the former document array. - `bpairs' specifies the pointer to the latter document array of the sum of elements. - `bnum' specifies the number of the elements of the latter document array. - `np' specifies the pointer to a variable to which the number of the elements of the return - value is assigned. - The return value is the pointer to a new document array whose elements belong to the former - set but not to the latter set. - Elements of the array are sorted in descending order of their scores. Because the region of - the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); - - -/* Sort a set of documents in descending order of scores. - `pairs' specifies the pointer to a document array. - `pnum' specifies the number of the elements of the document array. */ -void odpairssort(ODPAIR *pairs, int pnum); - - -/* Get the natural logarithm of a number. - `x' specifies a number. - The return value is the natural logarithm of the number. If the number is equal to or less - than 1.0, the return value is 0.0. - This function is useful when an application calculates the IDF of search results. */ -double odlogarithm(double x); - - -/* Get the cosine of the angle of two vectors. - `avec' specifies the pointer to one array of numbers. - `bvec' specifies the pointer to the other array of numbers. - `vnum' specifies the number of elements of each array. - The return value is the cosine of the angle of two vectors. - This function is useful when an application calculates similarity of documents. */ -double odvectorcosine(const int *avec, const int *bvec, int vnum); - - -/* Set the global tuning parameters. - `ibnum' specifies the number of buckets for inverted indexes. - `idnum' specifies the division number of inverted index. - `cbnum' specifies the number of buckets for dirty buffers. - `csiz' specifies the maximum bytes to use memory for dirty buffers. - The default setting is equivalent to `odsettuning(32749, 7, 262139, 8388608)'. This function - should be called before opening a handle. */ -void odsettuning(int ibnum, int idnum, int cbnum, int csiz); - - -/* Break a text into words and store appearance forms and normalized form into lists. - `odeum' specifies a database handle. - `text' specifies the string of a text. - `awords' specifies a list handle into which appearance form is store. - `nwords' specifies a list handle into which normalized form is store. If it is `NULL', it is - ignored. - Words are separated with space characters and such delimiters as period, comma and so on. */ -void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords); - - -/* Set the classes of characters used by `odanalyzetext'. - `odeum' specifies a database handle. - `spacechars' spacifies a string contains space characters. - `delimchars' spacifies a string contains delimiter characters. - `gluechars' spacifies a string contains glue characters. */ -void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, - const char *gluechars); - - -/* Query a database using a small boolean query language. - `odeum' specifies a database handle. - 'query' specifies the text of the query. - `np' specifies the pointer to a variable to which the number of the elements of the return - value is assigned. - `errors' specifies a list handle into which error messages are stored. If it is `NULL', it - is ignored. - If successful, the return value is the pointer to an array, else, it is `NULL'. Each - element of the array is a pair of the ID number and the score of a document, and sorted in - descending order of their scores. Even if no document corresponds to the specified condition, - it is not error but returns an dummy array. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. Note that each element of the array - of the return value can be data of a deleted document. */ -ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors); - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Get the internal database handle for documents. - `odeum' specifies a database handle. - The return value is the internal database handle for documents. - Note that the the returned handle should not be updated. */ -CURIA *odidbdocs(ODEUM *odeum); - - -/* Get the internal database handle for the inverted index. - `odeum' specifies a database handle. - The return value is the internal database handle for the inverted index. - Note that the the returned handle should not be updated. */ -CURIA *odidbindex(ODEUM *odeum); - - -/* Get the internal database handle for the reverse dictionary. - `odeum' specifies a database handle. - The return value is the internal database handle for the reverse dictionary. - Note that the the returned handle should not be updated. */ -VILLA *odidbrdocs(ODEUM *odeum); - - -/* Set the call back function called in merging. - `otcb' specifires the pointer to a function to report outturn. Its first argument is the name - of processing function. Its second argument is the handle of the database being processed. - Its third argument is ths string of a log message. If it is `NULL', the call back function is - cleared. */ -void odsetotcb(void (*otcb)(const char *, ODEUM *, const char *)); - - -/* Get the positive one of square roots of a number. - `x' specifies a number. - The return value is the positive one of square roots of a number. If the number is equal to - or less than 0.0, the return value is 0.0. */ -double odsquareroot(double x); - - -/* Get the absolute of a vector. - `vec' specifies the pointer to an array of numbers. - `vnum' specifies the number of elements of the array. - The return value is the absolute of a vector. */ -double odvecabsolute(const int *vec, int vnum); - - -/* Get the inner product of two vectors. - `avec' specifies the pointer to one array of numbers. - `bvec' specifies the pointer to the other array of numbers. - `vnum' specifies the number of elements of each array. - The return value is the inner product of two vectors. */ -double odvecinnerproduct(const int *avec, const int *bvec, int vnum); - - - -#undef MYEXTERN - -#if defined(__cplusplus) /* export for C++ */ -} -#endif - -#endif /* duplication check */ - - -/* END OF FILE */ Copied: box/trunk/qdbm/odeum.h (from rev 2716, box/trunk/qdbm/odeum.h) =================================================================== --- box/trunk/qdbm/odeum.h (rev 0) +++ box/trunk/qdbm/odeum.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,590 @@ +/************************************************************************************************* + * The inverted API of QDBM + * 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. + *************************************************************************************************/ + + +#ifndef _ODEUM_H /* duplication check */ +#define _ODEUM_H + +#if defined(__cplusplus) /* export for C++ */ +extern "C" { +#endif + + +#include +#include +#include +#include +#include +#include + + +#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) +#define MYEXTERN extern __declspec(dllimport) +#else +#define MYEXTERN extern +#endif + + + +/************************************************************************************************* + * API + *************************************************************************************************/ + + +typedef struct { /* type of structure for a database handle */ + char *name; /* name of the database directory */ + int wmode; /* whether to be writable */ + int fatal; /* whether a fatal error occured */ + int inode; /* inode of the database directory */ + CURIA *docsdb; /* database handle for documents */ + CURIA *indexdb; /* database handle for the inverted index */ + VILLA *rdocsdb; /* database handle for the reverse dictionary */ + CBMAP *cachemap; /* cache for dirty buffers of words */ + int cacheasiz; /* total allocated size of dirty buffers */ + CBMAP *sortmap; /* map handle for candidates of sorting */ + int dmax; /* max number of the document ID */ + int dnum; /* number of the documents */ + int ldid; /* ID number of the last registered document */ + char statechars[256]; /* state of single byte characters */ +} ODEUM; + +typedef struct { /* type of structure for a document handle */ + int id; /* ID number */ + char *uri; /* uniform resource identifier */ + CBMAP *attrs; /* map handle for attrubutes */ + CBLIST *nwords; /* list handle for words in normalized form */ + CBLIST *awords; /* list handle for words in appearance form */ +} ODDOC; + +typedef struct { /* type of structure for an element of search result */ + int id; /* ID number of the document */ + int score; /* score of the document */ +} ODPAIR; + +enum { /* enumeration for open modes */ + OD_OREADER = 1 << 0, /* open as a reader */ + OD_OWRITER = 1 << 1, /* open as a writer */ + OD_OCREAT = 1 << 2, /* a writer creating */ + OD_OTRUNC = 1 << 3, /* a writer truncating */ + OD_ONOLCK = 1 << 4, /* open without locking */ + OD_OLCKNB = 1 << 5 /* lock without blocking */ +}; + + +/* Get a database handle. + `name' specifies the name of a database directory. + `omode' specifies the connection mode: `OD_OWRITER' as a writer, `OD_OREADER' as a reader. + If the mode is `OD_OWRITER', the following may be added by bitwise or: `OD_OCREAT', which + means it creates a new database if not exist, `OD_OTRUNC', which means it creates a new + database regardless if one exists. Both of `OD_OREADER' and `OD_OWRITER' can be added to by + bitwise or: `OD_ONOLCK', which means it opens a database directory without file locking, or + `OD_OLCKNB', which means locking is performed without blocking. + The return value is the database handle or `NULL' if it is not successful. + While connecting as a writer, an exclusive lock is invoked to the database directory. + While connecting as a reader, a shared lock is invoked to the database directory. + The thread blocks until the lock is achieved. If `OD_ONOLCK' is used, the application is + responsible for exclusion control. */ +ODEUM *odopen(const char *name, int omode); + + +/* Close a database handle. + `odeum' specifies a database handle. + If successful, the return value is true, else, it is false. + Because the region of a closed handle is released, it becomes impossible to use the handle. + Updating a database is assured to be written when the handle is closed. If a writer opens + a database but does not close it appropriately, the database will be broken. */ +int odclose(ODEUM *odeum); + + +/* Store a document. + `odeum' specifies a database handle connected as a writer. + `doc' specifies a document handle. + `wmax' specifies the max number of words to be stored in the document database. If it is + negative, the number is unlimited. + `over' specifies whether the data of the duplicated document is overwritten or not. If it + is false and the URI of the document is duplicated, the function returns as an error. + If successful, the return value is true, else, it is false. */ +int odput(ODEUM *odeum, ODDOC *doc, int wmax, int over); + + +/* Delete a document specified by a URI. + `odeum' specifies a database handle connected as a writer. + `uri' specifies the string of the URI of a document. + If successful, the return value is true, else, it is false. False is returned when no + document corresponds to the specified URI. */ +int odout(ODEUM *odeum, const char *uri); + + +/* Delete a document specified by an ID number. + `odeum' specifies a database handle connected as a writer. + `id' specifies the ID number of a document. + If successful, the return value is true, else, it is false. False is returned when no + document corresponds to the specified ID number. */ +int odoutbyid(ODEUM *odeum, int id); + + +/* Retrieve a document specified by a URI. + `odeum' specifies a database handle. + `uri' specifies the string the URI of a document. + If successful, the return value is the handle of the corresponding document, else, it is + `NULL'. `NULL' is returned when no document corresponds to the specified URI. + Because the handle of the return value is opened with the function `oddocopen', it should + be closed with the function `oddocclose'. */ +ODDOC *odget(ODEUM *odeum, const char *uri); + + +/* Retrieve a document by an ID number. + `odeum' specifies a database handle. + `id' specifies the ID number of a document. + If successful, the return value is the handle of the corresponding document, else, it is + `NULL'. `NULL' is returned when no document corresponds to the specified ID number. + Because the handle of the return value is opened with the function `oddocopen', it should + be closed with the function `oddocclose'. */ +ODDOC *odgetbyid(ODEUM *odeum, int id); + + +/* Retrieve the ID of the document specified by a URI. + `odeum' specifies a database handle. + `uri' specifies the string the URI of a document. + If successful, the return value is the ID number of the document, else, it is -1. -1 is + returned when no document corresponds to the specified URI. */ +int odgetidbyuri(ODEUM *odeum, const char *uri); + + +/* Check whether the document specified by an ID number exists. + `odeum' specifies a database handle. + `id' specifies the ID number of a document. + The return value is true if the document exists, else, it is false. */ +int odcheck(ODEUM *odeum, int id); + + +/* Search the inverted index for documents including a particular word. + `odeum' specifies a database handle. + `word' specifies a searching word. + `max' specifies the max number of documents to be retrieve. + `np' specifies the pointer to a variable to which the number of the elements of the return + value is assigned. + If successful, the return value is the pointer to an array, else, it is `NULL'. Each + element of the array is a pair of the ID number and the score of a document, and sorted in + descending order of their scores. Even if no document corresponds to the specified word, + it is not error but returns an dummy array. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. Note that each element of the array + of the return value can be data of a deleted document. */ +ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np); + + +/* Get the number of documents including a word. + `odeum' specifies a database handle. + `word' specifies a searching word. + If successful, the return value is the number of documents including the word, else, it is -1. + Because this function does not read the entity of the inverted index, it is faster than + `odsearch'. */ +int odsearchdnum(ODEUM *odeum, const char *word); + + +/* Initialize the iterator of a database handle. + `odeum' specifies a database handle. + If successful, the return value is true, else, it is false. + The iterator is used in order to access every document stored in a database. */ +int oditerinit(ODEUM *odeum); + + +/* Get the next key of the iterator. + `odeum' specifies a database handle. + If successful, the return value is the handle of the next document, else, it is `NULL'. + `NULL' is returned when no document is to be get out of the iterator. + It is possible to access every document by iteration of calling this function. However, + it is not assured if updating the database is occurred while the iteration. Besides, the + order of this traversal access method is arbitrary, so it is not assured that the order of + string matches the one of the traversal access. Because the handle of the return value is + opened with the function `oddocopen', it should be closed with the function `oddocclose'. */ +ODDOC *oditernext(ODEUM *odeum); + + +/* Synchronize updating contents with the files and the devices. + `odeum' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. + This function is useful when another process uses the connected database directory. */ +int odsync(ODEUM *odeum); + + +/* Optimize a database. + `odeum' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. + Elements of the deleted documents in the inverted index are purged. */ +int odoptimize(ODEUM *odeum); + + +/* Get the name of a database. + `odeum' specifies a database handle. + If successful, the return value is the pointer to the region of the name of the database, + else, it is `NULL'. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *odname(ODEUM *odeum); + + +/* Get the total size of database files. + `odeum' specifies a database handle. + If successful, the return value is the total size of the database files, else, it is -1.0. */ +double odfsiz(ODEUM *odeum); + + +/* Get the total number of the elements of the bucket arrays in the inverted index. + `odeum' specifies a database handle. + If successful, the return value is the total number of the elements of the bucket arrays, + else, it is -1. */ +int odbnum(ODEUM *odeum); + + +/* Get the total number of the used elements of the bucket arrays in the inverted index. + `odeum' specifies a database handle. + If successful, the return value is the total number of the used elements of the bucket + arrays, else, it is -1. */ +int odbusenum(ODEUM *odeum); + + +/* Get the number of the documents stored in a database. + `odeum' specifies a database handle. + If successful, the return value is the number of the documents stored in the database, else, + it is -1. */ +int oddnum(ODEUM *odeum); + + +/* Get the number of the words stored in a database. + `odeum' specifies a database handle. + If successful, the return value is the number of the words stored in the database, else, + it is -1. + Because of the I/O buffer, the return value may be less than the hard number. */ +int odwnum(ODEUM *odeum); + + +/* Check whether a database handle is a writer or not. + `odeum' specifies a database handle. + The return value is true if the handle is a writer, false if not. */ +int odwritable(ODEUM *odeum); + + +/* Check whether a database has a fatal error or not. + `odeum' specifies a database handle. + The return value is true if the database has a fatal error, false if not. */ +int odfatalerror(ODEUM *odeum); + + +/* Get the inode number of a database directory. + `odeum' specifies a database handle. + The return value is the inode number of the database directory. */ +int odinode(ODEUM *odeum); + + +/* Get the last modified time of a database. + `odeum' specifies a database handle. + The return value is the last modified time of the database. */ +time_t odmtime(ODEUM *odeum); + + +/* Merge plural database directories. + `name' specifies the name of a database directory to create. + `elemnames' specifies a list of names of element databases. + If successful, the return value is true, else, it is false. + If two or more documents which have the same URL come in, the first one is adopted and the + others are ignored. */ +int odmerge(const char *name, const CBLIST *elemnames); + + +/* Remove a database directory. + `name' specifies the name of a database directory. + If successful, the return value is true, else, it is false. + A database directory can contain databases of other APIs of QDBM, they are also removed by + this function. */ +int odremove(const char *name); + + +/* Get a document handle. + `uri' specifies the URI of a document. + The return value is a document handle. + The ID number of a new document is not defined. It is defined when the document is stored + in a database. */ +ODDOC *oddocopen(const char *uri); + + +/* Close a document handle. + `doc' specifies a document handle. + Because the region of a closed handle is released, it becomes impossible to use the handle. */ +void oddocclose(ODDOC *doc); + + +/* Add an attribute to a document. + `doc' specifies a document handle. + `name' specifies the string of the name of an attribute. + `value' specifies the string of the value of the attribute. */ +void oddocaddattr(ODDOC *doc, const char *name, const char *value); + + +/* Add a word to a document. + `doc' specifies a document handle. + `normal' specifies the string of the normalized form of a word. Normalized forms are + treated as keys of the inverted index. If the normalized form of a word is an empty + string, the word is not reflected in the inverted index. + `asis' specifies the string of the appearance form of the word. Appearance forms are used + after the document is retrieved by an application. */ +void oddocaddword(ODDOC *doc, const char *normal, const char *asis); + + +/* Get the ID number of a document. + `doc' specifies a document handle. + The return value is the ID number of a document. */ +int oddocid(const ODDOC *doc); + + +/* Get the URI of a document. + `doc' specifies a document handle. + The return value is the string of the URI of a document. */ +const char *oddocuri(const ODDOC *doc); + + +/* Get the value of an attribute of a document. + `doc' specifies a document handle. + `name' specifies the string of the name of an attribute. + The return value is the string of the value of the attribute, or `NULL' if no attribute + corresponds. */ +const char *oddocgetattr(const ODDOC *doc, const char *name); + + +/* Get the list handle contains words in normalized form of a document. + `doc' specifies a document handle. + The return value is the list handle contains words in normalized form. */ +const CBLIST *oddocnwords(const ODDOC *doc); + + +/* Get the list handle contains words in appearance form of a document. + `doc' specifies a document handle. + The return value is the list handle contains words in appearance form. */ +const CBLIST *oddocawords(const ODDOC *doc); + + +/* Get the map handle contains keywords in normalized form and their scores. + `doc' specifies a document handle. + `max' specifies the max number of keywords to get. + `odeum' specifies a database handle with which the IDF for weighting is calculate. + If it is `NULL', it is not used. + The return value is the map handle contains keywords and their scores. Scores are expressed + as decimal strings. + Because the handle of the return value is opened with the function `cbmapopen', it should + be closed with the function `cbmapclose' if it is no longer in use. */ +CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum); + + +/* Break a text into words in appearance form. + `text' specifies the string of a text. + The return value is the list handle contains words in appearance form. + Words are separated with space characters and such delimiters as period, comma and so on. + Because the handle of the return value is opened with the function `cblistopen', it should + be closed with the function `cblistclose' if it is no longer in use. */ +CBLIST *odbreaktext(const char *text); + + +/* Make the normalized form of a word. + `asis' specifies the string of the appearance form of a word. + The return value is is the string of the normalized form of the word. + Alphabets of the ASCII code are unified into lower cases. Words composed of only delimiters + are treated as empty strings. Because the region of the return value is allocated with the + `malloc' call, it should be released with the `free' call if it is no longer in use. */ +char *odnormalizeword(const char *asis); + + +/* Get the common elements of two sets of documents. + `apairs' specifies the pointer to the former document array. + `anum' specifies the number of the elements of the former document array. + `bpairs' specifies the pointer to the latter document array. + `bnum' specifies the number of the elements of the latter document array. + `np' specifies the pointer to a variable to which the number of the elements of the return + value is assigned. + The return value is the pointer to a new document array whose elements commonly belong to + the specified two sets. + Elements of the array are sorted in descending order of their scores. Because the region of + the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); + + +/* Get the sum of elements of two sets of documents. + `apairs' specifies the pointer to the former document array. + `anum' specifies the number of the elements of the former document array. + `bpairs' specifies the pointer to the latter document array. + `bnum' specifies the number of the elements of the latter document array. + `np' specifies the pointer to a variable to which the number of the elements of the return + value is assigned. + The return value is the pointer to a new document array whose elements belong to both or + either of the specified two sets. + Elements of the array are sorted in descending order of their scores. Because the region of + the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); + + +/* Get the difference set of documents. + `apairs' specifies the pointer to the former document array. + `anum' specifies the number of the elements of the former document array. + `bpairs' specifies the pointer to the latter document array of the sum of elements. + `bnum' specifies the number of the elements of the latter document array. + `np' specifies the pointer to a variable to which the number of the elements of the return + value is assigned. + The return value is the pointer to a new document array whose elements belong to the former + set but not to the latter set. + Elements of the array are sorted in descending order of their scores. Because the region of + the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); + + +/* Sort a set of documents in descending order of scores. + `pairs' specifies the pointer to a document array. + `pnum' specifies the number of the elements of the document array. */ +void odpairssort(ODPAIR *pairs, int pnum); + + +/* Get the natural logarithm of a number. + `x' specifies a number. + The return value is the natural logarithm of the number. If the number is equal to or less + than 1.0, the return value is 0.0. + This function is useful when an application calculates the IDF of search results. */ +double odlogarithm(double x); + + +/* Get the cosine of the angle of two vectors. + `avec' specifies the pointer to one array of numbers. + `bvec' specifies the pointer to the other array of numbers. + `vnum' specifies the number of elements of each array. + The return value is the cosine of the angle of two vectors. + This function is useful when an application calculates similarity of documents. */ +double odvectorcosine(const int *avec, const int *bvec, int vnum); + + +/* Set the global tuning parameters. + `ibnum' specifies the number of buckets for inverted indexes. + `idnum' specifies the division number of inverted index. + `cbnum' specifies the number of buckets for dirty buffers. + `csiz' specifies the maximum bytes to use memory for dirty buffers. + The default setting is equivalent to `odsettuning(32749, 7, 262139, 8388608)'. This function + should be called before opening a handle. */ +void odsettuning(int ibnum, int idnum, int cbnum, int csiz); + + +/* Break a text into words and store appearance forms and normalized form into lists. + `odeum' specifies a database handle. + `text' specifies the string of a text. + `awords' specifies a list handle into which appearance form is store. + `nwords' specifies a list handle into which normalized form is store. If it is `NULL', it is + ignored. + Words are separated with space characters and such delimiters as period, comma and so on. */ +void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords); + + +/* Set the classes of characters used by `odanalyzetext'. + `odeum' specifies a database handle. + `spacechars' spacifies a string contains space characters. + `delimchars' spacifies a string contains delimiter characters. + `gluechars' spacifies a string contains glue characters. */ +void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, + const char *gluechars); + + +/* Query a database using a small boolean query language. + `odeum' specifies a database handle. + 'query' specifies the text of the query. + `np' specifies the pointer to a variable to which the number of the elements of the return + value is assigned. + `errors' specifies a list handle into which error messages are stored. If it is `NULL', it + is ignored. + If successful, the return value is the pointer to an array, else, it is `NULL'. Each + element of the array is a pair of the ID number and the score of a document, and sorted in + descending order of their scores. Even if no document corresponds to the specified condition, + it is not error but returns an dummy array. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. Note that each element of the array + of the return value can be data of a deleted document. */ +ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors); + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Get the internal database handle for documents. + `odeum' specifies a database handle. + The return value is the internal database handle for documents. + Note that the the returned handle should not be updated. */ +CURIA *odidbdocs(ODEUM *odeum); + + +/* Get the internal database handle for the inverted index. + `odeum' specifies a database handle. + The return value is the internal database handle for the inverted index. + Note that the the returned handle should not be updated. */ +CURIA *odidbindex(ODEUM *odeum); + + +/* Get the internal database handle for the reverse dictionary. + `odeum' specifies a database handle. + The return value is the internal database handle for the reverse dictionary. + Note that the the returned handle should not be updated. */ +VILLA *odidbrdocs(ODEUM *odeum); + + +/* Set the call back function called in merging. + `otcb' specifires the pointer to a function to report outturn. Its first argument is the name + of processing function. Its second argument is the handle of the database being processed. + Its third argument is ths string of a log message. If it is `NULL', the call back function is + cleared. */ +void odsetotcb(void (*otcb)(const char *, ODEUM *, const char *)); + + +/* Get the positive one of square roots of a number. + `x' specifies a number. + The return value is the positive one of square roots of a number. If the number is equal to + or less than 0.0, the return value is 0.0. */ +double odsquareroot(double x); + + +/* Get the absolute of a vector. + `vec' specifies the pointer to an array of numbers. + `vnum' specifies the number of elements of the array. + The return value is the absolute of a vector. */ +double odvecabsolute(const int *vec, int vnum); + + +/* Get the inner product of two vectors. + `avec' specifies the pointer to one array of numbers. + `bvec' specifies the pointer to the other array of numbers. + `vnum' specifies the number of elements of each array. + The return value is the inner product of two vectors. */ +double odvecinnerproduct(const int *avec, const int *bvec, int vnum); + + + +#undef MYEXTERN + +#if defined(__cplusplus) /* export for C++ */ +} +#endif + +#endif /* duplication check */ + + +/* END OF FILE */ Deleted: box/trunk/qdbm/odidx.c =================================================================== --- box/trunk/qdbm/odidx.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/odidx.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,890 +0,0 @@ -/************************************************************************************************* - * Utility for indexing document files into a database of Odeum - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define PATHCHR '/' /* delimiter character of path */ -#define EXTCHR '.' /* delimiter character of extension */ -#define CDIRSTR "." /* string of current directory */ -#define PDIRSTR ".." /* string of parent directory */ -#define MTDBNAME "_mtime" /* name of the database for last modified times */ -#define MTDBLRM 81 /* records in a leaf node of time database */ -#define MTDBNIM 192 /* records in a non-leaf node of time database */ -#define MTDBLCN 64 /* number of leaf cache of time database */ -#define MTDBNCN 32 /* number of non-leaf cache of time database */ -#define SCDBNAME "_score" /* name of the database for scores */ -#define SCDBBNUM 32749 /* bucket number of the score database */ -#define SCDBALIGN -3 /* alignment of the score database */ -#define PATHBUFSIZ 2048 /* size of a path buffer */ -#define MAXLOAD 0.85 /* max ratio of bucket loading */ -#define KEYNUM 32 /* number of keywords to store */ - - -/* for Win32 and RISC OS */ -#if defined(_WIN32) -#undef PATHCHR -#define PATHCHR '\\' -#undef EXTCHR -#define EXTCHR '.' -#undef CDIRSTR -#define CDIRSTR "." -#undef PDIRSTR -#define PDIRSTR ".." -#elif defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#undef PATHCHR -#define PATHCHR '.' -#undef EXTCHR -#define EXTCHR '/' -#undef CDIRSTR -#define CDIRSTR "@" -#undef PDIRSTR -#define PDIRSTR "^" -#endif - - -/* global variables */ -const char *progname; /* program name */ -int sigterm; /* flag for termination signal */ - - -/* function prototypes */ -int main(int argc, char **argv); -void setsignals(void); -void sigtermhandler(int num); -void usage(void); -int runregister(int argc, char **argv); -int runrelate(int argc, char **argv); -int runpurge(int argc, char **argv); -int bwimatchlist(const char *str, const CBLIST *keys); -char *fgetl(FILE *ifp); -void otcb(const char *fname, ODEUM *odeum, const char *msg); -void pdperror(const char *name); -void printferror(const char *format, ...); -void printfinfo(const char *format, ...); -const char *datestr(time_t t); -int proclist(const char *name, const char *lfile, int wmax, - const CBLIST *tsuflist, const CBLIST *hsuflist); -int procdir(const char *name, const char *dir, int wmax, - const CBLIST *tsuflist, const CBLIST *hsuflist); -int indexdir(ODEUM *odeum, VILLA *mtdb, const char *name, const char *dir, int wmax, - const CBLIST *tsuflist, const CBLIST *hsuflist); -int indexfile(ODEUM *odeum, VILLA *mtdb, const char *name, const char *file, int wmax, - const CBLIST *tsuflist, const CBLIST *hsuflist); -char *filetouri(const char *file); -ODDOC *makedocplain(const char *uri, const char *text, const char *date); -ODDOC *makedochtml(const char *uri, const char *html, const char *date); -CBMAP *htmlescpairs(void); -int procrelate(const char *name); -int procpurge(const char *name); - - -/* main routine */ -int main(int argc, char **argv){ - int rv; - cbstdiobin(); - progname = argv[0]; - sigterm = FALSE; - setsignals(); - if(argc < 2) usage(); - odsetotcb(otcb); - rv = 0; - if(!strcmp(argv[1], "register")){ - rv = runregister(argc, argv); - } else if(!strcmp(argv[1], "relate")){ - rv = runrelate(argc, argv); - } else if(!strcmp(argv[1], "purge")){ - rv = runpurge(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* set signal handlers */ -void setsignals(void){ - signal(1, sigtermhandler); - signal(2, sigtermhandler); - signal(3, sigtermhandler); - signal(13, sigtermhandler); - signal(15, sigtermhandler); -} - - -/* handler of termination signal */ -void sigtermhandler(int num){ - signal(num, SIG_DFL); - sigterm = TRUE; - printfinfo("the termination signal %d catched", num); -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: indexer of document files\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s register [-l file] [-wmax num] [-tsuf sufs] [-hsuf sufs] name [dir]\n", - progname); - fprintf(stderr, " %s relate name\n", progname); - fprintf(stderr, " %s purge name\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of register command */ -int runregister(int argc, char **argv){ - char *name, *dir, *lfile, *tsuf, *hsuf, path[PATHBUFSIZ]; - int i, wmax, plen, rv; - CBLIST *tsuflist, *hsuflist; - name = NULL; - dir = NULL; - lfile = NULL; - tsuf = NULL; - hsuf = NULL; - wmax = -1; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-l")){ - if(++i >= argc) usage(); - lfile = argv[i]; - } else if(!strcmp(argv[i], "-wmax")){ - if(++i >= argc) usage(); - wmax = atoi(argv[i]); - } else if(!strcmp(argv[i], "-tsuf")){ - if(++i >= argc) usage(); - tsuf = argv[i]; - } else if(!strcmp(argv[i], "-hsuf")){ - if(++i >= argc) usage(); - hsuf = argv[i]; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!dir){ - dir = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - if(!dir) dir = CDIRSTR; - plen = sprintf(path, "%s", dir); - if(plen > 1 && path[plen-1] == PATHCHR) path[plen-1] = '\0'; - tsuflist = cbsplit(tsuf ? tsuf : ".txt,.text", -1, ","); - hsuflist = cbsplit(hsuf ? hsuf : ".html,.htm", -1, ","); - if(lfile){ - rv = proclist(name, lfile, wmax, tsuflist, hsuflist); - } else { - rv = procdir(name, path, wmax, tsuflist, hsuflist); - } - cblistclose(hsuflist); - cblistclose(tsuflist); - return rv; -} - - -/* parse arguments of relate command */ -int runrelate(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = procrelate(name); - return rv; -} - - -/* parse arguments of purge command */ -int runpurge(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = procpurge(name); - return rv; -} - - -/* case insensitive backward matching with a list */ -int bwimatchlist(const char *str, const CBLIST *keys){ - int i; - for(i = 0; i < cblistnum(keys); i++){ - if(cbstrbwimatch(str, cblistval(keys, i, NULL))) return TRUE; - } - return FALSE; -} - - -/* read a line */ -char *fgetl(FILE *ifp){ - char *buf; - int c, len, blen; - buf = NULL; - len = 0; - blen = 256; - while((c = fgetc(ifp)) != EOF){ - if(blen <= len) blen *= 2; - buf = cbrealloc(buf, blen + 1); - if(c == '\n') c = '\0'; - buf[len++] = c; - if(c == '\0') break; - } - if(!buf) return NULL; - buf[len] = '\0'; - return buf; -} - - -/* report the outturn */ -void otcb(const char *fname, ODEUM *odeum, const char *msg){ - char *name; - name = odname(odeum); - printf("%s: %s: %s: %s\n", progname, fname, name, msg); - free(name); -} - - -/* print an error message */ -void pdperror(const char *name){ - printf("%s: ERROR: %s: %s\n", progname, name, dperrmsg(dpecode)); - fflush(stdout); -} - - -/* print formatted error string and flush the buffer */ -void printferror(const char *format, ...){ - va_list ap; - va_start(ap, format); - printf("%s: ERROR: ", progname); - vprintf(format, ap); - putchar('\n'); - fflush(stdout); - va_end(ap); -} - - -/* print formatted information string and flush the buffer */ -void printfinfo(const char *format, ...){ - va_list ap; - va_start(ap, format); - printf("%s: INFO: ", progname); - vprintf(format, ap); - putchar('\n'); - fflush(stdout); - va_end(ap); -} - - -/* get static string of the date */ -const char *datestr(time_t t){ - static char buf[32]; - struct tm *stp; - if(!(stp = localtime(&t))) return "0000/00/00 00:00:00"; - sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d", - stp->tm_year + 1900, stp->tm_mon + 1, stp->tm_mday, - stp->tm_hour, stp->tm_min, stp->tm_sec); - return buf; -} - - -/* processing with finding files in a list file */ -int proclist(const char *name, const char *lfile, int wmax, - const CBLIST *tsuflist, const CBLIST *hsuflist){ - ODEUM *odeum; - VILLA *mtdb; - FILE *ifp; - char *line, path[PATHBUFSIZ]; - int err, fatal; - if(!strcmp(lfile, "-")){ - ifp = stdin; - } else { - if(!(ifp = fopen(lfile, "rb"))){ - printferror("%s: file cannot be opened", lfile); - return 1; - } - } - printfinfo("%s: registration started", name); - if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT))){ - pdperror(name); - if(ifp != stdin) fclose(ifp); - return 1; - } - sprintf(path, "%s%c%s", name, PATHCHR, MTDBNAME); - if(!(mtdb = vlopen(path, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){ - pdperror(name); - odclose(odeum); - if(ifp != stdin) fclose(ifp); - return 1; - } - vlsettuning(mtdb, MTDBLRM, MTDBNIM, MTDBLCN, MTDBNCN); - printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - err = FALSE; - while((line = fgetl(ifp)) != NULL){ - if(sigterm){ - printferror("aborting due to a termination signal"); - free(line); - err = TRUE; - break; - } - if(!indexfile(odeum, mtdb, name, line, wmax, tsuflist, hsuflist)) err = TRUE; - free(line); - } - fatal = odfatalerror(odeum); - printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - if(!vlclose(mtdb)){ - pdperror(name); - err = TRUE; - } - if(!odclose(odeum)){ - pdperror(name); - err = TRUE; - } - if(ifp != stdin) fclose(ifp); - if(err){ - printfinfo("%s: registration was over%s", name, fatal ? " with fatal error" : ""); - } else { - printfinfo("%s: registration completed successfully", name); - } - return err ? 1 : 0; -} - - -/* processing with finding files in a directory */ -int procdir(const char *name, const char *dir, int wmax, - const CBLIST *tsuflist, const CBLIST *hsuflist){ - ODEUM *odeum; - VILLA *mtdb; - char path[PATHBUFSIZ]; - int err, fatal; - printfinfo("%s: registration started", name); - if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT))){ - pdperror(name); - return 1; - } - sprintf(path, "%s%c%s", name, PATHCHR, MTDBNAME); - if(!(mtdb = vlopen(path, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){ - pdperror(name); - odclose(odeum); - return 1; - } - vlsettuning(mtdb, MTDBLRM, MTDBNIM, MTDBLCN, MTDBNCN); - printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - err = FALSE; - if(!indexdir(odeum, mtdb, name, dir, wmax, tsuflist, hsuflist)) err = TRUE; - fatal = odfatalerror(odeum); - printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - if(!vlclose(mtdb)){ - pdperror(name); - err = TRUE; - } - if(!odclose(odeum)){ - pdperror(name); - err = TRUE; - } - if(err){ - printfinfo("%s: registration was over%s", name, fatal ? " with fatal error" : ""); - } else { - printfinfo("%s: registration completed successfully", name); - } - return err ? 1 : 0; -} - - -/* find and index files in a directory */ -int indexdir(ODEUM *odeum, VILLA *mtdb, const char *name, const char *dir, int wmax, - const CBLIST *tsuflist, const CBLIST *hsuflist){ - CBLIST *files; - const char *file; - char path[PATHBUFSIZ]; - int i, isroot, isdir, err; - if(!(files = cbdirlist(dir))){ - printferror("%s: directory cannot be opened", dir); - return FALSE; - } - isroot = dir[0] == PATHCHR && dir[1] == '\0'; - err = FALSE; - for(i = 0; i < cblistnum(files); i++){ - if(sigterm){ - printferror("aborting due to a termination signal"); - cblistclose(files); - return FALSE; - } - file = cblistval(files, i, NULL); - if(!strcmp(file, CDIRSTR) || !strcmp(file, PDIRSTR)) continue; - if(isroot){ - sprintf(path, "%s%s", dir, file); - } else { - sprintf(path, "%s%c%s", dir, PATHCHR, file); - } - if(!cbfilestat(path, &isdir, NULL, NULL)){ - printferror("%s: file does not exist", file); - err = TRUE; - continue; - } - if(isdir){ - if(!indexdir(odeum, mtdb, name, path, wmax, tsuflist, hsuflist)) err = TRUE; - } else { - if(!indexfile(odeum, mtdb, name, path, wmax, tsuflist, hsuflist)) err = TRUE; - } - } - cblistclose(files); - return err ? FALSE : TRUE; -} - - -/* index a file into the database */ -int indexfile(ODEUM *odeum, VILLA *mtdb, const char *name, const char *file, int wmax, - const CBLIST *tsuflist, const CBLIST *hsuflist){ - static int cnt = 0; - char *vbuf, *buf, *uri; - const char *title; - int size, hot, vsiz, wnum, bnum; - time_t mtime; - ODDOC *doc; - if(!cbfilestat(file, NULL, &size, &mtime)){ - printferror("%s: file does not exist", file); - return FALSE; - } - hot = TRUE; - if((vbuf = vlget(mtdb, file, -1, &vsiz)) != NULL){ - if(vsiz == sizeof(int) && mtime <= *(int *)vbuf) hot = FALSE; - free(vbuf); - } - if(!hot){ - printfinfo("%s: passed", file); - return TRUE; - } - doc = NULL; - uri = filetouri(file); - if(bwimatchlist(file, tsuflist)){ - if(!(buf = cbreadfile(file, NULL))){ - printferror("%s: file cannot be opened", file); - return FALSE; - } - doc = makedocplain(uri, buf, datestr(mtime)); - free(buf); - } else if(bwimatchlist(file, hsuflist)){ - if(!(buf = cbreadfile(file, NULL))){ - printferror("%s: file cannot be opened", file); - return FALSE; - } - doc = makedochtml(uri, buf, datestr(mtime)); - free(buf); - } - free(uri); - if(doc){ - if(!(title = oddocgetattr(doc, "title")) || strlen(title) < 1){ - if((title = strrchr(file, PATHCHR)) != NULL){ - title++; - } else { - title = file; - } - oddocaddattr(doc, "title", title); - } - if(odput(odeum, doc, wmax, TRUE) && - vlput(mtdb, file, -1, (char *)&mtime, sizeof(int), VL_DOVER)){ - printfinfo("%s: registered: id=%d wnum=%d", - file, oddocid(doc), cblistnum(oddocnwords(doc))); - cnt++; - } else { - pdperror(file); - } - oddocclose(doc); - } - wnum = odwnum(odeum); - bnum = odbnum(odeum); - if(wnum != -1 && bnum != -1 && (double)wnum / (double)bnum > MAXLOAD){ - printfinfo("%s: optimizing started: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - if(!odoptimize(odeum)){ - pdperror(file); - return FALSE; - } - printfinfo("%s: optimizing completed: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - } - if(cnt >= 256){ - printfinfo("%s: database status: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - cnt = 0; - } - return TRUE; -} - - -/* make the url from file path */ -char *filetouri(const char *file){ - CBLIST *list; - char str[PATHBUFSIZ], *wp, *enc; - const char *name; - int i, nsiz; - sprintf(str, "%c", PATHCHR); - list = cbsplit(file, -1, str); - wp = str; - for(i = 0; i < cblistnum(list); i++){ - if(i > 0) *(wp++) = '/'; - name = cblistval(list, i, &nsiz); - enc = cburlencode(name, nsiz); - wp += sprintf(wp, "%s", enc); - free(enc); - } - cblistclose(list); - *wp = '\0'; - return cbmemdup(str, -1); -} - - -/* make a document of plain text */ -ODDOC *makedocplain(const char *uri, const char *text, const char *date){ - ODDOC *doc; - CBLIST *awords; - const char *asis; - char *normal; - int i; - doc = oddocopen(uri); - if(date) oddocaddattr(doc, "date", date); - awords = odbreaktext(text); - for(i = 0; i < cblistnum(awords); i++){ - asis = cblistval(awords, i, NULL); - normal = odnormalizeword(asis); - oddocaddword(doc, normal, asis); - free(normal); - } - cblistclose(awords); - return doc; -} - - -/* make a document of HTML */ -ODDOC *makedochtml(const char *uri, const char *html, const char *date){ - ODDOC *doc; - CBMAP *pairs; - CBLIST *elems, *awords; - const char *text, *asis; - char *rtext, *normal; - int i, j, body; - pairs = htmlescpairs(); - doc = oddocopen(uri); - if(date) oddocaddattr(doc, "date", date); - elems = cbxmlbreak(html, TRUE); - body = FALSE; - for(i = 0; i < cblistnum(elems); i++){ - text = cblistval(elems, i, NULL); - if(cbstrfwimatch(text, "= 0){ - if(rtext[j] != ' ') break; - rtext[j] = '\0'; - } - for(j = 0; rtext[j] != '\0'; j++){ - if(rtext[j] != ' ') break; - } - oddocaddattr(doc, "title", rtext + j); - awords = odbreaktext(rtext); - for(j = 0; j < cblistnum(awords); j++){ - asis = cblistval(awords, j, NULL); - normal = odnormalizeword(asis); - oddocaddword(doc, normal, ""); - free(normal); - } - cblistclose(awords); - free(rtext); - } - } else if(cbstrfwimatch(text, ">", "(1/4)", "(1/2)", - "(3/4)", "?", "A", "A", "A", "A", "A", "A", "AE", "C", - "E", "E", "E", "E", "I", "I", "I", "I", "D", "N", - "O", "O", "O", "O", "O", "*", "O", "U", "U", "U", - "U", "Y", "P", "s", "a", "a", "a", "a", "a", "a", - "ae", "c", "e", "e", "e", "e", "i", "i", "i", "i", - "o", "n", "o", "o", "o", "o", "o", "/", "o", "u", - "u", "u", "u", "y", "p", "y", NULL - }; - static CBMAP *pairs = NULL; - char kbuf[8], vbuf[8]; - int i, ksiz, vsiz; - if(pairs) return pairs; - pairs = cbmapopen(); - cbglobalgc(pairs, (void (*)(void *))cbmapclose); - cbmapput(pairs, "&", -1, "&", -1, TRUE); - cbmapput(pairs, "<", -1, "<", -1, TRUE); - cbmapput(pairs, ">", -1, ">", -1, TRUE); - cbmapput(pairs, """, -1, "\"", -1, TRUE); - cbmapput(pairs, "'", -1, "'", -1, TRUE); - cbmapput(pairs, " ", -1, " ", -1, TRUE); - cbmapput(pairs, "©", -1, "(C)", -1, TRUE); - cbmapput(pairs, "®", -1, "(R)", -1, TRUE); - cbmapput(pairs, "™", -1, "(TM)", -1, TRUE); - for(i = 1; i <= 127; i++){ - ksiz = sprintf(kbuf, "&#%d;", i); - vsiz = sprintf(vbuf, "%c", i); - cbmapput(pairs, kbuf, ksiz, vbuf, vsiz, TRUE); - } - cbmapput(pairs, "‚", -1, ",", -1, TRUE); - cbmapput(pairs, "„", -1, ",,", -1, TRUE); - cbmapput(pairs, "…", -1, "...", -1, TRUE); - cbmapput(pairs, "‹", -1, "<", -1, TRUE); - cbmapput(pairs, "‘", -1, "'", -1, TRUE); - cbmapput(pairs, "’", -1, "'", -1, TRUE); - cbmapput(pairs, "“", -1, "\"", -1, TRUE); - cbmapput(pairs, "”", -1, "\"", -1, TRUE); - cbmapput(pairs, "–", -1, "-", -1, TRUE); - cbmapput(pairs, "—", -1, "-", -1, TRUE); - cbmapput(pairs, "˜", -1, "~", -1, TRUE); - cbmapput(pairs, "™", -1, "(TM)", -1, TRUE); - cbmapput(pairs, "›", -1, ">", -1, TRUE); - for(i = 0; latinext[i]; i++){ - ksiz = sprintf(kbuf, "&#%d;", i + 160); - cbmapput(pairs, kbuf, ksiz, latinext[i], -1, TRUE); - } - return pairs; -} - - -/* register scores of documents */ -int procrelate(const char *name){ - ODEUM *odeum; - DEPOT *scdb; - ODDOC *doc; - CBMAP *scores; - const char *file; - char path[PATHBUFSIZ], *mbuf; - int err, fatal, id, msiz; - printfinfo("%s: relating started", name); - if(!(odeum = odopen(name, OD_OWRITER))){ - pdperror(name); - return 1; - } - sprintf(path, "%s%c%s", name, PATHCHR, SCDBNAME); - if(!(scdb = dpopen(path, OD_OWRITER | OD_OCREAT, SCDBBNUM))){ - pdperror(name); - odclose(odeum); - return 1; - } - if(!dpsetalign(scdb, SCDBALIGN)){ - pdperror(name); - dpclose(scdb); - odclose(odeum); - return 1; - } - printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - err = FALSE; - if(!oditerinit(odeum)){ - pdperror(name); - err = TRUE; - } else { - while(TRUE){ - if(sigterm){ - printferror("aborting due to a termination signal"); - err = TRUE; - break; - } - if(!(doc = oditernext(odeum))){ - if(dpecode != DP_ENOITEM){ - pdperror(name); - err = TRUE; - } - break; - } - file = oddocuri(doc); - id = oddocid(doc); - scores = oddocscores(doc, KEYNUM, odeum); - mbuf = cbmapdump(scores, &msiz); - if(!dpput(scdb, (char *)&id, sizeof(int), mbuf, msiz, DP_DOVER)){ - pdperror(name); - err = TRUE; - } else { - printfinfo("%s: related", file); - } - free(mbuf); - cbmapclose(scores); - oddocclose(doc); - if(err) break; - } - } - fatal = odfatalerror(odeum); - printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - if(!dpclose(scdb)){ - pdperror(name); - err = TRUE; - } - if(!odclose(odeum)){ - pdperror(name); - err = TRUE; - } - if(err){ - printfinfo("%s: relating was over%s", name, fatal ? " with fatal error" : ""); - } else { - printfinfo("%s: relating completed successfully", name); - } - return err ? 1 : 0; -} - - -/* purge documents which is not existing. */ -int procpurge(const char *name){ - ODEUM *odeum; - ODDOC *doc; - const char *file; - int err, fatal; - printfinfo("%s: purging started", name); - if(!(odeum = odopen(name, OD_OWRITER))){ - pdperror(name); - return 1; - } - printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - err = FALSE; - if(!oditerinit(odeum)){ - pdperror(name); - err = TRUE; - } else { - while(TRUE){ - if(sigterm){ - printferror("aborting due to a termination signal"); - err = TRUE; - break; - } - if(!(doc = oditernext(odeum))){ - if(dpecode != DP_ENOITEM){ - pdperror(name); - err = TRUE; - } - break; - } - file = oddocuri(doc); - if(cbfilestat(file, NULL, NULL, NULL)){ - printfinfo("%s: passed", file); - } else { - if(!odout(odeum, file)){ - pdperror(file); - err = TRUE; - } - printfinfo("%s: purged", file); - } - oddocclose(doc); - } - } - fatal = odfatalerror(odeum); - printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", - name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); - if(!odclose(odeum)){ - pdperror(name); - err = TRUE; - } - if(err){ - printfinfo("%s: purging was over%s", name, fatal ? " with fatal error" : ""); - } else { - printfinfo("%s: purging completed successfully", name); - } - return err ? 1 : 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/odidx.c (from rev 2716, box/trunk/qdbm/odidx.c) =================================================================== --- box/trunk/qdbm/odidx.c (rev 0) +++ box/trunk/qdbm/odidx.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,890 @@ +/************************************************************************************************* + * Utility for indexing document files into a database of Odeum + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define PATHCHR '/' /* delimiter character of path */ +#define EXTCHR '.' /* delimiter character of extension */ +#define CDIRSTR "." /* string of current directory */ +#define PDIRSTR ".." /* string of parent directory */ +#define MTDBNAME "_mtime" /* name of the database for last modified times */ +#define MTDBLRM 81 /* records in a leaf node of time database */ +#define MTDBNIM 192 /* records in a non-leaf node of time database */ +#define MTDBLCN 64 /* number of leaf cache of time database */ +#define MTDBNCN 32 /* number of non-leaf cache of time database */ +#define SCDBNAME "_score" /* name of the database for scores */ +#define SCDBBNUM 32749 /* bucket number of the score database */ +#define SCDBALIGN -3 /* alignment of the score database */ +#define PATHBUFSIZ 2048 /* size of a path buffer */ +#define MAXLOAD 0.85 /* max ratio of bucket loading */ +#define KEYNUM 32 /* number of keywords to store */ + + +/* for Win32 and RISC OS */ +#if defined(_WIN32) +#undef PATHCHR +#define PATHCHR '\\' +#undef EXTCHR +#define EXTCHR '.' +#undef CDIRSTR +#define CDIRSTR "." +#undef PDIRSTR +#define PDIRSTR ".." +#elif defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#undef PATHCHR +#define PATHCHR '.' +#undef EXTCHR +#define EXTCHR '/' +#undef CDIRSTR +#define CDIRSTR "@" +#undef PDIRSTR +#define PDIRSTR "^" +#endif + + +/* global variables */ +const char *progname; /* program name */ +int sigterm; /* flag for termination signal */ + + +/* function prototypes */ +int main(int argc, char **argv); +void setsignals(void); +void sigtermhandler(int num); +void usage(void); +int runregister(int argc, char **argv); +int runrelate(int argc, char **argv); +int runpurge(int argc, char **argv); +int bwimatchlist(const char *str, const CBLIST *keys); +char *fgetl(FILE *ifp); +void otcb(const char *fname, ODEUM *odeum, const char *msg); +void pdperror(const char *name); +void printferror(const char *format, ...); +void printfinfo(const char *format, ...); +const char *datestr(time_t t); +int proclist(const char *name, const char *lfile, int wmax, + const CBLIST *tsuflist, const CBLIST *hsuflist); +int procdir(const char *name, const char *dir, int wmax, + const CBLIST *tsuflist, const CBLIST *hsuflist); +int indexdir(ODEUM *odeum, VILLA *mtdb, const char *name, const char *dir, int wmax, + const CBLIST *tsuflist, const CBLIST *hsuflist); +int indexfile(ODEUM *odeum, VILLA *mtdb, const char *name, const char *file, int wmax, + const CBLIST *tsuflist, const CBLIST *hsuflist); +char *filetouri(const char *file); +ODDOC *makedocplain(const char *uri, const char *text, const char *date); +ODDOC *makedochtml(const char *uri, const char *html, const char *date); +CBMAP *htmlescpairs(void); +int procrelate(const char *name); +int procpurge(const char *name); + + +/* main routine */ +int main(int argc, char **argv){ + int rv; + cbstdiobin(); + progname = argv[0]; + sigterm = FALSE; + setsignals(); + if(argc < 2) usage(); + odsetotcb(otcb); + rv = 0; + if(!strcmp(argv[1], "register")){ + rv = runregister(argc, argv); + } else if(!strcmp(argv[1], "relate")){ + rv = runrelate(argc, argv); + } else if(!strcmp(argv[1], "purge")){ + rv = runpurge(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* set signal handlers */ +void setsignals(void){ + signal(1, sigtermhandler); + signal(2, sigtermhandler); + signal(3, sigtermhandler); + signal(13, sigtermhandler); + signal(15, sigtermhandler); +} + + +/* handler of termination signal */ +void sigtermhandler(int num){ + signal(num, SIG_DFL); + sigterm = TRUE; + printfinfo("the termination signal %d catched", num); +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: indexer of document files\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s register [-l file] [-wmax num] [-tsuf sufs] [-hsuf sufs] name [dir]\n", + progname); + fprintf(stderr, " %s relate name\n", progname); + fprintf(stderr, " %s purge name\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of register command */ +int runregister(int argc, char **argv){ + char *name, *dir, *lfile, *tsuf, *hsuf, path[PATHBUFSIZ]; + int i, wmax, plen, rv; + CBLIST *tsuflist, *hsuflist; + name = NULL; + dir = NULL; + lfile = NULL; + tsuf = NULL; + hsuf = NULL; + wmax = -1; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-l")){ + if(++i >= argc) usage(); + lfile = argv[i]; + } else if(!strcmp(argv[i], "-wmax")){ + if(++i >= argc) usage(); + wmax = atoi(argv[i]); + } else if(!strcmp(argv[i], "-tsuf")){ + if(++i >= argc) usage(); + tsuf = argv[i]; + } else if(!strcmp(argv[i], "-hsuf")){ + if(++i >= argc) usage(); + hsuf = argv[i]; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!dir){ + dir = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + if(!dir) dir = CDIRSTR; + plen = sprintf(path, "%s", dir); + if(plen > 1 && path[plen-1] == PATHCHR) path[plen-1] = '\0'; + tsuflist = cbsplit(tsuf ? tsuf : ".txt,.text", -1, ","); + hsuflist = cbsplit(hsuf ? hsuf : ".html,.htm", -1, ","); + if(lfile){ + rv = proclist(name, lfile, wmax, tsuflist, hsuflist); + } else { + rv = procdir(name, path, wmax, tsuflist, hsuflist); + } + cblistclose(hsuflist); + cblistclose(tsuflist); + return rv; +} + + +/* parse arguments of relate command */ +int runrelate(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = procrelate(name); + return rv; +} + + +/* parse arguments of purge command */ +int runpurge(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = procpurge(name); + return rv; +} + + +/* case insensitive backward matching with a list */ +int bwimatchlist(const char *str, const CBLIST *keys){ + int i; + for(i = 0; i < cblistnum(keys); i++){ + if(cbstrbwimatch(str, cblistval(keys, i, NULL))) return TRUE; + } + return FALSE; +} + + +/* read a line */ +char *fgetl(FILE *ifp){ + char *buf; + int c, len, blen; + buf = NULL; + len = 0; + blen = 256; + while((c = fgetc(ifp)) != EOF){ + if(blen <= len) blen *= 2; + buf = cbrealloc(buf, blen + 1); + if(c == '\n') c = '\0'; + buf[len++] = c; + if(c == '\0') break; + } + if(!buf) return NULL; + buf[len] = '\0'; + return buf; +} + + +/* report the outturn */ +void otcb(const char *fname, ODEUM *odeum, const char *msg){ + char *name; + name = odname(odeum); + printf("%s: %s: %s: %s\n", progname, fname, name, msg); + free(name); +} + + +/* print an error message */ +void pdperror(const char *name){ + printf("%s: ERROR: %s: %s\n", progname, name, dperrmsg(dpecode)); + fflush(stdout); +} + + +/* print formatted error string and flush the buffer */ +void printferror(const char *format, ...){ + va_list ap; + va_start(ap, format); + printf("%s: ERROR: ", progname); + vprintf(format, ap); + putchar('\n'); + fflush(stdout); + va_end(ap); +} + + +/* print formatted information string and flush the buffer */ +void printfinfo(const char *format, ...){ + va_list ap; + va_start(ap, format); + printf("%s: INFO: ", progname); + vprintf(format, ap); + putchar('\n'); + fflush(stdout); + va_end(ap); +} + + +/* get static string of the date */ +const char *datestr(time_t t){ + static char buf[32]; + struct tm *stp; + if(!(stp = localtime(&t))) return "0000/00/00 00:00:00"; + sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d", + stp->tm_year + 1900, stp->tm_mon + 1, stp->tm_mday, + stp->tm_hour, stp->tm_min, stp->tm_sec); + return buf; +} + + +/* processing with finding files in a list file */ +int proclist(const char *name, const char *lfile, int wmax, + const CBLIST *tsuflist, const CBLIST *hsuflist){ + ODEUM *odeum; + VILLA *mtdb; + FILE *ifp; + char *line, path[PATHBUFSIZ]; + int err, fatal; + if(!strcmp(lfile, "-")){ + ifp = stdin; + } else { + if(!(ifp = fopen(lfile, "rb"))){ + printferror("%s: file cannot be opened", lfile); + return 1; + } + } + printfinfo("%s: registration started", name); + if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT))){ + pdperror(name); + if(ifp != stdin) fclose(ifp); + return 1; + } + sprintf(path, "%s%c%s", name, PATHCHR, MTDBNAME); + if(!(mtdb = vlopen(path, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){ + pdperror(name); + odclose(odeum); + if(ifp != stdin) fclose(ifp); + return 1; + } + vlsettuning(mtdb, MTDBLRM, MTDBNIM, MTDBLCN, MTDBNCN); + printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + err = FALSE; + while((line = fgetl(ifp)) != NULL){ + if(sigterm){ + printferror("aborting due to a termination signal"); + free(line); + err = TRUE; + break; + } + if(!indexfile(odeum, mtdb, name, line, wmax, tsuflist, hsuflist)) err = TRUE; + free(line); + } + fatal = odfatalerror(odeum); + printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + if(!vlclose(mtdb)){ + pdperror(name); + err = TRUE; + } + if(!odclose(odeum)){ + pdperror(name); + err = TRUE; + } + if(ifp != stdin) fclose(ifp); + if(err){ + printfinfo("%s: registration was over%s", name, fatal ? " with fatal error" : ""); + } else { + printfinfo("%s: registration completed successfully", name); + } + return err ? 1 : 0; +} + + +/* processing with finding files in a directory */ +int procdir(const char *name, const char *dir, int wmax, + const CBLIST *tsuflist, const CBLIST *hsuflist){ + ODEUM *odeum; + VILLA *mtdb; + char path[PATHBUFSIZ]; + int err, fatal; + printfinfo("%s: registration started", name); + if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT))){ + pdperror(name); + return 1; + } + sprintf(path, "%s%c%s", name, PATHCHR, MTDBNAME); + if(!(mtdb = vlopen(path, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){ + pdperror(name); + odclose(odeum); + return 1; + } + vlsettuning(mtdb, MTDBLRM, MTDBNIM, MTDBLCN, MTDBNCN); + printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + err = FALSE; + if(!indexdir(odeum, mtdb, name, dir, wmax, tsuflist, hsuflist)) err = TRUE; + fatal = odfatalerror(odeum); + printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + if(!vlclose(mtdb)){ + pdperror(name); + err = TRUE; + } + if(!odclose(odeum)){ + pdperror(name); + err = TRUE; + } + if(err){ + printfinfo("%s: registration was over%s", name, fatal ? " with fatal error" : ""); + } else { + printfinfo("%s: registration completed successfully", name); + } + return err ? 1 : 0; +} + + +/* find and index files in a directory */ +int indexdir(ODEUM *odeum, VILLA *mtdb, const char *name, const char *dir, int wmax, + const CBLIST *tsuflist, const CBLIST *hsuflist){ + CBLIST *files; + const char *file; + char path[PATHBUFSIZ]; + int i, isroot, isdir, err; + if(!(files = cbdirlist(dir))){ + printferror("%s: directory cannot be opened", dir); + return FALSE; + } + isroot = dir[0] == PATHCHR && dir[1] == '\0'; + err = FALSE; + for(i = 0; i < cblistnum(files); i++){ + if(sigterm){ + printferror("aborting due to a termination signal"); + cblistclose(files); + return FALSE; + } + file = cblistval(files, i, NULL); + if(!strcmp(file, CDIRSTR) || !strcmp(file, PDIRSTR)) continue; + if(isroot){ + sprintf(path, "%s%s", dir, file); + } else { + sprintf(path, "%s%c%s", dir, PATHCHR, file); + } + if(!cbfilestat(path, &isdir, NULL, NULL)){ + printferror("%s: file does not exist", file); + err = TRUE; + continue; + } + if(isdir){ + if(!indexdir(odeum, mtdb, name, path, wmax, tsuflist, hsuflist)) err = TRUE; + } else { + if(!indexfile(odeum, mtdb, name, path, wmax, tsuflist, hsuflist)) err = TRUE; + } + } + cblistclose(files); + return err ? FALSE : TRUE; +} + + +/* index a file into the database */ +int indexfile(ODEUM *odeum, VILLA *mtdb, const char *name, const char *file, int wmax, + const CBLIST *tsuflist, const CBLIST *hsuflist){ + static int cnt = 0; + char *vbuf, *buf, *uri; + const char *title; + int size, hot, vsiz, wnum, bnum; + time_t mtime; + ODDOC *doc; + if(!cbfilestat(file, NULL, &size, &mtime)){ + printferror("%s: file does not exist", file); + return FALSE; + } + hot = TRUE; + if((vbuf = vlget(mtdb, file, -1, &vsiz)) != NULL){ + if(vsiz == sizeof(int) && mtime <= *(int *)vbuf) hot = FALSE; + free(vbuf); + } + if(!hot){ + printfinfo("%s: passed", file); + return TRUE; + } + doc = NULL; + uri = filetouri(file); + if(bwimatchlist(file, tsuflist)){ + if(!(buf = cbreadfile(file, NULL))){ + printferror("%s: file cannot be opened", file); + return FALSE; + } + doc = makedocplain(uri, buf, datestr(mtime)); + free(buf); + } else if(bwimatchlist(file, hsuflist)){ + if(!(buf = cbreadfile(file, NULL))){ + printferror("%s: file cannot be opened", file); + return FALSE; + } + doc = makedochtml(uri, buf, datestr(mtime)); + free(buf); + } + free(uri); + if(doc){ + if(!(title = oddocgetattr(doc, "title")) || strlen(title) < 1){ + if((title = strrchr(file, PATHCHR)) != NULL){ + title++; + } else { + title = file; + } + oddocaddattr(doc, "title", title); + } + if(odput(odeum, doc, wmax, TRUE) && + vlput(mtdb, file, -1, (char *)&mtime, sizeof(int), VL_DOVER)){ + printfinfo("%s: registered: id=%d wnum=%d", + file, oddocid(doc), cblistnum(oddocnwords(doc))); + cnt++; + } else { + pdperror(file); + } + oddocclose(doc); + } + wnum = odwnum(odeum); + bnum = odbnum(odeum); + if(wnum != -1 && bnum != -1 && (double)wnum / (double)bnum > MAXLOAD){ + printfinfo("%s: optimizing started: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + if(!odoptimize(odeum)){ + pdperror(file); + return FALSE; + } + printfinfo("%s: optimizing completed: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + } + if(cnt >= 256){ + printfinfo("%s: database status: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + cnt = 0; + } + return TRUE; +} + + +/* make the url from file path */ +char *filetouri(const char *file){ + CBLIST *list; + char str[PATHBUFSIZ], *wp, *enc; + const char *name; + int i, nsiz; + sprintf(str, "%c", PATHCHR); + list = cbsplit(file, -1, str); + wp = str; + for(i = 0; i < cblistnum(list); i++){ + if(i > 0) *(wp++) = '/'; + name = cblistval(list, i, &nsiz); + enc = cburlencode(name, nsiz); + wp += sprintf(wp, "%s", enc); + free(enc); + } + cblistclose(list); + *wp = '\0'; + return cbmemdup(str, -1); +} + + +/* make a document of plain text */ +ODDOC *makedocplain(const char *uri, const char *text, const char *date){ + ODDOC *doc; + CBLIST *awords; + const char *asis; + char *normal; + int i; + doc = oddocopen(uri); + if(date) oddocaddattr(doc, "date", date); + awords = odbreaktext(text); + for(i = 0; i < cblistnum(awords); i++){ + asis = cblistval(awords, i, NULL); + normal = odnormalizeword(asis); + oddocaddword(doc, normal, asis); + free(normal); + } + cblistclose(awords); + return doc; +} + + +/* make a document of HTML */ +ODDOC *makedochtml(const char *uri, const char *html, const char *date){ + ODDOC *doc; + CBMAP *pairs; + CBLIST *elems, *awords; + const char *text, *asis; + char *rtext, *normal; + int i, j, body; + pairs = htmlescpairs(); + doc = oddocopen(uri); + if(date) oddocaddattr(doc, "date", date); + elems = cbxmlbreak(html, TRUE); + body = FALSE; + for(i = 0; i < cblistnum(elems); i++){ + text = cblistval(elems, i, NULL); + if(cbstrfwimatch(text, "= 0){ + if(rtext[j] != ' ') break; + rtext[j] = '\0'; + } + for(j = 0; rtext[j] != '\0'; j++){ + if(rtext[j] != ' ') break; + } + oddocaddattr(doc, "title", rtext + j); + awords = odbreaktext(rtext); + for(j = 0; j < cblistnum(awords); j++){ + asis = cblistval(awords, j, NULL); + normal = odnormalizeword(asis); + oddocaddword(doc, normal, ""); + free(normal); + } + cblistclose(awords); + free(rtext); + } + } else if(cbstrfwimatch(text, ">", "(1/4)", "(1/2)", + "(3/4)", "?", "A", "A", "A", "A", "A", "A", "AE", "C", + "E", "E", "E", "E", "I", "I", "I", "I", "D", "N", + "O", "O", "O", "O", "O", "*", "O", "U", "U", "U", + "U", "Y", "P", "s", "a", "a", "a", "a", "a", "a", + "ae", "c", "e", "e", "e", "e", "i", "i", "i", "i", + "o", "n", "o", "o", "o", "o", "o", "/", "o", "u", + "u", "u", "u", "y", "p", "y", NULL + }; + static CBMAP *pairs = NULL; + char kbuf[8], vbuf[8]; + int i, ksiz, vsiz; + if(pairs) return pairs; + pairs = cbmapopen(); + cbglobalgc(pairs, (void (*)(void *))cbmapclose); + cbmapput(pairs, "&", -1, "&", -1, TRUE); + cbmapput(pairs, "<", -1, "<", -1, TRUE); + cbmapput(pairs, ">", -1, ">", -1, TRUE); + cbmapput(pairs, """, -1, "\"", -1, TRUE); + cbmapput(pairs, "'", -1, "'", -1, TRUE); + cbmapput(pairs, " ", -1, " ", -1, TRUE); + cbmapput(pairs, "©", -1, "(C)", -1, TRUE); + cbmapput(pairs, "®", -1, "(R)", -1, TRUE); + cbmapput(pairs, "™", -1, "(TM)", -1, TRUE); + for(i = 1; i <= 127; i++){ + ksiz = sprintf(kbuf, "&#%d;", i); + vsiz = sprintf(vbuf, "%c", i); + cbmapput(pairs, kbuf, ksiz, vbuf, vsiz, TRUE); + } + cbmapput(pairs, "‚", -1, ",", -1, TRUE); + cbmapput(pairs, "„", -1, ",,", -1, TRUE); + cbmapput(pairs, "…", -1, "...", -1, TRUE); + cbmapput(pairs, "‹", -1, "<", -1, TRUE); + cbmapput(pairs, "‘", -1, "'", -1, TRUE); + cbmapput(pairs, "’", -1, "'", -1, TRUE); + cbmapput(pairs, "“", -1, "\"", -1, TRUE); + cbmapput(pairs, "”", -1, "\"", -1, TRUE); + cbmapput(pairs, "–", -1, "-", -1, TRUE); + cbmapput(pairs, "—", -1, "-", -1, TRUE); + cbmapput(pairs, "˜", -1, "~", -1, TRUE); + cbmapput(pairs, "™", -1, "(TM)", -1, TRUE); + cbmapput(pairs, "›", -1, ">", -1, TRUE); + for(i = 0; latinext[i]; i++){ + ksiz = sprintf(kbuf, "&#%d;", i + 160); + cbmapput(pairs, kbuf, ksiz, latinext[i], -1, TRUE); + } + return pairs; +} + + +/* register scores of documents */ +int procrelate(const char *name){ + ODEUM *odeum; + DEPOT *scdb; + ODDOC *doc; + CBMAP *scores; + const char *file; + char path[PATHBUFSIZ], *mbuf; + int err, fatal, id, msiz; + printfinfo("%s: relating started", name); + if(!(odeum = odopen(name, OD_OWRITER))){ + pdperror(name); + return 1; + } + sprintf(path, "%s%c%s", name, PATHCHR, SCDBNAME); + if(!(scdb = dpopen(path, OD_OWRITER | OD_OCREAT, SCDBBNUM))){ + pdperror(name); + odclose(odeum); + return 1; + } + if(!dpsetalign(scdb, SCDBALIGN)){ + pdperror(name); + dpclose(scdb); + odclose(odeum); + return 1; + } + printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + err = FALSE; + if(!oditerinit(odeum)){ + pdperror(name); + err = TRUE; + } else { + while(TRUE){ + if(sigterm){ + printferror("aborting due to a termination signal"); + err = TRUE; + break; + } + if(!(doc = oditernext(odeum))){ + if(dpecode != DP_ENOITEM){ + pdperror(name); + err = TRUE; + } + break; + } + file = oddocuri(doc); + id = oddocid(doc); + scores = oddocscores(doc, KEYNUM, odeum); + mbuf = cbmapdump(scores, &msiz); + if(!dpput(scdb, (char *)&id, sizeof(int), mbuf, msiz, DP_DOVER)){ + pdperror(name); + err = TRUE; + } else { + printfinfo("%s: related", file); + } + free(mbuf); + cbmapclose(scores); + oddocclose(doc); + if(err) break; + } + } + fatal = odfatalerror(odeum); + printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + if(!dpclose(scdb)){ + pdperror(name); + err = TRUE; + } + if(!odclose(odeum)){ + pdperror(name); + err = TRUE; + } + if(err){ + printfinfo("%s: relating was over%s", name, fatal ? " with fatal error" : ""); + } else { + printfinfo("%s: relating completed successfully", name); + } + return err ? 1 : 0; +} + + +/* purge documents which is not existing. */ +int procpurge(const char *name){ + ODEUM *odeum; + ODDOC *doc; + const char *file; + int err, fatal; + printfinfo("%s: purging started", name); + if(!(odeum = odopen(name, OD_OWRITER))){ + pdperror(name); + return 1; + } + printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + err = FALSE; + if(!oditerinit(odeum)){ + pdperror(name); + err = TRUE; + } else { + while(TRUE){ + if(sigterm){ + printferror("aborting due to a termination signal"); + err = TRUE; + break; + } + if(!(doc = oditernext(odeum))){ + if(dpecode != DP_ENOITEM){ + pdperror(name); + err = TRUE; + } + break; + } + file = oddocuri(doc); + if(cbfilestat(file, NULL, NULL, NULL)){ + printfinfo("%s: passed", file); + } else { + if(!odout(odeum, file)){ + pdperror(file); + err = TRUE; + } + printfinfo("%s: purged", file); + } + oddocclose(doc); + } + } + fatal = odfatalerror(odeum); + printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", + name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); + if(!odclose(odeum)){ + pdperror(name); + err = TRUE; + } + if(err){ + printfinfo("%s: purging was over%s", name, fatal ? " with fatal error" : ""); + } else { + printfinfo("%s: purging completed successfully", name); + } + return err ? 1 : 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/odmgr.c =================================================================== --- box/trunk/qdbm/odmgr.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/odmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,1085 +0,0 @@ -/************************************************************************************************* - * Utility for debugging Odeum and its applications - * 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 -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define MAXSRCHWORDS 256 /* max number of search words */ -#define WOCCRPOINT 10000 /* points per occurence */ -#define MAXKEYWORDS 8 /* max number of keywords */ -#define SUMMARYWIDTH 16 /* width of each phrase in a summary */ -#define MAXSUMMARY 128 /* max number of words in a summary */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -char *readstdin(int *sp); -void otcb(const char *fname, ODEUM *odeum, const char *msg); -int runcreate(int argc, char **argv); -int runput(int argc, char **argv); -int runout(int argc, char **argv); -int runget(int argc, char **argv); -int runsearch(int argc, char **argv); -int runlist(int argc, char **argv); -int runoptimize(int argc, char **argv); -int runinform(int argc, char **argv); -int runmerge(int argc, char **argv); -int runremove(int argc, char **argv); -int runbreak(int argc, char **argv); -void pdperror(const char *name); -void printdoc(const ODDOC *doc, int tb, int hb, int score, ODEUM *odeum, const CBLIST *skeys); -char *docsummary(const ODDOC *doc, const CBLIST *kwords, int num, int hilight); -CBMAP *listtomap(const CBLIST *list); -int docreate(const char *name); -int doput(const char *name, const char *text, const char *uri, const char *title, - const char *author, const char *date, int wmax, int keep); -int doout(const char *name, const char *uri, int id); -int doget(const char *name, const char *uri, int id, int tb, int hb); -int dosearch(const char *name, const char *text, int max, int or, int idf, int ql, - int tb, int hb, int nb); -int dolist(const char *name, int tb, int hb); -int dooptimize(const char *name); -int doinform(const char *name); -int domerge(const char *name, const CBLIST *elems); -int doremove(const char *name); -int dobreak(const char *text, int hb, int kb, int sb); - - -/* main routine */ -int main(int argc, char **argv){ - char *env; - int rv; - cbstdiobin(); - progname = argv[0]; - if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "create")){ - odsetotcb(otcb); - rv = runcreate(argc, argv); - } else if(!strcmp(argv[1], "put")){ - odsetotcb(otcb); - rv = runput(argc, argv); - } else if(!strcmp(argv[1], "out")){ - odsetotcb(otcb); - rv = runout(argc, argv); - } else if(!strcmp(argv[1], "get")){ - rv = runget(argc, argv); - } else if(!strcmp(argv[1], "search")){ - rv = runsearch(argc, argv); - } else if(!strcmp(argv[1], "list")){ - rv = runlist(argc, argv); - } else if(!strcmp(argv[1], "optimize")){ - odsetotcb(otcb); - rv = runoptimize(argc, argv); - } else if(!strcmp(argv[1], "inform")){ - rv = runinform(argc, argv); - } else if(!strcmp(argv[1], "merge")){ - odsetotcb(otcb); - rv = runmerge(argc, argv); - } else if(!strcmp(argv[1], "remove")){ - rv = runremove(argc, argv); - } else if(!strcmp(argv[1], "break")){ - rv = runbreak(argc, argv); - } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ - printf("Powered by QDBM version %s\n", dpversion); - printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); - rv = 0; - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: administration utility for Odeum\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s create name\n", progname); - fprintf(stderr, " %s put [-uri str] [-title str] [-author str] [-date str]" - " [-wmax num] [-keep] name [file]\n", progname); - fprintf(stderr, " %s out [-id] name expr\n", progname); - fprintf(stderr, " %s get [-id] [-t|-h] name expr\n", progname); - fprintf(stderr, " %s search [-max num] [-or] [-idf] [-t|-h|-n] name words...\n", progname); - fprintf(stderr, " %s list [-t|-h] name\n", progname); - fprintf(stderr, " %s optimize name\n", progname); - fprintf(stderr, " %s inform name\n", progname); - fprintf(stderr, " %s merge name elems...\n", progname); - fprintf(stderr, " %s remove name\n", progname); - fprintf(stderr, " %s break [-h|-k|-s] [file]\n", progname); - fprintf(stderr, " %s version\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* read the standard input */ -char *readstdin(int *sp){ - char *buf; - int i, blen, c; - blen = 256; - buf = cbmalloc(blen); - for(i = 0; (c = getchar()) != EOF; i++){ - if(i >= blen - 1) buf = cbrealloc(buf, blen *= 2); - buf[i] = c; - } - buf[i] = '\0'; - *sp = i; - return buf; -} - - -/* report the outturn */ -void otcb(const char *fname, ODEUM *odeum, const char *msg){ - char *name; - name = odname(odeum); - printf("%s: %s: %s: %s\n", progname, fname, name, msg); - free(name); -} - - -/* parse arguments of create command */ -int runcreate(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = docreate(name); - return rv; -} - - -/* parse arguments of put command */ -int runput(int argc, char **argv){ - char *name, *file, *uri, *title, *author, *date, *text; - int i, wmax, keep, size, rv; - name = NULL; - file = NULL; - uri = NULL; - title = NULL; - author = NULL; - date = NULL; - wmax = -1; - keep = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-uri")){ - if(++i >= argc) usage(); - uri = argv[i]; - } else if(!strcmp(argv[i], "-uri")){ - if(++i >= argc) usage(); - uri = argv[i]; - } else if(!strcmp(argv[i], "-title")){ - if(++i >= argc) usage(); - title = argv[i]; - } else if(!strcmp(argv[i], "-author")){ - if(++i >= argc) usage(); - author = argv[i]; - } else if(!strcmp(argv[i], "-date")){ - if(++i >= argc) usage(); - date = argv[i]; - } else if(!strcmp(argv[i], "-wmax")){ - if(++i >= argc) usage(); - wmax = atoi(argv[i]); - } else if(!strcmp(argv[i], "-keep")){ - keep = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - if(!uri) uri = file; - if(!uri) usage(); - if(file){ - if(!(text = cbreadfile(file, &size))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - text = readstdin(&size); - } - rv = doput(name, text, uri, title, author, date, wmax, keep); - free(text); - return rv; -} - - -/* parse arguments of out command */ -int runout(int argc, char **argv){ - char *name, *expr; - int i, ib, id, rv; - name = NULL; - expr = NULL; - ib = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-id")){ - ib = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!expr){ - expr = argv[i]; - } else { - usage(); - } - } - if(!name || !expr) usage(); - id = -1; - if(ib){ - id = atoi(expr); - if(id < 1) usage(); - } - rv = doout(name, expr, id); - return rv; -} - - -/* parse arguments of get command */ -int runget(int argc, char **argv){ - char *name, *expr; - int i, ib, tb, hb, id, rv; - name = NULL; - expr = NULL; - ib = FALSE; - tb = FALSE; - hb = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-id")){ - ib = TRUE; - } else if(!strcmp(argv[i], "-t")){ - tb = TRUE; - } else if(!strcmp(argv[i], "-h")){ - hb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!expr){ - expr = argv[i]; - } else { - usage(); - } - } - if(!name || !expr) usage(); - id = -1; - if(ib){ - id = atoi(expr); - if(id < 1) usage(); - } - rv = doget(name, expr, id, tb, hb); - return rv; -} - - -/* parse arguments of search command */ -int runsearch(int argc, char **argv){ - char *name, *srchwords[MAXSRCHWORDS]; - int i, wnum, max, or, idf, ql, tb, hb, nb, rv; - CBDATUM *text; - name = NULL; - wnum = 0; - max = -1; - or = FALSE; - idf = FALSE; - ql = FALSE; - tb = FALSE; - hb = FALSE; - nb = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-max")){ - if(++i >= argc) usage(); - max = atoi(argv[i]); - } else if(!strcmp(argv[i], "-or")){ - or = TRUE; - } else if(!strcmp(argv[i], "-idf")){ - idf = TRUE; - } else if(!strcmp(argv[i], "-ql")){ - ql = TRUE; - } else if(!strcmp(argv[i], "-t")){ - tb = TRUE; - } else if(!strcmp(argv[i], "-h")){ - hb = TRUE; - } else if(!strcmp(argv[i], "-n")){ - nb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(wnum < MAXSRCHWORDS){ - srchwords[wnum++] = argv[i]; - } - } - if(!name) usage(); - text = cbdatumopen(NULL, -1); - for(i = 0; i < wnum; i++){ - if(i > 0) cbdatumcat(text, " ", 1); - cbdatumcat(text, srchwords[i], -1); - } - rv = dosearch(name, cbdatumptr(text), max, or, idf, ql, tb, hb, nb); - cbdatumclose(text); - return rv; -} - - -/* parse arguments of list command */ -int runlist(int argc, char **argv){ - char *name; - int i, tb, hb, rv; - name = NULL; - tb = FALSE; - hb = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-t")){ - tb = TRUE; - } else if(!strcmp(argv[i], "-h")){ - hb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dolist(name, tb, hb); - return rv; -} - - -/* parse arguments of optimize command */ -int runoptimize(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dooptimize(name); - return rv; -} - - -/* parse arguments of inform command */ -int runinform(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doinform(name); - return rv; -} - - -/* parse arguments of merge command */ -int runmerge(int argc, char **argv){ - char *name; - CBLIST *elems; - int i, rv; - name = NULL; - elems = cblistopen(); - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - cblistpush(elems, argv[i], -1); - } - } - if(!name) usage(); - if(cblistnum(elems) < 1){ - cblistclose(elems); - usage(); - } - rv = domerge(name, elems); - cblistclose(elems); - return rv; -} - - -/* parse arguments of remove command */ -int runremove(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doremove(name); - return rv; -} - - -/* parse arguments of break command */ -int runbreak(int argc, char **argv){ - char *file, *text; - int i, hb, kb, sb, size, rv; - file = NULL; - hb = FALSE; - kb = FALSE; - sb = FALSE; - for(i = 2; i < argc; i++){ - if(!file && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-h")){ - hb = TRUE; - } else if(!strcmp(argv[i], "-k")){ - kb = TRUE; - } else if(!strcmp(argv[i], "-s")){ - sb = TRUE; - } else { - usage(); - } - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - if(file){ - if(!(text = cbreadfile(file, &size))){ - fprintf(stderr, "%s: %s: cannot open\n", progname, file); - return 1; - } - } else { - text = readstdin(&size); - } - rv = dobreak(text, hb, kb, sb); - free(text); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* print the contents of a document */ -void printdoc(const ODDOC *doc, int tb, int hb, int score, ODEUM *odeum, const CBLIST *skeys){ - const CBLIST *words; - CBMAP *scores; - CBLIST *kwords; - const char *title, *author, *word, *date; - char *summary; - int i, wsiz; - title = oddocgetattr(doc, "title"); - author = oddocgetattr(doc, "author"); - date = oddocgetattr(doc, "date"); - if(hb){ - printf("ID: %d\n", oddocid(doc)); - printf("URI: %s\n", oddocuri(doc)); - if(title) printf("TITLE: %s\n", title); - if(author) printf("AUTHOR: %s\n", author); - if(date) printf("DATE: %s\n", date); - if(score >= 0) printf("SCORE: %d\n", score); - scores = oddocscores(doc, MAXKEYWORDS, odeum); - kwords = cblistopen(); - printf("KEYWORDS: "); - cbmapiterinit(scores); - while((word = cbmapiternext(scores, &wsiz)) != NULL){ - if(cblistnum(kwords) > 0) printf(", "); - printf("%s (%s)", word, cbmapget(scores, word, wsiz, NULL)); - cblistpush(kwords, word, wsiz); - } - putchar('\n'); - summary = docsummary(doc, skeys ? skeys : kwords, MAXSUMMARY, skeys != NULL); - printf("SUMMARY: %s\n", summary); - free(summary); - cblistclose(kwords); - cbmapclose(scores); - printf("\n\n"); - } else if(tb){ - printf("%d\t%s\t%s\t%s\t%s\t%d\n", oddocid(doc), oddocuri(doc), - title ? title : "", author ? author : "", date ? date : "", score); - words = oddocnwords(doc); - for(i = 0; i < cblistnum(words); i++){ - word = cblistval(words, i, &wsiz); - if(i > 0) putchar('\t'); - printf("%s", word); - } - putchar('\n'); - words = oddocawords(doc); - for(i = 0; i < cblistnum(words); i++){ - word = cblistval(words, i, &wsiz); - if(i > 0) putchar('\t'); - printf("%s", word); - } - putchar('\n'); - } else { - printf("%d\t%s\t%d\n", oddocid(doc), oddocuri(doc), score); - } -} - - -/* get a list handle contains summary of a document */ -char *docsummary(const ODDOC *doc, const CBLIST *kwords, int num, int hilight){ - const CBLIST *nwords, *awords; - CBMAP *kmap, *map; - const char *normal, *asis; - char *sbuf; - int i, j, bsiz, ssiz, lnum, nwsiz, awsiz, pv, bi, first; - bsiz = 256; - sbuf = cbmalloc(bsiz); - ssiz = 0; - nwords = oddocnwords(doc); - awords = oddocawords(doc); - kmap = listtomap(kwords); - map = listtomap(kwords); - lnum = cblistnum(nwords); - first = TRUE; - for(i = 0; i < lnum && i < SUMMARYWIDTH; i++){ - normal = cblistval(nwords, i, &nwsiz); - asis = cblistval(awords, i, &awsiz); - if(awsiz < 1) continue; - cbmapout(map, normal, nwsiz); - if(ssiz + awsiz + 16 >= bsiz){ - bsiz = bsiz * 2 + awsiz; - sbuf = cbrealloc(sbuf, bsiz); - } - if(!first) ssiz += sprintf(sbuf + ssiz, " "); - if(hilight && normal[0] != '\0' && cbmapget(kmap, normal, nwsiz, NULL)){ - ssiz += sprintf(sbuf + ssiz, "<<%s>>", asis); - } else { - ssiz += sprintf(sbuf + ssiz, "%s", asis); - } - first = FALSE; - num--; - } - ssiz += sprintf(sbuf + ssiz, " ..."); - pv = i; - while(i < lnum){ - if(cbmaprnum(map) < 1){ - cbmapclose(map); - map = listtomap(kwords); - } - normal = cblistval(nwords, i, &nwsiz); - if(cbmapget(map, normal, nwsiz, NULL)){ - bi = i - SUMMARYWIDTH / 2; - bi = bi > pv ? bi : pv; - for(j = bi; j < lnum && j <= bi + SUMMARYWIDTH; j++){ - normal = cblistval(nwords, j, &nwsiz); - asis = cblistval(awords, j, &awsiz); - if(awsiz < 1) continue; - cbmapout(map, normal, nwsiz); - if(ssiz + awsiz + 16 >= bsiz){ - bsiz = bsiz * 2 + awsiz; - sbuf = cbrealloc(sbuf, bsiz); - } - ssiz += sprintf(sbuf + ssiz, " "); - if(hilight && normal[0] != '\0' && cbmapget(kmap, normal, nwsiz, NULL)){ - ssiz += sprintf(sbuf + ssiz, "<<%s>>", asis); - } else { - ssiz += sprintf(sbuf + ssiz, "%s", asis); - } - num--; - } - ssiz += sprintf(sbuf + ssiz, " ..."); - i = j; - pv = i; - } else { - i++; - } - if(num <= 0) break; - } - cbmapclose(map); - cbmapclose(kmap); - return sbuf; -} - - -/* get a map made from a list */ -CBMAP *listtomap(const CBLIST *list){ - CBMAP *map; - const char *tmp; - int i, tsiz; - map = cbmapopen(); - for(i = 0; i < cblistnum(list); i++){ - tmp = cblistval(list, i, &tsiz); - cbmapput(map, tmp, tsiz, "", 0, FALSE); - } - return map; -} - - -/* perform create command */ -int docreate(const char *name){ - ODEUM *odeum; - if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ - pdperror(name); - return 1; - } - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform put command */ -int doput(const char *name, const char *text, const char *uri, const char *title, - const char *author, const char *date, int wmax, int keep){ - ODEUM *odeum; - ODDOC *doc; - CBLIST *awords; - const char *asis; - char *normal; - int i; - if(!(odeum = odopen(name, OD_OWRITER))){ - pdperror(name); - return 1; - } - doc = oddocopen(uri); - if(title) oddocaddattr(doc, "title", title); - if(author) oddocaddattr(doc, "author", author); - if(date) oddocaddattr(doc, "date", date); - awords = odbreaktext(text); - for(i = 0; i < cblistnum(awords); i++){ - asis = cblistval(awords, i, NULL); - normal = odnormalizeword(asis); - oddocaddword(doc, normal, asis); - free(normal); - } - cblistclose(awords); - if(!odput(odeum, doc, wmax, keep ? FALSE : TRUE)){ - pdperror(name); - oddocclose(doc); - odclose(odeum); - return 1; - } - oddocclose(doc); - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform out command */ -int doout(const char *name, const char *uri, int id){ - ODEUM *odeum; - if(!(odeum = odopen(name, OD_OWRITER))){ - pdperror(name); - return 1; - } - if(id > 0){ - if(!odoutbyid(odeum, id)){ - pdperror(name); - odclose(odeum); - return 1; - } - } else { - if(!odout(odeum, uri)){ - pdperror(name); - odclose(odeum); - return 1; - } - } - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform get command */ -int doget(const char *name, const char *uri, int id, int tb, int hb){ - ODEUM *odeum; - ODDOC *doc; - if(!(odeum = odopen(name, OD_OREADER))){ - pdperror(name); - return 1; - } - if(id > 0){ - if(!(doc = odgetbyid(odeum, id))){ - pdperror(name); - odclose(odeum); - return 1; - } - } else { - if(!(doc = odget(odeum, uri))){ - pdperror(name); - odclose(odeum); - return 1; - } - } - printdoc(doc, tb, hb, -1, odeum, NULL); - oddocclose(doc); - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform search command */ -int dosearch(const char *name, const char *text, int max, int or, int idf, int ql, - int tb, int hb, int nb){ - ODEUM *odeum; - CBLIST *awords, *nwords, *uris, *hits; - ODPAIR *pairs, *last, *tmp; - ODDOC *doc; - const char *asis; - char *normal, numbuf[32]; - int i, j, pnum, lnum, hnum, tnum, shows; - double ival; - if(!(odeum = odopen(name, OD_OREADER))){ - pdperror(name); - return 1; - } - awords = odbreaktext(text); - nwords = cblistopen(); - uris = cblistopen(); - hits = cblistopen(); - last = NULL; - lnum = 0; - if(ql){ - last= odquery(odeum, text, &lnum, NULL); - } else { - for(i = 0; i < cblistnum(awords); i++){ - asis = cblistval(awords, i, NULL); - normal = odnormalizeword(asis); - cblistpush(nwords, normal, -1); - if(strlen(normal) < 1){ - free(normal); - continue; - } - if(!(pairs = odsearch(odeum, normal, or ? max : -1, &pnum))){ - pdperror(name); - free(normal); - continue; - } - if((hnum = odsearchdnum(odeum, normal)) < 0) hnum = 0; - if(idf){ - ival = odlogarithm(hnum); - ival = (ival * ival) / 4.0; - if(ival < 4.0) ival = 4.0; - for(j = 0; j < pnum; j++){ - pairs[j].score = (int)(pairs[j].score / ival); - } - } - cblistpush(uris, normal, -1); - sprintf(numbuf, "%d", hnum); - cblistpush(hits, numbuf, -1); - if(last){ - if(or){ - tmp = odpairsor(last, lnum, pairs, pnum, &tnum); - } else { - tmp = odpairsand(last, lnum, pairs, pnum, &tnum); - } - free(last); - free(pairs); - last = tmp; - lnum = tnum; - } else { - last = pairs; - lnum = pnum; - } - free(normal); - } - } - if(hb){ - printf("TOTAL: %d\n", lnum); - printf("EACHWORD: "); - } else { - printf("%d", lnum); - } - for(i = 0; i < cblistnum(uris); i++){ - if(hb){ - if(i > 0) printf(", "); - printf("%s(%s)", cblistval(uris, i, NULL), cblistval(hits, i, NULL)); - } else { - printf("\t%s\t%s", cblistval(uris, i, NULL), cblistval(hits, i, NULL)); - } - } - putchar('\n'); - if(hb) putchar('\n'); - if(last){ - if(max < 0) max = lnum; - shows = 0; - for(i = 0; i < lnum && shows < max; i++){ - if(nb){ - printf("%d\t%d\n", last[i].id, last[i].score); - shows++; - } else { - if(!(doc = odgetbyid(odeum, last[i].id))) continue; - printdoc(doc, tb, hb, last[i].score, odeum, nwords); - oddocclose(doc); - shows++; - } - } - free(last); - } - cblistclose(uris); - cblistclose(hits); - cblistclose(nwords); - cblistclose(awords); - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform list command */ -int dolist(const char *name, int tb, int hb){ - ODEUM *odeum; - ODDOC *doc; - if(!(odeum = odopen(name, OD_OREADER))){ - pdperror(name); - return 1; - } - if(!oditerinit(odeum)){ - odclose(odeum); - pdperror(name); - return 1; - } - while(TRUE){ - if(!(doc = oditernext(odeum))){ - if(dpecode == DP_ENOITEM) break; - odclose(odeum); - pdperror(name); - return 1; - } - printdoc(doc, tb, hb, -1, odeum, NULL); - oddocclose(doc); - } - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform optimize command */ -int dooptimize(const char *name){ - ODEUM *odeum; - if(!(odeum = odopen(name, OD_OWRITER))){ - pdperror(name); - return 1; - } - if(!odoptimize(odeum)){ - pdperror(name); - odclose(odeum); - return 1; - } - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform inform command */ -int doinform(const char *name){ - ODEUM *odeum; - char *tmp; - if(!(odeum = odopen(name, OD_OREADER))){ - pdperror(name); - return 1; - } - tmp = odname(odeum); - printf("name: %s\n", tmp ? tmp : "(null)"); - free(tmp); - printf("file size: %.0f\n", odfsiz(odeum)); - printf("index buckets: %d\n", odbnum(odeum)); - printf("used buckets: %d\n", odbusenum(odeum)); - printf("all documents: %d\n", oddnum(odeum)); - printf("all words: %d\n", odwnum(odeum)); - printf("inode number: %d\n", odinode(odeum)); - printf("modified time: %.0f\n", (double)odmtime(odeum)); - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform merge command */ -int domerge(const char *name, const CBLIST *elems){ - if(!odmerge(name, elems)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform remove command */ -int doremove(const char *name){ - if(!odremove(name)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform break command */ -int dobreak(const char *text, int hb, int kb, int sb){ - CBLIST *awords, *kwords; - CBMAP *scores; - ODDOC *doc; - const char *asis; - char *normal, *summary; - int i, first; - awords = odbreaktext(text); - if(kb || sb){ - doc = oddocopen(""); - for(i = 0; i < cblistnum(awords); i++){ - asis = cblistval(awords, i, NULL); - normal = odnormalizeword(asis); - oddocaddword(doc, normal, asis); - free(normal); - } - scores = oddocscores(doc, MAXKEYWORDS, NULL); - cbmapiterinit(scores); - kwords = cbmapkeys(scores); - if(kb){ - for(i = 0; i < cblistnum(kwords); i++){ - if(i > 0) putchar('\t'); - printf("%s", cblistval(kwords, i, NULL)); - } - putchar('\n'); - } else { - summary = docsummary(doc, kwords, MAXSUMMARY, FALSE); - printf("%s\n", summary); - free(summary); - } - cblistclose(kwords); - cbmapclose(scores); - oddocclose(doc); - } else if(hb){ - printf("NWORDS: "); - first = TRUE; - for(i = 0; i < cblistnum(awords); i++){ - asis = cblistval(awords, i, NULL); - normal = odnormalizeword(asis); - if(normal[0] == '\0'){ - free(normal); - continue; - } - if(!first) putchar(' '); - first = FALSE; - printf("%s", normal); - free(normal); - } - putchar('\n'); - printf("AWORDS: "); - first = TRUE; - for(i = 0; i < cblistnum(awords); i++){ - asis = cblistval(awords, i, NULL); - if(asis[0] == '\0') continue; - if(!first) putchar(' '); - first = FALSE; - printf("%s", asis); - } - putchar('\n'); - } else { - for(i = 0; i < cblistnum(awords); i++){ - asis = cblistval(awords, i, NULL); - normal = odnormalizeword(asis); - printf("%s\t%s\n", normal, asis); - free(normal); - } - } - cblistclose(awords); - return 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/odmgr.c (from rev 2716, box/trunk/qdbm/odmgr.c) =================================================================== --- box/trunk/qdbm/odmgr.c (rev 0) +++ box/trunk/qdbm/odmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,1085 @@ +/************************************************************************************************* + * Utility for debugging Odeum and its applications + * 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 +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define MAXSRCHWORDS 256 /* max number of search words */ +#define WOCCRPOINT 10000 /* points per occurence */ +#define MAXKEYWORDS 8 /* max number of keywords */ +#define SUMMARYWIDTH 16 /* width of each phrase in a summary */ +#define MAXSUMMARY 128 /* max number of words in a summary */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +char *readstdin(int *sp); +void otcb(const char *fname, ODEUM *odeum, const char *msg); +int runcreate(int argc, char **argv); +int runput(int argc, char **argv); +int runout(int argc, char **argv); +int runget(int argc, char **argv); +int runsearch(int argc, char **argv); +int runlist(int argc, char **argv); +int runoptimize(int argc, char **argv); +int runinform(int argc, char **argv); +int runmerge(int argc, char **argv); +int runremove(int argc, char **argv); +int runbreak(int argc, char **argv); +void pdperror(const char *name); +void printdoc(const ODDOC *doc, int tb, int hb, int score, ODEUM *odeum, const CBLIST *skeys); +char *docsummary(const ODDOC *doc, const CBLIST *kwords, int num, int hilight); +CBMAP *listtomap(const CBLIST *list); +int docreate(const char *name); +int doput(const char *name, const char *text, const char *uri, const char *title, + const char *author, const char *date, int wmax, int keep); +int doout(const char *name, const char *uri, int id); +int doget(const char *name, const char *uri, int id, int tb, int hb); +int dosearch(const char *name, const char *text, int max, int or, int idf, int ql, + int tb, int hb, int nb); +int dolist(const char *name, int tb, int hb); +int dooptimize(const char *name); +int doinform(const char *name); +int domerge(const char *name, const CBLIST *elems); +int doremove(const char *name); +int dobreak(const char *text, int hb, int kb, int sb); + + +/* main routine */ +int main(int argc, char **argv){ + char *env; + int rv; + cbstdiobin(); + progname = argv[0]; + if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "create")){ + odsetotcb(otcb); + rv = runcreate(argc, argv); + } else if(!strcmp(argv[1], "put")){ + odsetotcb(otcb); + rv = runput(argc, argv); + } else if(!strcmp(argv[1], "out")){ + odsetotcb(otcb); + rv = runout(argc, argv); + } else if(!strcmp(argv[1], "get")){ + rv = runget(argc, argv); + } else if(!strcmp(argv[1], "search")){ + rv = runsearch(argc, argv); + } else if(!strcmp(argv[1], "list")){ + rv = runlist(argc, argv); + } else if(!strcmp(argv[1], "optimize")){ + odsetotcb(otcb); + rv = runoptimize(argc, argv); + } else if(!strcmp(argv[1], "inform")){ + rv = runinform(argc, argv); + } else if(!strcmp(argv[1], "merge")){ + odsetotcb(otcb); + rv = runmerge(argc, argv); + } else if(!strcmp(argv[1], "remove")){ + rv = runremove(argc, argv); + } else if(!strcmp(argv[1], "break")){ + rv = runbreak(argc, argv); + } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ + printf("Powered by QDBM version %s\n", dpversion); + printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); + rv = 0; + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: administration utility for Odeum\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s create name\n", progname); + fprintf(stderr, " %s put [-uri str] [-title str] [-author str] [-date str]" + " [-wmax num] [-keep] name [file]\n", progname); + fprintf(stderr, " %s out [-id] name expr\n", progname); + fprintf(stderr, " %s get [-id] [-t|-h] name expr\n", progname); + fprintf(stderr, " %s search [-max num] [-or] [-idf] [-t|-h|-n] name words...\n", progname); + fprintf(stderr, " %s list [-t|-h] name\n", progname); + fprintf(stderr, " %s optimize name\n", progname); + fprintf(stderr, " %s inform name\n", progname); + fprintf(stderr, " %s merge name elems...\n", progname); + fprintf(stderr, " %s remove name\n", progname); + fprintf(stderr, " %s break [-h|-k|-s] [file]\n", progname); + fprintf(stderr, " %s version\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* read the standard input */ +char *readstdin(int *sp){ + char *buf; + int i, blen, c; + blen = 256; + buf = cbmalloc(blen); + for(i = 0; (c = getchar()) != EOF; i++){ + if(i >= blen - 1) buf = cbrealloc(buf, blen *= 2); + buf[i] = c; + } + buf[i] = '\0'; + *sp = i; + return buf; +} + + +/* report the outturn */ +void otcb(const char *fname, ODEUM *odeum, const char *msg){ + char *name; + name = odname(odeum); + printf("%s: %s: %s: %s\n", progname, fname, name, msg); + free(name); +} + + +/* parse arguments of create command */ +int runcreate(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = docreate(name); + return rv; +} + + +/* parse arguments of put command */ +int runput(int argc, char **argv){ + char *name, *file, *uri, *title, *author, *date, *text; + int i, wmax, keep, size, rv; + name = NULL; + file = NULL; + uri = NULL; + title = NULL; + author = NULL; + date = NULL; + wmax = -1; + keep = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-uri")){ + if(++i >= argc) usage(); + uri = argv[i]; + } else if(!strcmp(argv[i], "-uri")){ + if(++i >= argc) usage(); + uri = argv[i]; + } else if(!strcmp(argv[i], "-title")){ + if(++i >= argc) usage(); + title = argv[i]; + } else if(!strcmp(argv[i], "-author")){ + if(++i >= argc) usage(); + author = argv[i]; + } else if(!strcmp(argv[i], "-date")){ + if(++i >= argc) usage(); + date = argv[i]; + } else if(!strcmp(argv[i], "-wmax")){ + if(++i >= argc) usage(); + wmax = atoi(argv[i]); + } else if(!strcmp(argv[i], "-keep")){ + keep = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + if(!uri) uri = file; + if(!uri) usage(); + if(file){ + if(!(text = cbreadfile(file, &size))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + text = readstdin(&size); + } + rv = doput(name, text, uri, title, author, date, wmax, keep); + free(text); + return rv; +} + + +/* parse arguments of out command */ +int runout(int argc, char **argv){ + char *name, *expr; + int i, ib, id, rv; + name = NULL; + expr = NULL; + ib = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-id")){ + ib = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!expr){ + expr = argv[i]; + } else { + usage(); + } + } + if(!name || !expr) usage(); + id = -1; + if(ib){ + id = atoi(expr); + if(id < 1) usage(); + } + rv = doout(name, expr, id); + return rv; +} + + +/* parse arguments of get command */ +int runget(int argc, char **argv){ + char *name, *expr; + int i, ib, tb, hb, id, rv; + name = NULL; + expr = NULL; + ib = FALSE; + tb = FALSE; + hb = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-id")){ + ib = TRUE; + } else if(!strcmp(argv[i], "-t")){ + tb = TRUE; + } else if(!strcmp(argv[i], "-h")){ + hb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!expr){ + expr = argv[i]; + } else { + usage(); + } + } + if(!name || !expr) usage(); + id = -1; + if(ib){ + id = atoi(expr); + if(id < 1) usage(); + } + rv = doget(name, expr, id, tb, hb); + return rv; +} + + +/* parse arguments of search command */ +int runsearch(int argc, char **argv){ + char *name, *srchwords[MAXSRCHWORDS]; + int i, wnum, max, or, idf, ql, tb, hb, nb, rv; + CBDATUM *text; + name = NULL; + wnum = 0; + max = -1; + or = FALSE; + idf = FALSE; + ql = FALSE; + tb = FALSE; + hb = FALSE; + nb = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-max")){ + if(++i >= argc) usage(); + max = atoi(argv[i]); + } else if(!strcmp(argv[i], "-or")){ + or = TRUE; + } else if(!strcmp(argv[i], "-idf")){ + idf = TRUE; + } else if(!strcmp(argv[i], "-ql")){ + ql = TRUE; + } else if(!strcmp(argv[i], "-t")){ + tb = TRUE; + } else if(!strcmp(argv[i], "-h")){ + hb = TRUE; + } else if(!strcmp(argv[i], "-n")){ + nb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(wnum < MAXSRCHWORDS){ + srchwords[wnum++] = argv[i]; + } + } + if(!name) usage(); + text = cbdatumopen(NULL, -1); + for(i = 0; i < wnum; i++){ + if(i > 0) cbdatumcat(text, " ", 1); + cbdatumcat(text, srchwords[i], -1); + } + rv = dosearch(name, cbdatumptr(text), max, or, idf, ql, tb, hb, nb); + cbdatumclose(text); + return rv; +} + + +/* parse arguments of list command */ +int runlist(int argc, char **argv){ + char *name; + int i, tb, hb, rv; + name = NULL; + tb = FALSE; + hb = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-t")){ + tb = TRUE; + } else if(!strcmp(argv[i], "-h")){ + hb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dolist(name, tb, hb); + return rv; +} + + +/* parse arguments of optimize command */ +int runoptimize(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dooptimize(name); + return rv; +} + + +/* parse arguments of inform command */ +int runinform(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doinform(name); + return rv; +} + + +/* parse arguments of merge command */ +int runmerge(int argc, char **argv){ + char *name; + CBLIST *elems; + int i, rv; + name = NULL; + elems = cblistopen(); + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + cblistpush(elems, argv[i], -1); + } + } + if(!name) usage(); + if(cblistnum(elems) < 1){ + cblistclose(elems); + usage(); + } + rv = domerge(name, elems); + cblistclose(elems); + return rv; +} + + +/* parse arguments of remove command */ +int runremove(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doremove(name); + return rv; +} + + +/* parse arguments of break command */ +int runbreak(int argc, char **argv){ + char *file, *text; + int i, hb, kb, sb, size, rv; + file = NULL; + hb = FALSE; + kb = FALSE; + sb = FALSE; + for(i = 2; i < argc; i++){ + if(!file && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-h")){ + hb = TRUE; + } else if(!strcmp(argv[i], "-k")){ + kb = TRUE; + } else if(!strcmp(argv[i], "-s")){ + sb = TRUE; + } else { + usage(); + } + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + if(file){ + if(!(text = cbreadfile(file, &size))){ + fprintf(stderr, "%s: %s: cannot open\n", progname, file); + return 1; + } + } else { + text = readstdin(&size); + } + rv = dobreak(text, hb, kb, sb); + free(text); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* print the contents of a document */ +void printdoc(const ODDOC *doc, int tb, int hb, int score, ODEUM *odeum, const CBLIST *skeys){ + const CBLIST *words; + CBMAP *scores; + CBLIST *kwords; + const char *title, *author, *word, *date; + char *summary; + int i, wsiz; + title = oddocgetattr(doc, "title"); + author = oddocgetattr(doc, "author"); + date = oddocgetattr(doc, "date"); + if(hb){ + printf("ID: %d\n", oddocid(doc)); + printf("URI: %s\n", oddocuri(doc)); + if(title) printf("TITLE: %s\n", title); + if(author) printf("AUTHOR: %s\n", author); + if(date) printf("DATE: %s\n", date); + if(score >= 0) printf("SCORE: %d\n", score); + scores = oddocscores(doc, MAXKEYWORDS, odeum); + kwords = cblistopen(); + printf("KEYWORDS: "); + cbmapiterinit(scores); + while((word = cbmapiternext(scores, &wsiz)) != NULL){ + if(cblistnum(kwords) > 0) printf(", "); + printf("%s (%s)", word, cbmapget(scores, word, wsiz, NULL)); + cblistpush(kwords, word, wsiz); + } + putchar('\n'); + summary = docsummary(doc, skeys ? skeys : kwords, MAXSUMMARY, skeys != NULL); + printf("SUMMARY: %s\n", summary); + free(summary); + cblistclose(kwords); + cbmapclose(scores); + printf("\n\n"); + } else if(tb){ + printf("%d\t%s\t%s\t%s\t%s\t%d\n", oddocid(doc), oddocuri(doc), + title ? title : "", author ? author : "", date ? date : "", score); + words = oddocnwords(doc); + for(i = 0; i < cblistnum(words); i++){ + word = cblistval(words, i, &wsiz); + if(i > 0) putchar('\t'); + printf("%s", word); + } + putchar('\n'); + words = oddocawords(doc); + for(i = 0; i < cblistnum(words); i++){ + word = cblistval(words, i, &wsiz); + if(i > 0) putchar('\t'); + printf("%s", word); + } + putchar('\n'); + } else { + printf("%d\t%s\t%d\n", oddocid(doc), oddocuri(doc), score); + } +} + + +/* get a list handle contains summary of a document */ +char *docsummary(const ODDOC *doc, const CBLIST *kwords, int num, int hilight){ + const CBLIST *nwords, *awords; + CBMAP *kmap, *map; + const char *normal, *asis; + char *sbuf; + int i, j, bsiz, ssiz, lnum, nwsiz, awsiz, pv, bi, first; + bsiz = 256; + sbuf = cbmalloc(bsiz); + ssiz = 0; + nwords = oddocnwords(doc); + awords = oddocawords(doc); + kmap = listtomap(kwords); + map = listtomap(kwords); + lnum = cblistnum(nwords); + first = TRUE; + for(i = 0; i < lnum && i < SUMMARYWIDTH; i++){ + normal = cblistval(nwords, i, &nwsiz); + asis = cblistval(awords, i, &awsiz); + if(awsiz < 1) continue; + cbmapout(map, normal, nwsiz); + if(ssiz + awsiz + 16 >= bsiz){ + bsiz = bsiz * 2 + awsiz; + sbuf = cbrealloc(sbuf, bsiz); + } + if(!first) ssiz += sprintf(sbuf + ssiz, " "); + if(hilight && normal[0] != '\0' && cbmapget(kmap, normal, nwsiz, NULL)){ + ssiz += sprintf(sbuf + ssiz, "<<%s>>", asis); + } else { + ssiz += sprintf(sbuf + ssiz, "%s", asis); + } + first = FALSE; + num--; + } + ssiz += sprintf(sbuf + ssiz, " ..."); + pv = i; + while(i < lnum){ + if(cbmaprnum(map) < 1){ + cbmapclose(map); + map = listtomap(kwords); + } + normal = cblistval(nwords, i, &nwsiz); + if(cbmapget(map, normal, nwsiz, NULL)){ + bi = i - SUMMARYWIDTH / 2; + bi = bi > pv ? bi : pv; + for(j = bi; j < lnum && j <= bi + SUMMARYWIDTH; j++){ + normal = cblistval(nwords, j, &nwsiz); + asis = cblistval(awords, j, &awsiz); + if(awsiz < 1) continue; + cbmapout(map, normal, nwsiz); + if(ssiz + awsiz + 16 >= bsiz){ + bsiz = bsiz * 2 + awsiz; + sbuf = cbrealloc(sbuf, bsiz); + } + ssiz += sprintf(sbuf + ssiz, " "); + if(hilight && normal[0] != '\0' && cbmapget(kmap, normal, nwsiz, NULL)){ + ssiz += sprintf(sbuf + ssiz, "<<%s>>", asis); + } else { + ssiz += sprintf(sbuf + ssiz, "%s", asis); + } + num--; + } + ssiz += sprintf(sbuf + ssiz, " ..."); + i = j; + pv = i; + } else { + i++; + } + if(num <= 0) break; + } + cbmapclose(map); + cbmapclose(kmap); + return sbuf; +} + + +/* get a map made from a list */ +CBMAP *listtomap(const CBLIST *list){ + CBMAP *map; + const char *tmp; + int i, tsiz; + map = cbmapopen(); + for(i = 0; i < cblistnum(list); i++){ + tmp = cblistval(list, i, &tsiz); + cbmapput(map, tmp, tsiz, "", 0, FALSE); + } + return map; +} + + +/* perform create command */ +int docreate(const char *name){ + ODEUM *odeum; + if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ + pdperror(name); + return 1; + } + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform put command */ +int doput(const char *name, const char *text, const char *uri, const char *title, + const char *author, const char *date, int wmax, int keep){ + ODEUM *odeum; + ODDOC *doc; + CBLIST *awords; + const char *asis; + char *normal; + int i; + if(!(odeum = odopen(name, OD_OWRITER))){ + pdperror(name); + return 1; + } + doc = oddocopen(uri); + if(title) oddocaddattr(doc, "title", title); + if(author) oddocaddattr(doc, "author", author); + if(date) oddocaddattr(doc, "date", date); + awords = odbreaktext(text); + for(i = 0; i < cblistnum(awords); i++){ + asis = cblistval(awords, i, NULL); + normal = odnormalizeword(asis); + oddocaddword(doc, normal, asis); + free(normal); + } + cblistclose(awords); + if(!odput(odeum, doc, wmax, keep ? FALSE : TRUE)){ + pdperror(name); + oddocclose(doc); + odclose(odeum); + return 1; + } + oddocclose(doc); + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform out command */ +int doout(const char *name, const char *uri, int id){ + ODEUM *odeum; + if(!(odeum = odopen(name, OD_OWRITER))){ + pdperror(name); + return 1; + } + if(id > 0){ + if(!odoutbyid(odeum, id)){ + pdperror(name); + odclose(odeum); + return 1; + } + } else { + if(!odout(odeum, uri)){ + pdperror(name); + odclose(odeum); + return 1; + } + } + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform get command */ +int doget(const char *name, const char *uri, int id, int tb, int hb){ + ODEUM *odeum; + ODDOC *doc; + if(!(odeum = odopen(name, OD_OREADER))){ + pdperror(name); + return 1; + } + if(id > 0){ + if(!(doc = odgetbyid(odeum, id))){ + pdperror(name); + odclose(odeum); + return 1; + } + } else { + if(!(doc = odget(odeum, uri))){ + pdperror(name); + odclose(odeum); + return 1; + } + } + printdoc(doc, tb, hb, -1, odeum, NULL); + oddocclose(doc); + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform search command */ +int dosearch(const char *name, const char *text, int max, int or, int idf, int ql, + int tb, int hb, int nb){ + ODEUM *odeum; + CBLIST *awords, *nwords, *uris, *hits; + ODPAIR *pairs, *last, *tmp; + ODDOC *doc; + const char *asis; + char *normal, numbuf[32]; + int i, j, pnum, lnum, hnum, tnum, shows; + double ival; + if(!(odeum = odopen(name, OD_OREADER))){ + pdperror(name); + return 1; + } + awords = odbreaktext(text); + nwords = cblistopen(); + uris = cblistopen(); + hits = cblistopen(); + last = NULL; + lnum = 0; + if(ql){ + last= odquery(odeum, text, &lnum, NULL); + } else { + for(i = 0; i < cblistnum(awords); i++){ + asis = cblistval(awords, i, NULL); + normal = odnormalizeword(asis); + cblistpush(nwords, normal, -1); + if(strlen(normal) < 1){ + free(normal); + continue; + } + if(!(pairs = odsearch(odeum, normal, or ? max : -1, &pnum))){ + pdperror(name); + free(normal); + continue; + } + if((hnum = odsearchdnum(odeum, normal)) < 0) hnum = 0; + if(idf){ + ival = odlogarithm(hnum); + ival = (ival * ival) / 4.0; + if(ival < 4.0) ival = 4.0; + for(j = 0; j < pnum; j++){ + pairs[j].score = (int)(pairs[j].score / ival); + } + } + cblistpush(uris, normal, -1); + sprintf(numbuf, "%d", hnum); + cblistpush(hits, numbuf, -1); + if(last){ + if(or){ + tmp = odpairsor(last, lnum, pairs, pnum, &tnum); + } else { + tmp = odpairsand(last, lnum, pairs, pnum, &tnum); + } + free(last); + free(pairs); + last = tmp; + lnum = tnum; + } else { + last = pairs; + lnum = pnum; + } + free(normal); + } + } + if(hb){ + printf("TOTAL: %d\n", lnum); + printf("EACHWORD: "); + } else { + printf("%d", lnum); + } + for(i = 0; i < cblistnum(uris); i++){ + if(hb){ + if(i > 0) printf(", "); + printf("%s(%s)", cblistval(uris, i, NULL), cblistval(hits, i, NULL)); + } else { + printf("\t%s\t%s", cblistval(uris, i, NULL), cblistval(hits, i, NULL)); + } + } + putchar('\n'); + if(hb) putchar('\n'); + if(last){ + if(max < 0) max = lnum; + shows = 0; + for(i = 0; i < lnum && shows < max; i++){ + if(nb){ + printf("%d\t%d\n", last[i].id, last[i].score); + shows++; + } else { + if(!(doc = odgetbyid(odeum, last[i].id))) continue; + printdoc(doc, tb, hb, last[i].score, odeum, nwords); + oddocclose(doc); + shows++; + } + } + free(last); + } + cblistclose(uris); + cblistclose(hits); + cblistclose(nwords); + cblistclose(awords); + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform list command */ +int dolist(const char *name, int tb, int hb){ + ODEUM *odeum; + ODDOC *doc; + if(!(odeum = odopen(name, OD_OREADER))){ + pdperror(name); + return 1; + } + if(!oditerinit(odeum)){ + odclose(odeum); + pdperror(name); + return 1; + } + while(TRUE){ + if(!(doc = oditernext(odeum))){ + if(dpecode == DP_ENOITEM) break; + odclose(odeum); + pdperror(name); + return 1; + } + printdoc(doc, tb, hb, -1, odeum, NULL); + oddocclose(doc); + } + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform optimize command */ +int dooptimize(const char *name){ + ODEUM *odeum; + if(!(odeum = odopen(name, OD_OWRITER))){ + pdperror(name); + return 1; + } + if(!odoptimize(odeum)){ + pdperror(name); + odclose(odeum); + return 1; + } + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform inform command */ +int doinform(const char *name){ + ODEUM *odeum; + char *tmp; + if(!(odeum = odopen(name, OD_OREADER))){ + pdperror(name); + return 1; + } + tmp = odname(odeum); + printf("name: %s\n", tmp ? tmp : "(null)"); + free(tmp); + printf("file size: %.0f\n", odfsiz(odeum)); + printf("index buckets: %d\n", odbnum(odeum)); + printf("used buckets: %d\n", odbusenum(odeum)); + printf("all documents: %d\n", oddnum(odeum)); + printf("all words: %d\n", odwnum(odeum)); + printf("inode number: %d\n", odinode(odeum)); + printf("modified time: %.0f\n", (double)odmtime(odeum)); + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform merge command */ +int domerge(const char *name, const CBLIST *elems){ + if(!odmerge(name, elems)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform remove command */ +int doremove(const char *name){ + if(!odremove(name)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform break command */ +int dobreak(const char *text, int hb, int kb, int sb){ + CBLIST *awords, *kwords; + CBMAP *scores; + ODDOC *doc; + const char *asis; + char *normal, *summary; + int i, first; + awords = odbreaktext(text); + if(kb || sb){ + doc = oddocopen(""); + for(i = 0; i < cblistnum(awords); i++){ + asis = cblistval(awords, i, NULL); + normal = odnormalizeword(asis); + oddocaddword(doc, normal, asis); + free(normal); + } + scores = oddocscores(doc, MAXKEYWORDS, NULL); + cbmapiterinit(scores); + kwords = cbmapkeys(scores); + if(kb){ + for(i = 0; i < cblistnum(kwords); i++){ + if(i > 0) putchar('\t'); + printf("%s", cblistval(kwords, i, NULL)); + } + putchar('\n'); + } else { + summary = docsummary(doc, kwords, MAXSUMMARY, FALSE); + printf("%s\n", summary); + free(summary); + } + cblistclose(kwords); + cbmapclose(scores); + oddocclose(doc); + } else if(hb){ + printf("NWORDS: "); + first = TRUE; + for(i = 0; i < cblistnum(awords); i++){ + asis = cblistval(awords, i, NULL); + normal = odnormalizeword(asis); + if(normal[0] == '\0'){ + free(normal); + continue; + } + if(!first) putchar(' '); + first = FALSE; + printf("%s", normal); + free(normal); + } + putchar('\n'); + printf("AWORDS: "); + first = TRUE; + for(i = 0; i < cblistnum(awords); i++){ + asis = cblistval(awords, i, NULL); + if(asis[0] == '\0') continue; + if(!first) putchar(' '); + first = FALSE; + printf("%s", asis); + } + putchar('\n'); + } else { + for(i = 0; i < cblistnum(awords); i++){ + asis = cblistval(awords, i, NULL); + normal = odnormalizeword(asis); + printf("%s\t%s\n", normal, asis); + free(normal); + } + } + cblistclose(awords); + return 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/odtest.c =================================================================== --- box/trunk/qdbm/odtest.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/odtest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,694 +0,0 @@ -/************************************************************************************************* - * Test cases of Odeum - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define DOCBUFSIZ 256 /* buffer for documents */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -int runwrite(int argc, char **argv); -int runread(int argc, char **argv); -int runcombo(int argc, char **argv); -int runwicked(int argc, char **argv); -int printfflush(const char *format, ...); -void pdperror(const char *name); -int myrand(void); -ODDOC *makedoc(int id, int wnum, int pnum); -int dowrite(const char *name, int dnum, int wnum, int pnum, - int ibnum, int idnum, int cbnum, int csiz); -int doread(const char *name); -int docombo(const char *name); -int dowicked(const char *name, int dnum); - - -/* main routine */ -int main(int argc, char **argv){ - char *env; - int rv; - cbstdiobin(); - if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "write")){ - rv = runwrite(argc, argv); - } else if(!strcmp(argv[1], "read")){ - rv = runread(argc, argv); - } else if(!strcmp(argv[1], "combo")){ - rv = runcombo(argc, argv); - } else if(!strcmp(argv[1], "wicked")){ - rv = runwicked(argc, argv); - } else { - usage(); - } - return 0; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: test cases for Odeum\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s write [-tune ibnum idnum cbnum csiz] name dnum wnum pnum\n", progname); - fprintf(stderr, " %s read name\n", progname); - fprintf(stderr, " %s combo name\n", progname); - fprintf(stderr, " %s wicked name dnum\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of write command */ -int runwrite(int argc, char **argv){ - char *name, *dstr, *wstr, *pstr; - int i, dnum, wnum, pnum, ibnum, idnum, cbnum, csiz, rv; - name = NULL; - dstr = NULL; - wstr = NULL; - pstr = NULL; - dnum = 0; - wnum = 0; - pnum = 0; - ibnum = -1; - idnum = -1; - cbnum = -1; - csiz = -1; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-tune")){ - if(++i >= argc) usage(); - ibnum = atoi(argv[i]); - if(++i >= argc) usage(); - idnum = atoi(argv[i]); - if(++i >= argc) usage(); - cbnum = atoi(argv[i]); - if(++i >= argc) usage(); - csiz = atoi(argv[i]); - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!dstr){ - dstr = argv[i]; - } else if(!wstr){ - wstr = argv[i]; - } else if(!pstr){ - pstr = argv[i]; - } else { - usage(); - } - } - if(!name || !dstr || !wstr || !pstr) usage(); - dnum = atoi(dstr); - wnum = atoi(wstr); - pnum = atoi(pstr); - if(dnum < 1 || wnum < 1 || pnum < 1) usage(); - rv = dowrite(name, dnum, wnum, pnum, ibnum, idnum, cbnum, csiz); - return rv; -} - - -/* parse arguments of read command */ -int runread(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doread(name); - return rv; -} - - -/* parse arguments of combo command */ -int runcombo(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = docombo(name); - return rv; -} - - -/* parse arguments of wicked command */ -int runwicked(int argc, char **argv){ - char *name, *dstr; - int i, dnum, rv; - name = NULL; - dstr = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else if(!dstr){ - dstr = argv[i]; - } else { - usage(); - } - } - if(!name || !dstr) usage(); - dnum = atoi(dstr); - if(dnum < 1) usage(); - rv = dowicked(name, dnum); - return rv; -} - - -/* print formatted string and flush the buffer */ -int printfflush(const char *format, ...){ - va_list ap; - int rv; - va_start(ap, format); - rv = vprintf(format, ap); - if(fflush(stdout) == EOF) rv = -1; - va_end(ap); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* pseudo random number generator */ -int myrand(void){ - static int cnt = 0; - if(cnt == 0) srand(time(NULL)); - return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; -} - - -/* create a document */ -ODDOC *makedoc(int id, int wnum, int pnum){ - ODDOC *doc; - char buf[DOCBUFSIZ]; - int i; - sprintf(buf, "%08d", id); - doc = oddocopen(buf); - oddocaddattr(doc, "title", buf); - oddocaddattr(doc, "author", buf); - oddocaddattr(doc, "date", buf); - for(i = 0; i < wnum; i++){ - sprintf(buf, "%08d", myrand() % pnum); - oddocaddword(doc, buf, buf); - } - return doc; -} - - -/* perform write command */ -int dowrite(const char *name, int dnum, int wnum, int pnum, - int ibnum, int idnum, int cbnum, int csiz){ - ODEUM *odeum; - ODDOC *doc; - int i, err; - printfflush("\n name=%s dnum=%d wnum=%d pnum=%d" - " ibnum=%d idnum=%d cbnum=%d csiz=%d\n\n", - name, dnum, wnum, pnum, ibnum, idnum, cbnum, csiz); - /* open a database */ - if(ibnum > 0) odsettuning(ibnum, idnum, cbnum, csiz); - if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ - pdperror(name); - return 1; - } - err = FALSE; - /* loop for each document */ - for(i = 1; i <= dnum; i++){ - /* store a document */ - doc = makedoc(i, wnum, pnum); - if(!odput(odeum, doc, -1, FALSE)){ - pdperror(name); - oddocclose(doc); - err = TRUE; - break; - } - oddocclose(doc); - /* print progression */ - if(dnum > 250 && i % (dnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == dnum || i % (dnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform read command */ -int doread(const char *name){ - ODEUM *odeum; - ODDOC *doc; - char buf[DOCBUFSIZ]; - int i, dnum, err; - printfflush("\n name=%s\n\n", name); - /* open a database */ - if(!(odeum = odopen(name, OD_OREADER))){ - pdperror(name); - return 1; - } - /* get the number of documents */ - dnum = oddnum(odeum); - err = FALSE; - /* loop for each document */ - for(i = 1; i <= dnum; i++){ - /* retrieve a document */ - sprintf(buf, "%08d", i); - if(!(doc = odget(odeum, buf))){ - pdperror(name); - err = TRUE; - break; - } - oddocclose(doc); - /* print progression */ - if(dnum > 250 && i % (dnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == dnum || i % (dnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform combo command */ -int docombo(const char *name){ - ODEUM *odeum; - ODDOC *doc; - const CBLIST *nwords, *awords; - CBLIST *tawords, *tnwords, *oawords; - ODPAIR *pairs; - const char *asis; - char buf[DOCBUFSIZ], *normal; - int i, j, pnum; - printfflush("\n name=%s\n\n", name); - printfflush("Creating a database with ... "); - if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 20 documents including about 200 words ... "); - for(i = 1; i <= 20; i++){ - sprintf(buf, "%08d", i); - doc = makedoc(i, 120 + myrand() % 160, myrand() % 500 + 500); - if(!odput(odeum, doc, 180 + myrand() % 40, FALSE)){ - pdperror(name); - oddocclose(doc); - odclose(odeum); - return 1; - } - oddocclose(doc); - } - printfflush("ok\n"); - printfflush("Checking documents ... "); - for(i = 1; i <= 20; i++){ - sprintf(buf, "%08d", i); - if(!(doc = odget(odeum, buf))){ - pdperror(name); - return 1; - } - nwords = oddocnwords(doc); - awords = oddocawords(doc); - if(!oddocuri(doc) || !oddocgetattr(doc, "title") || cblistnum(nwords) != cblistnum(awords)){ - fprintf(stderr, "%s: %s: invalid document\n", progname, name); - oddocclose(doc); - odclose(odeum); - return 1; - } - for(j = 0; j < cblistnum(nwords); j++){ - if(strcmp(cblistval(nwords, j, NULL), cblistval(nwords, j, NULL))){ - fprintf(stderr, "%s: %s: invalid words\n", progname, name); - oddocclose(doc); - odclose(odeum); - return 1; - } - } - oddocclose(doc); - } - printfflush("ok\n"); - printfflush("Syncing the database ... "); - if(!odsync(odeum)){ - pdperror(name); - odclose(odeum); - return 1; - } - printfflush("ok\n"); - printfflush("Overwriting 1 - 10 documents ... "); - for(i = 1; i <= 10; i++){ - sprintf(buf, "%08d", i); - doc = makedoc(i, 120 + myrand() % 160, myrand() % 500 + 500); - if(!odput(odeum, doc, 180 + myrand() % 40, TRUE)){ - pdperror(name); - oddocclose(doc); - odclose(odeum); - return 1; - } - oddocclose(doc); - } - printfflush("ok\n"); - printfflush("Deleting 11 - 20 documents ... "); - for(i = 11; i <= 20; i++){ - sprintf(buf, "%08d", i); - if(!odout(odeum, buf)){ - pdperror(name); - odclose(odeum); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking documents ... "); - for(i = 1; i <= 10; i++){ - sprintf(buf, "%08d", i); - if(!(doc = odget(odeum, buf))){ - pdperror(name); - return 1; - } - nwords = oddocnwords(doc); - awords = oddocawords(doc); - if(!oddocuri(doc) || !oddocgetattr(doc, "title") || cblistnum(nwords) != cblistnum(awords)){ - fprintf(stderr, "%s: %s: invalid document\n", progname, name); - oddocclose(doc); - odclose(odeum); - return 1; - } - for(j = 0; j < cblistnum(nwords); j++){ - if(strcmp(cblistval(nwords, j, NULL), cblistval(nwords, j, NULL))){ - fprintf(stderr, "%s: %s: invalid words\n", progname, name); - oddocclose(doc); - odclose(odeum); - return 1; - } - } - oddocclose(doc); - } - if(oddnum(odeum) != 10){ - fprintf(stderr, "%s: %s: invalid document number\n", progname, name); - odclose(odeum); - return 1; - } - printfflush("ok\n"); - printfflush("Optimizing the database ... "); - if(!odoptimize(odeum)){ - pdperror(name); - odclose(odeum); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 10 documents including about 200 words ... "); - for(i = 11; i <= 20; i++){ - sprintf(buf, "%08d", i); - doc = makedoc(i, 120 + myrand() % 160, myrand() % 500 + 500); - if(!odput(odeum, doc, 180 + myrand() % 40, FALSE)){ - pdperror(name); - oddocclose(doc); - odclose(odeum); - return 1; - } - oddocclose(doc); - } - printfflush("ok\n"); - printfflush("Deleting 6 - 15 documents ... "); - for(i = 6; i <= 15; i++){ - sprintf(buf, "%08d", i); - if(!odout(odeum, buf)){ - pdperror(name); - odclose(odeum); - return 1; - } - } - printfflush("ok\n"); - printfflush("Retrieving documents 100 times ... "); - for(i = 1; i <= 100; i++){ - sprintf(buf, "%08d", myrand() % 1000 + 1); - if((pairs = odsearch(odeum, buf, -1, &pnum)) != NULL){ - for(j = 0; j < pnum; j++){ - if((doc = odgetbyid(odeum, pairs[j].id)) != NULL){ - oddocclose(doc); - } else if(dpecode != DP_ENOITEM){ - pdperror(name); - odclose(odeum); - return 1; - } - } - free(pairs); - } else if(dpecode != DP_ENOITEM){ - pdperror(name); - odclose(odeum); - return 1; - } - } - printfflush("ok\n"); - printfflush("Analyzing text ... "); - tawords = cblistopen(); - tnwords = cblistopen(); - odanalyzetext(odeum, "I'd like to ++see++ Mr. X-men tomorrow.", tawords, tnwords); - odanalyzetext(odeum, "=== :-) SMILE . @ . SAD :-< ===", tawords, tnwords); - for(i = 0; i < DOCBUFSIZ - 1; i++){ - buf[i] = myrand() % 255 + 1; - } - buf[DOCBUFSIZ-1] = '\0'; - cblistclose(tnwords); - cblistclose(tawords); - for(i = 0; i < 1000; i++){ - for(j = 0; j < DOCBUFSIZ - 1; j++){ - if((j + 1) % 32 == 0){ - buf[j] = ' '; - } else { - buf[j] = myrand() % 255 + 1; - } - } - buf[DOCBUFSIZ-1] = '\0'; - tawords = cblistopen(); - tnwords = cblistopen(); - odanalyzetext(odeum, buf, tawords, tnwords); - oawords = odbreaktext(buf); - if(cblistnum(tawords) != cblistnum(oawords) || cblistnum(tnwords) != cblistnum(oawords)){ - fprintf(stderr, "%s: %s: invalid analyzing\n", progname, name); - cblistclose(oawords); - cblistclose(tnwords); - cblistclose(tawords); - odclose(odeum); - return 1; - } - for(j = 0; j < cblistnum(oawords); j++){ - asis = cblistval(oawords, j, NULL); - normal = odnormalizeword(asis); - if(strcmp(asis, cblistval(oawords, j, NULL)) || strcmp(normal, cblistval(tnwords, j, NULL))){ - fprintf(stderr, "%s: %s: invalid analyzing\n", progname, name); - free(normal); - cblistclose(oawords); - cblistclose(tnwords); - cblistclose(tawords); - odclose(odeum); - return 1; - } - free(normal); - } - cblistclose(oawords); - cblistclose(tnwords); - cblistclose(tawords); - } - printfflush("ok\n"); - printfflush("Closing the database ... "); - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("all ok\n\n"); - return 0; -} - - -/* perform wicked command */ -int dowicked(const char *name, int dnum){ - ODEUM *odeum; - ODDOC *doc; - ODPAIR *pairs; - char buf[DOCBUFSIZ]; - int i, j, pnum, err; - printfflush("\n name=%s dnum=%d\n\n", name, dnum); - err = FALSE; - if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ - pdperror(name); - return 1; - } - for(i = 1; i <= dnum; i++){ - switch(myrand() % 8){ - case 1: - putchar('K'); - doc = makedoc(myrand() % dnum + 1, myrand() % 10 + 10, myrand() % dnum + 500); - if(!odput(odeum, doc, 5, FALSE) && dpecode != DP_EKEEP) err = TRUE; - oddocclose(doc); - break; - case 3: - putchar('D'); - if(!odoutbyid(odeum, myrand() % dnum + 1) && dpecode != DP_ENOITEM) err = TRUE; - break; - case 4: - putchar('R'); - sprintf(buf, "%08d", myrand() % (dnum + 500) + 1); - if((pairs = odsearch(odeum, buf, 5, &pnum)) != NULL){ - if(myrand() % 5 == 0){ - for(j = 0; j < pnum; j++){ - if((doc = odgetbyid(odeum, pairs[j].id)) != NULL){ - oddocclose(doc); - } else if(dpecode != DP_ENOITEM){ - err = TRUE; - break; - } - } - } - free(pairs); - } else if(dpecode != DP_ENOITEM){ - err = TRUE; - } - break; - default: - putchar('O'); - doc = makedoc(myrand() % dnum + 1, myrand() % 10 + 10, myrand() % dnum + 500); - if(!odput(odeum, doc, 5, TRUE)) err = TRUE; - oddocclose(doc); - break; - } - if(i % 50 == 0) printfflush(" (%08d)\n", i); - if(err){ - pdperror(name); - break; - } - } - if(!odoptimize(odeum)){ - pdperror(name); - err = TRUE; - } - for(i = 1; i <= dnum; i++){ - doc = makedoc(i, 5, 5); - if(!odput(odeum, doc, 5, FALSE) && dpecode != DP_EKEEP){ - pdperror(name); - oddocclose(doc); - err = TRUE; - break; - } - oddocclose(doc); - putchar(':'); - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - if(!odoptimize(odeum)){ - pdperror(name); - err = TRUE; - } - for(i = 1; i <= dnum; i++){ - sprintf(buf, "%08d", i); - if(!(doc = odget(odeum, buf))){ - pdperror(name); - err = TRUE; - break; - } - oddocclose(doc); - putchar('='); - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - if(!oditerinit(odeum)){ - pdperror(name); - err = TRUE; - } - for(i = 1; i <= dnum; i++){ - if(!(doc = oditernext(odeum))){ - pdperror(name); - err = TRUE; - break; - } - oddocclose(doc); - putchar('@'); - if(i % 50 == 0) printfflush(" (%08d)\n", i); - } - if(!odclose(odeum)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/odtest.c (from rev 2716, box/trunk/qdbm/odtest.c) =================================================================== --- box/trunk/qdbm/odtest.c (rev 0) +++ box/trunk/qdbm/odtest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,694 @@ +/************************************************************************************************* + * Test cases of Odeum + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define DOCBUFSIZ 256 /* buffer for documents */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +int runwrite(int argc, char **argv); +int runread(int argc, char **argv); +int runcombo(int argc, char **argv); +int runwicked(int argc, char **argv); +int printfflush(const char *format, ...); +void pdperror(const char *name); +int myrand(void); +ODDOC *makedoc(int id, int wnum, int pnum); +int dowrite(const char *name, int dnum, int wnum, int pnum, + int ibnum, int idnum, int cbnum, int csiz); +int doread(const char *name); +int docombo(const char *name); +int dowicked(const char *name, int dnum); + + +/* main routine */ +int main(int argc, char **argv){ + char *env; + int rv; + cbstdiobin(); + if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "write")){ + rv = runwrite(argc, argv); + } else if(!strcmp(argv[1], "read")){ + rv = runread(argc, argv); + } else if(!strcmp(argv[1], "combo")){ + rv = runcombo(argc, argv); + } else if(!strcmp(argv[1], "wicked")){ + rv = runwicked(argc, argv); + } else { + usage(); + } + return 0; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: test cases for Odeum\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s write [-tune ibnum idnum cbnum csiz] name dnum wnum pnum\n", progname); + fprintf(stderr, " %s read name\n", progname); + fprintf(stderr, " %s combo name\n", progname); + fprintf(stderr, " %s wicked name dnum\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of write command */ +int runwrite(int argc, char **argv){ + char *name, *dstr, *wstr, *pstr; + int i, dnum, wnum, pnum, ibnum, idnum, cbnum, csiz, rv; + name = NULL; + dstr = NULL; + wstr = NULL; + pstr = NULL; + dnum = 0; + wnum = 0; + pnum = 0; + ibnum = -1; + idnum = -1; + cbnum = -1; + csiz = -1; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-tune")){ + if(++i >= argc) usage(); + ibnum = atoi(argv[i]); + if(++i >= argc) usage(); + idnum = atoi(argv[i]); + if(++i >= argc) usage(); + cbnum = atoi(argv[i]); + if(++i >= argc) usage(); + csiz = atoi(argv[i]); + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!dstr){ + dstr = argv[i]; + } else if(!wstr){ + wstr = argv[i]; + } else if(!pstr){ + pstr = argv[i]; + } else { + usage(); + } + } + if(!name || !dstr || !wstr || !pstr) usage(); + dnum = atoi(dstr); + wnum = atoi(wstr); + pnum = atoi(pstr); + if(dnum < 1 || wnum < 1 || pnum < 1) usage(); + rv = dowrite(name, dnum, wnum, pnum, ibnum, idnum, cbnum, csiz); + return rv; +} + + +/* parse arguments of read command */ +int runread(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doread(name); + return rv; +} + + +/* parse arguments of combo command */ +int runcombo(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = docombo(name); + return rv; +} + + +/* parse arguments of wicked command */ +int runwicked(int argc, char **argv){ + char *name, *dstr; + int i, dnum, rv; + name = NULL; + dstr = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else if(!dstr){ + dstr = argv[i]; + } else { + usage(); + } + } + if(!name || !dstr) usage(); + dnum = atoi(dstr); + if(dnum < 1) usage(); + rv = dowicked(name, dnum); + return rv; +} + + +/* print formatted string and flush the buffer */ +int printfflush(const char *format, ...){ + va_list ap; + int rv; + va_start(ap, format); + rv = vprintf(format, ap); + if(fflush(stdout) == EOF) rv = -1; + va_end(ap); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* pseudo random number generator */ +int myrand(void){ + static int cnt = 0; + if(cnt == 0) srand(time(NULL)); + return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; +} + + +/* create a document */ +ODDOC *makedoc(int id, int wnum, int pnum){ + ODDOC *doc; + char buf[DOCBUFSIZ]; + int i; + sprintf(buf, "%08d", id); + doc = oddocopen(buf); + oddocaddattr(doc, "title", buf); + oddocaddattr(doc, "author", buf); + oddocaddattr(doc, "date", buf); + for(i = 0; i < wnum; i++){ + sprintf(buf, "%08d", myrand() % pnum); + oddocaddword(doc, buf, buf); + } + return doc; +} + + +/* perform write command */ +int dowrite(const char *name, int dnum, int wnum, int pnum, + int ibnum, int idnum, int cbnum, int csiz){ + ODEUM *odeum; + ODDOC *doc; + int i, err; + printfflush("\n name=%s dnum=%d wnum=%d pnum=%d" + " ibnum=%d idnum=%d cbnum=%d csiz=%d\n\n", + name, dnum, wnum, pnum, ibnum, idnum, cbnum, csiz); + /* open a database */ + if(ibnum > 0) odsettuning(ibnum, idnum, cbnum, csiz); + if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ + pdperror(name); + return 1; + } + err = FALSE; + /* loop for each document */ + for(i = 1; i <= dnum; i++){ + /* store a document */ + doc = makedoc(i, wnum, pnum); + if(!odput(odeum, doc, -1, FALSE)){ + pdperror(name); + oddocclose(doc); + err = TRUE; + break; + } + oddocclose(doc); + /* print progression */ + if(dnum > 250 && i % (dnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == dnum || i % (dnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform read command */ +int doread(const char *name){ + ODEUM *odeum; + ODDOC *doc; + char buf[DOCBUFSIZ]; + int i, dnum, err; + printfflush("\n name=%s\n\n", name); + /* open a database */ + if(!(odeum = odopen(name, OD_OREADER))){ + pdperror(name); + return 1; + } + /* get the number of documents */ + dnum = oddnum(odeum); + err = FALSE; + /* loop for each document */ + for(i = 1; i <= dnum; i++){ + /* retrieve a document */ + sprintf(buf, "%08d", i); + if(!(doc = odget(odeum, buf))){ + pdperror(name); + err = TRUE; + break; + } + oddocclose(doc); + /* print progression */ + if(dnum > 250 && i % (dnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == dnum || i % (dnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform combo command */ +int docombo(const char *name){ + ODEUM *odeum; + ODDOC *doc; + const CBLIST *nwords, *awords; + CBLIST *tawords, *tnwords, *oawords; + ODPAIR *pairs; + const char *asis; + char buf[DOCBUFSIZ], *normal; + int i, j, pnum; + printfflush("\n name=%s\n\n", name); + printfflush("Creating a database with ... "); + if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 20 documents including about 200 words ... "); + for(i = 1; i <= 20; i++){ + sprintf(buf, "%08d", i); + doc = makedoc(i, 120 + myrand() % 160, myrand() % 500 + 500); + if(!odput(odeum, doc, 180 + myrand() % 40, FALSE)){ + pdperror(name); + oddocclose(doc); + odclose(odeum); + return 1; + } + oddocclose(doc); + } + printfflush("ok\n"); + printfflush("Checking documents ... "); + for(i = 1; i <= 20; i++){ + sprintf(buf, "%08d", i); + if(!(doc = odget(odeum, buf))){ + pdperror(name); + return 1; + } + nwords = oddocnwords(doc); + awords = oddocawords(doc); + if(!oddocuri(doc) || !oddocgetattr(doc, "title") || cblistnum(nwords) != cblistnum(awords)){ + fprintf(stderr, "%s: %s: invalid document\n", progname, name); + oddocclose(doc); + odclose(odeum); + return 1; + } + for(j = 0; j < cblistnum(nwords); j++){ + if(strcmp(cblistval(nwords, j, NULL), cblistval(nwords, j, NULL))){ + fprintf(stderr, "%s: %s: invalid words\n", progname, name); + oddocclose(doc); + odclose(odeum); + return 1; + } + } + oddocclose(doc); + } + printfflush("ok\n"); + printfflush("Syncing the database ... "); + if(!odsync(odeum)){ + pdperror(name); + odclose(odeum); + return 1; + } + printfflush("ok\n"); + printfflush("Overwriting 1 - 10 documents ... "); + for(i = 1; i <= 10; i++){ + sprintf(buf, "%08d", i); + doc = makedoc(i, 120 + myrand() % 160, myrand() % 500 + 500); + if(!odput(odeum, doc, 180 + myrand() % 40, TRUE)){ + pdperror(name); + oddocclose(doc); + odclose(odeum); + return 1; + } + oddocclose(doc); + } + printfflush("ok\n"); + printfflush("Deleting 11 - 20 documents ... "); + for(i = 11; i <= 20; i++){ + sprintf(buf, "%08d", i); + if(!odout(odeum, buf)){ + pdperror(name); + odclose(odeum); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking documents ... "); + for(i = 1; i <= 10; i++){ + sprintf(buf, "%08d", i); + if(!(doc = odget(odeum, buf))){ + pdperror(name); + return 1; + } + nwords = oddocnwords(doc); + awords = oddocawords(doc); + if(!oddocuri(doc) || !oddocgetattr(doc, "title") || cblistnum(nwords) != cblistnum(awords)){ + fprintf(stderr, "%s: %s: invalid document\n", progname, name); + oddocclose(doc); + odclose(odeum); + return 1; + } + for(j = 0; j < cblistnum(nwords); j++){ + if(strcmp(cblistval(nwords, j, NULL), cblistval(nwords, j, NULL))){ + fprintf(stderr, "%s: %s: invalid words\n", progname, name); + oddocclose(doc); + odclose(odeum); + return 1; + } + } + oddocclose(doc); + } + if(oddnum(odeum) != 10){ + fprintf(stderr, "%s: %s: invalid document number\n", progname, name); + odclose(odeum); + return 1; + } + printfflush("ok\n"); + printfflush("Optimizing the database ... "); + if(!odoptimize(odeum)){ + pdperror(name); + odclose(odeum); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 10 documents including about 200 words ... "); + for(i = 11; i <= 20; i++){ + sprintf(buf, "%08d", i); + doc = makedoc(i, 120 + myrand() % 160, myrand() % 500 + 500); + if(!odput(odeum, doc, 180 + myrand() % 40, FALSE)){ + pdperror(name); + oddocclose(doc); + odclose(odeum); + return 1; + } + oddocclose(doc); + } + printfflush("ok\n"); + printfflush("Deleting 6 - 15 documents ... "); + for(i = 6; i <= 15; i++){ + sprintf(buf, "%08d", i); + if(!odout(odeum, buf)){ + pdperror(name); + odclose(odeum); + return 1; + } + } + printfflush("ok\n"); + printfflush("Retrieving documents 100 times ... "); + for(i = 1; i <= 100; i++){ + sprintf(buf, "%08d", myrand() % 1000 + 1); + if((pairs = odsearch(odeum, buf, -1, &pnum)) != NULL){ + for(j = 0; j < pnum; j++){ + if((doc = odgetbyid(odeum, pairs[j].id)) != NULL){ + oddocclose(doc); + } else if(dpecode != DP_ENOITEM){ + pdperror(name); + odclose(odeum); + return 1; + } + } + free(pairs); + } else if(dpecode != DP_ENOITEM){ + pdperror(name); + odclose(odeum); + return 1; + } + } + printfflush("ok\n"); + printfflush("Analyzing text ... "); + tawords = cblistopen(); + tnwords = cblistopen(); + odanalyzetext(odeum, "I'd like to ++see++ Mr. X-men tomorrow.", tawords, tnwords); + odanalyzetext(odeum, "=== :-) SMILE . @ . SAD :-< ===", tawords, tnwords); + for(i = 0; i < DOCBUFSIZ - 1; i++){ + buf[i] = myrand() % 255 + 1; + } + buf[DOCBUFSIZ-1] = '\0'; + cblistclose(tnwords); + cblistclose(tawords); + for(i = 0; i < 1000; i++){ + for(j = 0; j < DOCBUFSIZ - 1; j++){ + if((j + 1) % 32 == 0){ + buf[j] = ' '; + } else { + buf[j] = myrand() % 255 + 1; + } + } + buf[DOCBUFSIZ-1] = '\0'; + tawords = cblistopen(); + tnwords = cblistopen(); + odanalyzetext(odeum, buf, tawords, tnwords); + oawords = odbreaktext(buf); + if(cblistnum(tawords) != cblistnum(oawords) || cblistnum(tnwords) != cblistnum(oawords)){ + fprintf(stderr, "%s: %s: invalid analyzing\n", progname, name); + cblistclose(oawords); + cblistclose(tnwords); + cblistclose(tawords); + odclose(odeum); + return 1; + } + for(j = 0; j < cblistnum(oawords); j++){ + asis = cblistval(oawords, j, NULL); + normal = odnormalizeword(asis); + if(strcmp(asis, cblistval(oawords, j, NULL)) || strcmp(normal, cblistval(tnwords, j, NULL))){ + fprintf(stderr, "%s: %s: invalid analyzing\n", progname, name); + free(normal); + cblistclose(oawords); + cblistclose(tnwords); + cblistclose(tawords); + odclose(odeum); + return 1; + } + free(normal); + } + cblistclose(oawords); + cblistclose(tnwords); + cblistclose(tawords); + } + printfflush("ok\n"); + printfflush("Closing the database ... "); + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("all ok\n\n"); + return 0; +} + + +/* perform wicked command */ +int dowicked(const char *name, int dnum){ + ODEUM *odeum; + ODDOC *doc; + ODPAIR *pairs; + char buf[DOCBUFSIZ]; + int i, j, pnum, err; + printfflush("\n name=%s dnum=%d\n\n", name, dnum); + err = FALSE; + if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ + pdperror(name); + return 1; + } + for(i = 1; i <= dnum; i++){ + switch(myrand() % 8){ + case 1: + putchar('K'); + doc = makedoc(myrand() % dnum + 1, myrand() % 10 + 10, myrand() % dnum + 500); + if(!odput(odeum, doc, 5, FALSE) && dpecode != DP_EKEEP) err = TRUE; + oddocclose(doc); + break; + case 3: + putchar('D'); + if(!odoutbyid(odeum, myrand() % dnum + 1) && dpecode != DP_ENOITEM) err = TRUE; + break; + case 4: + putchar('R'); + sprintf(buf, "%08d", myrand() % (dnum + 500) + 1); + if((pairs = odsearch(odeum, buf, 5, &pnum)) != NULL){ + if(myrand() % 5 == 0){ + for(j = 0; j < pnum; j++){ + if((doc = odgetbyid(odeum, pairs[j].id)) != NULL){ + oddocclose(doc); + } else if(dpecode != DP_ENOITEM){ + err = TRUE; + break; + } + } + } + free(pairs); + } else if(dpecode != DP_ENOITEM){ + err = TRUE; + } + break; + default: + putchar('O'); + doc = makedoc(myrand() % dnum + 1, myrand() % 10 + 10, myrand() % dnum + 500); + if(!odput(odeum, doc, 5, TRUE)) err = TRUE; + oddocclose(doc); + break; + } + if(i % 50 == 0) printfflush(" (%08d)\n", i); + if(err){ + pdperror(name); + break; + } + } + if(!odoptimize(odeum)){ + pdperror(name); + err = TRUE; + } + for(i = 1; i <= dnum; i++){ + doc = makedoc(i, 5, 5); + if(!odput(odeum, doc, 5, FALSE) && dpecode != DP_EKEEP){ + pdperror(name); + oddocclose(doc); + err = TRUE; + break; + } + oddocclose(doc); + putchar(':'); + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + if(!odoptimize(odeum)){ + pdperror(name); + err = TRUE; + } + for(i = 1; i <= dnum; i++){ + sprintf(buf, "%08d", i); + if(!(doc = odget(odeum, buf))){ + pdperror(name); + err = TRUE; + break; + } + oddocclose(doc); + putchar('='); + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + if(!oditerinit(odeum)){ + pdperror(name); + err = TRUE; + } + for(i = 1; i <= dnum; i++){ + if(!(doc = oditernext(odeum))){ + pdperror(name); + err = TRUE; + break; + } + oddocclose(doc); + putchar('@'); + if(i % 50 == 0) printfflush(" (%08d)\n", i); + } + if(!odclose(odeum)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/qdbm.def =================================================================== --- box/trunk/qdbm/qdbm.def 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/qdbm.def 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,424 +0,0 @@ -EXPORTS - VL_CMPDEC = VL_CMPDEC DATA - VL_CMPINT = VL_CMPINT DATA - VL_CMPLEX = VL_CMPLEX DATA - VL_CMPNUM = VL_CMPNUM DATA - VST_CMPDEC = VST_CMPDEC DATA - VST_CMPINT = VST_CMPINT DATA - VST_CMPLEX = VST_CMPLEX DATA - VST_CMPNUM = VST_CMPNUM DATA - cbfatalfunc = cbfatalfunc DATA - dpdbgfd = dpdbgfd DATA - dpisreentrant = dpisreentrant DATA - dpsysname = dpsysname DATA - dpversion = dpversion DATA - gdbm_version = gdbm_version DATA - odcachebnum = odcachebnum DATA - odcachesiz = odcachesiz DATA - odindexbnum = odindexbnum DATA - odindexdnum = odindexdnum DATA - odotcb = odotcb DATA - cbbasedecode = cbbasedecode - cbbaseencode = cbbaseencode - cbbzdecode = cbbzdecode - cbbzencode = cbbzencode - cbcalendar = cbcalendar - cbcsvcells = cbcsvcells - cbcsvescape = cbcsvescape - cbcsvrows = cbcsvrows - cbcsvunescape = cbcsvunescape - cbdatestrhttp = cbdatestrhttp - cbdatestrwww = cbdatestrwww - cbdatumcat = cbdatumcat - cbdatumclose = cbdatumclose - cbdatumdup = cbdatumdup - cbdatumopen = cbdatumopen - cbdatumopenbuf = cbdatumopenbuf - cbdatumprintf = cbdatumprintf - cbdatumptr = cbdatumptr - cbdatumsetbuf = cbdatumsetbuf - cbdatumsetsize = cbdatumsetsize - cbdatumsize = cbdatumsize - cbdatumtomalloc = cbdatumtomalloc - cbdayofweek = cbdayofweek - cbdeflate = cbdeflate - cbdirlist = cbdirlist - cbencname = cbencname - cbfilestat = cbfilestat - cbfree = cbfree - cbgetcrc = cbgetcrc - cbggcsweep = cbggcsweep - cbglobalgc = cbglobalgc - cbgzdecode = cbgzdecode - cbgzencode = cbgzencode - cbheapclose = cbheapclose - cbheapdup = cbheapdup - cbheapinsert = cbheapinsert - cbheapnum = cbheapnum - cbheapopen = cbheapopen - cbheaptomalloc = cbheaptomalloc - cbheapval = cbheapval - cbhsort = cbhsort - cbiconv = cbiconv - cbinflate = cbinflate - cbisort = cbisort - cbjetlag = cbjetlag - cblistbsearch = cblistbsearch - cblistclose = cblistclose - cblistdump = cblistdump - cblistdup = cblistdup - cblistinsert = cblistinsert - cblistload = cblistload - cblistlsearch = cblistlsearch - cblistnum = cblistnum - cblistopen = cblistopen - cblistover = cblistover - cblistpop = cblistpop - cblistpush = cblistpush - cblistpushbuf = cblistpushbuf - cblistremove = cblistremove - cblistshift = cblistshift - cblistsort = cblistsort - cblistunshift = cblistunshift - cblistval = cblistval - cblzodecode = cblzodecode - cblzoencode = cblzoencode - cbmalloc = cbmalloc - cbmapclose = cbmapclose - cbmapdump = cbmapdump - cbmapdup = cbmapdup - cbmapget = cbmapget - cbmapiterinit = cbmapiterinit - cbmapiternext = cbmapiternext - cbmapiterval = cbmapiterval - cbmapkeys = cbmapkeys - cbmapload = cbmapload - cbmaploadone = cbmaploadone - cbmapmove = cbmapmove - cbmapopen = cbmapopen - cbmapopenex = cbmapopenex - cbmapout = cbmapout - cbmapput = cbmapput - cbmapputcat = cbmapputcat - cbmaprnum = cbmaprnum - cbmapvals = cbmapvals - cbmemdup = cbmemdup - cbmimebreak = cbmimebreak - cbmimedecode = cbmimedecode - cbmimeencode = cbmimeencode - cbmimeparts = cbmimeparts - cbmyfatal = cbmyfatal - cbproctime = cbproctime - cbqsort = cbqsort - cbquotedecode = cbquotedecode - cbquoteencode = cbquoteencode - cbreadfile = cbreadfile - cbreadlines = cbreadlines - cbrealloc = cbrealloc - cbremove = cbremove - cbreplace = cbreplace - cbsplit = cbsplit - cbsprintf = cbsprintf - cbssort = cbssort - cbstdiobin = cbstdiobin - cbstrbwimatch = cbstrbwimatch - cbstrbwmatch = cbstrbwmatch - cbstrcountutf = cbstrcountutf - cbstrcututf = cbstrcututf - cbstrfwimatch = cbstrfwimatch - cbstrfwmatch = cbstrfwmatch - cbstricmp = cbstricmp - cbstrmktime = cbstrmktime - cbstrsqzspc = cbstrsqzspc - cbstrstrbm = cbstrstrbm - cbstrstrkmp = cbstrstrkmp - cbstrtolower = cbstrtolower - cbstrtoupper = cbstrtoupper - cbstrtrim = cbstrtrim - cburlbreak = cburlbreak - cburldecode = cburldecode - cburlencode = cburlencode - cburlresolve = cburlresolve - cbvmemavail = cbvmemavail - cbwritefile = cbwritefile - cbxmlattrs = cbxmlattrs - cbxmlbreak = cbxmlbreak - cbxmlescape = cbxmlescape - cbxmlunescape = cbxmlunescape - crbnum = crbnum - crbusenum = crbusenum - crclose = crclose - crexportdb = crexportdb - crfatalerror = crfatalerror - crfsiz = crfsiz - crfsizd = crfsizd - crget = crget - crgetflags = crgetflags - crgetlob = crgetlob - crgetlobfd = crgetlobfd - crgetwb = crgetwb - crimportdb = crimportdb - crinode = crinode - criterinit = criterinit - criternext = criternext - crmemflush = crmemflush - crmemsync = crmemsync - crmtime = crmtime - crname = crname - cropen = cropen - croptimize = croptimize - crout = crout - croutlob = croutlob - crput = crput - crputlob = crputlob - crremove = crremove - crrepair = crrepair - crrnum = crrnum - crrnumlob = crrnumlob - crsetalign = crsetalign - crsetfbpsiz = crsetfbpsiz - crsetflags = crsetflags - crsnaffle = crsnaffle - crsync = crsync - crvsiz = crvsiz - crvsizlob = crvsizlob - crwritable = crwritable - dbm_clearerr = dbm_clearerr - dbm_close = dbm_close - dbm_delete = dbm_delete - dbm_dirfno = dbm_dirfno - dbm_error = dbm_error - dbm_fetch = dbm_fetch - dbm_firstkey = dbm_firstkey - dbm_nextkey = dbm_nextkey - dbm_open = dbm_open - dbm_pagfno = dbm_pagfno - dbm_rdonly = dbm_rdonly - dbm_store = dbm_store - dpbnum = dpbnum - dpbusenum = dpbusenum - dpclose = dpclose - dpecodeptr = dpecodeptr - dpecodeset = dpecodeset - dperrmsg = dperrmsg - dpexportdb = dpexportdb - dpfatalerror = dpfatalerror - dpfdesc = dpfdesc - dpfsiz = dpfsiz - dpget = dpget - dpgetflags = dpgetflags - dpgetwb = dpgetwb - dpimportdb = dpimportdb - dpinnerhash = dpinnerhash - dpinode = dpinode - dpiterinit = dpiterinit - dpiternext = dpiternext - dpmemflush = dpmemflush - dpmemsync = dpmemsync - dpmtime = dpmtime - dpname = dpname - dpopen = dpopen - dpoptimize = dpoptimize - dpout = dpout - dpouterhash = dpouterhash - dpprimenum = dpprimenum - dpput = dpput - dpremove = dpremove - dprepair = dprepair - dprnum = dprnum - dpsetalign = dpsetalign - dpsetfbpsiz = dpsetfbpsiz - dpsetflags = dpsetflags - dpsnaffle = dpsnaffle - dpsync = dpsync - dpvsiz = dpvsiz - dpwritable = dpwritable - gdbm_close = gdbm_close - gdbm_delete = gdbm_delete - gdbm_errnoptr = gdbm_errnoptr - gdbm_exists = gdbm_exists - gdbm_fdesc = gdbm_fdesc - gdbm_fetch = gdbm_fetch - gdbm_firstkey = gdbm_firstkey - gdbm_nextkey = gdbm_nextkey - gdbm_open = gdbm_open - gdbm_open2 = gdbm_open2 - gdbm_reorganize = gdbm_reorganize - gdbm_setopt = gdbm_setopt - gdbm_store = gdbm_store - gdbm_strerror = gdbm_strerror - gdbm_sync = gdbm_sync - odanalyzetext = odanalyzetext - odbnum = odbnum - odbreaktext = odbreaktext - odbusenum = odbusenum - odcheck = odcheck - odclose = odclose - oddnum = oddnum - oddocaddattr = oddocaddattr - oddocaddword = oddocaddword - oddocawords = oddocawords - oddocclose = oddocclose - oddocgetattr = oddocgetattr - oddocid = oddocid - oddocnwords = oddocnwords - oddocopen = oddocopen - oddocscores = oddocscores - oddocuri = oddocuri - odfatalerror = odfatalerror - odfsiz = odfsiz - odget = odget - odgetbyid = odgetbyid - odgetidbyuri = odgetidbyuri - odidbdocs = odidbdocs - odidbindex = odidbindex - odidbrdocs = odidbrdocs - odinode = odinode - oditerinit = oditerinit - oditernext = oditernext - odlogarithm = odlogarithm - odmerge = odmerge - odmtime = odmtime - odname = odname - odnormalizeword = odnormalizeword - odopen = odopen - odoptimize = odoptimize - odout = odout - odoutbyid = odoutbyid - odpairsand = odpairsand - odpairsnotand = odpairsnotand - odpairsor = odpairsor - odpairssort = odpairssort - odput = odput - odquery = odquery - odremove = odremove - odsearch = odsearch - odsearchdnum = odsearchdnum - odsetcharclass = odsetcharclass - odsetotcb = odsetotcb - odsettuning = odsettuning - odsquareroot = odsquareroot - odsync = odsync - odvecabsolute = odvecabsolute - odvecinnerproduct = odvecinnerproduct - odvectorcosine = odvectorcosine - odwnum = odwnum - odwritable = odwritable - vlclose = vlclose - vlcrdnumptr = vlcrdnumptr - vlcurfirst = vlcurfirst - vlcurjump = vlcurjump - vlcurkey = vlcurkey - vlcurkeycache = vlcurkeycache - vlcurlast = vlcurlast - vlcurnext = vlcurnext - vlcurout = vlcurout - vlcurprev = vlcurprev - vlcurput = vlcurput - vlcurval = vlcurval - vlcurvalcache = vlcurvalcache - vlexportdb = vlexportdb - vlfatalerror = vlfatalerror - vlfsiz = vlfsiz - vlget = vlget - vlgetcache = vlgetcache - vlgetcat = vlgetcat - vlgetflags = vlgetflags - vlgetlist = vlgetlist - vlimportdb = vlimportdb - vlinode = vlinode - vllnum = vllnum - vlmemflush = vlmemflush - vlmemsync = vlmemsync - vlmtime = vlmtime - vlmulcurclose = vlmulcurclose - vlmulcurfirst = vlmulcurfirst - vlmulcurjump = vlmulcurjump - vlmulcurkey = vlmulcurkey - vlmulcurkeycache = vlmulcurkeycache - vlmulcurlast = vlmulcurlast - vlmulcurnext = vlmulcurnext - vlmulcuropen = vlmulcuropen - vlmulcurprev = vlmulcurprev - vlmulcurval = vlmulcurval - vlmulcurvalcache = vlmulcurvalcache - vlname = vlname - vlnnum = vlnnum - vlopen = vlopen - vloptimize = vloptimize - vlout = vlout - vloutlist = vloutlist - vlput = vlput - vlputlist = vlputlist - vlremove = vlremove - vlrepair = vlrepair - vlrnum = vlrnum - vlsetfbpsiz = vlsetfbpsiz - vlsetflags = vlsetflags - vlsettuning = vlsettuning - vlsync = vlsync - vltranabort = vltranabort - vltranbegin = vltranbegin - vltrancommit = vltrancommit - vlvnum = vlvnum - vlvsiz = vlvsiz - vlwritable = vlwritable - vstclose = vstclose - vstcrdnumptr = vstcrdnumptr - vstcurfirst = vstcurfirst - vstcurjump = vstcurjump - vstcurkey = vstcurkey - vstcurkeycache = vstcurkeycache - vstcurlast = vstcurlast - vstcurnext = vstcurnext - vstcurout = vstcurout - vstcurprev = vstcurprev - vstcurput = vstcurput - vstcurval = vstcurval - vstcurvalcache = vstcurvalcache - vstexportdb = vstexportdb - vstfatalerror = vstfatalerror - vstfsiz = vstfsiz - vstget = vstget - vstgetcache = vstgetcache - vstgetcat = vstgetcat - vstgetflags = vstgetflags - vstgetlist = vstgetlist - vstimportdb = vstimportdb - vstinode = vstinode - vstlnum = vstlnum - vstmemflush = vstmemflush - vstmemsync = vstmemsync - vstmtime = vstmtime - vstmulcurclose = vstmulcurclose - vstmulcurfirst = vstmulcurfirst - vstmulcurjump = vstmulcurjump - vstmulcurkey = vstmulcurkey - vstmulcurkeycache = vstmulcurkeycache - vstmulcurlast = vstmulcurlast - vstmulcurnext = vstmulcurnext - vstmulcuropen = vstmulcuropen - vstmulcurprev = vstmulcurprev - vstmulcurval = vstmulcurval - vstmulcurvalcache = vstmulcurvalcache - vstname = vstname - vstnnum = vstnnum - vstopen = vstopen - vstoptimize = vstoptimize - vstout = vstout - vstoutlist = vstoutlist - vstput = vstput - vstputlist = vstputlist - vstremove = vstremove - vstrepair = vstrepair - vstrnum = vstrnum - vstsetfbpsiz = vstsetfbpsiz - vstsetflags = vstsetflags - vstsettuning = vstsettuning - vstsync = vstsync - vsttranabort = vsttranabort - vsttranbegin = vsttranbegin - vsttrancommit = vsttrancommit - vstvnum = vstvnum - vstvsiz = vstvsiz - vstwritable = vstwritable Copied: box/trunk/qdbm/qdbm.def (from rev 2716, box/trunk/qdbm/qdbm.def) =================================================================== --- box/trunk/qdbm/qdbm.def (rev 0) +++ box/trunk/qdbm/qdbm.def 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,424 @@ +EXPORTS + VL_CMPDEC = VL_CMPDEC DATA + VL_CMPINT = VL_CMPINT DATA + VL_CMPLEX = VL_CMPLEX DATA + VL_CMPNUM = VL_CMPNUM DATA + VST_CMPDEC = VST_CMPDEC DATA + VST_CMPINT = VST_CMPINT DATA + VST_CMPLEX = VST_CMPLEX DATA + VST_CMPNUM = VST_CMPNUM DATA + cbfatalfunc = cbfatalfunc DATA + dpdbgfd = dpdbgfd DATA + dpisreentrant = dpisreentrant DATA + dpsysname = dpsysname DATA + dpversion = dpversion DATA + gdbm_version = gdbm_version DATA + odcachebnum = odcachebnum DATA + odcachesiz = odcachesiz DATA + odindexbnum = odindexbnum DATA + odindexdnum = odindexdnum DATA + odotcb = odotcb DATA + cbbasedecode = cbbasedecode + cbbaseencode = cbbaseencode + cbbzdecode = cbbzdecode + cbbzencode = cbbzencode + cbcalendar = cbcalendar + cbcsvcells = cbcsvcells + cbcsvescape = cbcsvescape + cbcsvrows = cbcsvrows + cbcsvunescape = cbcsvunescape + cbdatestrhttp = cbdatestrhttp + cbdatestrwww = cbdatestrwww + cbdatumcat = cbdatumcat + cbdatumclose = cbdatumclose + cbdatumdup = cbdatumdup + cbdatumopen = cbdatumopen + cbdatumopenbuf = cbdatumopenbuf + cbdatumprintf = cbdatumprintf + cbdatumptr = cbdatumptr + cbdatumsetbuf = cbdatumsetbuf + cbdatumsetsize = cbdatumsetsize + cbdatumsize = cbdatumsize + cbdatumtomalloc = cbdatumtomalloc + cbdayofweek = cbdayofweek + cbdeflate = cbdeflate + cbdirlist = cbdirlist + cbencname = cbencname + cbfilestat = cbfilestat + cbfree = cbfree + cbgetcrc = cbgetcrc + cbggcsweep = cbggcsweep + cbglobalgc = cbglobalgc + cbgzdecode = cbgzdecode + cbgzencode = cbgzencode + cbheapclose = cbheapclose + cbheapdup = cbheapdup + cbheapinsert = cbheapinsert + cbheapnum = cbheapnum + cbheapopen = cbheapopen + cbheaptomalloc = cbheaptomalloc + cbheapval = cbheapval + cbhsort = cbhsort + cbiconv = cbiconv + cbinflate = cbinflate + cbisort = cbisort + cbjetlag = cbjetlag + cblistbsearch = cblistbsearch + cblistclose = cblistclose + cblistdump = cblistdump + cblistdup = cblistdup + cblistinsert = cblistinsert + cblistload = cblistload + cblistlsearch = cblistlsearch + cblistnum = cblistnum + cblistopen = cblistopen + cblistover = cblistover + cblistpop = cblistpop + cblistpush = cblistpush + cblistpushbuf = cblistpushbuf + cblistremove = cblistremove + cblistshift = cblistshift + cblistsort = cblistsort + cblistunshift = cblistunshift + cblistval = cblistval + cblzodecode = cblzodecode + cblzoencode = cblzoencode + cbmalloc = cbmalloc + cbmapclose = cbmapclose + cbmapdump = cbmapdump + cbmapdup = cbmapdup + cbmapget = cbmapget + cbmapiterinit = cbmapiterinit + cbmapiternext = cbmapiternext + cbmapiterval = cbmapiterval + cbmapkeys = cbmapkeys + cbmapload = cbmapload + cbmaploadone = cbmaploadone + cbmapmove = cbmapmove + cbmapopen = cbmapopen + cbmapopenex = cbmapopenex + cbmapout = cbmapout + cbmapput = cbmapput + cbmapputcat = cbmapputcat + cbmaprnum = cbmaprnum + cbmapvals = cbmapvals + cbmemdup = cbmemdup + cbmimebreak = cbmimebreak + cbmimedecode = cbmimedecode + cbmimeencode = cbmimeencode + cbmimeparts = cbmimeparts + cbmyfatal = cbmyfatal + cbproctime = cbproctime + cbqsort = cbqsort + cbquotedecode = cbquotedecode + cbquoteencode = cbquoteencode + cbreadfile = cbreadfile + cbreadlines = cbreadlines + cbrealloc = cbrealloc + cbremove = cbremove + cbreplace = cbreplace + cbsplit = cbsplit + cbsprintf = cbsprintf + cbssort = cbssort + cbstdiobin = cbstdiobin + cbstrbwimatch = cbstrbwimatch + cbstrbwmatch = cbstrbwmatch + cbstrcountutf = cbstrcountutf + cbstrcututf = cbstrcututf + cbstrfwimatch = cbstrfwimatch + cbstrfwmatch = cbstrfwmatch + cbstricmp = cbstricmp + cbstrmktime = cbstrmktime + cbstrsqzspc = cbstrsqzspc + cbstrstrbm = cbstrstrbm + cbstrstrkmp = cbstrstrkmp + cbstrtolower = cbstrtolower + cbstrtoupper = cbstrtoupper + cbstrtrim = cbstrtrim + cburlbreak = cburlbreak + cburldecode = cburldecode + cburlencode = cburlencode + cburlresolve = cburlresolve + cbvmemavail = cbvmemavail + cbwritefile = cbwritefile + cbxmlattrs = cbxmlattrs + cbxmlbreak = cbxmlbreak + cbxmlescape = cbxmlescape + cbxmlunescape = cbxmlunescape + crbnum = crbnum + crbusenum = crbusenum + crclose = crclose + crexportdb = crexportdb + crfatalerror = crfatalerror + crfsiz = crfsiz + crfsizd = crfsizd + crget = crget + crgetflags = crgetflags + crgetlob = crgetlob + crgetlobfd = crgetlobfd + crgetwb = crgetwb + crimportdb = crimportdb + crinode = crinode + criterinit = criterinit + criternext = criternext + crmemflush = crmemflush + crmemsync = crmemsync + crmtime = crmtime + crname = crname + cropen = cropen + croptimize = croptimize + crout = crout + croutlob = croutlob + crput = crput + crputlob = crputlob + crremove = crremove + crrepair = crrepair + crrnum = crrnum + crrnumlob = crrnumlob + crsetalign = crsetalign + crsetfbpsiz = crsetfbpsiz + crsetflags = crsetflags + crsnaffle = crsnaffle + crsync = crsync + crvsiz = crvsiz + crvsizlob = crvsizlob + crwritable = crwritable + dbm_clearerr = dbm_clearerr + dbm_close = dbm_close + dbm_delete = dbm_delete + dbm_dirfno = dbm_dirfno + dbm_error = dbm_error + dbm_fetch = dbm_fetch + dbm_firstkey = dbm_firstkey + dbm_nextkey = dbm_nextkey + dbm_open = dbm_open + dbm_pagfno = dbm_pagfno + dbm_rdonly = dbm_rdonly + dbm_store = dbm_store + dpbnum = dpbnum + dpbusenum = dpbusenum + dpclose = dpclose + dpecodeptr = dpecodeptr + dpecodeset = dpecodeset + dperrmsg = dperrmsg + dpexportdb = dpexportdb + dpfatalerror = dpfatalerror + dpfdesc = dpfdesc + dpfsiz = dpfsiz + dpget = dpget + dpgetflags = dpgetflags + dpgetwb = dpgetwb + dpimportdb = dpimportdb + dpinnerhash = dpinnerhash + dpinode = dpinode + dpiterinit = dpiterinit + dpiternext = dpiternext + dpmemflush = dpmemflush + dpmemsync = dpmemsync + dpmtime = dpmtime + dpname = dpname + dpopen = dpopen + dpoptimize = dpoptimize + dpout = dpout + dpouterhash = dpouterhash + dpprimenum = dpprimenum + dpput = dpput + dpremove = dpremove + dprepair = dprepair + dprnum = dprnum + dpsetalign = dpsetalign + dpsetfbpsiz = dpsetfbpsiz + dpsetflags = dpsetflags + dpsnaffle = dpsnaffle + dpsync = dpsync + dpvsiz = dpvsiz + dpwritable = dpwritable + gdbm_close = gdbm_close + gdbm_delete = gdbm_delete + gdbm_errnoptr = gdbm_errnoptr + gdbm_exists = gdbm_exists + gdbm_fdesc = gdbm_fdesc + gdbm_fetch = gdbm_fetch + gdbm_firstkey = gdbm_firstkey + gdbm_nextkey = gdbm_nextkey + gdbm_open = gdbm_open + gdbm_open2 = gdbm_open2 + gdbm_reorganize = gdbm_reorganize + gdbm_setopt = gdbm_setopt + gdbm_store = gdbm_store + gdbm_strerror = gdbm_strerror + gdbm_sync = gdbm_sync + odanalyzetext = odanalyzetext + odbnum = odbnum + odbreaktext = odbreaktext + odbusenum = odbusenum + odcheck = odcheck + odclose = odclose + oddnum = oddnum + oddocaddattr = oddocaddattr + oddocaddword = oddocaddword + oddocawords = oddocawords + oddocclose = oddocclose + oddocgetattr = oddocgetattr + oddocid = oddocid + oddocnwords = oddocnwords + oddocopen = oddocopen + oddocscores = oddocscores + oddocuri = oddocuri + odfatalerror = odfatalerror + odfsiz = odfsiz + odget = odget + odgetbyid = odgetbyid + odgetidbyuri = odgetidbyuri + odidbdocs = odidbdocs + odidbindex = odidbindex + odidbrdocs = odidbrdocs + odinode = odinode + oditerinit = oditerinit + oditernext = oditernext + odlogarithm = odlogarithm + odmerge = odmerge + odmtime = odmtime + odname = odname + odnormalizeword = odnormalizeword + odopen = odopen + odoptimize = odoptimize + odout = odout + odoutbyid = odoutbyid + odpairsand = odpairsand + odpairsnotand = odpairsnotand + odpairsor = odpairsor + odpairssort = odpairssort + odput = odput + odquery = odquery + odremove = odremove + odsearch = odsearch + odsearchdnum = odsearchdnum + odsetcharclass = odsetcharclass + odsetotcb = odsetotcb + odsettuning = odsettuning + odsquareroot = odsquareroot + odsync = odsync + odvecabsolute = odvecabsolute + odvecinnerproduct = odvecinnerproduct + odvectorcosine = odvectorcosine + odwnum = odwnum + odwritable = odwritable + vlclose = vlclose + vlcrdnumptr = vlcrdnumptr + vlcurfirst = vlcurfirst + vlcurjump = vlcurjump + vlcurkey = vlcurkey + vlcurkeycache = vlcurkeycache + vlcurlast = vlcurlast + vlcurnext = vlcurnext + vlcurout = vlcurout + vlcurprev = vlcurprev + vlcurput = vlcurput + vlcurval = vlcurval + vlcurvalcache = vlcurvalcache + vlexportdb = vlexportdb + vlfatalerror = vlfatalerror + vlfsiz = vlfsiz + vlget = vlget + vlgetcache = vlgetcache + vlgetcat = vlgetcat + vlgetflags = vlgetflags + vlgetlist = vlgetlist + vlimportdb = vlimportdb + vlinode = vlinode + vllnum = vllnum + vlmemflush = vlmemflush + vlmemsync = vlmemsync + vlmtime = vlmtime + vlmulcurclose = vlmulcurclose + vlmulcurfirst = vlmulcurfirst + vlmulcurjump = vlmulcurjump + vlmulcurkey = vlmulcurkey + vlmulcurkeycache = vlmulcurkeycache + vlmulcurlast = vlmulcurlast + vlmulcurnext = vlmulcurnext + vlmulcuropen = vlmulcuropen + vlmulcurprev = vlmulcurprev + vlmulcurval = vlmulcurval + vlmulcurvalcache = vlmulcurvalcache + vlname = vlname + vlnnum = vlnnum + vlopen = vlopen + vloptimize = vloptimize + vlout = vlout + vloutlist = vloutlist + vlput = vlput + vlputlist = vlputlist + vlremove = vlremove + vlrepair = vlrepair + vlrnum = vlrnum + vlsetfbpsiz = vlsetfbpsiz + vlsetflags = vlsetflags + vlsettuning = vlsettuning + vlsync = vlsync + vltranabort = vltranabort + vltranbegin = vltranbegin + vltrancommit = vltrancommit + vlvnum = vlvnum + vlvsiz = vlvsiz + vlwritable = vlwritable + vstclose = vstclose + vstcrdnumptr = vstcrdnumptr + vstcurfirst = vstcurfirst + vstcurjump = vstcurjump + vstcurkey = vstcurkey + vstcurkeycache = vstcurkeycache + vstcurlast = vstcurlast + vstcurnext = vstcurnext + vstcurout = vstcurout + vstcurprev = vstcurprev + vstcurput = vstcurput + vstcurval = vstcurval + vstcurvalcache = vstcurvalcache + vstexportdb = vstexportdb + vstfatalerror = vstfatalerror + vstfsiz = vstfsiz + vstget = vstget + vstgetcache = vstgetcache + vstgetcat = vstgetcat + vstgetflags = vstgetflags + vstgetlist = vstgetlist + vstimportdb = vstimportdb + vstinode = vstinode + vstlnum = vstlnum + vstmemflush = vstmemflush + vstmemsync = vstmemsync + vstmtime = vstmtime + vstmulcurclose = vstmulcurclose + vstmulcurfirst = vstmulcurfirst + vstmulcurjump = vstmulcurjump + vstmulcurkey = vstmulcurkey + vstmulcurkeycache = vstmulcurkeycache + vstmulcurlast = vstmulcurlast + vstmulcurnext = vstmulcurnext + vstmulcuropen = vstmulcuropen + vstmulcurprev = vstmulcurprev + vstmulcurval = vstmulcurval + vstmulcurvalcache = vstmulcurvalcache + vstname = vstname + vstnnum = vstnnum + vstopen = vstopen + vstoptimize = vstoptimize + vstout = vstout + vstoutlist = vstoutlist + vstput = vstput + vstputlist = vstputlist + vstremove = vstremove + vstrepair = vstrepair + vstrnum = vstrnum + vstsetfbpsiz = vstsetfbpsiz + vstsetflags = vstsetflags + vstsettuning = vstsettuning + vstsync = vstsync + vsttranabort = vsttranabort + vsttranbegin = vsttranbegin + vsttrancommit = vsttrancommit + vstvnum = vstvnum + vstvsiz = vstvsiz + vstwritable = vstwritable Deleted: box/trunk/qdbm/qdbm.pc.in =================================================================== --- box/trunk/qdbm/qdbm.pc.in 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/qdbm.pc.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,14 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ -libexecdir=@libexecdir@ -includedir=@includedir@ -datadir=@datadir@ - -Name: QDBM -Description: a high performance embedded database library -Version: @PACKAGE_VERSION@ -Requires: -Libs: -L${libdir} -lqdbm @LIBS@ -Cflags: -I${includedir} Copied: box/trunk/qdbm/qdbm.pc.in (from rev 2716, box/trunk/qdbm/qdbm.pc.in) =================================================================== --- box/trunk/qdbm/qdbm.pc.in (rev 0) +++ box/trunk/qdbm/qdbm.pc.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,14 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +libdir=@libdir@ +libexecdir=@libexecdir@ +includedir=@includedir@ +datadir=@datadir@ + +Name: QDBM +Description: a high performance embedded database library +Version: @PACKAGE_VERSION@ +Requires: +Libs: -L${libdir} -lqdbm @LIBS@ +Cflags: -I${includedir} Deleted: box/trunk/qdbm/qdbm.spec.in =================================================================== --- box/trunk/qdbm/qdbm.spec.in 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/qdbm.spec.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,218 +0,0 @@ -#================================================================ -# RPM Specification for QDBM -#================================================================ - - - -%define name @PACKAGE_NAME@ -%define version @PACKAGE_VERSION@ -%define release 1 -%define libver @LIBVER@ -%define librev @LIBREV@ -%define disturl http://qdbm.sourceforge.net/ -%define homeurl http://qdbm.sourceforge.net/ - -Summary: Quick Database Manager -Name: %{name} -Version: %{version} -Release: %{release} -Source: %{disturl}%{name}-%{version}.tar.gz -Copyright: LGPL -Group: Development/Libraries -Packager: Mikio Hirabayashi -Distribution: Private -Vendor: Private -Url: %{homeurl} -Requires: zlib -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root - -%description -QDBM is an embeded database library compatible with GDBM and NDBM. -It features hash database and B+ tree database and is developed referring -to GDBM for the purpose of the following three points: higher processing -speed, smaller size of a database file, and simpler API. -This package includes APIs for C, C++, and Java. CGI scripts are also -contained. APIs for Perl and Ruby should be installed with a source package. - -%package devel -Summary: Headers, libraries, utilities and documentation for QDBM -Group: Development/Libraries -Requires: %{name} = %{version} - -%description devel -This package contains header files and libraries needed to develop programs -using the QDBM library. Some utility commands are also provided. - -%package plus -Summary: C++ libraries for QDBM -Group: Development/Libraries -Requires: %{name} = %{version} - -%description plus -This package contains libraries needed to develop and run programs using the -QDBM C++ bindings. - -%package java -Summary: Java libraries for QDBM -Group: Development/Libraries -Requires: %{name} = %{version} - -%description java -This package contains libraries needed to develop and run programs using the -QDBM Java bindings. - -%package cgi -Summary: CGI scripts with QDBM -Group: Development/Libraries -Requires: %{name} = %{version} - -%description cgi -This package contains CGI scripts with QDBM, for administration of databases, -file uploading, and full-text search. - -%prep -rm -rf $RPM_BUILD_ROOT - -%setup -q - -%build -( cd . ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} \ - --enable-stable --enable-zlib --enable-iconv --enable-pthread ; make ) -( cd plus ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} ; make ) -( cd java ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} ; make ) -( cd cgi ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} ; make ) - -%install -rm -rf $RPM_BUILD_ROOT -( cd . ; make DESTDIR=$RPM_BUILD_ROOT install-strip ) -( cd plus ; make DESTDIR=$RPM_BUILD_ROOT install-strip ) -( cd java ; make DESTDIR=$RPM_BUILD_ROOT install ) -( cd cgi ; make DESTDIR=$RPM_BUILD_ROOT install-strip ) -( mkdir -p $RPM_BUILD_ROOT%{_datadir}/doc/qdbm && \ - cd $RPM_BUILD_ROOT%{_usr}/share/qdbm && \ - cp -Rf spex-ja.html spex.html COPYING ChangeLog NEWS THANKS \ - plus/xspex.html plus/xspex-ja.html plus/xapidoc \ - java/jspex.html java/jspex-ja.html java/japidoc \ - cgi/cgispex-ja.html cgi/cgispex.html $RPM_BUILD_ROOT%{_datadir}/doc/qdbm ) - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root) -%{_libdir}/libqdbm.so.%{libver}.%{librev}.0 -%{_libdir}/libqdbm.so.%{libver} -%{_libdir}/libqdbm.so - -%files devel -%defattr(-,root,root) -%{_includedir}/depot.h -%{_includedir}/curia.h -%{_includedir}/relic.h -%{_includedir}/hovel.h -%{_includedir}/cabin.h -%{_includedir}/villa.h -%{_includedir}/vista.h -%{_includedir}/odeum.h -%{_libdir}/libqdbm.a -%{_bindir}/dpmgr -%{_bindir}/dptest -%{_bindir}/dptsv -%{_bindir}/crmgr -%{_bindir}/crtest -%{_bindir}/crtsv -%{_bindir}/rlmgr -%{_bindir}/rltest -%{_bindir}/hvmgr -%{_bindir}/hvtest -%{_bindir}/cbtest -%{_bindir}/cbcodec -%{_bindir}/vlmgr -%{_bindir}/vltest -%{_bindir}/vltsv -%{_bindir}/odmgr -%{_bindir}/odtest -%{_bindir}/odidx -%{_bindir}/qmttest -%{_mandir}/man1/dpmgr.1.gz -%{_mandir}/man1/dptest.1.gz -%{_mandir}/man1/dptsv.1.gz -%{_mandir}/man1/crmgr.1.gz -%{_mandir}/man1/crtest.1.gz -%{_mandir}/man1/crtsv.1.gz -%{_mandir}/man1/rlmgr.1.gz -%{_mandir}/man1/rltest.1.gz -%{_mandir}/man1/hvmgr.1.gz -%{_mandir}/man1/hvtest.1.gz -%{_mandir}/man1/cbtest.1.gz -%{_mandir}/man1/cbcodec.1.gz -%{_mandir}/man1/vlmgr.1.gz -%{_mandir}/man1/vltest.1.gz -%{_mandir}/man1/vltsv.1.gz -%{_mandir}/man1/odmgr.1.gz -%{_mandir}/man1/odtest.1.gz -%{_mandir}/man1/odidx.1.gz -%{_mandir}/man1/qmttest.1.gz -%{_mandir}/man3/qdbm.3.gz -%{_mandir}/man3/depot.3.gz -%{_mandir}/man3/dpopen.3.gz -%{_mandir}/man3/curia.3.gz -%{_mandir}/man3/cropen.3.gz -%{_mandir}/man3/relic.3.gz -%{_mandir}/man3/hovel.3.gz -%{_mandir}/man3/cabin.3.gz -%{_mandir}/man3/villa.3.gz -%{_mandir}/man3/vlopen.3.gz -%{_mandir}/man3/vista.3.gz -%{_mandir}/man3/odeum.3.gz -%{_mandir}/man3/odopen.3.gz -%{_datadir}/doc/qdbm/spex.html -%{_datadir}/doc/qdbm/spex-ja.html -%{_datadir}/doc/qdbm/COPYING -%{_datadir}/doc/qdbm/ChangeLog -%{_datadir}/doc/qdbm/NEWS -%{_datadir}/doc/qdbm/THANKS -%{_libdir}/pkgconfig/qdbm.pc - -%files plus -%defattr(-,root,root) -%{_includedir}/xqdbm.h -%{_includedir}/xadbm.h -%{_includedir}/xdepot.h -%{_includedir}/xcuria.h -%{_includedir}/xvilla.h -%{_libdir}/libxqdbm.a -%{_libdir}/libxqdbm.so.3.0.0 -%{_libdir}/libxqdbm.so.3 -%{_libdir}/libxqdbm.so -%{_bindir}/xdptest -%{_bindir}/xcrtest -%{_bindir}/xvltest -%{_datadir}/doc/qdbm/xspex.html -%{_datadir}/doc/qdbm/xspex-ja.html -%{_datadir}/doc/qdbm/xapidoc/ - -%files java -%defattr(-,root,root) -%{_libdir}/qdbm.jar -%{_libdir}/libjqdbm.so.1.0.0 -%{_libdir}/libjqdbm.so.1 -%{_libdir}/libjqdbm.so -%{_datadir}/doc/qdbm/jspex.html -%{_datadir}/doc/qdbm/jspex-ja.html -%{_datadir}/doc/qdbm/japidoc/ - -%files cgi -%defattr(-,root,root) -%{_libexecdir}/qadm.cgi -%{_libexecdir}/qupl.cgi -%{_libexecdir}/qfts.cgi -%{_datadir}/qdbm/cgi/qadm.conf -%{_datadir}/qdbm/cgi/qupl.conf -%{_datadir}/qdbm/cgi/qfts.conf -%{_datadir}/doc/qdbm/cgispex.html -%{_datadir}/doc/qdbm/cgispex-ja.html - - - -# END OF FILE Copied: box/trunk/qdbm/qdbm.spec.in (from rev 2716, box/trunk/qdbm/qdbm.spec.in) =================================================================== --- box/trunk/qdbm/qdbm.spec.in (rev 0) +++ box/trunk/qdbm/qdbm.spec.in 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,218 @@ +#================================================================ +# RPM Specification for QDBM +#================================================================ + + + +%define name @PACKAGE_NAME@ +%define version @PACKAGE_VERSION@ +%define release 1 +%define libver @LIBVER@ +%define librev @LIBREV@ +%define disturl http://qdbm.sourceforge.net/ +%define homeurl http://qdbm.sourceforge.net/ + +Summary: Quick Database Manager +Name: %{name} +Version: %{version} +Release: %{release} +Source: %{disturl}%{name}-%{version}.tar.gz +Copyright: LGPL +Group: Development/Libraries +Packager: Mikio Hirabayashi +Distribution: Private +Vendor: Private +Url: %{homeurl} +Requires: zlib +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root + +%description +QDBM is an embeded database library compatible with GDBM and NDBM. +It features hash database and B+ tree database and is developed referring +to GDBM for the purpose of the following three points: higher processing +speed, smaller size of a database file, and simpler API. +This package includes APIs for C, C++, and Java. CGI scripts are also +contained. APIs for Perl and Ruby should be installed with a source package. + +%package devel +Summary: Headers, libraries, utilities and documentation for QDBM +Group: Development/Libraries +Requires: %{name} = %{version} + +%description devel +This package contains header files and libraries needed to develop programs +using the QDBM library. Some utility commands are also provided. + +%package plus +Summary: C++ libraries for QDBM +Group: Development/Libraries +Requires: %{name} = %{version} + +%description plus +This package contains libraries needed to develop and run programs using the +QDBM C++ bindings. + +%package java +Summary: Java libraries for QDBM +Group: Development/Libraries +Requires: %{name} = %{version} + +%description java +This package contains libraries needed to develop and run programs using the +QDBM Java bindings. + +%package cgi +Summary: CGI scripts with QDBM +Group: Development/Libraries +Requires: %{name} = %{version} + +%description cgi +This package contains CGI scripts with QDBM, for administration of databases, +file uploading, and full-text search. + +%prep +rm -rf $RPM_BUILD_ROOT + +%setup -q + +%build +( cd . ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} \ + --enable-stable --enable-zlib --enable-iconv --enable-pthread ; make ) +( cd plus ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} ; make ) +( cd java ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} ; make ) +( cd cgi ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} ; make ) + +%install +rm -rf $RPM_BUILD_ROOT +( cd . ; make DESTDIR=$RPM_BUILD_ROOT install-strip ) +( cd plus ; make DESTDIR=$RPM_BUILD_ROOT install-strip ) +( cd java ; make DESTDIR=$RPM_BUILD_ROOT install ) +( cd cgi ; make DESTDIR=$RPM_BUILD_ROOT install-strip ) +( mkdir -p $RPM_BUILD_ROOT%{_datadir}/doc/qdbm && \ + cd $RPM_BUILD_ROOT%{_usr}/share/qdbm && \ + cp -Rf spex-ja.html spex.html COPYING ChangeLog NEWS THANKS \ + plus/xspex.html plus/xspex-ja.html plus/xapidoc \ + java/jspex.html java/jspex-ja.html java/japidoc \ + cgi/cgispex-ja.html cgi/cgispex.html $RPM_BUILD_ROOT%{_datadir}/doc/qdbm ) + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%{_libdir}/libqdbm.so.%{libver}.%{librev}.0 +%{_libdir}/libqdbm.so.%{libver} +%{_libdir}/libqdbm.so + +%files devel +%defattr(-,root,root) +%{_includedir}/depot.h +%{_includedir}/curia.h +%{_includedir}/relic.h +%{_includedir}/hovel.h +%{_includedir}/cabin.h +%{_includedir}/villa.h +%{_includedir}/vista.h +%{_includedir}/odeum.h +%{_libdir}/libqdbm.a +%{_bindir}/dpmgr +%{_bindir}/dptest +%{_bindir}/dptsv +%{_bindir}/crmgr +%{_bindir}/crtest +%{_bindir}/crtsv +%{_bindir}/rlmgr +%{_bindir}/rltest +%{_bindir}/hvmgr +%{_bindir}/hvtest +%{_bindir}/cbtest +%{_bindir}/cbcodec +%{_bindir}/vlmgr +%{_bindir}/vltest +%{_bindir}/vltsv +%{_bindir}/odmgr +%{_bindir}/odtest +%{_bindir}/odidx +%{_bindir}/qmttest +%{_mandir}/man1/dpmgr.1.gz +%{_mandir}/man1/dptest.1.gz +%{_mandir}/man1/dptsv.1.gz +%{_mandir}/man1/crmgr.1.gz +%{_mandir}/man1/crtest.1.gz +%{_mandir}/man1/crtsv.1.gz +%{_mandir}/man1/rlmgr.1.gz +%{_mandir}/man1/rltest.1.gz +%{_mandir}/man1/hvmgr.1.gz +%{_mandir}/man1/hvtest.1.gz +%{_mandir}/man1/cbtest.1.gz +%{_mandir}/man1/cbcodec.1.gz +%{_mandir}/man1/vlmgr.1.gz +%{_mandir}/man1/vltest.1.gz +%{_mandir}/man1/vltsv.1.gz +%{_mandir}/man1/odmgr.1.gz +%{_mandir}/man1/odtest.1.gz +%{_mandir}/man1/odidx.1.gz +%{_mandir}/man1/qmttest.1.gz +%{_mandir}/man3/qdbm.3.gz +%{_mandir}/man3/depot.3.gz +%{_mandir}/man3/dpopen.3.gz +%{_mandir}/man3/curia.3.gz +%{_mandir}/man3/cropen.3.gz +%{_mandir}/man3/relic.3.gz +%{_mandir}/man3/hovel.3.gz +%{_mandir}/man3/cabin.3.gz +%{_mandir}/man3/villa.3.gz +%{_mandir}/man3/vlopen.3.gz +%{_mandir}/man3/vista.3.gz +%{_mandir}/man3/odeum.3.gz +%{_mandir}/man3/odopen.3.gz +%{_datadir}/doc/qdbm/spex.html +%{_datadir}/doc/qdbm/spex-ja.html +%{_datadir}/doc/qdbm/COPYING +%{_datadir}/doc/qdbm/ChangeLog +%{_datadir}/doc/qdbm/NEWS +%{_datadir}/doc/qdbm/THANKS +%{_libdir}/pkgconfig/qdbm.pc + +%files plus +%defattr(-,root,root) +%{_includedir}/xqdbm.h +%{_includedir}/xadbm.h +%{_includedir}/xdepot.h +%{_includedir}/xcuria.h +%{_includedir}/xvilla.h +%{_libdir}/libxqdbm.a +%{_libdir}/libxqdbm.so.3.0.0 +%{_libdir}/libxqdbm.so.3 +%{_libdir}/libxqdbm.so +%{_bindir}/xdptest +%{_bindir}/xcrtest +%{_bindir}/xvltest +%{_datadir}/doc/qdbm/xspex.html +%{_datadir}/doc/qdbm/xspex-ja.html +%{_datadir}/doc/qdbm/xapidoc/ + +%files java +%defattr(-,root,root) +%{_libdir}/qdbm.jar +%{_libdir}/libjqdbm.so.1.0.0 +%{_libdir}/libjqdbm.so.1 +%{_libdir}/libjqdbm.so +%{_datadir}/doc/qdbm/jspex.html +%{_datadir}/doc/qdbm/jspex-ja.html +%{_datadir}/doc/qdbm/japidoc/ + +%files cgi +%defattr(-,root,root) +%{_libexecdir}/qadm.cgi +%{_libexecdir}/qupl.cgi +%{_libexecdir}/qfts.cgi +%{_datadir}/qdbm/cgi/qadm.conf +%{_datadir}/qdbm/cgi/qupl.conf +%{_datadir}/qdbm/cgi/qfts.conf +%{_datadir}/doc/qdbm/cgispex.html +%{_datadir}/doc/qdbm/cgispex-ja.html + + + +# END OF FILE Deleted: box/trunk/qdbm/qmttest.c =================================================================== --- box/trunk/qdbm/qmttest.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/qmttest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,300 +0,0 @@ -/************************************************************************************************* - * Test cases for thread-safety - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(MYPTHREAD) -#include -#include -#endif - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define PATHBUFSIZ 1024 /* buffer for paths */ -#define RECBUFSIZ 32 /* buffer for records */ - -typedef struct { /* type of structure of thread arguments */ - int id; /* ID of the thread */ - const char *name; /* prefix of the database */ - int rnum; /* number of records */ - int alive; /* alive or not */ -} MYARGS; - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -void pdperror(const char *name); -void *procthread(void *args); -int dotest(const char *name, int rnum, int tnum); - - -/* main routine */ -int main(int argc, char **argv){ - char *env, *name; - int rv, rnum, tnum; - cbstdiobin(); - if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); - progname = argv[0]; - srand(time(NULL)); - if(argc < 4) usage(); - name = argv[1]; - if((rnum = atoi(argv[2])) < 1) usage(); - if((tnum = atoi(argv[3])) < 1) usage(); - rv = dotest(name, rnum, tnum); - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: test cases for thread-safety\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s name rnum tnum\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* print formatted string and flush the buffer */ -int printfflush(const char *format, ...){ -#if defined(MYPTHREAD) - static pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; - va_list ap; - int rv; - if(pthread_mutex_lock(&mymutex) != 0) return -1; - va_start(ap, format); - rv = vprintf(format, ap); - if(fflush(stdout) == EOF) rv = -1; - va_end(ap); - pthread_mutex_unlock(&mymutex); - return rv; -#else - va_list ap; - int rv; - va_start(ap, format); - rv = vprintf(format, ap); - if(fflush(stdout) == EOF) rv = -1; - va_end(ap); - return rv; -#endif -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* pseudo random number generator */ -int myrand(void){ - static int cnt = 0; - return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; -} - - -/* process the test */ -void *procthread(void *args){ - MYARGS *myargs; - DEPOT *depot; - CURIA *curia; - VILLA *villa; - CBLIST *list; - CBMAP *map; - char name[PATHBUFSIZ], buf[RECBUFSIZ]; - int i, err, len; - myargs = (MYARGS *)args; - err = FALSE; - sprintf(name, "%s-%04d", myargs->name, myargs->id); - dpremove(name); - crremove(name); - vlremove(name); - switch(myrand() % 4){ - case 0: - printfflush("\n[Depot Test] name=%s rnum=%d\n", name, myargs->rnum); - if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))){ - pdperror(name); - return "error"; - } - for(i = 1; i <= myargs->rnum; i++){ - len = sprintf(buf, "%d", myrand() % i + 1); - if(!dpput(depot, buf, len, buf, len, i % 2 == 0 ? DP_DOVER : DP_DCAT)){ - pdperror(name); - err = TRUE; - } - if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ - printfflush("."); - if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ - printfflush("\n%s: (%d)\n", name, i); - } - } - } - if(!dpclose(depot)){ - pdperror(name); - err = TRUE; - } - printfflush("\n%s: finished\n", name); - break; - case 1: - printfflush("\n[Curia Test] name=%s rnum=%d\n", name, myargs->rnum); - if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, -1, -1))){ - pdperror(name); - return "error"; - } - for(i = 1; i <= myargs->rnum; i++){ - len = sprintf(buf, "%d", myrand() % i + 1); - if(!crput(curia, buf, len, buf, len, i % 2 == 0 ? CR_DOVER : CR_DCAT)){ - pdperror(name); - err = TRUE; - } - if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ - printfflush("."); - if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ - printfflush("\n%s: (%d)\n", name, i); - } - } - } - if(!crclose(curia)){ - pdperror(name); - err = TRUE; - } - printfflush("\n%s: finished\n", name); - break; - case 2: - printfflush("\n[Villa Test] name=%s rnum=%d\n", name, myargs->rnum); - if(!(villa = vlopen(name, VL_OWRITER | VL_OCREAT | VL_OTRUNC, VL_CMPLEX))){ - pdperror(name); - return "error"; - } - for(i = 1; i <= myargs->rnum; i++){ - len = sprintf(buf, "%d", myrand() % i + 1); - if(!vlput(villa, buf, len, buf, len, i % 2 == 0 ? VL_DOVER : VL_DDUP)){ - pdperror(name); - err = TRUE; - } - if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ - printfflush("."); - if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ - printfflush("\n%s: (%d)\n", name, i); - } - } - } - if(!vlclose(villa)){ - pdperror(name); - err = TRUE; - } - printfflush("\n%s: finished\n", name); - break; - case 3: - printfflush("\n[Cabin Test] name=%s rnum=%d\n", name, myargs->rnum); - list = cblistopen(); - map = cbmapopen(); - for(i = 1; i <= myargs->rnum; i++){ - len = sprintf(buf, "%d", myrand() % i + 1); - cblistpush(list, buf, len); - cbmapput(map, buf, len, buf, len, i % 2 == 0 ? TRUE : FALSE); - if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ - printfflush("."); - if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ - printfflush("\n%s: (%d)\n", name, i); - } - } - } - cbmapclose(map); - cblistclose(list); - printfflush("\n%s: finished\n", name); - break; - } - return err ? "error" : NULL; -} - - -/* drive the test */ -int dotest(const char *name, int rnum, int tnum){ -#if defined(MYPTHREAD) - pthread_t *thary; - MYARGS *argsary; - char *rv; - int i, err; - printfflush("\n name=%s rnum=%d tnum=%d\n", name, rnum, tnum); - err = FALSE; - thary = cbmalloc(tnum * sizeof(pthread_t)); - argsary = cbmalloc(tnum * sizeof(MYARGS)); - for(i = 0; i < tnum; i++){ - argsary[i].id = i + 1; - argsary[i].name = name; - argsary[i].rnum = rnum; - argsary[i].alive = TRUE; - if(pthread_create(thary + i, NULL, procthread, argsary + i) != 0){ - argsary[i].alive = FALSE; - err = TRUE; - } - } - for(i = 0; i < tnum; i++){ - if(!argsary[i].alive) continue; - if(pthread_join(thary[i], (void *)&rv) != 0 || rv) err = TRUE; - } - free(argsary); - free(thary); - if(!err) printfflush("\nall ok\n"); - return err ? 1 : 0; -#else - MYARGS *argsary; - int i, err; - printfflush("\n name=%s rnum=%d tnum=%d\n", name, rnum, tnum); - err = FALSE; - argsary = cbmalloc(tnum * sizeof(MYARGS)); - for(i = 0; i < tnum; i++){ - argsary[i].id = i + 1; - argsary[i].name = name; - argsary[i].rnum = rnum; - argsary[i].alive = TRUE; - if(procthread(argsary + i)) err = TRUE; - } - free(argsary); - if(!err) printfflush("\nall ok\n"); - return err ? 1 : 0; -#endif -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/qmttest.c (from rev 2716, box/trunk/qdbm/qmttest.c) =================================================================== --- box/trunk/qdbm/qmttest.c (rev 0) +++ box/trunk/qdbm/qmttest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,300 @@ +/************************************************************************************************* + * Test cases for thread-safety + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(MYPTHREAD) +#include +#include +#endif + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define PATHBUFSIZ 1024 /* buffer for paths */ +#define RECBUFSIZ 32 /* buffer for records */ + +typedef struct { /* type of structure of thread arguments */ + int id; /* ID of the thread */ + const char *name; /* prefix of the database */ + int rnum; /* number of records */ + int alive; /* alive or not */ +} MYARGS; + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +void pdperror(const char *name); +void *procthread(void *args); +int dotest(const char *name, int rnum, int tnum); + + +/* main routine */ +int main(int argc, char **argv){ + char *env, *name; + int rv, rnum, tnum; + cbstdiobin(); + if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); + progname = argv[0]; + srand(time(NULL)); + if(argc < 4) usage(); + name = argv[1]; + if((rnum = atoi(argv[2])) < 1) usage(); + if((tnum = atoi(argv[3])) < 1) usage(); + rv = dotest(name, rnum, tnum); + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: test cases for thread-safety\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s name rnum tnum\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* print formatted string and flush the buffer */ +int printfflush(const char *format, ...){ +#if defined(MYPTHREAD) + static pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; + va_list ap; + int rv; + if(pthread_mutex_lock(&mymutex) != 0) return -1; + va_start(ap, format); + rv = vprintf(format, ap); + if(fflush(stdout) == EOF) rv = -1; + va_end(ap); + pthread_mutex_unlock(&mymutex); + return rv; +#else + va_list ap; + int rv; + va_start(ap, format); + rv = vprintf(format, ap); + if(fflush(stdout) == EOF) rv = -1; + va_end(ap); + return rv; +#endif +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* pseudo random number generator */ +int myrand(void){ + static int cnt = 0; + return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; +} + + +/* process the test */ +void *procthread(void *args){ + MYARGS *myargs; + DEPOT *depot; + CURIA *curia; + VILLA *villa; + CBLIST *list; + CBMAP *map; + char name[PATHBUFSIZ], buf[RECBUFSIZ]; + int i, err, len; + myargs = (MYARGS *)args; + err = FALSE; + sprintf(name, "%s-%04d", myargs->name, myargs->id); + dpremove(name); + crremove(name); + vlremove(name); + switch(myrand() % 4){ + case 0: + printfflush("\n[Depot Test] name=%s rnum=%d\n", name, myargs->rnum); + if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))){ + pdperror(name); + return "error"; + } + for(i = 1; i <= myargs->rnum; i++){ + len = sprintf(buf, "%d", myrand() % i + 1); + if(!dpput(depot, buf, len, buf, len, i % 2 == 0 ? DP_DOVER : DP_DCAT)){ + pdperror(name); + err = TRUE; + } + if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ + printfflush("."); + if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ + printfflush("\n%s: (%d)\n", name, i); + } + } + } + if(!dpclose(depot)){ + pdperror(name); + err = TRUE; + } + printfflush("\n%s: finished\n", name); + break; + case 1: + printfflush("\n[Curia Test] name=%s rnum=%d\n", name, myargs->rnum); + if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, -1, -1))){ + pdperror(name); + return "error"; + } + for(i = 1; i <= myargs->rnum; i++){ + len = sprintf(buf, "%d", myrand() % i + 1); + if(!crput(curia, buf, len, buf, len, i % 2 == 0 ? CR_DOVER : CR_DCAT)){ + pdperror(name); + err = TRUE; + } + if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ + printfflush("."); + if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ + printfflush("\n%s: (%d)\n", name, i); + } + } + } + if(!crclose(curia)){ + pdperror(name); + err = TRUE; + } + printfflush("\n%s: finished\n", name); + break; + case 2: + printfflush("\n[Villa Test] name=%s rnum=%d\n", name, myargs->rnum); + if(!(villa = vlopen(name, VL_OWRITER | VL_OCREAT | VL_OTRUNC, VL_CMPLEX))){ + pdperror(name); + return "error"; + } + for(i = 1; i <= myargs->rnum; i++){ + len = sprintf(buf, "%d", myrand() % i + 1); + if(!vlput(villa, buf, len, buf, len, i % 2 == 0 ? VL_DOVER : VL_DDUP)){ + pdperror(name); + err = TRUE; + } + if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ + printfflush("."); + if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ + printfflush("\n%s: (%d)\n", name, i); + } + } + } + if(!vlclose(villa)){ + pdperror(name); + err = TRUE; + } + printfflush("\n%s: finished\n", name); + break; + case 3: + printfflush("\n[Cabin Test] name=%s rnum=%d\n", name, myargs->rnum); + list = cblistopen(); + map = cbmapopen(); + for(i = 1; i <= myargs->rnum; i++){ + len = sprintf(buf, "%d", myrand() % i + 1); + cblistpush(list, buf, len); + cbmapput(map, buf, len, buf, len, i % 2 == 0 ? TRUE : FALSE); + if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ + printfflush("."); + if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ + printfflush("\n%s: (%d)\n", name, i); + } + } + } + cbmapclose(map); + cblistclose(list); + printfflush("\n%s: finished\n", name); + break; + } + return err ? "error" : NULL; +} + + +/* drive the test */ +int dotest(const char *name, int rnum, int tnum){ +#if defined(MYPTHREAD) + pthread_t *thary; + MYARGS *argsary; + char *rv; + int i, err; + printfflush("\n name=%s rnum=%d tnum=%d\n", name, rnum, tnum); + err = FALSE; + thary = cbmalloc(tnum * sizeof(pthread_t)); + argsary = cbmalloc(tnum * sizeof(MYARGS)); + for(i = 0; i < tnum; i++){ + argsary[i].id = i + 1; + argsary[i].name = name; + argsary[i].rnum = rnum; + argsary[i].alive = TRUE; + if(pthread_create(thary + i, NULL, procthread, argsary + i) != 0){ + argsary[i].alive = FALSE; + err = TRUE; + } + } + for(i = 0; i < tnum; i++){ + if(!argsary[i].alive) continue; + if(pthread_join(thary[i], (void *)&rv) != 0 || rv) err = TRUE; + } + free(argsary); + free(thary); + if(!err) printfflush("\nall ok\n"); + return err ? 1 : 0; +#else + MYARGS *argsary; + int i, err; + printfflush("\n name=%s rnum=%d tnum=%d\n", name, rnum, tnum); + err = FALSE; + argsary = cbmalloc(tnum * sizeof(MYARGS)); + for(i = 0; i < tnum; i++){ + argsary[i].id = i + 1; + argsary[i].name = name; + argsary[i].rnum = rnum; + argsary[i].alive = TRUE; + if(procthread(argsary + i)) err = TRUE; + } + free(argsary); + if(!err) printfflush("\nall ok\n"); + return err ? 1 : 0; +#endif +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/relic.c =================================================================== --- box/trunk/qdbm/relic.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/relic.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,266 +0,0 @@ -/************************************************************************************************* - * Implementation of Relic - * 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. - *************************************************************************************************/ - - -#define QDBM_INTERNAL 1 - -#include "relic.h" -#include "myconf.h" - -#define RL_NAMEMAX 512 /* max size of a database name */ -#define RL_DIRFSUF MYEXTSTR "dir" /* suffix of a directory file */ -#define RL_DATAFSUF MYEXTSTR "pag" /* suffix of a page file */ -#define RL_PATHBUFSIZ 1024 /* size of a path buffer */ -#define RL_INITBNUM 1913 /* initial bucket number */ -#define RL_ALIGNSIZ 16 /* size of alignment */ -#define RL_MAXLOAD 1.25 /* max ratio of bucket loading */ -#define RL_DIRMAGIC "[depot]\0\v" /* magic number of a directory file */ - - -/* private function prototypes */ -static void dbm_writedummy(int fd); -static int dbm_writestr(int fd, const char *str); - - - -/************************************************************************************************* - * public objects - *************************************************************************************************/ - - -/* Get a database handle. */ -DBM *dbm_open(char *name, int flags, int mode){ - DBM *db; - DEPOT *depot; - int dpomode; - char path[RL_PATHBUFSIZ]; - int dfd, fd; - assert(name); - if(strlen(name) > RL_NAMEMAX) return NULL; - dpomode = DP_OREADER; - if((flags & O_WRONLY) || (flags & O_RDWR)){ - dpomode = DP_OWRITER; - if(flags & O_CREAT) dpomode |= DP_OCREAT; - if(flags & O_TRUNC) dpomode |= DP_OTRUNC; - } - mode |= 00600; - sprintf(path, "%s%s", name, RL_DIRFSUF); - if((dfd = open(path, flags, mode)) == -1) return NULL; - dbm_writedummy(dfd); - sprintf(path, "%s%s", name, RL_DATAFSUF); - if((fd = open(path, flags, mode)) == -1 || close(fd) == -1){ - close(dfd); - return NULL; - } - if(!(depot = dpopen(path, dpomode, RL_INITBNUM))){ - close(dfd); - return NULL; - } - if(dpomode & DP_OWRITER){ - if(!dpsetalign(depot, RL_ALIGNSIZ)){ - close(dfd); - dpclose(depot); - return NULL; - } - } - if(!(db = malloc(sizeof(DBM)))){ - close(dfd); - dpclose(depot); - return NULL; - } - db->depot = depot; - db->dfd = dfd; - db->dbm_fetch_vbuf = NULL; - db->dbm_nextkey_kbuf = NULL; - return db; -} - - -/* Close a database handle. */ -void dbm_close(DBM *db){ - assert(db); - free(db->dbm_fetch_vbuf); - free(db->dbm_nextkey_kbuf); - close(db->dfd); - dpclose(db->depot); - free(db); -} - - -/* Store a record. */ -int dbm_store(DBM *db, datum key, datum content, int flags){ - int dmode; - int bnum, rnum; - assert(db); - if(!key.dptr || key.dsize < 0 || !content.dptr || content.dsize < 0) return -1; - dmode = (flags == DBM_INSERT) ? DP_DKEEP : DP_DOVER; - if(!dpput(db->depot, key.dptr, key.dsize, content.dptr, content.dsize, dmode)){ - if(dpecode == DP_EKEEP) return 1; - return -1; - } - bnum = dpbnum(db->depot); - rnum = dprnum(db->depot); - if(bnum > 0 && rnum > 0 && ((double)rnum / (double)bnum > RL_MAXLOAD)){ - if(!dpoptimize(db->depot, -1)) return -1; - } - return 0; -} - - -/* Delete a record. */ -int dbm_delete(DBM *db, datum key){ - assert(db); - if(!key.dptr || key.dsize < 0) return -1; - if(!dpout(db->depot, key.dptr, key.dsize)) return -1; - return 0; -} - - -/* Retrieve a record. */ -datum dbm_fetch(DBM *db, datum key){ - datum content; - char *vbuf; - int vsiz; - assert(db); - if(!key.dptr || key.dsize < 0 || - !(vbuf = dpget(db->depot, key.dptr, key.dsize, 0, -1, &vsiz))){ - content.dptr = NULL; - content.dsize = 0; - return content; - } - free(db->dbm_fetch_vbuf); - db->dbm_fetch_vbuf = vbuf; - content.dptr = vbuf; - content.dsize = vsiz; - return content; -} - - -/* Get the first key of a database. */ -datum dbm_firstkey(DBM *db){ - assert(db); - dpiterinit(db->depot); - return dbm_nextkey(db); -} - - -/* Get the next key of a database. */ -datum dbm_nextkey(DBM *db){ - datum key; - char *kbuf; - int ksiz; - if(!(kbuf = dpiternext(db->depot, &ksiz))){ - key.dptr = NULL; - key.dsize = 0; - return key; - } - free(db->dbm_nextkey_kbuf); - db->dbm_nextkey_kbuf = kbuf; - key.dptr = kbuf; - key.dsize = ksiz; - return key; -} - - -/* Check whether a database has a fatal error or not. */ -int dbm_error(DBM *db){ - assert(db); - return dpfatalerror(db->depot) ? TRUE : FALSE; -} - - -/* No effect. */ -int dbm_clearerr(DBM *db){ - assert(db); - return 0; -} - - -/* Check whether a handle is read-only or not. */ -int dbm_rdonly(DBM *db){ - assert(db); - return dpwritable(db->depot) ? FALSE : TRUE; -} - - -/* Get the file descriptor of a directory file. */ -int dbm_dirfno(DBM *db){ - assert(db); - return db->dfd; -} - - -/* Get the file descriptor of a data file. */ -int dbm_pagfno(DBM *db){ - assert(db); - return dpfdesc(db->depot); -} - - - -/************************************************************************************************* - * private objects - *************************************************************************************************/ - - -/* Write dummy data into a dummy file. - `fd' specifies a file descriptor. */ -static void dbm_writedummy(int fd){ - struct stat sbuf; - if(fstat(fd, &sbuf) == -1 || sbuf.st_size > 0) return; - write(fd, RL_DIRMAGIC, sizeof(RL_DIRMAGIC) - 1); - dbm_writestr(fd, "\n\n"); - dbm_writestr(fd, "\x20\x20\xa2\xca\xa1\xb2\xa2\xca\x20\x20\x20\x20\x20\xa1\xbf\xa1"); - dbm_writestr(fd, "\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1"); - dbm_writestr(fd, "\xb1\x0a\xa1\xca\x20\xa1\xad\xa2\xcf\xa1\xae\xa1\xcb\xa1\xe3\x20"); - dbm_writestr(fd, "\x20\x4e\x44\x42\x4d\x20\x43\x6f\x6d\x70\x61\x74\x69\x62\x69\x6c"); - dbm_writestr(fd, "\x69\x74\x79\x0a\xa1\xca\x20\x20\x20\x20\x20\x20\x20\xa1\xcb\x20"); - dbm_writestr(fd, "\x20\xa1\xc0\xa1\xb2\xa1\xb2\xa1\xb2\xa1\xb2\xa1\xb2\xa1\xb2\xa1"); - dbm_writestr(fd, "\xb2\xa1\xb2\xa1\xb2\x0a\x20\xa1\xc3\x20\x20\xa1\xc3\x20\xa1\xc3"); - dbm_writestr(fd, "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"); - dbm_writestr(fd, "\x20\x20\x20\x20\x20\x20\x20\x0a\xa1\xca\x5f\x5f\xa1\xb2\xa1\xcb"); - dbm_writestr(fd, "\x5f\xa1\xcb\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"); - dbm_writestr(fd, "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a"); -} - - -/* Write a string into a file. - `fd' specifies a file descriptor. - `str' specifies a string. */ -static int dbm_writestr(int fd, const char *str){ - const char *lbuf; - int size, rv, wb; - assert(fd >= 0 && str); - lbuf = str; - size = strlen(str); - rv = 0; - do { - wb = write(fd, lbuf, size); - switch(wb){ - case -1: if(errno != EINTR) return -1; - case 0: break; - default: - lbuf += wb; - size -= wb; - rv += wb; - break; - } - } while(size > 0); - return rv; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/relic.c (from rev 2716, box/trunk/qdbm/relic.c) =================================================================== --- box/trunk/qdbm/relic.c (rev 0) +++ box/trunk/qdbm/relic.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,266 @@ +/************************************************************************************************* + * Implementation of Relic + * 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. + *************************************************************************************************/ + + +#define QDBM_INTERNAL 1 + +#include "relic.h" +#include "myconf.h" + +#define RL_NAMEMAX 512 /* max size of a database name */ +#define RL_DIRFSUF MYEXTSTR "dir" /* suffix of a directory file */ +#define RL_DATAFSUF MYEXTSTR "pag" /* suffix of a page file */ +#define RL_PATHBUFSIZ 1024 /* size of a path buffer */ +#define RL_INITBNUM 1913 /* initial bucket number */ +#define RL_ALIGNSIZ 16 /* size of alignment */ +#define RL_MAXLOAD 1.25 /* max ratio of bucket loading */ +#define RL_DIRMAGIC "[depot]\0\v" /* magic number of a directory file */ + + +/* private function prototypes */ +static void dbm_writedummy(int fd); +static int dbm_writestr(int fd, const char *str); + + + +/************************************************************************************************* + * public objects + *************************************************************************************************/ + + +/* Get a database handle. */ +DBM *dbm_open(char *name, int flags, int mode){ + DBM *db; + DEPOT *depot; + int dpomode; + char path[RL_PATHBUFSIZ]; + int dfd, fd; + assert(name); + if(strlen(name) > RL_NAMEMAX) return NULL; + dpomode = DP_OREADER; + if((flags & O_WRONLY) || (flags & O_RDWR)){ + dpomode = DP_OWRITER; + if(flags & O_CREAT) dpomode |= DP_OCREAT; + if(flags & O_TRUNC) dpomode |= DP_OTRUNC; + } + mode |= 00600; + sprintf(path, "%s%s", name, RL_DIRFSUF); + if((dfd = open(path, flags, mode)) == -1) return NULL; + dbm_writedummy(dfd); + sprintf(path, "%s%s", name, RL_DATAFSUF); + if((fd = open(path, flags, mode)) == -1 || close(fd) == -1){ + close(dfd); + return NULL; + } + if(!(depot = dpopen(path, dpomode, RL_INITBNUM))){ + close(dfd); + return NULL; + } + if(dpomode & DP_OWRITER){ + if(!dpsetalign(depot, RL_ALIGNSIZ)){ + close(dfd); + dpclose(depot); + return NULL; + } + } + if(!(db = malloc(sizeof(DBM)))){ + close(dfd); + dpclose(depot); + return NULL; + } + db->depot = depot; + db->dfd = dfd; + db->dbm_fetch_vbuf = NULL; + db->dbm_nextkey_kbuf = NULL; + return db; +} + + +/* Close a database handle. */ +void dbm_close(DBM *db){ + assert(db); + free(db->dbm_fetch_vbuf); + free(db->dbm_nextkey_kbuf); + close(db->dfd); + dpclose(db->depot); + free(db); +} + + +/* Store a record. */ +int dbm_store(DBM *db, datum key, datum content, int flags){ + int dmode; + int bnum, rnum; + assert(db); + if(!key.dptr || key.dsize < 0 || !content.dptr || content.dsize < 0) return -1; + dmode = (flags == DBM_INSERT) ? DP_DKEEP : DP_DOVER; + if(!dpput(db->depot, key.dptr, key.dsize, content.dptr, content.dsize, dmode)){ + if(dpecode == DP_EKEEP) return 1; + return -1; + } + bnum = dpbnum(db->depot); + rnum = dprnum(db->depot); + if(bnum > 0 && rnum > 0 && ((double)rnum / (double)bnum > RL_MAXLOAD)){ + if(!dpoptimize(db->depot, -1)) return -1; + } + return 0; +} + + +/* Delete a record. */ +int dbm_delete(DBM *db, datum key){ + assert(db); + if(!key.dptr || key.dsize < 0) return -1; + if(!dpout(db->depot, key.dptr, key.dsize)) return -1; + return 0; +} + + +/* Retrieve a record. */ +datum dbm_fetch(DBM *db, datum key){ + datum content; + char *vbuf; + int vsiz; + assert(db); + if(!key.dptr || key.dsize < 0 || + !(vbuf = dpget(db->depot, key.dptr, key.dsize, 0, -1, &vsiz))){ + content.dptr = NULL; + content.dsize = 0; + return content; + } + free(db->dbm_fetch_vbuf); + db->dbm_fetch_vbuf = vbuf; + content.dptr = vbuf; + content.dsize = vsiz; + return content; +} + + +/* Get the first key of a database. */ +datum dbm_firstkey(DBM *db){ + assert(db); + dpiterinit(db->depot); + return dbm_nextkey(db); +} + + +/* Get the next key of a database. */ +datum dbm_nextkey(DBM *db){ + datum key; + char *kbuf; + int ksiz; + if(!(kbuf = dpiternext(db->depot, &ksiz))){ + key.dptr = NULL; + key.dsize = 0; + return key; + } + free(db->dbm_nextkey_kbuf); + db->dbm_nextkey_kbuf = kbuf; + key.dptr = kbuf; + key.dsize = ksiz; + return key; +} + + +/* Check whether a database has a fatal error or not. */ +int dbm_error(DBM *db){ + assert(db); + return dpfatalerror(db->depot) ? TRUE : FALSE; +} + + +/* No effect. */ +int dbm_clearerr(DBM *db){ + assert(db); + return 0; +} + + +/* Check whether a handle is read-only or not. */ +int dbm_rdonly(DBM *db){ + assert(db); + return dpwritable(db->depot) ? FALSE : TRUE; +} + + +/* Get the file descriptor of a directory file. */ +int dbm_dirfno(DBM *db){ + assert(db); + return db->dfd; +} + + +/* Get the file descriptor of a data file. */ +int dbm_pagfno(DBM *db){ + assert(db); + return dpfdesc(db->depot); +} + + + +/************************************************************************************************* + * private objects + *************************************************************************************************/ + + +/* Write dummy data into a dummy file. + `fd' specifies a file descriptor. */ +static void dbm_writedummy(int fd){ + struct stat sbuf; + if(fstat(fd, &sbuf) == -1 || sbuf.st_size > 0) return; + write(fd, RL_DIRMAGIC, sizeof(RL_DIRMAGIC) - 1); + dbm_writestr(fd, "\n\n"); + dbm_writestr(fd, "\x20\x20\xa2\xca\xa1\xb2\xa2\xca\x20\x20\x20\x20\x20\xa1\xbf\xa1"); + dbm_writestr(fd, "\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1"); + dbm_writestr(fd, "\xb1\x0a\xa1\xca\x20\xa1\xad\xa2\xcf\xa1\xae\xa1\xcb\xa1\xe3\x20"); + dbm_writestr(fd, "\x20\x4e\x44\x42\x4d\x20\x43\x6f\x6d\x70\x61\x74\x69\x62\x69\x6c"); + dbm_writestr(fd, "\x69\x74\x79\x0a\xa1\xca\x20\x20\x20\x20\x20\x20\x20\xa1\xcb\x20"); + dbm_writestr(fd, "\x20\xa1\xc0\xa1\xb2\xa1\xb2\xa1\xb2\xa1\xb2\xa1\xb2\xa1\xb2\xa1"); + dbm_writestr(fd, "\xb2\xa1\xb2\xa1\xb2\x0a\x20\xa1\xc3\x20\x20\xa1\xc3\x20\xa1\xc3"); + dbm_writestr(fd, "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"); + dbm_writestr(fd, "\x20\x20\x20\x20\x20\x20\x20\x0a\xa1\xca\x5f\x5f\xa1\xb2\xa1\xcb"); + dbm_writestr(fd, "\x5f\xa1\xcb\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"); + dbm_writestr(fd, "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a"); +} + + +/* Write a string into a file. + `fd' specifies a file descriptor. + `str' specifies a string. */ +static int dbm_writestr(int fd, const char *str){ + const char *lbuf; + int size, rv, wb; + assert(fd >= 0 && str); + lbuf = str; + size = strlen(str); + rv = 0; + do { + wb = write(fd, lbuf, size); + switch(wb){ + case -1: if(errno != EINTR) return -1; + case 0: break; + default: + lbuf += wb; + size -= wb; + rv += wb; + break; + } + } while(size > 0); + return rv; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/relic.h =================================================================== --- box/trunk/qdbm/relic.h 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/relic.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,170 +0,0 @@ -/************************************************************************************************* - * The NDBM-compatible API of QDBM - * 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. - *************************************************************************************************/ - - -#ifndef _RELIC_H /* duplication check */ -#define _RELIC_H - -#if defined(__cplusplus) /* export for C++ */ -extern "C" { -#endif - - -#include -#include -#include -#include -#include - - -#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) -#define MYEXTERN extern __declspec(dllimport) -#else -#define MYEXTERN extern -#endif - - - -/************************************************************************************************* - * API - *************************************************************************************************/ - - -typedef struct { /* type of structure for a database handle */ - DEPOT *depot; /* internal database handle */ - int dfd; /* file descriptor of a dummy file */ - char *dbm_fetch_vbuf; /* buffer for dbm_fetch */ - char *dbm_nextkey_kbuf; /* buffer for dbm_nextkey */ -} DBM; - -typedef struct { /* type of structure for a key or a value */ - void *dptr; /* pointer to the region */ - size_t dsize; /* size of the region */ -} datum; - -enum { /* enumeration for write modes */ - DBM_INSERT, /* keep an existing value */ - DBM_REPLACE /* overwrite an existing value */ -}; - - -/* Get a database handle. - `name' specifies the name of a database. The file names are concatenated with suffixes. - `flags' is the same as the one of `open' call, although `O_WRONLY' is treated as `O_RDWR' - and additional flags except for `O_CREAT' and `O_TRUNC' have no effect. - `mode' specifies the mode of the database file as the one of `open' call does. - The return value is the database handle or `NULL' if it is not successful. */ -DBM *dbm_open(char *name, int flags, int mode); - - -/* Close a database handle. - `db' specifies a database handle. - Because the region of the closed handle is released, it becomes impossible to use the - handle. */ -void dbm_close(DBM *db); - - -/* Store a record. - `db' specifies a database handle. - `key' specifies a structure of a key. - `content' specifies a structure of a value. - `flags' specifies behavior when the key overlaps, by the following values: `DBM_REPLACE', - which means the specified value overwrites the existing one, `DBM_INSERT', which means the - existing value is kept. - The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, - -1 if other error occurs. */ -int dbm_store(DBM *db, datum key, datum content, int flags); - - -/* Delete a record. - `db' specifies a database handle. - `key' specifies a structure of a key. - The return value is 0 if it is successful, -1 if some errors occur. */ -int dbm_delete(DBM *db, datum key); - - -/* Retrieve a record. - `db' specifies a database handle. - `key' specifies a structure of a key. - The return value is a structure of the result. - If a record corresponds, the member `dptr' of the structure is the pointer to the region of - the value. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points - to the region related with the handle. The region is available until the next time of - calling this function with the same handle. */ -datum dbm_fetch(DBM *db, datum key); - - -/* Get the first key of a database. - `db' specifies a database handle. - The return value is a structure of the result. - If a record corresponds, the member `dptr' of the structure is the pointer to the region of - the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' - points to the region related with the handle. The region is available until the next time - of calling this function or the function `dbm_nextkey' with the same handle. */ -datum dbm_firstkey(DBM *db); - - -/* Get the next key of a database. - `db' specifies a database handle. - The return value is a structure of the result. - If a record corresponds, the member `dptr' of the structure is the pointer to the region of - the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' - points to the region related with the handle. The region is available until the next time - of calling this function or the function `dbm_firstkey' with the same handle. */ -datum dbm_nextkey(DBM *db); - - -/* Check whether a database has a fatal error or not. - `db' specifies a database handle. - The return value is true if the database has a fatal error, false if not. */ -int dbm_error(DBM *db); - - -/* No effect. - `db' specifies a database handle. - The return value is 0. - The function is only for compatibility. */ -int dbm_clearerr(DBM *db); - - -/* Check whether a handle is read-only or not. - `db' specifies a database handle. - The return value is true if the handle is read-only, or false if not read-only. */ -int dbm_rdonly(DBM *db); - - -/* Get the file descriptor of a directory file. - `db' specifies a database handle. - The return value is the file descriptor of the directory file. */ -int dbm_dirfno(DBM *db); - - -/* Get the file descriptor of a data file. - `db' specifies a database handle. - The return value is the file descriptor of the data file. */ -int dbm_pagfno(DBM *db); - - - -#undef MYEXTERN - -#if defined(__cplusplus) /* export for C++ */ -} -#endif - -#endif /* duplication check */ - - -/* END OF FILE */ Copied: box/trunk/qdbm/relic.h (from rev 2716, box/trunk/qdbm/relic.h) =================================================================== --- box/trunk/qdbm/relic.h (rev 0) +++ box/trunk/qdbm/relic.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,170 @@ +/************************************************************************************************* + * The NDBM-compatible API of QDBM + * 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. + *************************************************************************************************/ + + +#ifndef _RELIC_H /* duplication check */ +#define _RELIC_H + +#if defined(__cplusplus) /* export for C++ */ +extern "C" { +#endif + + +#include +#include +#include +#include +#include + + +#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) +#define MYEXTERN extern __declspec(dllimport) +#else +#define MYEXTERN extern +#endif + + + +/************************************************************************************************* + * API + *************************************************************************************************/ + + +typedef struct { /* type of structure for a database handle */ + DEPOT *depot; /* internal database handle */ + int dfd; /* file descriptor of a dummy file */ + char *dbm_fetch_vbuf; /* buffer for dbm_fetch */ + char *dbm_nextkey_kbuf; /* buffer for dbm_nextkey */ +} DBM; + +typedef struct { /* type of structure for a key or a value */ + void *dptr; /* pointer to the region */ + size_t dsize; /* size of the region */ +} datum; + +enum { /* enumeration for write modes */ + DBM_INSERT, /* keep an existing value */ + DBM_REPLACE /* overwrite an existing value */ +}; + + +/* Get a database handle. + `name' specifies the name of a database. The file names are concatenated with suffixes. + `flags' is the same as the one of `open' call, although `O_WRONLY' is treated as `O_RDWR' + and additional flags except for `O_CREAT' and `O_TRUNC' have no effect. + `mode' specifies the mode of the database file as the one of `open' call does. + The return value is the database handle or `NULL' if it is not successful. */ +DBM *dbm_open(char *name, int flags, int mode); + + +/* Close a database handle. + `db' specifies a database handle. + Because the region of the closed handle is released, it becomes impossible to use the + handle. */ +void dbm_close(DBM *db); + + +/* Store a record. + `db' specifies a database handle. + `key' specifies a structure of a key. + `content' specifies a structure of a value. + `flags' specifies behavior when the key overlaps, by the following values: `DBM_REPLACE', + which means the specified value overwrites the existing one, `DBM_INSERT', which means the + existing value is kept. + The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, + -1 if other error occurs. */ +int dbm_store(DBM *db, datum key, datum content, int flags); + + +/* Delete a record. + `db' specifies a database handle. + `key' specifies a structure of a key. + The return value is 0 if it is successful, -1 if some errors occur. */ +int dbm_delete(DBM *db, datum key); + + +/* Retrieve a record. + `db' specifies a database handle. + `key' specifies a structure of a key. + The return value is a structure of the result. + If a record corresponds, the member `dptr' of the structure is the pointer to the region of + the value. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points + to the region related with the handle. The region is available until the next time of + calling this function with the same handle. */ +datum dbm_fetch(DBM *db, datum key); + + +/* Get the first key of a database. + `db' specifies a database handle. + The return value is a structure of the result. + If a record corresponds, the member `dptr' of the structure is the pointer to the region of + the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' + points to the region related with the handle. The region is available until the next time + of calling this function or the function `dbm_nextkey' with the same handle. */ +datum dbm_firstkey(DBM *db); + + +/* Get the next key of a database. + `db' specifies a database handle. + The return value is a structure of the result. + If a record corresponds, the member `dptr' of the structure is the pointer to the region of + the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' + points to the region related with the handle. The region is available until the next time + of calling this function or the function `dbm_firstkey' with the same handle. */ +datum dbm_nextkey(DBM *db); + + +/* Check whether a database has a fatal error or not. + `db' specifies a database handle. + The return value is true if the database has a fatal error, false if not. */ +int dbm_error(DBM *db); + + +/* No effect. + `db' specifies a database handle. + The return value is 0. + The function is only for compatibility. */ +int dbm_clearerr(DBM *db); + + +/* Check whether a handle is read-only or not. + `db' specifies a database handle. + The return value is true if the handle is read-only, or false if not read-only. */ +int dbm_rdonly(DBM *db); + + +/* Get the file descriptor of a directory file. + `db' specifies a database handle. + The return value is the file descriptor of the directory file. */ +int dbm_dirfno(DBM *db); + + +/* Get the file descriptor of a data file. + `db' specifies a database handle. + The return value is the file descriptor of the data file. */ +int dbm_pagfno(DBM *db); + + + +#undef MYEXTERN + +#if defined(__cplusplus) /* export for C++ */ +} +#endif + +#endif /* duplication check */ + + +/* END OF FILE */ Deleted: box/trunk/qdbm/rlmgr.c =================================================================== --- box/trunk/qdbm/rlmgr.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/rlmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,465 +0,0 @@ -/************************************************************************************************* - * Utility for debugging Relic and its applications - * 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 -#include -#include -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -char *hextoobj(const char *str, int *sp); -int runcreate(int argc, char **argv); -int runstore(int argc, char **argv); -int rundelete(int argc, char **argv); -int runfetch(int argc, char **argv); -int runlist(int argc, char **argv); -void pmyerror(const char *name, const char *msg); -void printobj(const char *obj, int size); -void printobjhex(const char *obj, int size); -int docreate(char *name); -int dostore(char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins); -int dodelete(char *name, const char *kbuf, int ksiz); -int dofetch(char *name, const char *kbuf, int ksiz, int ox, int nb); -int dolist(char *name, int ox); - - -/* main routine */ -int main(int argc, char **argv){ - int rv; - cbstdiobin(); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "create")){ - rv = runcreate(argc, argv); - } else if(!strcmp(argv[1], "store")){ - rv = runstore(argc, argv); - } else if(!strcmp(argv[1], "delete")){ - rv = rundelete(argc, argv); - } else if(!strcmp(argv[1], "fetch")){ - rv = runfetch(argc, argv); - } else if(!strcmp(argv[1], "list")){ - rv = runlist(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: administration utility for Relic\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s create name\n", progname); - fprintf(stderr, " %s store [-kx] [-vx|-vf] [-insert] name key val\n", progname); - fprintf(stderr, " %s delete [-kx] name key\n", progname); - fprintf(stderr, " %s fetch [-kx] [-ox] [-n] name key\n", progname); - fprintf(stderr, " %s list [-ox] name\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* create a binary object from a hexadecimal string */ -char *hextoobj(const char *str, int *sp){ - char *buf, mbuf[3]; - int len, i, j; - len = strlen(str); - if(!(buf = malloc(len + 1))) return NULL; - j = 0; - for(i = 0; i < len; i += 2){ - while(strchr(" \n\r\t\f\v", str[i])){ - i++; - } - if((mbuf[0] = str[i]) == '\0') break; - if((mbuf[1] = str[i+1]) == '\0') break; - mbuf[2] = '\0'; - buf[j++] = (char)strtol(mbuf, NULL, 16); - } - buf[j] = '\0'; - *sp = j; - return buf; -} - - -/* parse arguments of create command */ -int runcreate(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = docreate(name); - return rv; -} - - -/* parse arguments of store command */ -int runstore(int argc, char **argv){ - char *name, *key, *val, *kbuf, *vbuf; - int i, kx, vx, vf, ins, ksiz, vsiz, rv; - name = NULL; - kx = FALSE; - vx = FALSE; - vf = FALSE; - ins = FALSE; - key = NULL; - val = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-vx")){ - vx = TRUE; - } else if(!strcmp(argv[i], "-vf")){ - vf = TRUE; - } else if(!strcmp(argv[i], "-insert")){ - ins = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else if(!val){ - val = argv[i]; - } else { - usage(); - } - } - if(!name || !key || !val) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = strlen(kbuf); - } - if(vx){ - vbuf = hextoobj(val, &vsiz); - } else if(vf){ - vbuf = cbreadfile(val, &vsiz); - } else { - vbuf = cbmemdup(val, -1); - vsiz = strlen(vbuf); - } - if(kbuf && vbuf){ - rv = dostore(name, kbuf, ksiz, vbuf, vsiz, ins); - } else { - if(vf){ - fprintf(stderr, "%s: %s: cannot read\n", progname, val); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - } - rv = 1; - } - free(kbuf); - free(vbuf); - return rv; -} - - -/* parse arguments of delete command */ -int rundelete(int argc, char **argv){ - char *name, *key, *kbuf; - int i, kx, ksiz, rv; - name = NULL; - kx = FALSE; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = strlen(kbuf); - } - if(kbuf){ - rv = dodelete(name, kbuf, ksiz); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* parse arguments of fetch command */ -int runfetch(int argc, char **argv){ - char *name, *key, *kbuf; - int i, kx, ox, nb, ksiz, rv; - name = NULL; - kx = FALSE; - ox = FALSE; - nb = FALSE; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else if(!strcmp(argv[i], "-n")){ - nb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = strlen(kbuf); - } - if(kbuf){ - rv = dofetch(name, kbuf, ksiz, ox, nb); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* parse arguments of list command */ -int runlist(int argc, char **argv){ - char *name; - int i, ox, rv; - name = NULL; - ox = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dolist(name, ox); - return rv; -} - - -/* print an error message */ -void pmyerror(const char *name, const char *msg){ - fprintf(stderr, "%s: %s: %s\n", progname, name, msg); -} - - -/* print an object */ -void printobj(const char *obj, int size){ - int i; - for(i = 0; i < size; i++){ - putchar(obj[i]); - } -} - - -/* print an object as a hexadecimal string */ -void printobjhex(const char *obj, int size){ - int i; - for(i = 0; i < size; i++){ - printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); - } -} - - -/* perform create command */ -int docreate(char *name){ - DBM *db; - if(!(db = dbm_open(name, O_RDWR | O_CREAT | O_TRUNC, 00644))){ - pmyerror(name, "dbm_open failed"); - return 1; - } - dbm_close(db); - return 0; -} - - -/* perform store command */ -int dostore(char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins){ - DBM *db; - datum key, content; - int rv; - if(!(db = dbm_open(name, O_RDWR, 00644))){ - pmyerror(name, "dbm_open failed"); - return 1; - } - key.dptr = (char *)kbuf; - key.dsize = ksiz; - content.dptr = (char *)vbuf; - content.dsize = vsiz; - switch(dbm_store(db, key, content, ins ? DBM_INSERT : DBM_REPLACE)){ - case 0: - rv = 0; - break; - case 1: - pmyerror(name, "dbm_store failed by insert"); - rv = 1; - break; - default: - pmyerror(name, "dbm_store failed"); - rv = 1; - break; - } - dbm_close(db); - return rv; -} - - -/* perform delete command */ -int dodelete(char *name, const char *kbuf, int ksiz){ - DBM *db; - datum key; - int rv; - if(!(db = dbm_open((char *)name, O_RDWR, 00644))){ - pmyerror(name, "dbm_open failed"); - return 1; - } - key.dptr = (char *)kbuf; - key.dsize = ksiz; - if(dbm_delete(db, key) == 0){ - rv = 0; - } else { - pmyerror(name, "dbm_delete failed"); - rv = 1; - } - dbm_close(db); - return rv; -} - - -/* perform fetch command */ -int dofetch(char *name, const char *kbuf, int ksiz, int ox, int nb){ - DBM *db; - datum key, content; - int rv; - if(!(db = dbm_open((char *)name, O_RDONLY, 00644))){ - pmyerror(name, "dbm_open failed"); - return 1; - } - key.dptr = (char *)kbuf; - key.dsize = ksiz; - content = dbm_fetch(db, key); - if(content.dptr){ - if(ox){ - printobjhex(content.dptr, content.dsize); - } else { - printobj(content.dptr, content.dsize); - } - if(!nb) putchar('\n'); - rv = 0; - } else { - pmyerror(name, "dbm_fetch failed"); - rv = 1; - } - dbm_close(db); - return rv; -} - - -/* perform list command */ -int dolist(char *name, int ox){ - DBM *db; - datum key, val; - if(!(db = dbm_open((char *)name, O_RDONLY, 00644))){ - pmyerror(name, "dbm_open failed"); - return 1; - } - for(key = dbm_firstkey(db); key.dptr != NULL; key = dbm_nextkey(db)){ - val = dbm_fetch(db, key); - if(!val.dptr) break; - if(ox){ - printobjhex(key.dptr, key.dsize); - putchar('\t'); - printobjhex(val.dptr, val.dsize); - } else { - printobj(key.dptr, key.dsize); - putchar('\t'); - printobj(val.dptr, val.dsize); - } - putchar('\n'); - } - dbm_close(db); - return 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/rlmgr.c (from rev 2716, box/trunk/qdbm/rlmgr.c) =================================================================== --- box/trunk/qdbm/rlmgr.c (rev 0) +++ box/trunk/qdbm/rlmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,465 @@ +/************************************************************************************************* + * Utility for debugging Relic and its applications + * 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 +#include +#include +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +char *hextoobj(const char *str, int *sp); +int runcreate(int argc, char **argv); +int runstore(int argc, char **argv); +int rundelete(int argc, char **argv); +int runfetch(int argc, char **argv); +int runlist(int argc, char **argv); +void pmyerror(const char *name, const char *msg); +void printobj(const char *obj, int size); +void printobjhex(const char *obj, int size); +int docreate(char *name); +int dostore(char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins); +int dodelete(char *name, const char *kbuf, int ksiz); +int dofetch(char *name, const char *kbuf, int ksiz, int ox, int nb); +int dolist(char *name, int ox); + + +/* main routine */ +int main(int argc, char **argv){ + int rv; + cbstdiobin(); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "create")){ + rv = runcreate(argc, argv); + } else if(!strcmp(argv[1], "store")){ + rv = runstore(argc, argv); + } else if(!strcmp(argv[1], "delete")){ + rv = rundelete(argc, argv); + } else if(!strcmp(argv[1], "fetch")){ + rv = runfetch(argc, argv); + } else if(!strcmp(argv[1], "list")){ + rv = runlist(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: administration utility for Relic\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s create name\n", progname); + fprintf(stderr, " %s store [-kx] [-vx|-vf] [-insert] name key val\n", progname); + fprintf(stderr, " %s delete [-kx] name key\n", progname); + fprintf(stderr, " %s fetch [-kx] [-ox] [-n] name key\n", progname); + fprintf(stderr, " %s list [-ox] name\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* create a binary object from a hexadecimal string */ +char *hextoobj(const char *str, int *sp){ + char *buf, mbuf[3]; + int len, i, j; + len = strlen(str); + if(!(buf = malloc(len + 1))) return NULL; + j = 0; + for(i = 0; i < len; i += 2){ + while(strchr(" \n\r\t\f\v", str[i])){ + i++; + } + if((mbuf[0] = str[i]) == '\0') break; + if((mbuf[1] = str[i+1]) == '\0') break; + mbuf[2] = '\0'; + buf[j++] = (char)strtol(mbuf, NULL, 16); + } + buf[j] = '\0'; + *sp = j; + return buf; +} + + +/* parse arguments of create command */ +int runcreate(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = docreate(name); + return rv; +} + + +/* parse arguments of store command */ +int runstore(int argc, char **argv){ + char *name, *key, *val, *kbuf, *vbuf; + int i, kx, vx, vf, ins, ksiz, vsiz, rv; + name = NULL; + kx = FALSE; + vx = FALSE; + vf = FALSE; + ins = FALSE; + key = NULL; + val = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-vx")){ + vx = TRUE; + } else if(!strcmp(argv[i], "-vf")){ + vf = TRUE; + } else if(!strcmp(argv[i], "-insert")){ + ins = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else if(!val){ + val = argv[i]; + } else { + usage(); + } + } + if(!name || !key || !val) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = strlen(kbuf); + } + if(vx){ + vbuf = hextoobj(val, &vsiz); + } else if(vf){ + vbuf = cbreadfile(val, &vsiz); + } else { + vbuf = cbmemdup(val, -1); + vsiz = strlen(vbuf); + } + if(kbuf && vbuf){ + rv = dostore(name, kbuf, ksiz, vbuf, vsiz, ins); + } else { + if(vf){ + fprintf(stderr, "%s: %s: cannot read\n", progname, val); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + } + rv = 1; + } + free(kbuf); + free(vbuf); + return rv; +} + + +/* parse arguments of delete command */ +int rundelete(int argc, char **argv){ + char *name, *key, *kbuf; + int i, kx, ksiz, rv; + name = NULL; + kx = FALSE; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = strlen(kbuf); + } + if(kbuf){ + rv = dodelete(name, kbuf, ksiz); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* parse arguments of fetch command */ +int runfetch(int argc, char **argv){ + char *name, *key, *kbuf; + int i, kx, ox, nb, ksiz, rv; + name = NULL; + kx = FALSE; + ox = FALSE; + nb = FALSE; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else if(!strcmp(argv[i], "-n")){ + nb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = strlen(kbuf); + } + if(kbuf){ + rv = dofetch(name, kbuf, ksiz, ox, nb); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* parse arguments of list command */ +int runlist(int argc, char **argv){ + char *name; + int i, ox, rv; + name = NULL; + ox = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dolist(name, ox); + return rv; +} + + +/* print an error message */ +void pmyerror(const char *name, const char *msg){ + fprintf(stderr, "%s: %s: %s\n", progname, name, msg); +} + + +/* print an object */ +void printobj(const char *obj, int size){ + int i; + for(i = 0; i < size; i++){ + putchar(obj[i]); + } +} + + +/* print an object as a hexadecimal string */ +void printobjhex(const char *obj, int size){ + int i; + for(i = 0; i < size; i++){ + printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); + } +} + + +/* perform create command */ +int docreate(char *name){ + DBM *db; + if(!(db = dbm_open(name, O_RDWR | O_CREAT | O_TRUNC, 00644))){ + pmyerror(name, "dbm_open failed"); + return 1; + } + dbm_close(db); + return 0; +} + + +/* perform store command */ +int dostore(char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins){ + DBM *db; + datum key, content; + int rv; + if(!(db = dbm_open(name, O_RDWR, 00644))){ + pmyerror(name, "dbm_open failed"); + return 1; + } + key.dptr = (char *)kbuf; + key.dsize = ksiz; + content.dptr = (char *)vbuf; + content.dsize = vsiz; + switch(dbm_store(db, key, content, ins ? DBM_INSERT : DBM_REPLACE)){ + case 0: + rv = 0; + break; + case 1: + pmyerror(name, "dbm_store failed by insert"); + rv = 1; + break; + default: + pmyerror(name, "dbm_store failed"); + rv = 1; + break; + } + dbm_close(db); + return rv; +} + + +/* perform delete command */ +int dodelete(char *name, const char *kbuf, int ksiz){ + DBM *db; + datum key; + int rv; + if(!(db = dbm_open((char *)name, O_RDWR, 00644))){ + pmyerror(name, "dbm_open failed"); + return 1; + } + key.dptr = (char *)kbuf; + key.dsize = ksiz; + if(dbm_delete(db, key) == 0){ + rv = 0; + } else { + pmyerror(name, "dbm_delete failed"); + rv = 1; + } + dbm_close(db); + return rv; +} + + +/* perform fetch command */ +int dofetch(char *name, const char *kbuf, int ksiz, int ox, int nb){ + DBM *db; + datum key, content; + int rv; + if(!(db = dbm_open((char *)name, O_RDONLY, 00644))){ + pmyerror(name, "dbm_open failed"); + return 1; + } + key.dptr = (char *)kbuf; + key.dsize = ksiz; + content = dbm_fetch(db, key); + if(content.dptr){ + if(ox){ + printobjhex(content.dptr, content.dsize); + } else { + printobj(content.dptr, content.dsize); + } + if(!nb) putchar('\n'); + rv = 0; + } else { + pmyerror(name, "dbm_fetch failed"); + rv = 1; + } + dbm_close(db); + return rv; +} + + +/* perform list command */ +int dolist(char *name, int ox){ + DBM *db; + datum key, val; + if(!(db = dbm_open((char *)name, O_RDONLY, 00644))){ + pmyerror(name, "dbm_open failed"); + return 1; + } + for(key = dbm_firstkey(db); key.dptr != NULL; key = dbm_nextkey(db)){ + val = dbm_fetch(db, key); + if(!val.dptr) break; + if(ox){ + printobjhex(key.dptr, key.dsize); + putchar('\t'); + printobjhex(val.dptr, val.dsize); + } else { + printobj(key.dptr, key.dsize); + putchar('\t'); + printobj(val.dptr, val.dsize); + } + putchar('\n'); + } + dbm_close(db); + return 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/rltest.c =================================================================== --- box/trunk/qdbm/rltest.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/rltest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,241 +0,0 @@ -/************************************************************************************************* - * Test cases of Relic - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define RECBUFSIZ 32 /* buffer for records */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -int runwrite(int argc, char **argv); -int runread(int argc, char **argv); -int printfflush(const char *format, ...); -void pmyerror(const char *name, const char *msg); -int dowrite(char *name, int rnum); -int doread(char *name, int rnum); - - -/* main routine */ -int main(int argc, char **argv){ - int rv; - cbstdiobin(); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "write")){ - rv = runwrite(argc, argv); - } else if(!strcmp(argv[1], "read")){ - rv = runread(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: test cases for Relic\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s write name rnum\n", progname); - fprintf(stderr, " %s read name rnum\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of write command */ -int runwrite(int argc, char **argv){ - char *name, *rstr; - int i, rnum, rv; - name = NULL; - rstr = NULL; - rnum = 0; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = dowrite(name, rnum); - return rv; -} - - -/* parse arguments of read command */ -int runread(int argc, char **argv){ - char *name, *rstr; - int i, rnum, rv; - name = NULL; - rstr = NULL; - rnum = 0; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = doread(name, rnum); - return rv; -} - - -/* print formatted string and flush the buffer */ -int printfflush(const char *format, ...){ - va_list ap; - int rv; - va_start(ap, format); - rv = vprintf(format, ap); - if(fflush(stdout) == EOF) rv = -1; - va_end(ap); - return rv; -} - - -/* print an error message */ -void pmyerror(const char *name, const char *msg){ - fprintf(stderr, "%s: %s: %s\n", progname, name, msg); -} - - -/* perform write command */ -int dowrite(char *name, int rnum){ - DBM *db; - datum key, content; - int i, err, len; - char buf[RECBUFSIZ]; - printfflush("\n name=%s rnum=%d\n\n", name, rnum); - /* open a database */ - if(!(db = dbm_open(name, O_RDWR | O_CREAT | O_TRUNC, 00644))){ - pmyerror(name, "dbm_open failed"); - return 1; - } - err = FALSE; - /* loop for each record */ - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", i); - key.dptr = buf; - key.dsize = len; - content.dptr = buf; - content.dsize = len; - /* store a record */ - if(dbm_store(db, key, content, DBM_REPLACE) < 0){ - pmyerror(name, "dbm_store failed"); - err = TRUE; - break; - } - /* print progression */ - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - dbm_close(db); - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - -/* perform read command */ -int doread(char *name, int rnum){ - DBM *db; - datum key, content; - int i, err, len; - char buf[RECBUFSIZ]; - printfflush("\n name=%s rnum=%d\n\n", name, rnum); - /* open a database */ - if(!(db = dbm_open(name, O_RDONLY, 00644))){ - pmyerror(name, "dbm_open failed"); - return 1; - } - err = FALSE; - /* loop for each record */ - for(i = 1; i <= rnum; i++){ - /* retrieve a record */ - len = sprintf(buf, "%08d", i); - key.dptr = buf; - key.dsize = len; - content = dbm_fetch(db, key); - if(!content.dptr){ - pmyerror(name, "dbm_fetch failed"); - err = TRUE; - break; - } - /* print progression */ - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - dbm_close(db); - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/rltest.c (from rev 2716, box/trunk/qdbm/rltest.c) =================================================================== --- box/trunk/qdbm/rltest.c (rev 0) +++ box/trunk/qdbm/rltest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,241 @@ +/************************************************************************************************* + * Test cases of Relic + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define RECBUFSIZ 32 /* buffer for records */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +int runwrite(int argc, char **argv); +int runread(int argc, char **argv); +int printfflush(const char *format, ...); +void pmyerror(const char *name, const char *msg); +int dowrite(char *name, int rnum); +int doread(char *name, int rnum); + + +/* main routine */ +int main(int argc, char **argv){ + int rv; + cbstdiobin(); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "write")){ + rv = runwrite(argc, argv); + } else if(!strcmp(argv[1], "read")){ + rv = runread(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: test cases for Relic\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s write name rnum\n", progname); + fprintf(stderr, " %s read name rnum\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of write command */ +int runwrite(int argc, char **argv){ + char *name, *rstr; + int i, rnum, rv; + name = NULL; + rstr = NULL; + rnum = 0; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = dowrite(name, rnum); + return rv; +} + + +/* parse arguments of read command */ +int runread(int argc, char **argv){ + char *name, *rstr; + int i, rnum, rv; + name = NULL; + rstr = NULL; + rnum = 0; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = doread(name, rnum); + return rv; +} + + +/* print formatted string and flush the buffer */ +int printfflush(const char *format, ...){ + va_list ap; + int rv; + va_start(ap, format); + rv = vprintf(format, ap); + if(fflush(stdout) == EOF) rv = -1; + va_end(ap); + return rv; +} + + +/* print an error message */ +void pmyerror(const char *name, const char *msg){ + fprintf(stderr, "%s: %s: %s\n", progname, name, msg); +} + + +/* perform write command */ +int dowrite(char *name, int rnum){ + DBM *db; + datum key, content; + int i, err, len; + char buf[RECBUFSIZ]; + printfflush("\n name=%s rnum=%d\n\n", name, rnum); + /* open a database */ + if(!(db = dbm_open(name, O_RDWR | O_CREAT | O_TRUNC, 00644))){ + pmyerror(name, "dbm_open failed"); + return 1; + } + err = FALSE; + /* loop for each record */ + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", i); + key.dptr = buf; + key.dsize = len; + content.dptr = buf; + content.dsize = len; + /* store a record */ + if(dbm_store(db, key, content, DBM_REPLACE) < 0){ + pmyerror(name, "dbm_store failed"); + err = TRUE; + break; + } + /* print progression */ + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + dbm_close(db); + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + +/* perform read command */ +int doread(char *name, int rnum){ + DBM *db; + datum key, content; + int i, err, len; + char buf[RECBUFSIZ]; + printfflush("\n name=%s rnum=%d\n\n", name, rnum); + /* open a database */ + if(!(db = dbm_open(name, O_RDONLY, 00644))){ + pmyerror(name, "dbm_open failed"); + return 1; + } + err = FALSE; + /* loop for each record */ + for(i = 1; i <= rnum; i++){ + /* retrieve a record */ + len = sprintf(buf, "%08d", i); + key.dptr = buf; + key.dsize = len; + content = dbm_fetch(db, key); + if(!content.dptr){ + pmyerror(name, "dbm_fetch failed"); + err = TRUE; + break; + } + /* print progression */ + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + dbm_close(db); + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/spex-ja.html =================================================================== --- box/trunk/qdbm/spex-ja.html 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/spex-ja.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,4348 +0,0 @@ - - - - - - - - - - - - - - - -Specifications of QDBM Version 1 (Japanese) - - - - - -

QDBM?????????????????????????????????

- -
Copyright (C) 2000-2007 Mikio Hirabayashi
-
Last Update: Thu, 26 Oct 2006 15:00:20 +0900
- - -
- -

??????

- -
    -
  1. ??????
  2. -
  3. ??????
  4. -
  5. ??????????????????
  6. -
  7. Depot: ??????API
  8. -
  9. Depot???????????????
  10. -
  11. Curia: ??????API
  12. -
  13. Curia???????????????
  14. -
  15. Relic: NDBM??????API
  16. -
  17. Relic???????????????
  18. -
  19. Hovel: GDBM??????API
  20. -
  21. Hovel???????????????
  22. -
  23. Cabin: ?????????????????????API
  24. -
  25. Cabin???????????????
  26. -
  27. Villa: ??????API
  28. -
  29. Villa???????????????
  30. -
  31. Odeum: ??????API
  32. -
  33. Odeum???????????????
  34. -
  35. ??????????????????????????????
  36. -
  37. ????????????
  38. -
  39. ??????
  40. -
  41. ????????????????????????
  42. -
  43. ???????????????
  44. -
- -
- -

??????

- -

QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+????????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????UNIX??????????????????????????????DBM?????????????????????????????????????????????NDBM???GDBM??????????????????????????????QDBM???DBM???????????????????????????????????????????????????????????????

- -

B+????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+???????????????????????????????????????????????????????????????????????????

- -

QDBM???C??????????????????C???C++???Java???Perl?????????Ruby???API???????????????????????????QDBM???POSIX?????????API?????????????????????????????????????????????????????????QDBM???GNU Lesser General Public License???????????????????????????????????????????????????

- -
- -

??????

- -

???????????????????????????????????????????????????

- -

QDBM???GDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API???????????????????????????????????????????????????????????????????????????????????????GDBM???????????????????????????DBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

QDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? O(1) ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? O(log n) ?????????????????????

- -

QDBM??????????????????????????????RAM??????????????????????????????????????????????????????????????????????????????????????????RAM????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `read' ????????????RAM????????????????????????????????????`mmap' ????????????RAM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????56.7%??????????????????????????????36.8%???2?????????21.3%???4?????????11.5%???8?????????6.0%??????????????????????????????????????????2???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????100????????????????????????????????????????????????50????????????????????????????????????????????????????????????????????????????????????4????????????????????????????????????2M????????????RAM?????????????????????100?????????????????????????????????????????????????????????

- -

QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

????????????DBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????DBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

??????????????????????????????????????????2GB????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1TB???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????RAID-0????????????????????????????????????????????????????????????????????????????????????????????????NFS???????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

?????????B+??????????????????????????????

- -

B+?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? O(log n) ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? O(1) ????????????

- -

B+???????????????????????????????????????????????????????????????????????????????????????????????????B+????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+?????????????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1????????????????????????

- -

B+??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

?????????????????????????????????????????????ZLIB???LZO???BZIP2??????????????????QDBM????????????????????????B+?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Lempel-Ziv??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????25%?????????????????????????????????????????????????????????????????????I/O?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

?????????????????????????????????????????????

- -

QDBM???API??????????????????????????????ANSI C?????????????????? `FILE' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????API???????????????????????????????????????????????????????????????????????????????????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

NDBM?????????GDBM???????????????API?????????????????????NDBM???GDBM??????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????#include??????????????????????????????????????????????????????????????????????????????????????????NDBM???GDBM????????????????????????????????????????????????QDBM?????????????????????????????????

- -

??????????????????????????????????????????????????????????????????????????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????C????????????Perl???Ruby?????????????????????????????????????????????????????????????????????????????????????????????

- -

B+??????????????????????????????API?????????????????????????????????API?????????API????????????????????????API???????????????????????????????????????API?????????API?????????API????????????????????????????????????????????????????????????????????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

QDBM???C?????????????????????C++???Java???Perl?????????Ruby???API??????????????????C?????????API???????????????API?????????API???NDBM??????API???GDBM??????API????????????????????????API?????????API???????????????API???????????????????????????API???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????C++???API?????????API?????????API?????????API???????????????????????????????????????C++????????????????????????????????????????????????????????????Java???API???Java Native Interface??????????????????API?????????API?????????API?????????????????????????????????Perl???API???XS????????????????????????API?????????API?????????API?????????????????????????????????Ruby???API???Ruby?????????????????????????????????API?????????API?????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????CGI???????????? ????????????????????????

- -

??????????????????

- -

QDBM???ANSI C???C89????????????????????????ANSI C?????????POSIX??????????????????API?????????????????????????????????????????????????????????????????????UNIX?????????????????????????????????OS???????????????????????????????????????C?????????API???????????????????????????????????????????????????????????????????????????????????????????????????

- -
    -
  • Linux (2.2, 2.4, 2.6) (IA32, IA64, AMD64, PA-RISC, Alpha, PowerPC, M68000, ARM)
  • -
  • FreeBSD (4.9, 5.0, 5.1, 5.2, 5.3) (IA32, IA64, SPARC, Alpha)
  • -
  • NetBSD (1.6) (IA32)
  • -
  • OpenBSD (3.4) (IA32)
  • -
  • SunOS (5.6, 5.7, 5.8, 5.9, 5.10) (IA32, SPARC)
  • -
  • HP-UX (11.11, 11.23) (IA64, PA-RISC)
  • -
  • AIX (5.2) (POWER)
  • -
  • Windows (2000, XP) (IA32, IA64, AMD64) (Cygwin, MinGW, Visual C++)
  • -
  • Mac OS X (10.2, 10.3, 10.4) (IA32, PowerPC)
  • -
  • Tru64 (5.1) (Alpha)
  • -
  • RISC OS (5.03) (ARM)
  • -
- -

QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
- -

??????????????????

- -

??????

- -

????????????????????????????????????QDBM????????????????????????????????????GCC??????????????????2.8????????? `make' ?????????????????????

- -

QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????????

- -

Linux???BSD???SunOS?????????????????????????????????

- -

?????????????????????????????????

- -
./configure
-
- -

????????????????????????????????????

- -
make
-
- -

???????????????????????????????????????????????????

- -
make check
-
- -

?????????????????????????????????????????????????????? `root' ?????????????????????

- -
make install
-
- -

GNU Libtool???????????????

- -

????????????????????????????????????????????????????????????????????????????????????????????????GNU Libtool??????????????????1.5???????????????????????????

- -

?????????????????????????????????

- -
./configure
-
- -

????????????????????????????????????

- -
make -f LTmakefile
-
- -

???????????????????????????????????????????????????

- -
make -f LTmakefile check
-
- -

?????????????????????????????????????????????????????? `root' ?????????????????????

- -
make -f LTmakefile install
-
- -

??????

- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `/usr/local/man/man1' ??? `/usr/local/man/man3' ?????????????????????????????? `/usr/local/share/qdbm' ??????`pkg-config' ??????????????????????????? `/usr/local/lib/pkgconfig' ?????????????????????????????????

- -
/usr/local/include/depot.h
-/usr/local/include/curia.h
-/usr/local/include/relic.h
-/usr/local/include/hovel.h
-/usr/local/include/cabin.h
-/usr/local/include/villa.h
-/usr/local/include/vista.h
-/usr/local/include/odeum.h
-/usr/local/lib/libqdbm.a
-/usr/local/lib/libqdbm.so.14.13.0
-/usr/local/lib/libqdbm.so.14
-/usr/local/lib/libqdbm.so
-/usr/local/bin/dpmgr
-/usr/local/bin/dptest
-/usr/local/bin/dptsv
-/usr/local/bin/crmgr
-/usr/local/bin/crtest
-/usr/local/bin/crtsv
-/usr/local/bin/rlmgr
-/usr/local/bin/rltest
-/usr/local/bin/hvmgr
-/usr/local/bin/hvtest
-/usr/local/bin/cbtest
-/usr/local/bin/cbcodec
-/usr/local/bin/vlmgr
-/usr/local/bin/vltest
-/usr/local/bin/vltsv
-/usr/local/bin/odmgr
-/usr/local/bin/odtest
-/usr/local/bin/odidx
-/usr/local/bin/qmttest
-
- -

`libqdbm.so' ?????????????????????????????????????????????????????????????????????????????????????????????????????? `/usr/local/lib' ?????????????????????????????????????????? `LD_LIBRARY_PATH' ?????????????????????????????????????????????????????????????????????

- -

QDBM??????????????????????????????????????????`./configure' ???????????????????????????????????????????????????????????????????????? `root' ?????????????????????

- -
make uninstall
-
- -

QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

C???????????????API???CGI????????????????????????????????????????????????????????????????????????C++???API????????????????????????????????????????????????????????????????????? `plus' ????????? `xspex-ja.html' ????????????????????????JAVA???API????????????????????????????????????????????????????????????????????? `java' ????????? `jspex-ja.html' ????????????????????????Perl???API????????????????????????????????????????????????????????????????????? `perl' ????????? `plspex-ja.html' ????????????????????????Ruby???API????????????????????????????????????????????????????????????????????? `ruby' ????????? `rbspex-ja.html' ????????????????????????CGI???????????????????????????????????????????????????????????????????????????????????? `cgi' ????????? `cgispex.html' ????????????????????????

- -

RPM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????RPM?????????????????????????????????????????????????????? `root' ???????????????????????????

- -
rpm -ivh qdbm-1.x.x-x.i386.rpm
-
- -

Windows?????????

- -

Windows???Cygwin??????????????????????????????????????????????????????????????????

- -

?????????????????????????????????

- -
./configure
-
- -

????????????????????????????????????

- -
make win
-
- -

???????????????????????????????????????????????????

- -
make check-win
-
- -

????????????????????????????????????????????????????????????????????????????????????????????? `make uninstall-win' ????????????

- -
make install-win
-
- -

Windows?????????????????????????????? `libqdbm.a' ?????????????????????????????????????????? `libqdbm.dll.a' ??????????????????????????????????????? `libqdbm.so' ???????????????????????????????????????????????????????????? `qdbm.dll' ?????????????????????`qdbm.dll' ??? `/usr/local/bin' ?????????????????????????????????

- -

Cygwin?????????MinGW????????????????????????????????????`make win' ??????????????? `make mingw' ???????????????Cygwin???UNIX????????????????????????????????????????????????????????????????????????????????? `cygwin1.dll' ?????????????????????????????????GNU GPL???????????????????????????MinGW????????????Win32??????????????????DLL?????????????????????????????????????????????????????????

- -

Visual C++????????????????????????????????????`VCmakefile' ?????????????????????????????????????????????????????????????????????????????????`nmake /f VCMakefile' ???????????????????????????????????? `qdbm.dll' ?????????????????????????????????????????????????????????????????? `/MD' ????????? `/MDd' ??????????????????????????? `msvcrt.dll' ?????????????????????????????????????????????????????????????????? `VCmakefile' ?????????????????????

- -

Mac OS X?????????

- -

Mac OS X???Darwin??????????????????????????????????????????????????????????????????

- -

?????????????????????????????????

- -
./configure
-
- -

????????????????????????????????????

- -
make mac
-
- -

???????????????????????????????????????????????????

- -
make check-mac
-
- -

????????????????????????????????????????????????????????????????????????????????????????????? `make uninstall-mac' ????????????

- -
make install-mac
-
- -

Mac OS X?????????`libqdbm.so' ?????????????????? `libqdbm.dylib' ?????????????????????????????????????????????????????????????????????????????? `DYLD_LIBRARY_PATH' ??????????????????????????????

- -

HP-UX?????????

- -

HP-UX???????????????????????????????????????????????????????????????

- -

?????????????????????????????????

- -
./configure
-
- -

????????????????????????????????????

- -
make hpux
-
- -

???????????????????????????????????????????????????

- -
make check-hpux
-
- -

????????????????????????????????????????????????????????????????????????????????????????????? `make uninstall-hpux' ????????????

- -
make install-hpux
-
- -

HP-UX?????????`libqdbm.so' ?????????????????? `libqdbm.sl' ??????????????????????????????????????????????????????????????????????????? `SHLIB_PATH' ??????????????????????????????

- -

RISC OS?????????

- -

RISC OS???????????????????????????????????????????????????????????????

- -

??????????????????????????????????????????????????????????????????????????? `cc' ??????????????????????????????????????????`gcc' ????????????????????? `CC=gcc' ???????????????????????????????????????

- -
make -f RISCmakefile
-
- -

??????????????????????????????`libqdbm' ??????????????????????????????????????? `dpmgr' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`depot.h' ?????????????????????????????????????????????????????????????????????????????????

- -

????????????

- -

`./configure' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
    -
  • --enable-debug : ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
  • -
  • --enable-devel : ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
  • -
  • --enable-stable : ????????????????????????????????????????????????????????????????????????????????????????????????????????????
  • -
  • --enable-pthread : POSIX?????????????????????????????????????????????????????????????????????????????????????????????
  • -
  • --disable-lock : ????????????????????????????????????????????????????????????????????????????????????
  • -
  • --disable-mmap : ?????????????????????????????????????????????????????????????????????????????????
  • -
  • --enable-zlib : ZLIB?????????B+????????????????????????????????????????????????????????????????????????
  • -
  • --enable-lzo : LZO?????????B+????????????????????????????????????????????????????????????????????????
  • -
  • --enable-bzip : BZIP2?????????B+????????????????????????????????????????????????????????????????????????
  • -
  • --enable-iconv : ICONV????????????????????????????????????????????????????????????????????????
  • -
- -

?????????QDBM???????????????????????????????????? `libqdbm.*' ????????????????????????????????????????????????????????????????????????????????????????????????????????????POSIX??????????????????????????????????????? `libpthread.*' ???????????????ZLIB??????????????????????????? `libz.*' ???????????????LZO??????????????????????????? `liblzo2.*' ???????????????BZIP2??????????????????????????? `libbz2.*' ???????????????ICONV??????????????????????????? `libiconv.*' ?????????????????????????????????

- -

LZO?????????????????????GNU GPL????????????`liblzo2.*' ?????????????????????????????????????????????GNU GPL???????????????????????????????????????????????????

- -
- -

Depot: ??????API

- -

??????

- -

Depot???QDBM?????????API????????????QDBM???????????????????????????????????????????????????????????????Depot??????????????????????????????????????????API???Depot???????????????????????????????????????????????????QDBM???API?????????Depot?????????????????????????????????

- -

Depot????????????????????????`depot.h' ??? `stdlib.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
-
#include <depot.h>
-
#include <stdlib.h>
-
- -

Depot??????????????????????????????????????????`DEPOT' ?????????????????????????????????????????????????????????????????????`stdio.h' ???????????????????????????????????????????????? `FILE' ?????????????????????????????????????????????????????????????????????????????? `dpopen' ?????????????????? `dpclose' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dpclose' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

API

- -

???????????? `dpversion' ????????????????????????????????????????????????

- -
-
extern const char *dpversion;
-
????????????????????????????????????????????????????????????
-
- -

???????????? `dpecode' ???????????????????????????????????????????????????????????????????????????????????????????????? `depot.h' ????????????????????????

- -
-
extern int dpecode;
-
??????????????????????????? `DP_ENOERR' ???????????????????????????????????????`DP_EFATAL'???`DP_EMODE'???`DP_EBROKEN'???`DP_EKEEP'???`DP_ENOITEM'???`DP_EALLOC'???`DP_EMAP'???`DP_EOPEN'???`DP_ECLOSE'???`DP_ETRUNC'???`DP_ESYNC'???`DP_ESTAT'???`DP_ESEEK'???`DP_EREAD'???`DP_EWRITE'???`DP_ELOCK'???`DP_EUNLINK'???`DP_EMKDIR'???`DP_ERMDIR' ????????? `DP_EMISC' ????????????
-
- -

????????????????????????????????????????????????????????????????????????????????? `dperrmsg' ???????????????

- -
-
const char *dperrmsg(int ecode);
-
`ecode' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `dpopen' ???????????????

- -
-
DEPOT *dpopen(const char *name, int omode, int bnum);
-
`name' ????????????????????????????????????????????????????????????`omode' ?????????????????????????????????`DP_OREADER' ??????????????????`DP_OWRITER' ???????????????????????????`DP_OWRITER' ????????????`DP_OCREAT' ????????? `DP_OTRUNC' ??????????????????????????????????????????????????????`DP_OCREAT' ????????????????????????????????????????????????????????????????????????`DP_OTRUNC' ?????????????????????????????????????????????????????????????????????`DP_OREADER' ??? `DP_OWRITER' ???????????? `DP_ONOLCK' ????????? `DP_OLCKNB' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`DP_OCREAT' ??? `DP_OSPARSE' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`bnum' ????????????????????????????????????????????????? ??????????????0 ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`DP_ONOLCK' ??????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `dpclose' ???????????????

- -
-
int dpclose(DEPOT *depot);
-
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `dpput' ???????????????

- -
-
int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
-
`depot' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`dmode' ???????????????????????????????????????????????????????????????????????????`DP_DOVER' ????????????????????????????????????????????????`DP_DKEEP' ?????????????????????????????????????????????????????????`DP_DCAT' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `dpout' ???????????????

- -
-
int dpout(DEPOT *depot, const char *kbuf, int ksiz);
-
`depot' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `dpget' ???????????????

- -
-
char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp);
-
`depot' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `mall oc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `dpgetwb' ???????????????

- -
-
int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf);
-
`depot' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`vbuf' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ??????????????????????????????????????????????????? -1 ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `dpvsiz' ???????????????

- -
-
int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz);
-
`depot' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????????????????`dpget' ?????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `dpiterinit' ???????????????

- -
-
int dpiterinit(DEPOT *depot);
-
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????????????????????????????? `dpiternext' ???????????????

- -
-
char *dpiternext(DEPOT *depot, int *sp);
-
`depot' ???????????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????
-
- -

???????????????????????????????????????????????????????????????????????? `dpsetalign' ???????????????

- -
-
int dpsetalign(DEPOT *depot, int align);
-
`depot' ???????????????????????????????????????????????????????????????????????????`align' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`vsiz' ???????????????????????????????????????????????????????????? `(vsiz / pow(2, abs(align) - 1))' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `dpsetfbpsiz' ???????????????

- -
-
int dpsetfbpsiz(DEPOT *depot, int size);
-
`depot' ???????????????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????16?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????? `dpsync' ???????????????

- -
-
int dpsync(DEPOT *depot);
-
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `dpoptimize' ???????????????

- -
-
int dpoptimize(DEPOT *depot, int bnum);
-
`depot' ???????????????????????????????????????????????????????????????????????????`bnum' ???????????????????????????????????????????????????????????????0 ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `dpname' ???????????????

- -
-
char *dpname(DEPOT *depot);
-
`depot' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `dpfsiz' ???????????????

- -
-
int dpfsiz(DEPOT *depot);
-
`depot' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

??????????????????????????????????????????????????????????????????????????? `dpbnum' ???????????????

- -
-
int dpbnum(DEPOT *depot);
-
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `dpbusenum' ???????????????

- -
-
int dpbusenum(DEPOT *depot);
-
`depot' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ?????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `dprnum' ???????????????

- -
-
int dprnum(DEPOT *depot);
-
`depot' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

????????????????????????????????????????????????????????????????????????????????? `dpwritable' ???????????????

- -
-
int dpwritable(DEPOT *depot);
-
`depot' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `dpfatalerror' ???????????????

- -
-
int dpfatalerror(DEPOT *depot);
-
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????inode?????????????????????????????? `dpinode' ???????????????

- -
-
int dpinode(DEPOT *depot);
-
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????inode??????????????????
-
- -

??????????????????????????????????????????????????????????????? `dpmtime' ???????????????

- -
-
time_t dpmtime(DEPOT *depot);
-
`depot' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `dpfdesc' ???????????????

- -
-
int dpfdesc(DEPOT *depot);
-
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `dpremove' ???????????????

- -
-
int dpremove(const char *name);
-
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `dprepair' ???????????????

- -
-
int dprepair(const char *name);
-
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????? `dpexportdb' ???????????????

- -
-
int dpexportdb(DEPOT *depot, const char *name);
-
`depot' ???????????????????????????????????????????????????`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????????????????? `dpimportdb' ???????????????

- -
-
int dpimportdb(DEPOT *depot, const char *name);
-
`depot' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `dpsnaffle' ???????????????

- -
-
char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
-
`name' ????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????1?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????? `dpinnerhash' ????????????

- -
-
int dpinnerhash(const char *kbuf, int ksiz);
-
`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????????????????????????????31??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????? `dpouterhash' ????????????

- -
-
int dpouterhash(const char *kbuf, int ksiz);
-
`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????????????????????????????31??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `dpprimenum' ???????????????

- -
-
int dpprimenum(int num);
-
`num' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define NAME     "mikio"
-#define NUMBER   "000-1234-5678"
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  DEPOT *depot;
-  char *val;
-
-  /* ??????????????????????????? */
-  if(!(depot = dpopen(DBNAME, DP_OWRITER | DP_OCREAT, -1))){
-    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* ??????????????????????????? */
-  if(!dpput(depot, NAME, -1, NUMBER, -1, DP_DOVER)){
-    fprintf(stderr, "dpput: %s\n", dperrmsg(dpecode));
-  }
-
-  /* ??????????????????????????? */
-  if(!(val = dpget(depot, NAME, -1, 0, -1, NULL))){
-    fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
-  } else {
-    printf("Name: %s\n", NAME);
-    printf("Number: %s\n", val);
-    free(val);
-  }
-
-  /* ?????????????????????????????? */
-  if(!dpclose(depot)){
-    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  DEPOT *depot;
-  char *key, *val;
-
-  /* ??????????????????????????? */
-  if(!(depot = dpopen(DBNAME, DP_OREADER, -1))){
-    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* ????????????????????????????????? */
-  if(!dpiterinit(depot)){
-    fprintf(stderr, "dpiterinit: %s\n", dperrmsg(dpecode));
-  }
-
-  /* ?????????????????????????????? */
-  while((key = dpiternext(depot, NULL)) != NULL){
-    if(!(val = dpget(depot, key, -1, 0, -1, NULL))){
-      fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
-      free(key);
-      break;
-    }
-    printf("%s: %s\n", key, val);
-    free(val);
-    free(key);
-  }
-
-  /* ?????????????????????????????? */
-  if(!dpclose(depot)){
-    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

??????

- -

Depot???????????????????????????????????????????????????????????????????????? `libqdbm.a' ????????? `libqdbm.so' ????????????????????????????????????????????????????????????`sample.c' ?????? `sample' ?????????????????????????????????????????????????????????

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

POSIX??????????????????????????????QDBM??????????????????????????????????????? `dpecode' ???????????????????????????????????????????????????????????????Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

- -
- -

Depot???????????????

- -

Depot???????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `dpmgr' ???Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`key' ???????????????????????????`val' ???????????????????????????????????????

- -
-
dpmgr create [-s] [-bnum num] name
-
????????????????????????????????????????????????
-
dpmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-na] name key val
-
?????????????????????????????????????????????????????????
-
dpmgr out [-kx|-ki] name key
-
???????????????????????????????????????????????????
-
dpmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-n] name key
-
???????????????????????????????????????????????????????????????????????????
-
dpmgr list [-nl] [-k|-v] [-ox] name
-
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
dpmgr optimize [-bnum num] [-na] name
-
???????????????????????????????????????
-
dpmgr inform [-nl] name
-
??????????????????????????????????????????????????????
-
dpmgr remove name
-
????????????????????????????????????????????????
-
dpmgr repair name
-
?????????????????????????????????????????????????????????
-
dpmgr exportdb name file
-
??????????????????????????????????????????????????????????????????????????????????????????
-
dpmgr importdb [-bnum num] name file
-
????????????????????????????????????????????????????????????????????????????????????
-
dpmgr snaffle [-kx|-ki] [-ox] [-n] name key
-
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
dpmgr version
-
QDBM????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -s : ???????????????????????????????????????
  • -
  • -bnum num : ????????????????????????????????? `num' ??????????????????
  • -
  • -kx : 2????????????16?????????????????????????????????????????? `key' ????????????
  • -
  • -ki : 10???????????????????????????????????? `key' ????????????
  • -
  • -vx : 2????????????16?????????????????????????????????????????? `val' ????????????
  • -
  • -vi : 10???????????????????????????????????? `val' ????????????
  • -
  • -vf : ????????? `val' ?????????????????????????????????????????????????????????
  • -
  • -keep : ????????????????????????????????????????????????????????????????????????????????????
  • -
  • -cat : ???????????????????????????????????????????????????????????????????????????
  • -
  • -na : ??????????????????????????????????????????
  • -
  • -nl : ??????????????????????????????????????????????????????????????????
  • -
  • -start : ????????????????????????????????????????????????????????????????????????
  • -
  • -max : ??????????????????????????????????????????????????????????????????
  • -
  • -ox : 2????????????16??????????????????????????????????????????????????????????????????
  • -
  • -n : ??????????????????????????????????????????????????????????????????????????????
  • -
  • -k : ??????????????????????????????
  • -
  • -v : ???????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `dptest' ???Depot??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dpmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`rnum' ?????????????????????`bnum' ????????????????????????????????????`pnum' ??????????????????????????????`align' ?????????????????????????????????????????????`fbpsiz' ???????????????????????????????????????????????????????????????

- -
-
dptest write [-s] name rnum bnum
-
`00000001'???`00000002' ????????????????????????8??????????????????????????????8??????????????????????????????????????????????????????????????????
-
dptest read [-wb] name
-
???????????????????????????????????????????????????????????????????????????
-
dptest rcat [-c] name rnum bnum pnum align fbpsiz
-
????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
dptest combo name
-
???????????????????????????????????????????????????
-
dptest wicked [-c] name rnum
-
????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -s : ???????????????????????????????????????
  • -
  • -wb : ?????? `dpget' ????????????????????? `dpgetwb' ???????????????
  • -
  • -c : Cabin???????????????????????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `dptsv' ???????????????????????????????????????????????????????????????TSV???????????????Depot?????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????DBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ??????????????????????????????????????????`export' ????????????????????????TSV????????????????????????????????????????????????????????????????????????????????????????????????????????????`-bnum' ???????????????????????? `num' ???????????????????????????????????????????????????`import' ????????????????????????TSV???????????????????????????????????????????????????

- -
-
dptsv import [-bnum num] [-bin] name
-
TSV??????????????????????????????????????????????????????????????????
-
dptsv export [-bin] name
-
?????????????????????????????????????????????TSV????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -bnum num : ????????????????????????????????? `num' ??????????????????
  • -
  • -bin : Base64?????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -

Depot???????????????????????????????????????????????????????????????????????????????????????????????????????????? `/etc/password' ????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
cat /etc/passwd | tr ':' '\t' | dptsv import casket
-
- -

????????????`mikio' ??????????????????????????????????????????????????????????????????????????????

- -
dpmgr get casket mikio
-
- -

?????????????????????????????????????????????Depot???API???????????????????????????????????????????????????

- -
- -

Curia: ??????API

- -

??????

- -

Curia???QDBM?????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Depot???????????????????????????????????????????????????????????????????????????Curia??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`depot' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4??????10?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `depot' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`casket' ???????????????????????????????????????????????????????????????3??????????????????`casket/depot'???`casket/0001/depot'???`casket/0002/depot'???`casket/0003/depot' ???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Curia???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `lob' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????

- -

Curia????????????????????????`depot.h' ??? `curia.h' ??? `stdlib.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
-
#include <depot.h>
-
#include <curia.h>
-
#include <stdlib.h>
-
- -

Curia??????????????????????????????????????????`CURIA' ?????????????????????????????????????????????????????????????????????`stdio.h' ???????????????????????????????????????????????? `FILE' ?????????????????????????????????????????????????????????????????????????????? `cropen' ?????????????????? `crclose' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `crclose' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Curia??????Depot???????????????????????? `dpecode' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dperrmsg' ???????????????

- -

API

- -

??????????????????????????????????????????????????????????????? `cropen' ???????????????

- -
-
CURIA *cropen(const char *name, int omode, int bnum, int dnum);
-
`name' ??????????????????????????????????????????????????????????????????`omode' ?????????????????????????????????`CR_OREADER' ??????????????????`CR_OWRITER' ???????????????????????????`CR_OWRITER' ????????????`CR_OCREAT' ????????? `CR_OTRUNC' ??????????????????????????????????????????????????????`CR_OCREAT' ????????????????????????????????????????????????????????????????????????`CR_OTRUNC' ?????????????????????????????????????????????????????????????????????`CR_OREADER' ??? `CR_OWRITER' ???????????? `CR_ONOLCK' ????????? `CR_OLCKNB' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`CR_OCREAT' ??? `CR_OSPARSE' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`bnum' ??????????????????????????????????????????? ????????????????????0 ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4?????????????????????????????????`dnum' ??????????????????????????????????????????????????????0 ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 512 ??????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????????????????????????????????`CR_ONOLCK' ??????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `crclose' ???????????????

- -
-
int crclose(CURIA *curia);
-
`curia' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `crput' ???????????????

- -
-
int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
-
`curia' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`dmode' ???????????????????????????????????????????????????????????????????????????`CR_DOVER' ????????????????????????????????????????????????`CR_DKEEP' ?????????????????????????????????????????????????????????`DP_DCAT' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `crout' ???????????????

- -
-
int crout(CURIA *curia, const char *kbuf, int ksiz);
-
`curia' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `crget' ???????????????

- -
-
char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
-
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `mall oc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `crgetwb' ???????????????

- -
-
int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf);
-
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`vbuf' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ??????????????????????????????????????????????????? -1 ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `crvsiz' ???????????????

- -
-
int crvsiz(CURIA *curia, const char *kbuf, int ksiz);
-
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????????????????`crget' ?????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `criterinit' ???????????????

- -
-
int criterinit(CURIA *curia);
-
`curia' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????????????????????????????? `criternext' ???????????????

- -
-
char *criternext(CURIA *curia, int *sp);
-
`curia' ???????????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????
-
- -

???????????????????????????????????????????????????????????????????????? `crsetalign' ???????????????

- -
-
int crsetalign(CURIA *curia, int align);
-
`curia' ???????????????????????????????????????????????????????????????????????????`align' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`vsiz' ???????????????????????????????????????????????????????????? `(vsiz / pow(2, abs(align) - 1))' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `crsetfbpsiz' ???????????????

- -
-
int crsetfbpsiz(CURIA *curia, int size);
-
`curia' ???????????????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????16?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????? `crsync' ???????????????

- -
-
int crsync(CURIA *curia);
-
`curia' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `croptimize' ???????????????

- -
-
int croptimize(CURIA *curia, int bnum);
-
`curia' ???????????????????????????????????????????????????????????????????????????`bnum' ???????????????????????????????????????????????????????????????0 ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `crname' ???????????????

- -
-
char *crname(CURIA *curia);
-
`curia' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????? `crfsiz' ???????????????

- -
-
int crfsiz(CURIA *curia);
-
`curia' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????????????????2GB?????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????????????????????????????????????????? `crfsizd' ???????????????

- -
-
double crfsizd(CURIA *curia);
-
`curia' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `crbnum' ???????????????

- -
-
int crbnum(CURIA *curia);
-
`curia' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

??????????????????????????????????????????????????????????????????????????????????????????????????? `crbusenum' ???????????????

- -
-
int crbusenum(CURIA *curia);
-
`curia' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ?????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `crrnum' ???????????????

- -
-
int crrnum(CURIA *curia);
-
`curia' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

????????????????????????????????????????????????????????????????????????????????? `crwritable' ???????????????

- -
-
int crwritable(CURIA *curia);
-
`curia' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `crfatalerror' ???????????????

- -
-
int crfatalerror(CURIA *curia);
-
`curia' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????inode?????????????????????????????? `crinode' ???????????????

- -
-
int crinode(CURIA *curia);
-
`curia' ??????????????????????????????????????????????????????????????????????????????????????????????????????inode??????????????????
-
- -

??????????????????????????????????????????????????????????????? `crmtime' ???????????????

- -
-
time_t crmtime(CURIA *curia);
-
`curia' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `crremove' ???????????????

- -
-
int crremove(const char *name);
-
`name' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????? `crrepair' ???????????????

- -
-
int crrepair(const char *name);
-
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????? `crexportdb' ???????????????

- -
-
int crexportdb(CURIA *curia, const char *name);
-
`curia' ???????????????????????????????????????????????????`name' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????????????????? `crimportdb' ???????????????

- -
-
int crimportdb(CURIA *curia, const char *name);
-
`curia' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `crsnaffle' ???????????????

- -
-
char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
-
`name' ??????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????????????????????????????? `crputlob' ???????????????

- -
-
int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
-
`curia' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`dmode' ???????????????????????????????????????????????????????????????????????????`CR_DOVER' ????????????????????????????????????????????????`CR_DKEEP' ?????????????????????????????????????????????????????????`DP_DCAT' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????????????????? `croutlob' ???????????????

- -
-
int croutlob(CURIA *curia, const char *kbuf, int ksiz);
-
`curia' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????? `crgetlob' ???????????????

- -
-
char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
-
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `mall oc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `crgetlobfd' ???????????????

- -
-
int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz);
-
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ??????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????? `open' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????O_RDWR????????????????????????????????????????????????????????????O_RDONLY???????????????????????????????????????????????????????????? `close' ??????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `crvsizlob' ???????????????

- -
-
int crvsizlob(CURIA *curia, const char *kbuf, int ksiz);
-
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????????????????`crgetlob' ?????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????????????????????????????? `crrnumlob' ???????????????

- -
-
int crrnumlob(CURIA *curia);
-
`curia' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

?????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <curia.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define NAME     "mikio"
-#define NUMBER   "000-1234-5678"
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  CURIA *curia;
-  char *val;
-
-  /* ??????????????????????????? */
-  if(!(curia = cropen(DBNAME, CR_OWRITER | CR_OCREAT, -1, -1))){
-    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* ??????????????????????????? */
-  if(!crput(curia, NAME, -1, NUMBER, -1, CR_DOVER)){
-    fprintf(stderr, "crput: %s\n", dperrmsg(dpecode));
-  }
-
-  /* ??????????????????????????? */
-  if(!(val = crget(curia, NAME, -1, 0, -1, NULL))){
-    fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
-  } else {
-    printf("Name: %s\n", NAME);
-    printf("Number: %s\n", val);
-    free(val);
-  }
-
-  /* ?????????????????????????????? */
-  if(!crclose(curia)){
-    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <curia.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  CURIA *curia;
-  char *key, *val;
-
-  /* ??????????????????????????? */
-  if(!(curia = cropen(DBNAME, CR_OREADER, -1, -1))){
-    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* ????????????????????????????????? */
-  if(!criterinit(curia)){
-    fprintf(stderr, "criterinit: %s\n", dperrmsg(dpecode));
-  }
-
-  /* ?????????????????????????????? */
-  while((key = criternext(curia, NULL)) != NULL){
-    if(!(val = crget(curia, key, -1, 0, -1, NULL))){
-      fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
-      free(key);
-      break;
-    }
-    printf("%s: %s\n", key, val);
-    free(val);
-    free(key);
-  }
-
-  /* ?????????????????????????????? */
-  if(!crclose(curia)){
-    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

??????

- -

Curia????????????????????????????????????????????????????????????Depot????????????????????????????????????

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

POSIX??????????????????????????????QDBM??????????????????????????????????????? `dpecode' ???????????????????????????????????????????????????????????????Curia?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

- -
- -

Curia???????????????

- -

Curia???????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `crmgr' ???Curia?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`key' ???????????????????????????`val' ???????????????????????????????????????

- -
-
crmgr create [-s] [-bnum num] [-dnum num] name
-
??????????????????????????????????????????????????????
-
crmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] name key val
-
?????????????????????????????????????????????????????????
-
crmgr out [-kx|-ki] [-lob] name key
-
???????????????????????????????????????????????????
-
crmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-lob] [-n] name key
-
???????????????????????????????????????????????????????????????????????????
-
crmgr list [-nl] [-k|-v] [-ox] name
-
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
crmgr optimize [-bnum num] [-na] name
-
???????????????????????????????????????
-
crmgr inform [-nl] name
-
??????????????????????????????????????????????????????
-
crmgr remove name
-
??????????????????????????????????????????????????????
-
crmgr repair name
-
???????????????????????????????????????????????????????????????
-
crmgr exportdb name dir
-
??????????????????????????????????????????????????????????????????????????????????????????
-
crmgr importdb [-bnum num] [-dnum num] name dir
-
????????????????????????????????????????????????????????????????????????????????????
-
crmgr snaffle [-kx|-ki] [-ox] [-n] name key
-
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
crmgr version
-
QDBM????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -s : ???????????????????????????????????????
  • -
  • -bnum num : ????????????????????????????????? `num' ??????????????????
  • -
  • -dnum num : ????????????????????????????????????????????? `num' ??????????????????
  • -
  • -kx : 2????????????16?????????????????????????????????????????? `key' ????????????
  • -
  • -ki : 10???????????????????????????????????? `key' ????????????
  • -
  • -vx : 2????????????16?????????????????????????????????????????? `val' ????????????
  • -
  • -vi : 10???????????????????????????????????? `val' ????????????
  • -
  • -vf : ????????? `val' ?????????????????????????????????????????????????????????
  • -
  • -keep : ????????????????????????????????????????????????????????????????????????????????????
  • -
  • -cat : ???????????????????????????????????????????????????????????????????????????
  • -
  • -na : ??????????????????????????????????????????
  • -
  • -nl : ??????????????????????????????????????????????????????????????????
  • -
  • -start : ????????????????????????????????????????????????????????????????????????
  • -
  • -max : ??????????????????????????????????????????????????????????????????
  • -
  • -ox : 2????????????16??????????????????????????????????????????????????????????????????
  • -
  • -lob : ???????????????????????????????????????
  • -
  • -n : ??????????????????????????????????????????????????????????????????????????????
  • -
  • -k : ??????????????????????????????
  • -
  • -v : ???????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `crtest' ???Curia?????????????????????????????????????????????????????????????????????`crtest' ?????????????????????????????????????????????????????????????????? `crmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`rnum' ?????????????????????`bnum' ????????????????????????????????????`dnum' ????????????????????????????????????????????????`pnum' ??????????????????????????????`align' ?????????????????????????????????????????????`fbpsiz' ???????????????????????????????????????????????????????????????

- -
-
crtest write [-s] [-lob] name rnum bnum dnum
-
`00000001'???`00000002' ????????????????????????8??????????????????????????????8??????????????????????????????????????????????????????????????????
-
crtest read [-wb] [-lob] name
-
???????????????????????????????????????????????????????????????????????????
-
crtest rcat [-c] name rnum bnum dnum pnum align fbpsiz
-
????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
crtest combo name
-
???????????????????????????????????????????????????
-
crtest wicked [-c] name rnum
-
????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -s : ???????????????????????????????????????
  • -
  • -lob : ???????????????????????????????????????
  • -
  • -wb : ?????? `crget' ????????????????????? `crgetwb' ???????????????
  • -
  • -c : Cabin???????????????????????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `crtsv' ???????????????????????????????????????????????????????????????TSV???????????????Curia?????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????DBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ??????????????????????????????????????????`export' ????????????????????????TSV????????????????????????????????????????????????????????????????????????????????????????????????????????????`-bnum' ???????????????????????? `num' ???????????????????????????????????????????????????`-dnum' ???????????????????????? `num' ???????????????????????????????????????????????????`import' ????????????????????????TSV???????????????????????????????????????????????????

- -
-
crtsv import [-bnum num] [-dnum num] [-bin] name
-
TSV??????????????????????????????????????????????????????????????????
-
crtsv export [-bin] name
-
?????????????????????????????????????????????TSV????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -bnum num : ????????????????????????????????? `num' ??????????????????
  • -
  • -dnum num : ????????????????????????????????????????????? `num' ??????????????????
  • -
  • -bin : Base64?????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -

Curia???????????????????????????????????????????????????????????????????????????????????????????????????????????? `/etc/password' ????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
cat /etc/passwd | tr ':' '\t' | crtsv import casket
-
- -

????????????`mikio' ??????????????????????????????????????????????????????????????????????????????

- -
crmgr get casket mikio
-
- -

?????????????????????????????????????????????Curia???API???????????????????????????????????????????????????

- -
- -

Relic: NDBM??????API

- -

??????

- -

Relic??????NDBM???????????????API???????????????????????????Depot???????????????NDBM???API??????????????????????????????Relic????????????NDBM??????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????? `ndbm.h' ?????? `relic.h' ????????????????????????????????????????????????????????? `-lndbm' ?????? `-lqdbm' ??????????????????????????????

- -

??????????????????NDBM???????????????????????????????????????????????????????????????????????????????????????????????? `.dir' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `.pag' ?????????????????????????????????????????????????????????????????????????????????????????????Relic????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Relic????????????????????????NDBM?????????????????????????????????????????????????????????????????????????????????????????????NDBM????????????????????????????????????????????????Relic?????????????????????????????????

- -

Relic????????????????????????`relic.h' ??? `stdlib.h' ??? `sys/types.h' ??? `sys/stat.h' ??? `fcntl.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
-
#include <relic.h>
-
#include <stdlib.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
- -

Relic??????????????????????????????????????????`DBM' ????????????????????????????????????????????????????????????????????????????????? `dbm_open' ?????????????????? `dbm_close' ??????????????????????????????????????????????????????????????????????????????????????????

- -

API

- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `datum' ??????????????????????????????

- -
-
typedef struct { void *dptr; size_t dsize; } datum;
-
`dptr' ????????????????????????????????????????????????`dsize' ??????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `dbm_open' ???????????????

- -
-
DBM *dbm_open(char *name, int flags, int mode);
-
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`flags' ??? `open' ??????????????????????????????????????????`O_WRONLY' ??? `O_RDWR' ?????????????????????????????????????????? `O_CREAT' ??? `O_TRUNC' ???????????????????????????`mode' ??? `open' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `dbm_close' ???????????????

- -
-
void dbm_close(DBM *db);
-
`db' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `dbm_store' ???????????????

- -
-
int dbm_store(DBM *db, datum key, datum content, int flags);
-
`db' ???????????????????????????????????????????????????`key' ???????????????????????????????????????`content' ????????????????????????????????????`frags' ??? `DBM_INSERT' ??????????????????????????????????????????????????????`DBM_REPLACE' ??????????????????????????????????????????????????? 0 ???????????????????????????????????? 1 ??????????????????????????????????????? -1 ????????????
-
- -

?????????????????????????????????????????? `dbm_delete' ???????????????

- -
-
int dbm_delete(DBM *db, datum key);
-
`db' ???????????????????????????????????????????????????`key' ??????????????????????????????????????????????????????????????? 0 ??????????????????????????? -1 ????????????
-
- -

?????????????????????????????????????????? `dbm_fetch' ???????????????

- -
-
datum dbm_fetch(DBM *db, datum key);
-
`db' ???????????????????????????????????????????????????`key' ????????????????????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????????????? `dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????`dptr' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `dbm_firstkey' ???????????????

- -
-
datum dbm_firstkey(DBM *db);
-
`db' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????`dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????`dptr' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dbm_nextkey' ??????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????? `dbm_nextkey' ???????????????

- -
-
datum dbm_nextkey(DBM *db);
-
`db' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????`dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????`dptr' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dbm_firstkey' ??????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `dbm_error' ???????????????

- -
-
int dbm_error(DBM *db);
-
`db' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????? `dbm_clearerr' ?????????????????????

- -
-
int dbm_clearerr(DBM *db);
-
`db' ??????????????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????? `dbm_rdonly' ???????????????

- -
-
int dbm_rdonly(DBM *db);
-
`db' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `dbm_dirfno' ???????????????

- -
-
int dbm_dirfno(DBM *db);
-
`db' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????????????????? `dbm_pagfno' ???????????????

- -
-
int dbm_pagfno(DBM *db);
-
`db' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <relic.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <string.h>
-
-#define NAME     "mikio"
-#define NUMBER   "000-1234-5678"
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  DBM *db;
-  datum key, val;
-  int i;
-
-  /* ??????????????????????????? */
-  if(!(db = dbm_open(DBNAME, O_RDWR | O_CREAT, 00644))){
-    perror("dbm_open");
-    return 1;
-  }
-
-  /* ??????????????????????????? */
-  key.dptr = NAME;
-  key.dsize = strlen(NAME);
-  val.dptr = NUMBER;
-  val.dsize = strlen(NUMBER);
-
-  /* ??????????????????????????? */
-  if(dbm_store(db, key, val, DBM_REPLACE) != 0){
-    perror("dbm_store");
-  }
-
-  /* ??????????????????????????? */
-  val = dbm_fetch(db, key);
-  if(val.dptr){
-    printf("Name: %s\n", NAME);
-    printf("Number: ");
-    for(i = 0; i < val.dsize; i++){
-      putchar(((char *)val.dptr)[i]);
-    }
-    putchar('\n');
-  } else {
-    perror("dbm_fetch");
-  }
-
-  /* ?????????????????????????????? */
-  dbm_close(db);
-
-  return 0;
-}
-
- -

??????

- -

Relic????????????????????????????????????????????????????????????Depot???????????????????????????????????????????????????????????????????????? `-lndbm' ???????????? `-lqdbm' ????????????

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

?????????????????????????????????????????????????????????????????????????????????Relic????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

- -
- -

Relic???????????????

- -

Relic???????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `rlmgr' ???Relic?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`key' ???????????????????????????`val' ???????????????????????????????????????

- -
-
rlmgr create name
-
????????????????????????????????????????????????
-
rlmgr store [-kx] [-vx|-vf] [-insert] name key val
-
?????????????????????????????????????????????????????????
-
rlmgr delete [-kx] name key
-
???????????????????????????????????????????????????
-
rlmgr fetch [-kx] [-ox] [-n] name key
-
???????????????????????????????????????????????????????????????????????????
-
rlmgr list [-ox] name
-
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -kx : 2????????????16?????????????????????????????????????????? `key' ????????????
  • -
  • -vx : 2????????????16?????????????????????????????????????????? `val' ????????????
  • -
  • -vf : ????????? `val' ?????????????????????????????????????????????????????????
  • -
  • -insert : ????????????????????????????????????????????????????????????????????????????????????
  • -
  • -ox : 2????????????16??????????????????????????????????????????????????????????????????
  • -
  • -n : ??????????????????????????????????????????????????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -

???????????? `rltest' ???Relic??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `rlmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`rnum' ????????????????????????????????????

- -
-
rltest write name rnum
-
`00000001'???`00000002' ????????????????????????8??????????????????????????????8??????????????????????????????????????????????????????????????????
-
rltest read name rnum
-
?????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -
- -

Hovel: GDBM??????API

- -

??????

- -

Hovel??????GDBM???????????????API???????????????????????????Depot?????????Curia???????????????GDBM???API??????????????????????????????Hovel????????????GDBM??????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????? `gdbm.h' ?????? `hovel.h' ????????????????????????????????????????????????????????? `-lgdbm' ?????? `-lqdbm' ?????????????????????????????????????????????????????????GDBM????????????????????????????????????????????????Hovel?????????????????????????????????

- -

Hovel????????????????????????`hovel.h' ??? `stdlib.h' ??? `sys/types.h' ??? `sys/stat.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
-
#include <hovel.h>
-
#include <stdlib.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
- -

Hovel??????????????????????????????????????????`GDBM_FILE' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `gdbm_open' ?????????????????? `gdbm_close' ??????????????????????????????????????????????????????????????????????????????????????????Hovel????????????Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `gdbm_open2' ??????????????????????????????Curia?????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

API

- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `datum' ??????????????????????????????

- -
-
typedef struct { char *dptr; size_t dsize; } datum;
-
`dptr' ????????????????????????????????????????????????`dsize' ??????????????????????????????????????????
-
- -

???????????? `gdbm_version' ????????????????????????????????????????????????

- -
-
extern char *gdbm_version;
-
????????????????????????????????????????????????????????????
-
- -

???????????? `gdbm_errno' ???????????????????????????????????????????????????????????????????????????????????????????????? `hovel.h' ????????????????????????

- -
-
extern gdbm_error gdbm_errno;
-
??????????????????????????? `GDBM_NO_ERROR' ???????????????????????????????????????`GDBM_MALLOC_ERROR'???`GDBM_BLOCK_SIZE_ERROR'???`GDBM_FILE_OPEN_ERROR'???`GDBM_FILE_WRITE_ERROR'???`GDBM_FILE_SEEK_ERROR'???`GDBM_FILE_READ_ERROR'???`GDBM_BAD_MAGIC_NUMBER'???`GDBM_EMPTY_DATABASE'???`GDBM_CANT_BE_READER'???`GDBM_CANT_BE_WRITER'???`GDBM_READER_CANT_DELETE'???`GDBM_READER_CANT_STORE'???`GDBM_READER_CANT_REORGANIZE'???`GDBM_UNKNOWN_UPDATE'???`GDBM_ITEM_NOT_FOUND'???`GDBM_REORGANIZE_FAILED'???`GDBM_CANNOT_REPLACE'???`GDBM_ILLEGAL_DATA'???`GDBM_OPT_ALREADY_SET' ????????? `GDBM_OPT_ILLEGAL' ????????????
-
- -

????????????????????????????????????????????????????????????????????????????????? `gdbm_strerror' ???????????????

- -
-
char *gdbm_strerror(gdbm_error gdbmerrno);
-
`gdbmerrno' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

GDBM????????????????????????????????????????????????????????????????????? `gdbm_open' ???????????????

- -
-
GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, void (*fatal_func)(void));
-
`name' ????????????????????????????????????????????????`block_size' ?????????????????????`read_write' ?????????????????????????????????`GDBM_READER' ??????????????????`GDBM_WRITER' ??? `GDBM_WRCREAT' ??? `GDBM_NEWDB' ???????????????????????????`GDBM_WRCREAT' ??????????????????????????????????????????????????????????????????`GDBM_NEWDB' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????`GDBM_SYNC' ??? `GDBM_NOLOCK' ??? `GDBM_LOCKNB' ??? `GDBM_FAST' ??? `GDBM_SPARSE' ??????????????????????????????????????????????????????`GDBM_SYNC' ?????????????????????????????????????????????????????????????????????`GDBM_NOLOCK' ?????????????????????????????????????????????????????????????????????`GDBM_LOCKNB' ?????????????????????????????????????????????`GDBM_FAST' ?????????????????????`GDBM_SPARSE' ???QDBM??????????????????????????????????????????????????????????????????????????????`mode' ??? `open' ??????????????????????????? ???????????????????????????????????????????????????`fatal_func' ?????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????
-
- -

QDBM????????????????????????????????????????????????????????????????????? `gdbm_open2' ???????????????

- -
-
GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align);
-
`name' ????????????????????????????????????????????????`read_write' ?????????????????????????????????`GDBM_READER' ??????????????????`GDBM_WRITER' ??? `GDBM_WRCREAT' ??? `GDBM_NEWDB' ???????????????????????????`GDBM_WRCREAT' ??????????????????????????????????????????????????????????????????`GDBM_NEWDB' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????`GDBM_SYNC' ??? `GDBM_NOLOCK' ??? `GDBM_LOCKNB' ??? `GDBM_FAST' ??? `GDBM_SPARSE' ??????????????????????????????????????????????????????`GDBM_SYNC' ?????????????????????????????????????????????????????????????????????`GDBM_NOLOCK' ?????????????????????????????????????????????????????????????????????`GDBM_LOCKNB' ?????????????????????????????????????????????`GDBM_FAST' ?????????????????????`GDBM_SPARSE' ???QDBM??????????????????????????????????????????????????????????????????????????????`mode' ??? `open' ????????????????????? `mkdir' ??????????????????????????????? ????????????????????????????????????????????????????????????????????`bnum' ???????????????????????????????????????????????????????????????0 ????????????????????????????????????????????????`dnum' ??????????????????????????????????????????????????????0 ???????????????????????????????????????Depot????????????????????????????????????????????????????????????Curia???????????????????????????`align' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????Depot????????????Curia?????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `gdbm_close' ???????????????

- -
-
void gdbm_close(GDBM_FILE dbf);
-
`dbf' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `gdbm_store' ???????????????

- -
-
int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag);
-
`dbf' ???????????????????????????????????????????????????????????????????????????`key' ???????????????????????????????????????`content' ????????????????????????????????????`frags' ??? `GDBM_INSERT' ??????????????????????????????????????????????????????`GDBM_REPLACE' ??????????????????????????????????????????????????? 0 ??????????????????????????? 1 ?????????????????????????????? -1 ????????????
-
- -

?????????????????????????????????????????? `gdbm_delete' ???????????????

- -
-
int gdbm_delete(GDBM_FILE dbf, datum key);
-
`dbf' ???????????????????????????????????????????????????????????????????????????`key' ??????????????????????????????????????????????????????????????? 0 ?????????????????? -1 ????????????
-
- -

?????????????????????????????????????????? `gdbm_fetch' ???????????????

- -
-
datum gdbm_fetch(GDBM_FILE dbf, datum key);
-
`dbf' ???????????????????????????????????????????????????`key' ????????????????????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????`dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????????????????????????? `dptr' ?????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `gdbm_exists' ???????????????

- -
-
int gdbm_exists(GDBM_FILE dbf, datum key);
-
`dbf' ???????????????????????????????????????????????????`key' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `gdbm_firstkey' ???????????????

- -
-
datum gdbm_firstkey(GDBM_FILE dbf);
-
`dbf' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????`dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????????????????????????? `dptr' ?????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????????????????????????? gdbm_nextkey ???????????????

- -
-
datum gdbm_nextkey(GDBM_FILE dbf, datum key);
-
`dbf' ???????????????????????????????????????????????????`key' ?????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????`dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????????????????????????? `dptr' ?????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????? `gdbm_sync' ???????????????

- -
-
void gdbm_sync(GDBM_FILE dbf);
-
`dbf' ???????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `gdbm_reorganize' ???????????????

- -
-
int gdbm_reorganize(GDBM_FILE dbf);
-
`dbf' ??????????????????????????????????????????????????????????????????????????????????????????????????? 0 ??????????????????????????? -1 ????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `gdbm_fdesc' ???????????????

- -
-
int gdbm_fdesc(GDBM_FILE dbf);
-
`dbf' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

?????? `gdbm_setopt' ?????????????????????

- -
-
int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size);
-
`dbf' ???????????????????????????????????????????????????`option' ?????????????????????`value' ?????????????????????`size' ????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????
-
- -

?????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <hovel.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <string.h>
-
-#define NAME     "mikio"
-#define NUMBER   "000-1234-5678"
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  GDBM_FILE dbf;
-  datum key, val;
-  int i;
-
-  /* ??????????????????????????? */
-  if(!(dbf = gdbm_open(DBNAME, 0, GDBM_WRCREAT, 00644, NULL))){
-    fprintf(stderr, "gdbm_open: %s\n", gdbm_strerror(gdbm_errno));
-    return 1;
-  }
-
-  /* ??????????????????????????? */
-  key.dptr = NAME;
-  key.dsize = strlen(NAME);
-  val.dptr = NUMBER;
-  val.dsize = strlen(NUMBER);
-
-  /* ??????????????????????????? */
-  if(gdbm_store(dbf, key, val, GDBM_REPLACE) != 0){
-    fprintf(stderr, "gdbm_store: %s\n", gdbm_strerror(gdbm_errno));
-  }
-
-  /* ??????????????????????????? */
-  val = gdbm_fetch(dbf, key);
-  if(val.dptr){
-    printf("Name: %s\n", NAME);
-    printf("Number: ");
-    for(i = 0; i < val.dsize; i++){
-      putchar(val.dptr[i]);
-    }
-    putchar('\n');
-    free(val.dptr);
-  } else {
-    fprintf(stderr, "gdbm_fetch: %s\n", gdbm_strerror(gdbm_errno));
-  }
-
-  /* ?????????????????????????????? */
-  gdbm_close(dbf);
-
-  return 0;
-}
-
- -

??????

- -

Hovel????????????????????????????????????????????????????????????Depot???????????????????????????????????????????????????????????????????????? `-lgdbm' ???????????? `-lqdbm' ????????????

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

POSIX??????????????????????????????QDBM??????????????????????????????????????? `gdbm_errno' ???????????????????????????????????????????????????????????????Hovel?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

- -
- -

Hovel???????????????

- -

Hovel???????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `hvmgr' ???Hovel??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`key' ???????????????????????????`val' ???????????????????????????????????????

- -
-
hvmgr [-qdbm bnum dnum] [-s] create name
-
????????????????????????????????????????????????
-
hvmgr store [-qdbm] [-kx] [-vx|-vf] [-insert] name key val
-
?????????????????????????????????????????????????????????
-
hvmgr delete [-qdbm] [-kx] name key
-
???????????????????????????????????????????????????
-
hvmgr fetch [-qdbm] [-kx] [-ox] [-n] name key
-
???????????????????????????????????????????????????????????????????????????
-
hvmgr list [-qdbm] [-ox] name
-
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
hvmgr optimize [-qdbm] name
-
???????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -qdbm [bnum dnum] : `gdbm_open2' ?????????????????????????????????`bnum' ??? `dnum' ????????????????????????????????????????????????????????????????????????????????????
  • -
  • -s : ???????????????????????????????????????
  • -
  • -kx : 2????????????16?????????????????????????????????????????? `key' ????????????
  • -
  • -vx : 2????????????16?????????????????????????????????????????? `val' ????????????
  • -
  • -vf : ????????? `val' ?????????????????????????????????????????????????????????
  • -
  • -insert : ????????????????????????????????????????????????????????????????????????????????????
  • -
  • -ox : 2????????????16??????????????????????????????????????????????????????????????????
  • -
  • -n : ??????????????????????????????????????????????????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -

???????????? `hvtest' ???Hovel??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `hvmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`rnum' ????????????????????????????????????

- -
-
hvtest write [-qdbm] [-s] name rnum
-
`00000001'???`00000002' ????????????????????????8??????????????????????????????8??????????????????????????????????????????????????????????????????
-
hvtest read [-qdbm] name rnum
-
?????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -qdbm : `gdbm_open2' ????????????Curia???????????????????????????
  • -
  • -s : ???????????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -
- -

Cabin: ?????????????????????API

- -

??????

- -

Cabin??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API????????????MIME???CSV???XML????????????????????????????????????????????????????????????????????????????????????

- -

Cabin????????????????????????`cabin.h' ??? `stdlib.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
-
#include <cabin.h>
-
#include <stdlib.h>
-
- -

?????????????????????????????????????????????`CBDATUM' ?????????????????????????????????????????????????????????????????????????????????????????? `cbdatumopen' ?????????????????? `cbdatumclose' ?????????????????????????????????????????????`CBLIST' ?????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ?????????????????? `cblistclose' ?????????????????????????????????????????????`CBMAP' ?????????????????????????????????????????????????????????????????????????????????????????? `cbmapopen' ?????????????????? `cbmapclose' ???????????????????????????????????????????????? `CBHEAP' ??????????????????????????????????????????????????????????????????????????????????????? `cbheapopen' ?????????????????? `cbheapclose' ????????????????????????????????????????????????????????????????????????????????????????????? - -

- -

API

- -

???????????? `cbfatalfunc' ????????????????????????????????????????????????????????????????????????????????????

- -
-
extern void (*cbfatalfunc)(const char *message);
-
?????????????????????????????????????????????????????????????????????????????? `NULL' ????????????`NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbmalloc' ???????????????

- -
-
void *cbmalloc(size_t size);
-
`size' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `cbrealloc' ???????????????

- -
-
void *cbrealloc(void *ptr, size_t size);
-
`ptr' ?????????????????????????????????????????????`size' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `remalloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbmemdup' ???????????????

- -
-
char *cbmemdup(const char *ptr, int size);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbfree' ???????????????

- -
-
void cbfree(void *ptr);
-
`ptr' ????????????????????????????????????????????????`NULL' ????????????????????????????????????????????? `free' ????????????????????????????????????`malloc' ?????????????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbglobalgc' ???????????????

- -
-
void cbglobalgc(void *ptr, void (*func)(void *));
-
`ptr' ?????????????????????????????????????????????????????????????????????`func' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`main' ?????????????????????????????? `exit' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `cbggcsweep' ???????????????

- -
-
void cbggcsweep(void);
-
???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `cbvmemavail' ???????????????

- -
-
int cbvmemavail(size_t size);
-
`size' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `cbisort' ???????????????

- -
-
void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
-
`base' ??????????????????????????????????????????`nmemb' ???????????????????????????????????????`size' ??????????????????????????????????????????`compar' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `cbssort' ???????????????

- -
-
void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
-
`base' ??????????????????????????????????????????`nmemb' ???????????????????????????????????????`size' ??????????????????????????????????????????`compar' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `cbhsort' ???????????????

- -
-
void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
-
`base' ??????????????????????????????????????????`nmemb' ???????????????????????????????????????`size' ??????????????????????????????????????????`compar' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????? `cbqsort' ???????????????

- -
-
void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
-
`base' ??????????????????????????????????????????`nmemb' ???????????????????????????????????????`size' ??????????????????????????????????????????`compar' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????????????????????????????? `cbstricmp' ???????????????

- -
-
int cbstricmp(const char *astr, const char *bstr);
-
`astr' ?????????????????????????????????????????????????????????`bstr' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ????????????ASCII????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `cbstrfwmatch' ???????????????

- -
-
int cbstrfwmatch(const char *str, const char *key);
-
`str' ?????????????????????????????????????????????????????????`key' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbstrfwimatch' ???????????????

- -
-
int cbstrfwimatch(const char *str, const char *key);
-
`str' ?????????????????????????????????????????????????????????`key' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ASCII????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `cbstrbwmatch' ???????????????

- -
-
int cbstrbwmatch(const char *str, const char *key);
-
`str' ?????????????????????????????????????????????????????????`key' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbstrbwimatch' ???????????????

- -
-
int cbstrbwimatch(const char *str, const char *key);
-
`str' ?????????????????????????????????????????????????????????`key' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ASCII????????????????????????????????????????????????????????????????????????????????????
-
- -

KMP??????????????????????????????????????????????????????????????????????????? `cbstrstrkmp' ???????????????

- -
-
char *cbstrstrkmp(const char *haystack, const char *needle);
-
`haystack' ????????????????????????????????????????????????`needle' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????? `strstr' ???????????????????????????
-
- -

BM??????????????????????????????????????????????????????????????????????????? `cbstrstrbm' ???????????????

- -
-
char *cbstrstrbm(const char *haystack, const char *needle);
-
`haystack' ????????????????????????????????????????????????`needle' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????? `strstr' ???????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `cbstrtoupper' ???????????????

- -
-
char *cbstrtoupper(char *str);
-
`str' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `cbstrtolower' ???????????????

- -
-
char *cbstrtolower(char *str);
-
`str' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????? `cbstrtrim' ???????????????

- -
-
char *cbstrtrim(char *str);
-
`str' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `cbstrsqzcpc' ???????????????

- -
-
char *cbstrsqzspc(char *str);
-
`str' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

UTF-8??????????????????????????????????????????????????????????????? `cbstrcountutf' ???????????????

- -
-
int cbstrcountutf(const char *str);
-
`str' ???UTF-8???????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

UTF-8???????????????????????????????????????????????????????????? `cbstrcututf' ???????????????

- -
-
char *cbstrcututf(char *str, int num);
-
`str' ???UTF-8????????????????????????????????????????????????`num' ???????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbdatumopen' ???????????????

- -
-
CBDATUM *cbdatumopen(const char *ptr, int size);
-
`ptr' ???????????????????????????????????????????????????????????????`NULL' ???????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ???????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????? `cbdatumdup' ???????????????

- -
-
CBDATUM *cbdatumdup(const CBDATUM *datum);
-
`datum' ????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbdatumclose' ???????????????

- -
-
void cbdatumclose(CBDATUM *datum);
-
`datum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `cbdatumcat' ???????????????

- -
-
void cbdatumcat(CBDATUM *datum, const char *ptr, int size);
-
`datum' ??????????????????????????????????????????`ptr' ?????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????
-
- -

???????????????????????????????????????????????????????????? `cbdatumptr' ???????????????

- -
-
const char *cbdatumptr(const CBDATUM *datum);
-
`datum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `cbdatumsize' ???????????????

- -
-
int cbdatumsize(const CBDATUM *datum);
-
`datum' ????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `cbdatumsetsize' ???????????????

- -
-
void cbdatumsetsize(CBDATUM *datum, int size);
-
`datum' ??????????????????????????????????????????`size' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbdatumprintf' ???????????????

- -
-
void cbdatumprintf(CBDATUM *datum, const char *format, ...);
-
`format' ???printf??????????????????????????????????????????????????? `%' ??? `s'???`d'???`o'???`u'???`x'???`X'???`c'???`e'???`E'???`f'???`g'???`G'???`@'???`?'???`:'???`%' ?????????????????????????????????????????????`@' ??? `s' ??????????????????????????????XML??????????????????????????????????????????`?' ??? `s' ??????????????????????????????URL??????????????????????????????????????????`:' ??? `s' ??????????????????????????????UTF-8????????????MIME????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `cbdatumtomalloc' ???????????????

- -
-
char *cbdatumtomalloc(CBDATUM *datum, int *sp);
-
`datum' ??????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cblistopen' ???????????????

- -
-
CBLIST *cblistopen(void);
-
?????????????????????????????????????????????
-
- -

??????????????????????????????????????? `cblistdup' ???????????????

- -
-
CBLIST *cblistdup(const CBLIST *list);
-
`list' ????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cblistclose' ???????????????

- -
-
void cblistclose(CBLIST *list);
-
`list' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `cblistnum' ???????????????

- -
-
int cblistnum(const CBLIST *list);
-
`list' ??????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????? `cblistval' ???????????????

- -
-
const char *cblistval(const CBLIST *list, int index, int *sp);
-
`list' ??????????????????????????????????????????`index' ????????????????????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????`index' ?????????????????????????????????????????? `NULL' ????????????
-
- -

?????????????????????????????????????????????????????? `cblistpush' ???????????????

- -
-
void cblistpush(CBLIST *list, const char *ptr, int size);
-
`list' ??????????????????????????????????????????`ptr' ??????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????
-
- -

????????????????????????????????????????????????????????? `cblistpop' ???????????????

- -
-
char *cblistpop(CBLIST *list, int *sp);
-
`list' ??????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????? `NULL' ????????????
-
- -

?????????????????????????????????????????????????????? `cblistunshift' ???????????????

- -
-
void cblistunshift(CBLIST *list, const char *ptr, int size);
-
`list' ??????????????????????????????????????????`ptr' ??????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????
-
- -

????????????????????????????????????????????????????????? `cblistshift' ???????????????

- -
-
char *cblistshift(CBLIST *list, int *sp);
-
`list' ??????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????? `NULL' ????????????
-
- -

????????????????????????????????????????????????????????????????????? `cblistinsert' ???????????????

- -
-
void cblistinsert(CBLIST *list, int index, const char *ptr, int size);
-
`list' ??????????????????????????????????????????`index' ????????????????????????????????????????????????????????????`ptr' ??????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `cblistremove' ???????????????

- -
-
char *cblistremove(CBLIST *list, int index, int *sp);
-
`list' ??????????????????????????????????????????`index' ????????????????????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????`index' ????????????????????????????????????????????????????????????????????? `NULL' ????????????
-
- -

??????????????????????????????????????????????????????????????????????????? `cblistover' ???????????????

- -
-
void cblistover(CBLIST *list, int index, const char *ptr, int size);
-
`list' ??????????????????????????????????????????`index' ????????????????????????????????????????????????????????????`ptr' ???????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`index' ???????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `cblistsort' ???????????????

- -
-
void cblistsort(CBLIST *list);
-
`list' ????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `cblistlsearch' ???????????????

- -
-
int cblistlsearch(const CBLIST *list, const char *ptr, int size);
-
`list' ??????????????????????????????????????????`ptr' ????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ?????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `cblistbsearch' ???????????????

- -
-
int cblistbsearch(const CBLIST *list, const char *ptr, int size);
-
`list' ????????????????????????????????????????????????????????????????????????????????????????????????????????????`ptr' ????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ?????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `cblistdump' ???????????????

- -
-
char *cblistdump(const CBLIST *list, int *sp);
-
`list' ??????????????????????????????????????????`sp' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

????????????????????????????????????????????????????????? `cblistload' ???????????????

- -
-
CBLIST *cblistload(const char *ptr, int size);
-
`ptr' ??????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbmapopen' ???????????????

- -
-
CBMAP *cbmapopen(void);
-
?????????????????????????????????????????????
-
- -

??????????????????????????????????????? `cbmapdup' ???????????????

- -
-
CBMAP *cbmapdup(CBMAP *map);
-
`map' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbmapclose' ???????????????

- -
-
void cbmapclose(CBMAP *map);
-
`map' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `cbmapput' ???????????????

- -
-
int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over);
-
`map' ??????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`over' ????????????????????????????????????????????????????????????????????????`over' ????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `cbmapputcat' ???????????????

- -
-
void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz);
-
`map' ??????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `cbmapout' ???????????????

- -
-
int cbmapout(CBMAP *map, const char *kbuf, int ksiz);
-
`map' ??????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `cbmapget' ???????????????

- -
-
const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp);
-
`map' ??????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `cbmapmove' ???????????????

- -
-
int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head);
-
`map' ??????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`head' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `cbmapiterinit' ???????????????

- -
-
void cbmapiterinit(CBMAP *map);
-
`map' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `cbmapiternext' ???????????????

- -
-
const char *cbmapiternext(CBMAP *map, int *sp);
-
`map' ??????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????`cbmapiterval' ???????????????

- -
-
const char *cbmapiterval(const char *kbuf, int *sp);
-
`kbuf' ??????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbmaprnum' ???????????????

- -
-
int cbmaprnum(const CBMAP *map);
-
`map' ??????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????????????????? `cbmapkeys' ???????????????

- -
-
CBLIST *cbmapkeys(CBMAP *map);
-
`map' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????? `cbmapvals' ???????????????

- -
-
CBLIST *cbmapvals(CBMAP *map);
-
`map' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `cbmapdump' ???????????????

- -
-
char *cbmapdump(const CBMAP *map, int *sp);
-
`map' ??????????????????????????????????????????`sp' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

????????????????????????????????????????????????????????? `cbmapload' ???????????????

- -
-
CBMAP *cbmapload(const char *ptr, int size);
-
`ptr' ??????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `cbmaploadone' ???????????????

- -
-
char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp);
-
`ptr' ??????????????????????????????????????????????????????`size' ?????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbheapopen' ???????????????

- -
-
CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *));
-
`size' ?????????????????????????????????????????????????????????`max' ?????????????????????????????????????????????????????????????????????`compar' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ???????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbheapdup' ???????????????

- -
-
CBHEAP *cbheapdup(CBHEAP *heap);
-
`heap' ????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbheapclose' ???????????????

- -
-
void cbheapclose(CBHEAP *heap);
-
`heap' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `cbheapnum' ???????????????

- -
-
int cbheapnum(CBHEAP *heap);
-
`heap' ????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `cbheapinsert' ???????????????

- -
-
int cbheapinsert(CBHEAP *heap, const void *ptr);
-
`heap' ??????????????????????????????????????????`ptr' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `cbheapget' ???????????????

- -
-
void *cbheapval(CBHEAP *heap, int index);
-
`heap' ??????????????????????????????????????????`index' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`index' ?????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `cbheaptomalloc' ???????????????

- -
-
void *cbheaptomalloc(CBHEAP *heap, int *np);
-
`heap' ??????????????????????????????????????????`np' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????? `cbsprintf' ???????????????

- -
-
char *cbsprintf(const char *format, ...);
-
`format' ???printf??????????????????????????????????????????????????? `%' ?????????????????? `d'???`o'???`u'???`x'???`X'???`e'???`E'???`f'???`g'???`G'???`c'???`s' ????????? `%' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????10????????????`.'???`+'???`-' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

????????????????????????????????????????????????????????? `cbreplace' ???????????????

- -
-
char *cbreplace(const char *str, CBMAP *pairs);
-
`str' ??????????????????????????????????????????`pairs' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `cbsplit' ???????????????

- -
-
CBLIST *cbsplit(const char *ptr, int size, const char *delim);
-
`ptr' ??????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`delim' ?????????????????????????????????????????????????????????`NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
-
- -

????????????????????????????????????????????????????????? `cbreadfile' ???????????????

- -
-
char *cbreadfile(const char *name, int *sp);
-
`name' ?????????????????????????????????????????????`NULL' ????????????????????????????????????`sp' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `cbwritefile' ???????????????

- -
-
int cbwritefile(const char *name, const char *ptr, int size);
-
`name' ???????????????????????????????????????`NULL' ??????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `cbreadlines' ???????????????

- -
-
CBLIST *cbreadlines(const char *name);
-
`name' ?????????????????????????????????????????????`NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `cbdirlist' ???????????????

- -
-
CBLIST *cbdirlist(const char *name);
-
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `cbfilestat' ???????????????

- -
-
int cbfilestat(const char *name, int *isdirp, int *sizep, int *mtimep);
-
`name' ???????????????????????????????????????????????????????????????`dirp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????`sizep' ??? `NULL' ??????????????????????????????????????????????????????????????????????????????`mtimep' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????? `cbremove' ???????????????

- -
-
int cbremove(const char *name);
-
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

URL????????????????????????????????????????????? `cburlbreak' ???????????????

- -
-
CBMAP *cburlbreak(const char *str);
-
`str' ???URL???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? "self" ???URL???????????????????????????????????? "scheme" ???URL??????????????????????????????????????? "host" ??????????????????????????????????????????????????? "port" ?????????????????????????????????????????????????????? "authority" ??????????????????????????????????????? "path" ???????????????????????????????????????????????? "file" ?????????????????????????????????????????????????????????????????????????????? "query" ????????????????????????????????????????????? "fragment" ????????????????????????????????????????????????????????????????????????????????????HTTP???HTTPS???FTP???FILE??????????????????URL????????????URL?????????????????????????????????????????????????????? `cbmapopen' ????????????????????????????????????????????? `cbmapclose' ??????????????????????????????
-
- -

??????URL?????????URL??????????????????????????????????????? `cburlresolve' ???????????????

- -
-
char *cburlresolve(const char *base, const char *target);
-
`base' ???????????????????????????????????????URL??????????????????`target' ??????????????????URL?????????????????????????????????????????????URL???????????????????????????URL?????????URL???????????????????????????????????????????????????????????????URL???????????????????????????URL?????????URL???????????????????????????URL????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????URL????????????????????????????????????????????????????????? `cburlencode' ???????????????

- -
-
char *cburlencode(const char *ptr, int size);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

URL???????????????????????????????????????????????????????????????????????????????????? `cburldecode' ???????????????

- -
-
char *cburldecode(const char *str, int *sp);
-
`str' ??????????????????????????????????????????????????????????????????`sp' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????Base64????????????????????????????????????????????????????????? `cbbaseencode' ???????????????

- -
-
char *cbbaseencode(const char *ptr, int size);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

Base64???????????????????????????????????????????????????????????????????????????????????? `cbbasedecode' ???????????????

- -
-
char *cbbasedecode(const char *str, int *sp);
-
`str' ??????????????????????????????????????????????????????????????????`sp' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????quoted-printable????????????????????????????????????????????????????????? `cbquoteencode' ???????????????

- -
-
char *cbquoteencode(const char *ptr, int size);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

quoted-printable???????????????????????????????????????????????????????????????????????????????????? `cbquotedecode' ???????????????

- -
-
char *cbquotedecode(const char *str, int *sp);
-
`str' ??????????????????????????????????????????????????????????????????`sp' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

MIME?????????????????????????????????????????????????????????????????? `cbmimebreak' ???????????????

- -
-
char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp);
-
`ptr' ???MIME?????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`attrs' ???????????????????????????????????????????????????????????????????????????`NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? "TYPE" ?????????????????????????????????????????????????????????????????????????????????????????? "CHARSET" ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? "BOUNDARY" ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? "DISPOSITION" ??????????????????????????? ???????????????????????????????????????????????????????????? "FILENAME" ????????????????????????????????????????????????????????????????????????????????? "NAME" ?????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

MIME??????????????????????????????????????????????????????????????????????????????????????? `cbmimeparts' ???????????????

- -
-
CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary);
-
`ptr' ???MIME?????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`boundary' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
-
- -

????????????MIME????????????????????????????????????????????????????????? `cbmimeencode' ???????????????

- -
-
char *cbmimeencode(const char *str, const char *encname, int base);
-
`str' ????????????????????????????????????????????????`encname' ???????????????????????????????????????????????????`base' ???Base64??????????????????????????????????????????????????????????????????quoted-printable?????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

MIME???????????????????????????????????????????????????????????????????????????????????? `cbmimedecode' ???????????????

- -
-
char *cbmimedecode(const char *str, char *enp);
-
`str' ??????????????????????????????????????????????????????????????????`enp' ??????????????????????????????????????????????????????????????????????????????????????????`NULL' ????????????????????????????????????????????????????????????32?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

CSV???????????????????????????????????????????????? `cbcsvrows' ???????????????

- -
-
CBLIST *cbcsvrows(const char *str);
-
`str' ???CSV????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????????????????????????????????????????US-ASCII???UTF-8???ISO-8859-*???EUC-*???Shift_JIS???????????????????????????????????????MS-Excel???????????????????????????CSV?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

CSV????????????????????????????????????????????????????????? `cbcsvcells' ???????????????

- -
-
CBLIST *cbcsvcells(const char *str);
-
`str' ???CSV??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
-
- -

CSV???????????????????????????????????????????????????????????????????????? `cbcsvescape' ???????????????

- -
-
char *cbcsvescape(const char *str);
-
`str' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

XML?????????????????????????????????????????????????????????????????????????????? `cbcsvunescape' ???????????????

- -
-
char *cbcsvunescape(const char *str);
-
`str' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

XML????????????????????????????????????????????????????????????????????????????????? `cbxmlbreak' ???????????????

- -
-
CBLIST *cbxmlbreak(const char *str, int cr);
-
`str' ???XML????????????????????????????????????????????????`cr' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????????????????????????????????????????US-ASCII???UTF-8???ISO-8859-*???EUC-*???Shift_JIS????????????????????????????????????????????????XML???????????????????????????????????????XML??????????????????????????????HTML???SGML??????????????????????????????
-
- -

XML?????????????????????????????????????????????????????? `cbxmlattrs' ???????????????

- -
-
CBMAP *cbxmlattrs(const char *str);
-
`str' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbmapopen' ????????????????????????????????????????????? `cbmapclose' ??????????????????????????????
-
- -

XML???????????????????????????????????????????????????????????????????????? `cbxmlescape' ???????????????

- -
-
char *cbxmlescape(const char *str);
-
`str' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `&'??? `<'???`>'???`"' ????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

XML?????????????????????????????????????????????????????????????????????????????? `cbxmlunescape' ???????????????

- -
-
char *cbxmlunescape(const char *str);
-
`str' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `&amp;'???`&lt;'???`&gt;'???`&quot;' ????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

ZLIB????????????????????????????????????????????????????????????????????? `cbdeflate' ???????????????

- -
-
char *cbdeflate(const char *ptr, int size, int *sp);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`sp' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???ZLIB??????????????????????????????????????????????????????????????????
-
- -

ZLIB??????????????????????????????????????????????????????????????????????????? `cbinflate' ???????????????

- -
-
char *cbinflate(const char *ptr, int size, int *sp);
-
`ptr' ?????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???ZLIB??????????????????????????????????????????????????????????????????
-
- -

GZIP????????????????????????????????????????????????????????????????????? `cbgzencode' ???????????????

- -
-
char *cbgzencode(const char *ptr, int size, int *sp);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`sp' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???ZLIB??????????????????????????????????????????????????????????????????
-
- -

GZIP??????????????????????????????????????????????????????????????????????????? `cbgzdecode' ???????????????

- -
-
char *cbgzdecode(const char *ptr, int size, int *sp);
-
`ptr' ?????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???ZLIB??????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????CRC32?????????????????????????????????????????? `cbgetcrc' ???????????????

- -
-
unsigned int cbgetcrc(const char *ptr, int size);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ???????????????????????????????????????????????????CRC32?????????????????????????????????????????????QDBM???ZLIB??????????????????????????????????????????????????????????????????
-
- -

LZO????????????????????????????????????????????????????????????????????? `cblzoencode' ???????????????

- -
-
char *cblzoencode(const char *ptr, int size, int *sp);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`sp' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???LZO??????????????????????????????????????????????????????????????????
-
- -

LZO??????????????????????????????????????????????????????????????????????????? `cblzodecode' ???????????????

- -
-
char *cblzodecode(const char *ptr, int size, int *sp);
-
`ptr' ?????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???LZO??????????????????????????????????????????????????????????????????
-
- -

BZIP2????????????????????????????????????????????????????????????????????? `cbbzencode' ???????????????

- -
-
char *cbbzencode(const char *ptr, int size, int *sp);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`sp' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???BZIP2??????????????????????????????????????????????????????????????????
-
- -

BZIP2??????????????????????????????????????????????????????????????????????????? `cbbzdecode' ???????????????

- -
-
char *cbbzdecode(const char *ptr, int size, int *sp);
-
`ptr' ?????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???BZIP2??????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????? `cbiconv' ???????????????

- -
-
char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`icode' ???????????????????????????????????????????????????????????????`outcode' ???????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????`mp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???ICONV??????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `cbencname' ???????????????

- -
-
const char *cbencname(const char *str, int size);
-
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`icode' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????US-ASCII???ISO-2022-JP???Shift_JIS???CP932???EUC-JP???UTF-8???UTF-16???UTF-16BE?????????UTF-16LE???????????????????????????????????????????????????????????????ISO-8859-1?????????????????????????????????QDBM???ICONV??????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `cbjetlag' ???????????????

- -
-
int cbjetlag(void);
-
???????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????? `cbcalendar' ???????????????

- -
-
void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp);
-
`t' ?????????????????????????????????????????????????????????????????????????????????`jl' ??????????????????????????????????????????????????????`yearp' ??? `NULL' ?????????????????????????????????????????????????????????`monp' ??? `NULL' ?????????????????????????????????????????????????????????1???1??????????????????12???12?????????????????????`dayp' ??? `NULL' ?????????????????????????????????????????????????????????`hourp' ??? `NULL' ?????????????????????????????????????????????????????????`minp' ??? `NULL' ?????????????????????????????????????????????????????????`secp' ??? `NULL' ?????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????? `cbdayofweek' ???????????????

- -
-
int cbdayofweek(int year, int mon, int day);
-
`year' ?????????????????????????????????`mon' ?????????????????????????????????`day' ?????????????????????????????????????????????????????????????????????0????????????????????????6???????????????????????????
-
- -

???????????????W3CDTF?????????????????????????????????????????????????????? `cbdatestrwww' ???????????????

- -
-
char *cbdatestrwww(time_t t, int jl);
-
`t' ?????????????????????????????????????????????????????????????????????????????????`jl' ??????????????????????????????????????????????????????????????????W3CDTF????????????YYYY-MM-DDThh:mm:ddTZD???????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

???????????????RFC 1123?????????????????????????????????????????????????????? `cbdatestrhttp' ???????????????

- -
-
char *cbdatestrhttp(time_t t, int jl);
-
`t' ?????????????????????????????????????????????????????????????????????????????????`jl' ??????????????????????????????????????????????????????????????????RFC 1123????????????Wdy, DD-Mon-YYYY hh:mm:dd TZD???????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

10?????????16?????????W3CDTF???RFC 822???1123??????????????????????????????????????????????????????????????????????????? `cbstrmktime' ???????????????

- -
-
time_t cbstrmktime(const char *str);
-
`str' ???10?????????16?????????W3CDTF???RFC 822???1123?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????10????????? "s" ??????????????????????????????????????????"m" ??????????????????????????????????????????"h" ??????????????????????????????????????????"d" ?????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `cbproctime' ???????????????

- -
-
void cbproctime(double *usrp, double *sysp);
-
`usrp' ??? `NULL' ??????????????????????????????????????????????????????????????????????????????????????????????????????`sysp' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `cbstdiobin' ???????????????

- -
-
void cbstdiobin(void);
-
???????????????DOS????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????

- -

??????????????????????????????????????????????????????????????????

- -
#include <cabin.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-int main(int argc, char **argv){
-  CBDATUM *datum;
-  CBLIST *list;
-  CBMAP *map;
-  char *buf1, *buf2;
-  int i;
-
-  /* ?????????????????????????????? */
-  datum = cbdatumopen("123", -1);
-  /* ???????????????????????? */
-  cbdatumcat(datum, "abc", -1);
-  /* ???????????????????????? */
-  printf("%s\n", cbdatumptr(datum));
-  /* ????????????????????????????????? */
-  cbdatumclose(datum);
-
-  /* ?????????????????????????????? */
-  list = cblistopen();
-  /* ????????????????????????????????? */
-  cblistpush(list, "apple", -1);
-  cblistpush(list, "orange", -1);
-  /* ?????????????????????????????? */
-  for(i = 0; i < cblistnum(list); i++){
-    printf("%s\n", cblistval(list, i, NULL));
-  }
-  /* ????????????????????????????????? */
-  cblistclose(list);
-
-  /* ?????????????????????????????? */
-  map = cbmapopen();
-  /* ??????????????????????????????????????? */
-  cbmapput(map, "dog", -1, "bowwow", -1, 1);
-  cbmapput(map, "cat", -1, "meow", -1, 1);
-  /* ?????????????????????????????? */
-  printf("%s\n", cbmapget(map, "dog", -1, NULL));
-  printf("%s\n", cbmapget(map, "cat", -1, NULL));
-  /* ????????????????????????????????? */
-  cbmapclose(map);
-
-  /* Base64????????????????????? */
-  buf1 = cbbaseencode("I miss you.", -1);
-  printf("%s\n", buf1);
-  /* Base64?????????????????? */
-  buf2 = cbbasedecode(buf1, NULL);
-  printf("%s\n", buf2);
-  /* ??????????????????????????? */
-  free(buf2);
-  free(buf1);
-
-  /* ?????????????????????????????????????????????????????????????????????????????? */
-  buf1 = cbmemdup("Take it easy.", -1);
-  cbglobalgc(buf1, free);
-  /* ???????????????????????????????????????????????????????????? */
-  printf("%s\n", buf1);
-
-  /* ?????????????????????????????????????????????????????????????????? */
-  list = cblistopen();
-  cbglobalgc(list, (void (*)(void *))cblistclose);
-  /* ????????????????????????????????????????????????????????? */
-  cblistpush(list, "Don't hesitate.", -1);
-  for(i = 0; i < cblistnum(list); i++){
-    printf("%s\n", cblistval(list, i, NULL));
-  }
-
-  return 0;
-}
-
- -

??????

- -

Cabin????????????????????????????????????????????????????????????Depot????????????????????????????????????

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

?????????????????????????????????????????????????????????????????????????????????`cbglobalgc' ????????????Cabin????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

- -
- -

Cabin???????????????

- -

Cabin???????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `cbtest' ???Cabin?????????????????????????????????????????????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????`rnum' ????????????????????????????????????

- -
-
cbtest sort [-d] rnum
-
???????????????????????????????????????????????????
-
cbtest strstr [-d] rnum
-
?????????????????????????????????????????????????????????
-
cbtest list [-d] rnum
-
?????????????????????????????????????????????
-
cbtest map [-d] rnum
-
?????????????????????????????????????????????
-
cbtest wicked rnum
-
????????????????????????????????????????????????????????????????????????????????????
-
cbtest misc
-
???????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -d : ???????????????????????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -

???????????? `cbcodec' ???Cabin??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`file' ??????????????????????????????????????????????????????????????????????????????????????????

- -
-
cbcodec url [-d] [-br] [-rs base target] [-l] [-e expr] [file]
-
URL????????????????????????????????????????????????
-
cbcodec base [-d] [-l] [-c num] [-e expr] [file]
-
Base64????????????????????????????????????????????????
-
cbcodec quote [-d] [-l] [-c num] [-e expr] [file]
-
quoted-printable????????????????????????????????????????????????
-
cbcodec mime [-d] [-hd] [-bd] [-part num] [-l] [-ec code] [-qp] [-dc] [-e expr] [file]
-
MIME????????????????????????????????????????????????
-
cbcodec csv [-d] [-t] [-l] [-e expr] [-html] [file]
-
CSV????????????????????????????????????????????????????????????????????????????????????
-
cbcodec xml [-d] [-p] [-l] [-e expr] [-tsv] [file]
-
XML????????????????????????????????????????????????????????????????????????????????????
-
cbcodec zlib [-d] [-gz] [-crc] [file]
-
ZLIB????????????????????????????????????ZLIB??????????????????QDBM?????????????????????????????????????????????????????????
-
cbcodec lzo [-d] [file]
-
LZO????????????????????????????????????LZO??????????????????QDBM?????????????????????????????????????????????????????????
-
cbcodec bzip [-d] [file]
-
BZIP2????????????????????????????????????BZIP2??????????????????QDBM?????????????????????????????????????????????????????????
-
cbcodec iconv [-ic code] [-oc code] [-ol ltype] [-cn] [-um] [-wc] [file]
-
ICONV?????????????????????????????????????????????ICONV??????????????????QDBM?????????????????????????????????????????????????????????
-
cbcodec date [-wf] [-rf] [-utc] [str]
-
`str' ????????????????????????????????????????????????????????????????????????????????????UNIX????????????????????????`str' ????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -d : ??????????????????????????????????????????????????????????????????????????????????????????????????????
  • -
  • -br : URL?????????????????????????????????
  • -
  • -rs : ??????URL??????????????????
  • -
  • -l : ?????????????????????????????????????????????
  • -
  • -e expr : ???????????????????????????????????????
  • -
  • -c num : ??????????????????????????????????????????????????????
  • -
  • -hd : MIME???????????????????????????????????????TSV????????????????????????
  • -
  • -bd : MIME??????????????????????????????????????????????????????
  • -
  • -part num : MIME???????????????????????????????????????????????????????????????
  • -
  • -ec code : ????????????????????????????????????????????????????????????UTF-8????????????
  • -
  • -qp : quoted-printable????????????????????????????????????????????????Base64????????????
  • -
  • -dc : ??????????????????????????????????????????????????????????????????????????????
  • -
  • -t : CSV???????????????????????????TSV??????????????????????????????????????????????????????????????????????????????
  • -
  • -html : CSV???????????????????????????HTML??????????????????????????????
  • -
  • -p : XML??????????????????????????????????????????????????????????????????????????????????????????????????????
  • -
  • -tsv : XML????????????????????????????????????TSV????????????????????????????????????????????????????????????????????????URL???????????????????????????
  • -
  • -gz : GZIP?????????????????????
  • -
  • -crc : CRC32??????????????????????????????????????????????????????16????????????????????????
  • -
  • -ic code : ????????????????????????????????????????????????????????????????????????????????????
  • -
  • -oc code : ???????????????????????????????????????????????????????????????UTF-8????????????
  • -
  • -ol ltype : ??????????????????????????????`unix'(LF)???`dos'(CRLF)???`mac'(CR) ??????????????????????????????
  • -
  • -cn : ???????????????????????????????????????????????????????????????????????????
  • -
  • -wc : ???????????????????????????UTF-8????????????????????????????????????????????????
  • -
  • -um : UCS-2???????????????C??????????????????????????????UTF-16BE???UTF-8??????????????????????????????
  • -
  • -wf : W3CDTF???????????????????????????
  • -
  • -rf : RFC 1123???????????????????????????
  • -
  • -utc : ?????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -
- -

Villa: ??????API

- -

??????

- -

Villa???QDBM?????????API????????????B+????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Villa???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Villa???Depot?????????Cabin????????????????????????????????????Villa????????????????????????????????????Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????Depot?????????????????????????????????????????????????????????????????????????????????

- -

Villa????????????????????????`depot.h' ??? `cabin.h' ??? `villa.h' ??? `stdlib.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
-
#include <depot.h>
-
#include <cabin.h>
-
#include <villa.h>
-
#include <stdlib.h>
-
- -

Villa??????????????????????????????????????????`VILLA' ?????????????????????????????????????????????????????????????????????`stdio.h' ???????????????????????????????????????????????? `FILE' ?????????????????????????????????????????????????????????????????????????????? `vlopen' ?????????????????? `vlclose' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `vlclose' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `vlcurfirst' ??? `vlcurlast' ??? `vlcurjump' ????????????????????????????????????????????????`vlcurput' ??? `vlcurout' ?????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????

- -

Villa??????Depot???????????????????????? `dpecode' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dperrmsg' ???????????????

- -

API

- -

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
-
typedef int(*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz);
-
`aptr' ????????????????????????????????????????????????????????????????????????`asiz' ???????????????????????????????????????????????????????????????`bptr' ????????????????????????????????????????????????????????????????????????`bsiz' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ????????????
-
- -

??????????????????????????????????????????????????????????????? `vlopen' ???????????????

- -
-
VILLA *vlopen(const char *name, int omode, VLCFUNC cmp);
-
`name' ????????????????????????????????????????????????????????????`omode' ?????????????????????????????????`VL_OREADER' ??????????????????`VL_OWRITER' ???????????????????????????`VL_OWRITER' ????????????`VL_OCREAT' ????????? `VL_OTRUNC' ??????????????????????????????????????????????????????`VL_OCREAT' ????????????????????????????????????????????????????????????????????????`VL_OTRUNC' ??????????????????????????????????????????????????????????????????`VL_OZCOMP' ???????????????????????????????????????ZLIB????????????????????????????????????`VL_OYCOMP' ???????????????????????????????????????LZO????????????????????????????????????`VL_OXCOMP' ???????????????????????????????????????BZIP2???????????????????????????????????????`VL_OREADER' ??? `VL_OWRITER' ???????????? `VL_ONOLCK' ????????? `VL_OLCKNB' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????`cmp' ?????????????????????????????????`VL_CMPLEX' ???????????????????????????????????????`VL_CMPINT' ???????????? `int' ??????????????????????????????????????????????????????`VL_CMPNUM' ??????????????????????????????????????????????????????????????????????????????`VL_CMPDEC' ????????????10???????????????????????????????????????????????????????????????`VLCFUNC' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????`VL_OZCOMP' ??? `VL_OYCOMP' ??? `VL_OXCOMP' ???QDBM???????????????ZLIB???LZO???BZIP2?????????????????????????????????????????????????????????????????????`VL_ONOLCK' ??????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `vlclose' ???????????????

- -
-
int vlclose(VILLA *villa);
-
`villa' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `vlput' ???????????????

- -
-
int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
-
`villa' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`dmode' ???????????????????????????????????????????????????????????????????????????`VL_DOVER' ????????????????????????????????????????????????`VL_DKEEP' ?????????????????????????????????????????????????????????`VL_DCAT' ?????????????????????????????????????????????????????????`VL_DDUP' ?????????????????????????????????????????????????????????????????????????????????`VL_DDUPR' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `vlout' ???????????????

- -
-
int vlout(VILLA *villa, const char *kbuf, int ksiz);
-
`villa' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????? `vlget' ???????????????

- -
-
char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp);
-
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `vlvsiz' ???????????????

- -
-
int vlvsiz(VILLA *villa, const char *kbuf, int ksiz);
-
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `vlvnum' ???????????????

- -
-
int vlvnum(VILLA *villa, const char *kbuf, int ksiz);
-
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ????????????
-
- -

???????????????????????????????????????????????????????????????????????? `vlputlist' ???????????????

- -
-
int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals);
-
`villa' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vals' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `vloutlist' ???????????????

- -
-
int vloutlist(VILLA *villa, const char *kbuf, int ksiz);
-
`villa' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `vlgetlist' ???????????????

- -
-
CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz);
-
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `vlgetcat' ???????????????

- -
-
char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp);
-
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `vlcurfirst' ???????????????

- -
-
int vlcurfirst(VILLA *villa);
-
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `vlcurlast' ???????????????

- -
-
int vlcurlast(VILLA *villa);
-
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `vlcurprev' ???????????????

- -
-
int vlcurprev(VILLA *villa);
-
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `vlcurnext' ???????????????

- -
-
int vlcurnext(VILLA *villa);
-
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????? `vlcurjump' ???????????????

- -
-
int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode);
-
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`jmode' ????????????????????????????????????`VL_JFORWARD' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`VL_JBACKWORD' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `vlcurkey' ???????????????

- -
-
char *vlcurkey(VILLA *villa, int *sp);
-
`villa' ???????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `vlcurkey' ???????????????

- -
-
char *vlcurval(VILLA *villa, int *sp);
-
`villa' ???????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????????????????? `vlcurput' ???????????????

- -
-
int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode);
-
`villa' ???????????????????????????????????????????????????????????????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`cpmode' ????????????????????????????????????`VL_CPCURRENT' ?????????????????????????????????????????????????????????????????????`VL_CPBEFORE' ???????????????????????????????????????????????????????????????????????????`VL_CPAFTER' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `vlcurout' ???????????????

- -
-
int vlcurout(VILLA *villa);
-
`villa' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `vlsettuning' ???????????????

- -
-
void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum);
-
`villa' ???????????????????????????????????????????????????`lrecmax' ???B+????????????????????????????????????????????????????????????????????????????????????0 ????????????????????????????????????????????????`nidxmax' ???B+??????????????????????????????????????????????????????????????????????????????????????????0 ????????????????????????????????????????????????`lcnum' ????????????????????????????????????????????????????????????????????????0 ????????????????????????????????????????????????`ncnum' ????????????????????????????????????????????????????????????????????????????????????0 ??????????????????????????????????????????????????????????????????????????? `vlsettuning(49, 192, 1024, 512)' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `vlsetfbpsiz' ???????????????

- -
-
int vlsetfbpsiz(VILLA *villa, int size);
-
`villa' ???????????????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????256?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????? `vlsync' ???????????????

- -
-
int vlsync(VILLA *villa);
-
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `vloptimize' ???????????????

- -
-
int vloptimize(VILLA *villa);
-
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `vlname' ???????????????

- -
-
char *vlname(VILLA *villa);
-
`villa' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `vlfsiz' ???????????????

- -
-
int vlfsiz(VILLA *villa);
-
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????I/O?????????????????????????????????????????????????????????????????????????????????????????????
-
- -

B+?????????????????????????????????????????????????????? `vllnum' ???????????????

- -
-
int vllnum(VILLA *villa);
-
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

B+????????????????????????????????????????????????????????? `vlnnum' ???????????????

- -
-
int vlnnum(VILLA *villa);
-
`villa' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

???????????????????????????????????????????????????????????? `vlrnum' ???????????????

- -
-
int vlrnum(VILLA *villa);
-
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

????????????????????????????????????????????????????????????????????????????????? `vlwritable' ???????????????

- -
-
int vlwritable(VILLA *villa);
-
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `vlfatalerror' ???????????????

- -
-
int vlfatalerror(VILLA *villa);
-
`villa' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????inode?????????????????????????????? `vlinode' ???????????????

- -
-
int vlinode(VILLA *villa);
-
`villa' ????????????????????????????????????????????????????????????????????????????????????????????????inode??????????????????
-
- -

??????????????????????????????????????????????????????????????? `vlmtime' ???????????????

- -
-
time_t vlmtime(VILLA *villa);
-
`villa' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `vltranbegin' ???????????????

- -
-
int vltranbegin(VILLA *villa);
-
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `vltrancommit' ???????????????

- -
-
int vltrancommit(VILLA *villa);
-
`villa' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? `vltranabort' ???????????????

- -
-
int vltranabort(VILLA *villa);
-
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `vlremove' ???????????????

- -
-
int vlremove(const char *name);
-
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `vlrepair' ???????????????

- -
-
int vlrepair(const char *name, VLCFUNC cmp);
-
`name' ????????????????????????????????????????????????????????????`cmp' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????? `vlexportdb' ???????????????

- -
-
int vlexportdb(VILLA *villa, const char *name);
-
`villa' ???????????????????????????????????????????????????`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????????????????? `vlimportdb' ???????????????

- -
-
int vlimportdb(VILLA *villa, const char *name);
-
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????

- -

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <cabin.h>
-#include <villa.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define NAME     "mikio"
-#define NUMBER   "000-1234-5678"
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  VILLA *villa;
-  char *val;
-
-  /* ??????????????????????????? */
-  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
-    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* ??????????????????????????? */
-  if(!vlput(villa, NAME, -1, NUMBER, -1, VL_DOVER)){
-    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
-  }
-
-  /* ??????????????????????????? */
-  if(!(val = vlget(villa, NAME, -1, NULL))){
-    fprintf(stderr, "vlget: %s\n", dperrmsg(dpecode));
-  } else {
-    printf("Name: %s\n", NAME);
-    printf("Number: %s\n", val);
-    free(val);
-  }
-
-  /* ?????????????????????????????? */
-  if(!vlclose(villa)){
-    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <cabin.h>
-#include <villa.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#define DBNAME   "words"
-#define PREFIX   "apple"
-
-int main(int argc, char **argv){
-  VILLA *villa;
-  char *key, *val;
-
-  /* ??????????????????????????? */
-  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
-    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* ??????????????????????????? */
-  if(!vlput(villa, "applet", -1, "little application", -1, VL_DDUP) ||
-     !vlput(villa, "aurora", -1, "polar wonderwork", -1, VL_DDUP) ||
-     !vlput(villa, "apple", -1, "delicious fruit", -1, VL_DDUP) ||
-     !vlput(villa, "amigo", -1, "good friend", -1, VL_DDUP) ||
-     !vlput(villa, "apple", -1, "big city", -1, VL_DDUP)){
-    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
-  }
-
-  /* ??????????????????????????????????????? */
-  vlcurjump(villa, PREFIX, -1, VL_JFORWARD);
-
-  /* ??????????????????????????? */
-  while((key = vlcurkey(villa, NULL)) != NULL){
-    if(strstr(key, PREFIX) != key){
-      free(key);
-      break;
-    }
-    if(!(val = vlcurval(villa, NULL))){
-      fprintf(stderr, "vlcurval: %s\n", dperrmsg(dpecode));
-      free(key);
-      break;
-    }
-    printf("%s: %s\n", key, val);
-    free(val);
-    free(key);
-    vlcurnext(villa);
-  }
-
-  /* ?????????????????????????????? */
-  if(!vlclose(villa)){
-    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

??????

- -

Villa????????????????????????????????????????????????????????????Depot????????????????????????????????????

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

POSIX??????????????????????????????QDBM??????????????????????????????????????? `dpecode' ???????????????????????????????????????????????????????????????Villa?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

- -

Vista: ????????????API

- -

Vista???Villa???????????????API????????????Villa???2GB???????????????????????????????????????????????????????????????????????????????????????Vista??????Depot????????????Curia??????????????????????????????????????????????????????Vista???Villa????????????B+???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Vista??????????????????`villa.h' ??????????????? `vista.h' ???????????????????????????????????????Vista???Villa???????????????????????????????????????????????????????????????????????????????????????Villa??????????????????API?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Vista????????????????????????????????????????????????????????????Villa???????????????????????????????????????`villa.h' ????????????????????????????????????????????????

- -
- -

Villa???????????????

- -

Villa???????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `vlmgr' ???Villa?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`key' ???????????????????????????`val' ???????????????????????????????????????

- -
-
vlmgr create [-cz|-cy|-cx] name
-
????????????????????????????????????????????????
-
vlmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat|-dup] name key val
-
?????????????????????????????????????????????????????????
-
vlmgr out [-l] [-kx|-ki] name key
-
???????????????????????????????????????????????????
-
vlmgr get [-nl] [-l] [-kx|-ki] [-ox] [-n] name key
-
???????????????????????????????????????????????????????????????????????????
-
vlmgr list [-nl] [-k|-v] [-kx|-ki] [-ox] [-top key] [-bot key] [-gt] [-lt] [-max num] [-desc] name
-
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
vlmgr optimize name
-
???????????????????????????????????????
-
vlmgr inform [-nl] name
-
??????????????????????????????????????????????????????
-
vlmgr remove name
-
????????????????????????????????????????????????
-
vlmgr repair [-ki] name
-
?????????????????????????????????????????????????????????
-
vlmgr exportdb [-ki] name file
-
??????????????????????????????????????????????????????????????????????????????????????????
-
vlmgr importdb [-ki] name file
-
????????????????????????????????????????????????????????????????????????????????????
-
vlmgr version
-
QDBM????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -cz : ?????????????????????????????????ZLIB??????????????????
  • -
  • -cy : ?????????????????????????????????LZO??????????????????
  • -
  • -cx : ?????????????????????????????????BZIP2??????????????????
  • -
  • -l : ?????????????????????????????????????????????????????????????????????
  • -
  • -kx : 2????????????16?????????????????????????????????????????? `key' ????????????
  • -
  • -ki : 10???????????????????????????????????? `key' ????????????
  • -
  • -vx : 2????????????16?????????????????????????????????????????? `val' ????????????
  • -
  • -vi : 10???????????????????????????????????? `val' ????????????
  • -
  • -vf : ????????? `val' ?????????????????????????????????????????????????????????
  • -
  • -keep : ????????????????????????????????????????????????????????????????????????????????????
  • -
  • -cat : ???????????????????????????????????????????????????????????????????????????
  • -
  • -dup : ???????????????????????????????????????????????????
  • -
  • -nl : ??????????????????????????????????????????????????????????????????
  • -
  • -top key : ?????????????????????????????????????????????
  • -
  • -bot key : ?????????????????????????????????????????????
  • -
  • -gt : ?????????????????????????????????????????????
  • -
  • -lt : ?????????????????????????????????????????????
  • -
  • -max num : ??????????????????????????????????????????
  • -
  • -desc : ??????????????????????????????
  • -
  • -ox : 2????????????16??????????????????????????????????????????????????????????????????
  • -
  • -n : ??????????????????????????????????????????????????????????????????????????????
  • -
  • -k : ??????????????????????????????
  • -
  • -v : ???????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `vltest' ???Villa??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `vlmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`rnum' ?????????????????????`pnum' ?????????????????????????????????????????????

- -
-
vltest write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum
-
`00000001'???`00000002' ????????????????????????8??????????????????????????????8??????????????????????????????????????????????????????????????????
-
vltest read [-int] [-vc] name
-
???????????????????????????????????????????????????????????????????????????
-
vltest rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum pnum
-
????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
vltest combo [-cz|-cy|-cx] name
-
???????????????????????????????????????????????????
-
vltest wicked [-cz|-cy|-cx] name rnum
-
????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -int : `int' ??????????????????????????????????????????????????????????????????????????????????????????
  • -
  • -cz : ?????????????????????????????????ZLIB??????????????????
  • -
  • -cy : ?????????????????????????????????LZO??????????????????
  • -
  • -cx : ?????????????????????????????????BZIP2??????????????????
  • -
  • -vc : ??????????????????????????????????????????
  • -
  • -cc : ???????????????????????????????????????????????????????????????
  • -
  • -tune lrecmax nidxmax lcnum ncnum : ???????????????????????????????????????
  • -
  • -fbp num : ????????????????????????????????????????????????????????????
  • -
  • -c : Cabin???????????????????????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `vltsv' ???????????????????????????????????????????????????????????????TSV???????????????Villa?????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????DBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ??????????????????????????????????????????`export' ????????????????????????TSV????????????????????????????????????????????????`import' ????????????????????????TSV???????????????????????????????????????????????????

- -
-
vltsv import [-bin] name
-
TSV??????????????????????????????????????????????????????????????????
-
vltsv export [-bin] name
-
?????????????????????????????????????????????TSV????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -bin : Base64?????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -

Villa???????????????????????????????????????????????????????????????????????????????????????????????????????????? `/etc/password' ????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
cat /etc/passwd | tr ':' '\t' | vltsv import casket
-
- -

????????????`mikio' ??????????????????????????????????????????????????????????????????????????????

- -
vlmgr get casket mikio
-
- -

?????????????????????????????????????????????Villa???API???????????????????????????????????????????????????

- -

???????????? `qmttest' ???Depot???Curia???Villa????????????????????????????????????????????????????????????????????????????????????POSIX??????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????`name' ??????????????????????????????????????????????????????`rnum' ????????????????????????????????????????????????????????????????????????`tnum' ????????????????????????????????????

- -
-
qmttest name rnum tnum
-
????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -
- -

Odeum: ??????API

- -

??????

- -

Odeum????????????????????????????????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Odeum?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????N-gram??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????

- -

Odeum???Curia???Cabin???Villa????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Curia???Villa???????????????????????????????????????????????????`casket' ????????????????????????????????????????????????????????????`casket/docs'???`casket/index' ????????? `casket/rdocs' ?????????????????????`docs' ???Curia?????????????????????????????????????????????????????????????????????ID????????????????????????URI??????????????????????????????`index' ???Curia????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID????????????????????????????????????????????????????????????`rdocs' ???Villa???????????????????????????????????????????????????????????????URI???????????????????????????ID??????????????????

- -

Odeum????????????????????????`depot.h' ??? `cabin.h' ??? `odeum.h' ??? `stdlib.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
-
#include <depot.h>
-
#include <cabin.h>
-
#include <odeum.h>
-
#include <stdlib.h>
-
- -

Odeum??????????????????????????????????????????`ODEUM' ????????????????????????????????????????????????????????????????????????????????? `odopen' ?????????????????? `odclose' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `odclose' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

??????????????????????????????`ODDOC' ????????????????????????????????????????????????????????????????????????????????? `oddocopen' ?????????????????? `oddocclose' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Odeum??????Depot???????????????????????? `dpecode' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dperrmsg' ???????????????

- -

API

- -

????????????????????????????????????`ODPAIR' ??????????????????????????????

- -
-
typedef struct { int id; int score; } ODPAIR;
-
`id' ????????????ID??????????????????`score' ????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????? `odopen' ???????????????

- -
-
ODEUM *odopen(const char *name, int omode);
-
`name' ??????????????????????????????????????????????????????????????????`omode' ?????????????????????????????????`OD_OREADER' ??????????????????`OD_OWRITER' ???????????????????????????`OD_OWRITER' ????????????`OD_OCREAT' ????????? `OD_OTRUNC' ??????????????????????????????????????????????????????`OD_OCREAT' ????????????????????????????????????????????????????????????????????????`OD_OTRUNC' ?????????????????????????????????????????????????????????????????????`OD_OREADER' ??? `OD_OWRITER' ???????????? `OD_ONOLCK' ??? `OD_OLCKNB' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`OD_ONOLCK' ??????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `odclose' ???????????????

- -
-
int odclose(ODEUM *odeum);
-
`odeum' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????? `odput' ???????????????

- -
-
int odput(ODEUM *odeum, const ODDOC *doc, int wmax, int over);
-
`odeum' ???????????????????????????????????????????????????????????????????????????`doc' ???????????????????????????????????????`wmax' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????`over' ?????????????????????????????????????????????????????????????????????????????????????????????URI??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

URI??????????????????????????????????????????????????? `odout' ???????????????

- -
-
int odout(ODEUM *odeum, const char *uri);
-
`odeum' ???????????????????????????????????????????????????????????????????????????`uri' ????????????URI??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

ID????????????????????????????????????????????????????????? `odoutbyid' ???????????????

- -
-
int odoutbyid(ODEUM *odeum, int id);
-
`odeum' ???????????????????????????????????????????????????????????????????????????`id' ????????????ID????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

URI??????????????????????????????????????????????????? `odget' ???????????????

- -
-
ODDOC *odget(ODEUM *odeum, const char *uri);
-
`odeum' ???????????????????????????????????????????????????`uri' ????????????URI??????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????? `NULL' ???????????????????????????????????????????????? `oddocopen' ????????????????????????????????????????????? `oddocclose' ??????????????????????????????
-
- -

ID????????????????????????????????????????????????????????? `odgetbyid' ???????????????

- -
-
ODDOC *odgetbyid(ODEUM *odeum, int id);
-
`odeum' ???????????????????????????????????????????????????`id' ????????????ID????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????? `NULL' ???????????????????????????????????????????????? `oddocopen' ????????????????????????????????????????????? `oddocclose' ??????????????????????????????
-
- -

URI????????????????????????ID?????????????????????????????? `odgetidbyuri' ???????????????

- -
-
int odgetidbyuri(ODEUM *odeum, const char *uri);
-
`odeum' ???????????????????????????????????????????????????`uri' ????????????URI????????????????????????????????????????????????????????????????????????ID??????????????????????????? -1 ????????????????????????????????????????????? -1 ????????????
-
- -

ID??????????????????????????????????????????????????????????????????????????? `odcheck' ???????????????

- -
-
int odcheck(ODEUM *odeum, int id);
-
`odeum' ???????????????????????????????????????????????????`id' ????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????????????????????????????? `odsearch' ???????????????

- -
-
ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np);
-
`odeum' ???????????????????????????????????????????????????`word' ??????????????????????????????`max' ???????????????????????????????????????????????????`np' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????? `odsearchdnum' ???????????????

- -
-
int odsearchdnum(ODEUM *odeum, const char *word);
-
`odeum' ???????????????????????????????????????????????????`word' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `oditerinit' ???????????????

- -
-
int oditerinit(ODEUM *odeum);
-
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????? `oditernext' ???????????????

- -
-
ODDOC *oditernext(ODEUM *odeum);
-
`odeum' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????????????????????????????????????? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `oddocopen' ????????????????????????????????????????????? `oddocclose' ??????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????????????????? `odsync' ???????????????

- -
-
int odsync(ODEUM *odeum);
-
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `odoptimize' ???????????????

- -
-
int odoptimize(ODEUM *odeum);
-
`odeum' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????? `odname' ???????????????

- -
-
char *odname(ODEUM *odeum);
-
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????? `odfsiz' ???????????????

- -
-
double odfsiz(ODEUM *odeum);
-
`odeum' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1.0 ????????????
-
- -

????????????????????????????????????????????????????????????????????????????????????????????? `odbnum' ???????????????

- -
-
int odbnum(ODEUM *odeum);
-
`odeum' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????? `odbusenum' ???????????????

- -
-
int odbusenum(ODEUM *odeum);
-
`odeum' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- - -

????????????????????????????????????????????????????????????????????? `oddnum' ???????????????

- -
-
int oddnum(ODEUM *odeum);
-
`odeum' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
-
- -

????????????????????????????????????????????????????????????????????? `odwnum' ???????????????

- -
-
int odwnum(ODEUM *odeum);
-
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????I/O?????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????????????????? `odwritable' ???????????????

- -
-
int odwritable(ODEUM *odeum);
-
`odeum' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `odfatalerror' ???????????????

- -
-
int odfatalerror(ODEUM *odeum);
-
`odeum' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????inode?????????????????????????????? `odinode' ???????????????

- -
-
int odinode(ODEUM *odeum);
-
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????inode??????????????????
-
- -

??????????????????????????????????????????????????????????????? `odmtime' ???????????????

- -
-
time_t odmtime(ODEUM *odeum);
-
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `odmerge' ???????????????

- -
-
int odmerge(const char *name, const CBLIST *elemnames);
-
`name' ??????????????????????????????????????????????????????????????????????????????`elemnames' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????URL??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `odremove' ???????????????

- -
-
int odremove(const char *name);
-
`name' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????API??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????? `oddocopen' ???????????????

- -
-
ODDOC *oddocopen(const char *uri);
-
`uri' ????????????URI??????????????????????????????????????????????????????????????????????????????ID????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????? `oddocclose' ???????????????

- -
-
void oddocclose(ODDOC *doc);
-
`doc' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????? `oddocaddattr' ???????????????

- -
-
void oddocaddattr(ODDOC *doc, const char *name, const char *value);
-
`doc' ???????????????????????????????????????`name' ??????????????????????????????????????????`value' ??????????????????????????????????????????
-
- -

?????????????????????????????????????????? `oddocaddword' ???????????????

- -
-
void oddocaddword(ODDOC *doc, const char *normal, const char *asis);
-
`doc' ???????????????????????????????????????`normal' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`asis' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????ID???????????????????????? `oddocid' ???????????????

- -
-
int oddocid(const ODDOC *doc);
-
`doc' ????????????????????????????????????????????????????????????ID??????????????????
-
- -

?????????URI???????????????????????? `oddocuri' ???????????????

- -
-
const char *oddocuri(const ODDOC *doc);
-
`doc' ????????????????????????????????????????????????????????????URI????????????????????????
-
- -

?????????????????????????????????????????? `oddocgetattr' ???????????????

- -
-
const char *oddocgetattr(const ODDOC *doc, const char *name);
-
`doc' ???????????????????????????????????????`name' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????
-
- -

?????????????????????????????????????????????????????????????????? `oddocnwords' ???????????????

- -
-
const CBLIST *oddocnwords(const ODDOC *doc);
-
`doc' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `oddocawords' ???????????????

- -
-
const CBLIST *oddocawords(const ODDOC *doc);
-
`doc' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????????????????? `oddocscores' ???????????????

- -
-
CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum);
-
`doc' ???????????????????????????????????????`max' ????????????????????????????????????????????????????????????`odeum' ??? `NULL' ????????????????????????????????????????????????????????????IDF??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????10???????????????????????????????????????????????????????????????????????? `cbmapopen' ????????????????????????????????????????????? `cbmapclose' ??????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????????????????? `odbreaktext' ???????????????

- -
-
CBLIST *odbreaktext(const char *text);
-
`text' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
-
- -

????????????????????????????????????????????? `odnormalizeword' ???????????????

- -
-
char *odnormalizeword(const char *asis);
-
`asis' ???????????????????????????????????????????????????????????????????????????????????????????????????ASCII????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

????????????????????????????????????????????????????????????????????? `odpairsand' ???????????????

- -
-
ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
-
`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`np' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `odpairsor' ???????????????

- -
-
ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
-
`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`np' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `odpairsnotand' ???????????????

- -
-
ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
-
`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`np' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
-
- -

???????????????????????????????????????????????????????????? `odpairssort' ???????????????

- -
-
void odpairssort(ODPAIR *pairs, int pnum);
-
`pairs' ??????????????????????????????????????????`pnum' ?????????????????????????????????????????????
-
- -

???????????????????????????????????????????????? `odlogarithm' ???????????????

- -
-
double odlogarithm(double x);
-
`x' ???????????????????????????????????????????????????????????????????????????????????????????????? 1.0 ????????????????????????????????? 0.0 ?????????????????????????????????????????????????????????????????????IDF???????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????? `odvectorcosine' ???????????????

- -
-
double odvectorcosine(const int *avec, const int *bvec, int vnum);
-
`avec' ??????????????????????????????????????????`bvec' ??????????????????????????????????????????`vnum' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????????????????????????????????????????????????????????????? `odsettuning' ???????????????

- -
-
void odsettuning(int ibnum, int idnum, int cbnum, int csiz);
-
`ibnum' ???????????????????????????????????????????????????????????????`idnum' ?????????????????????????????????????????????????????????`cbnum' ???????????????????????????????????????????????????????????????`csiz' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????? `odsettuning(32749, 7, 262139, 8388608)' ??????????????????????????????????????????????????????????????????????????????????????????
-
- -

??????????????????????????????????????????????????????????????????????????????????????????????????? `odanalyzetext' ???????????????

- -
-
void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords);
-
`odeum' ???????????????????????????????????????????????????`text' ?????????????????????????????????????????????`awords' ??????????????????????????????????????????????????????????????????`nwords' ?????????????????????????????????????????????????????????????????????`NULL' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????? `odanalyzetext' ???????????????????????????????????????????????????????????? `odsetcharclass' ???????????????

- -
-
void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars);
-
`odeum' ???????????????????????????????????????????????????`spachechars' ???????????????????????????????????????????????????`delimchars' ??????????????????????????????????????????????????????`gluechars' ???????????????????????????????????????????????????
-
- -

???????????????????????????????????????????????????????????????????????? `odquery' ???????????????

- -
-
ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors);
-
`odeum' ???????????????????????????????????????????????????`query' ??????????????????????????????????????????????????????`np' ????????????????????????????????????????????????????????????????????????`error' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -

?????????????????????

- -

????????????????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <cabin.h>
-#include <odeum.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#define DBNAME   "index"
-
-int main(int argc, char **argv){
-  ODEUM *odeum;
-  ODDOC *doc;
-  CBLIST *awords;
-  const char *asis;
-  char *normal;
-  int i;
-
-  /* ??????????????????????????? */
-  if(!(odeum = odopen(DBNAME, OD_OWRITER | OD_OCREAT))){
-    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* ????????????????????????????????? */
-  doc = oddocopen("http://www.foo.bar/baz.txt");
-
-  /* ?????????????????????????????? */
-  oddocaddattr(doc, "title", "Balcony Scene");
-  oddocaddattr(doc, "author", "Shakespeare");
-
-  /* ??????????????????????????????????????????????????? */
-  awords = odbreaktext("Parting is such sweet sorrow.");
-
-  /* ?????????????????????????????????????????? */
-  for(i = 0; i < cblistnum(awords); i++){
-    /* ?????????????????????????????????????????? */
-    asis = cblistval(awords, i, NULL);
-    /* ??????????????????????????????????????? */
-    normal = odnormalizeword(asis);
-    /* ??????????????????????????????????????? */
-    oddocaddword(doc, normal, asis);
-    /* ????????????????????????????????? */
-    free(normal);
-  }
-
-  /* ?????????????????????????????????????????? */
-  if(!odput(odeum, doc, -1, 1)){
-    fprintf(stderr, "odput: %s\n", dperrmsg(dpecode));
-  }
-
-  /* ?????????????????????????????? */
-  cblistclose(awords);
-
-  /* ????????????????????????????????? */
-  oddocclose(doc);
-
-  /* ?????????????????????????????? */
-  if(!odclose(odeum)){
-    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

???????????????????????????????????????????????????????????????????????????????????????

- -
#include <depot.h>
-#include <cabin.h>
-#include <odeum.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#define DBNAME   "index"
-
-int main(int argc, char **argv){
-  ODEUM *odeum;
-  ODPAIR *pairs;
-  ODDOC *doc;
-  const CBLIST *words;
-  const char *title, *author, *asis;
-  int i, j, pnum;
-
-  /* ????????????????????????????????? */
-  if(!(odeum = odopen(DBNAME, OD_OREADER))){
-    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* ???????????????????????? */
-  if((pairs = odsearch(odeum, "sorrow", -1, &pnum)) != NULL){
-
-    /* ?????????????????????????????? */
-    for(i = 0; i < pnum; i++){
-      /* ????????????????????????????????? */
-      if(!(doc = odgetbyid(odeum, pairs[i].id))) continue;
-      /* ?????????????????????????????? */
-      printf("URI: %s\n", oddocuri(doc));
-      title = oddocgetattr(doc, "title");
-      if(title) printf("TITLE: %s\n", title);
-      author = oddocgetattr(doc, "author");
-      if(author) printf("AUTHOR: %s\n", author);
-      /* ?????????????????????????????????????????? */
-      printf("WORDS:");
-      words = oddocawords(doc);
-      for(j = 0; j < cblistnum(words); j++){
-        asis = cblistval(words, j, NULL);
-        printf(" %s", asis);
-      }
-      putchar('\n');
-      /* ????????????????????????????????? */
-      oddocclose(doc);
-    }
-
-    /* ?????????????????????????????? */
-    free(pairs);
-
-  } else {
-    fprintf(stderr, "odsearch: %s\n", dperrmsg(dpecode));
-  }
-
-  /* ?????????????????????????????? */
-  if(!odclose(odeum)){
-    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

??????

- -

Odeum????????????????????????????????????????????????????????????Depot????????????????????????????????????

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

POSIX??????????????????????????????QDBM??????????????????????????????????????? `dpecode' ???????????????????????????????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

- -

ZLIB??????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????30%????????????????????????????????????Odeum????????????????????????ZLIB?????????????????????????????????ZLIB??????????????????????????????Odeum???????????????????????????ZLIB?????????????????????????????????????????????????????????????????????????????????????????????????????????ZLIB??????????????????LZO????????????????????????ZLIB???????????????LZO?????????????????????

- -

?????????????????????

- -

?????? `odquery' ?????????????????????????????????????????????????????????

- -
expr ::= subexpr ( op subexpr )*
-subexpr ::= WORD
-subexpr ::= LPAREN expr RPAREN
-
- -

????????????????????? "&"???AND?????? "|"???OR?????? "!"???NOTAND??????????????????????????????????????? "()" ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `odanalyzetext' ????????????????????????????????????"&"???"|"???"!"???"("???")" ???????????????????????????????????????????????????????????????????????????????????????????????????????????? "&" ?????????????????????????????????????????????????????? "joe blow" ??? "joe & blow" ?????????????????????

- -

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1?????????????????????????????????

- -
- -

Odeum???????????????

- -

Odeum???????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `odmgr' ???Odeum???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`file' ?????????????????????`expr' ????????????URI???ID?????????`words' ???????????????`elems' ?????????????????????????????????????????????

- -
-
odmgr create name
-
????????????????????????????????????????????????
-
odmgr put [-uri str] [-title str] [-author str] [-date str] [-wmax num] [-keep] name [file]
-
??????????????????????????????????????????????????????`file' ??????????????????????????????????????????????????????????????????URI??????????????????????????????
-
odmgr out [-id] name expr
-
URI???????????????????????????????????????
-
odmgr get [-id] [-t|-h] name expr
-
URI?????????????????????????????????????????????????????????ID?????????URI??????????????????????????????????????????????????????
-
odmgr search [-max num] [-or] [-idf] [-t|-h|-n] name words...
-
????????????????????????????????????????????????????????????1????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????2????????????????????????????????????ID?????????URI??????????????????????????????????????????????????????
-
odmgr list [-t|-h] name
-
????????????????????????????????????????????????????????????????????????????????????ID?????????URI??????????????????????????????????????????????????????
-
odmgr optimize name
-
???????????????????????????????????????
-
odmgr inform name
-
??????????????????????????????????????????????????????
-
odmgr merge name elems...
-
????????????????????????????????????????????????
-
odmgr remove name
-
??????????????????????????????????????????????????????
-
odmgr break [-h|-k|-s] [file]
-
???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
odmgr version
-
QDBM??????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -uri str : ?????????URI??????????????????????????????
  • -
  • -title str : ???????????????????????????????????????
  • -
  • -author str : ????????????????????????????????????
  • -
  • -date str : ???????????????????????????????????????
  • -
  • -wmax num : ?????????????????????????????????????????????
  • -
  • -keep : ??????URI?????????????????????????????????????????????????????????
  • -
  • -id : URI?????????ID?????????????????????????????????
  • -
  • -t : ?????????????????????????????????????????????????????????
  • -
  • -h : ????????????????????????????????????????????????????????????????????????
  • -
  • -k : ????????????????????????????????????????????????
  • -
  • -s : ???????????????????????????????????????
  • -
  • -max num : ????????????????????????????????????????????????
  • -
  • -or : AND???????????????OR??????????????????
  • -
  • -idf : IDF????????????????????????????????????
  • -
  • -n : ?????????ID????????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `odtest' ???Odeum????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `odmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`dnum' ???????????????`wnum' ????????????????????????`pnum' ??????????????????????????????????????????

- -
-
odtest write [-tune ibnum idnum cbnum csiz] name dnum wnum pnum
-
??????????????????????????????????????????????????????????????????????????????????????????
-
odtest read name
-
?????????????????????????????????????????????????????????????????????
-
odtest combo name
-
???????????????????????????????????????????????????
-
odtest wicked name dnum
-
????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -tune ibnum idnum cbnum csiz : ???????????????????????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????? `odidx' ???????????????????????????????????????????????????????????????????????????Odeum??????????????????????????????????????????????????????????????????????????????????????????Web??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????HTML???????????????????????????????????????????????????US-ASCII???ISO-8859-1????????????????????????URI??????????????????????????????????????????????????????????????????`title' ??? `date' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? '_mtime' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `_score' ??????????????????????????????????????????????? ?????????????????????????????????????`name' ???????????????????????????`dir' ??????????????????????????????????????????

- -
-
odidx register [-l file] [-wmax num] [-tsuf sufs] [-hsuf sufs] name [dir]
-
???????????????????????????????????????????????????????????????????????????????????????`dir' ??????????????????????????????????????????????????????????????????????????????
-
odidx relate name
-
????????????????????????????????????????????????????????????????????????????????????????????????
-
odidx purge name
-
??????????????????????????????????????????????????????????????????????????????????????????
-
- -

????????????????????????????????????????????????

- -
    -
  • -l file : ????????????????????????????????????????????????????????????????????????????????????`-' ????????????????????????????????????????????????????????????
  • -
  • -wmax num : ??????????????????????????????????????????????????????????????????
  • -
  • -tsuf sufs : ????????????????????????????????????????????????????????????????????????????????????????????????????????? `-tsuf .txt,.text' ?????????????????????
  • -
  • -hsuf sufs : HTML????????????????????????????????????????????????????????????????????????????????? `-hsuf .html,.htm' ?????????????????????
  • -
- -

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

- -

Odeum????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `/home/mikio' ???????????????????????? `.txt' ??? `.c' ??? `.h' ????????????????????????????????????????????? `casket' ???????????????????????????????????????????????????????????????????????????????????????

- -
odidx register -tsuf ".txt,.c,.h" -hsuf "" casket /home/mikio
-
- -

????????????`unix' ????????? `posix' ????????????????????????????????????????????????8??????????????????????????????????????????????????????

- -
odmgr search -max 8 -h casket "unix posix"
-
- -

`odidx' ???????????????????????????????????????QDBM??????????????????????????????????????????CGI??????????????? `qfts.cgi' ????????????????????????????????????????????????

- -
- -

??????????????????????????????

- -

Depot?????????????????????????????????

- -

Depot??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

?????????????????????????????????????????? 48 ????????????????????????????????????????????????????????????????????????

- -
    -
  1. ????????????????????? : ??????????????? 0 ??????????????????????????????????????????????????????????????? "[DEPOT]\n\f" ??????????????????????????????????????????????????????????????? "[depot]\n\f" ?????????????????????
  2. -
  3. ????????????????????? : ??????????????? 12 ????????????????????????????????????????????????????????????10???????????????????????????????????????????????????
  4. -
  5. ???????????????????????? : ??????????????? 16 ??????????????????`int' ????????????????????????
  6. -
  7. ????????????????????? : ??????????????? 24 ??????????????????`int' ????????????????????????
  8. -
  9. ?????????????????????????????? : ??????????????? 32 ??????????????????`int' ????????????????????????
  10. -
  11. ??????????????? : ??????????????? 40 ??????????????????`int' ????????????????????????
  12. -
- -

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
    -
  1. ????????? : `int' ????????????????????????
  2. -
  3. ?????????????????????????????? : `int' ????????????????????????
  4. -
  5. ?????????????????? : `int' ????????????????????????
  6. -
  7. ??????????????? : `int' ????????????????????????
  8. -
  9. ??????????????????????????? : `int' ????????????????????????
  10. -
  11. ?????????????????? : `int' ????????????????????????
  12. -
  13. ?????????????????? : `int' ????????????????????????
  14. -
  15. ????????????????????? : ?????????????????????????????????????????????????????????????????????????????????
  16. -
  17. ?????????????????? : ??????????????????????????????????????????????????????????????????????????????
  18. -
  19. ??????????????? : ????????????????????????????????????????????????????????????????????????????????????????????????????????????
  20. -
- -

Villa?????????????????????????????????

- -

Villa??????????????????????????????Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `int' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Villa?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????BER??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????128?????????????????????????????????

- -

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
    -
  1. ?????????????????? : ??????????????????????????????
  2. -
  3. ????????????????????? : ?????????????????????????????????????????????????????????????????????????????????
  4. -
  5. ????????? : ??????????????????????????????
  6. -
  7. ??????????????? : ??????????????????????????????????????????????????????????????????????????????
      -
    1. ????????? : ??????????????????????????????
    2. -
    3. ???????????? : ????????????????????????????????????????????????????????????????????????
    4. -
  8. -
- -

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `int' ??????ID????????????????????????????????????????????????????????????Depot????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
    -
  1. ??????????????????ID : ??????????????????????????????
  2. -
  3. ??????????????????ID : ??????????????????????????????
  4. -
  5. ???????????????????????? : ???????????????????????????????????????????????????
  6. -
- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
    -
  1. ????????????????????????ID : ??????????????????????????????
  2. -
  3. ?????????????????? : ??????????????????????????????
  4. -
  5. ????????????????????? : ?????????????????????????????????????????????????????????????????????????????????
  6. -
- -

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `int' ??????ID????????????????????????????????????????????????????????????Depot??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
    -
  1. ????????????????????????ID : ??????????????????????????????
  2. -
  3. ?????????????????????????????? : ?????????????????????????????????????????????????????????
  4. -
- -

??????

- -

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

Depot???Villa?????????????????????????????????????????????????????????????????????????????????MIME???????????? `application/x-qdbm' ??????????????????????????????????????????????????? `.qdb' ?????????????????????Curia???????????????????????????????????????????????????????????????????????????????????????TAR??????????????????????????????????????????????????????????????????????????????

- -

????????????????????????????????????????????????????????? `file' ?????????????????????????????????????????????`magic' ??????????????????????????????????????????????????????

- -
0       string          [DEPOT]\n\f     QDBM, big endian
->12     string          x               \b, version=%s
->19     byte            ^1              \b, Hash
->19     byte            &1              \b, B+ tree
->19     byte            &2              \b (deflated:ZLIB)
->19     byte            &4              \b (deflated:LZO)
->19     byte            &8              \b (deflated:BZIP2)
->24     belong          x               \b, filesize=%d
->32     belong          x               \b, buckets=%d
->40     belong          x               \b, records=%d
-0       string          [depot]\n\f     QDBM, little endian
->12     string          x               \b, version=%s
->16     byte            ^1              \b, Hash
->16     byte            &1              \b, B+ tree
->16     byte            &2              \b (deflated:ZLIB)
->16     byte            &4              \b (deflated:LZO)
->16     byte            &8              \b (deflated:BZIP2)
->24     lelong          x               \b, filesize=%d
->32     lelong          x               \b, buckets=%d
->40     lelong          x               \b, records=%d
-
- -
- -

????????????

- -

QDBM???POSIX?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API??????????????????????????????????????????????????????????????????????????????????????????????????????GCC????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `Makefile' ?????????????????????????????????????????????????????????????????????????????????????????????????????????C?????????API???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
    -
  • Makefile.in : `./configure' ??????????????????`Makefile' ????????????????????????
  • -
  • myconf.h : ??????????????????????????????????????????
  • -
  • depot.h : ??????API???????????????
  • -
  • curia.h : ??????API???????????????
  • -
  • relic.h : NDBM??????API???????????????
  • -
  • hovel.h : GDBM??????API???????????????
  • -
  • cabin.h : ?????????????????????API???????????????
  • -
  • villa.h : ??????API???????????????
  • -
  • vista.h : ????????????API???????????????
  • -
  • odeum.h : ??????API???????????????
  • -
  • myconf.c : ??????????????????????????????
  • -
  • depot.c : ??????API????????????
  • -
  • curia.c : ??????API????????????
  • -
  • relic.c : NDBM??????API????????????
  • -
  • hovel.c : GDBM??????API????????????
  • -
  • cabin.c : ?????????????????????API????????????
  • -
  • villa.c : ??????API????????????
  • -
  • vista.c : ????????????API????????????
  • -
  • odeum.c : ??????API????????????
  • -
- -

`fcntl' ?????????????????????????????????????????????????????????????????????????????????????????????????????????`Makefile' ?????????????????? `CFLAGS' ???????????? `-DMYNOLOCK' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`mmap' ???????????????????????????????????????????????????`CFLAGS' ??? `-DMYNOMMAP' ???????????????????????????`mmap' ??????????????? `malloc' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`myconf.h' ??? `myconf.c' ?????????????????????????????????????????????????????????????????????????????????????????????

- -

C++??????API??????POSIX???????????????????????????????????????????????????????????????????????????????????????????????????C++???API????????????????????????Java??????API??????JNI????????????????????????????????????????????????????????????????????????????????????????????????????????????`long long' ??? `int64' ??????????????????????????????????????????????????????Perl???Ruby??????API??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -
- -

??????

- -

QDBM?????????????????????????????????????????????????????????????????????????????????????????????

- -

segmentation fault???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

- -

???????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????OS????????????????????????????????????????????????????????????

- -

1.7.13??????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????

- -
- -

????????????????????????

- -
-
Q. : QDBM???SQL???????????????????????????
-
A. : QDBM???SQL???????????????????????????QDBM???RDBMS??????????????????????????????????????????????????????????????????????????????RDBMS?????????????????????SQLite?????????????????????????????????
-
Q. : ?????????????????????GDBM???NDBM???SDBM???Berkeley DB???????????????????????????
-
A. : ???????????????????????????????????????????????????????????????API??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????100???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????DBM???DBMS????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
Q. : ????????????????????????
-
A. : QDBM???????????????????????????????????????Aho?????? `Data Structures and Algorithms'??????????????????????????????????????????????????????????????????Sedgewick??? `Algorithms in C'?????????????????????????????????C?????????????????????????????????????????????
-
Q. : ??????API???????????????????????????
-
A. : ???????????????????????????????????????????????????????????????Depot??????????????????????????????????????????????????????Curia?????????????????????????????????????????????????????????????????????????????????Villa??????????????????????????????????????????????????????Vista?????????????????????????????????????????????????????????????????????ZLIB???LZO??????????????????QDBM??????????????????????????????Vista???????????????????????????
-
Q. : ?????????????????????????????????????????????????????????????????????
-
A. : ???API??????????????????????????????????????????????????????????????????`dptsv.c' ??? `crtsv.c' ??? `vltsv.c' ???????????????????????????
-
Q. : ????????????????????????????????????????????????????????????
-
A. : ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????CGI??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????CGI??????????????????SIGPIPE???SIGTERM??????????????????????????????????????????????????????????????????????????????
-
Q. : QDBM?????????????????????????????????????????????????????????
-
A. : QDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Villa?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????
-
Q. : Depot???Curia??????????????????????????????????????????????????????????????????
-
A. : ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????32????????????????????????????????????
-
Q. : Villa???????????????????????????????????????????????????????????????
-
A. : ???????????????????????????????????????????????????????????????`lrecmax' ??? `nidxmax' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????RAM??????????????????????????????`lcnum' ??? `ncnum' ????????????????????????????????????????????????ZLIB???LZO???BZIP2???????????????????????????`lrecmax' ??????????????????????????????????????????????????????
-
Q. : Villa???????????????????????????ZLIB???LZO???BZIP2???????????????????????????
-
A. : ??????????????????????????????BZIP2???????????????????????????????????????LZO??????ZLIB?????????????????????????????????????????????????????????????????????ZLIB???????????????????????????????????????????????????????????????????????????LZO???????????????????????????????????????????????????BZIP2???????????????????????????????????????????????????????????????LZO????????????????????????LZO?????????????????????GNU GPL???????????????????????????????????????
-
Q. : ???????????????????????????????????????
-
A. : ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????DP_OSPARSE?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
Q. : ??????Depot???Curia??????????????????????????????????????????????????????
-
A. : ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Cabin???????????????????????????????????????????????????
-
Q. : ??????????????????????????????????????????????????????????????????
-
A. : ????????????????????????????????????????????????RAM???????????????????????????????????????????????????????????????I/O?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Linux?????????????????????EXT2???????????????????????????EXT3??? `writeback' ??????????????????????????????????????????ReiserFS???????????????????????????EXT3?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
Q. : `gcc' ??????????????? `cc' ????????????????????????????????????
-
A. : `LTmakefile' ????????????????????????
-
Q. : Visual C++????????????????????????????????????
-
A. : ????????????`Makefile' ??????????????? `VCmakefile' ??????????????????
-
Q. : ??????QDBM???????????????????????????????????????
-
A. : PHP???Scheme???Gauche??????OCaml????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
Q. : ???QDBM???????????????????????????????????????
-
A. : ???QDBM?????????Quick Database Manager???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
Q. : ???API?????????????????????????????????????????????????????????????????????
-
A. : 5?????????????????????????????????????????????????????????????????????????????????????????????depot????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????curia?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????relic????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????hovel?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????cabin??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????villa???????????????? ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????vista?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????odeum??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-
- -
- -

???????????????

- -

QDBM?????????????????????????????????????????????????????????Free Software Foundation???????????????GNU Lesser General Public License??????????????????2.1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????????????????????????????????????????

- -

QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????GNU Lesser General Public License????????????????????????

- -

???????????????QDBM????????????GNU Lesser General Public License???????????????????????????????????????????????????`COPYING' ??????????????????????????????????????????????????????Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ???????????????????????????

- -

QDBM??????????????????????????????????????????????????????????????????`mikio at users.sourceforge.net' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`http://lists.sourceforge.net/lists/listinfo/qdbm-users' ????????????????????????

- -
- - - - - - Copied: box/trunk/qdbm/spex-ja.html (from rev 2716, box/trunk/qdbm/spex-ja.html) =================================================================== --- box/trunk/qdbm/spex-ja.html (rev 0) +++ box/trunk/qdbm/spex-ja.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,4348 @@ + + + + + + + + + + + + + + + +Specifications of QDBM Version 1 (Japanese) + + + + + +

QDBM?????????????????????????????????

+ +
Copyright (C) 2000-2007 Mikio Hirabayashi
+
Last Update: Thu, 26 Oct 2006 15:00:20 +0900
+ + +
+ +

??????

+ +
    +
  1. ??????
  2. +
  3. ??????
  4. +
  5. ??????????????????
  6. +
  7. Depot: ??????API
  8. +
  9. Depot???????????????
  10. +
  11. Curia: ??????API
  12. +
  13. Curia???????????????
  14. +
  15. Relic: NDBM??????API
  16. +
  17. Relic???????????????
  18. +
  19. Hovel: GDBM??????API
  20. +
  21. Hovel???????????????
  22. +
  23. Cabin: ?????????????????????API
  24. +
  25. Cabin???????????????
  26. +
  27. Villa: ??????API
  28. +
  29. Villa???????????????
  30. +
  31. Odeum: ??????API
  32. +
  33. Odeum???????????????
  34. +
  35. ??????????????????????????????
  36. +
  37. ????????????
  38. +
  39. ??????
  40. +
  41. ????????????????????????
  42. +
  43. ???????????????
  44. +
+ +
+ +

??????

+ +

QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+????????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????UNIX??????????????????????????????DBM?????????????????????????????????????????????NDBM???GDBM??????????????????????????????QDBM???DBM???????????????????????????????????????????????????????????????

+ +

B+????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+???????????????????????????????????????????????????????????????????????????

+ +

QDBM???C??????????????????C???C++???Java???Perl?????????Ruby???API???????????????????????????QDBM???POSIX?????????API?????????????????????????????????????????????????????????QDBM???GNU Lesser General Public License???????????????????????????????????????????????????

+ +
+ +

??????

+ +

???????????????????????????????????????????????????

+ +

QDBM???GDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API???????????????????????????????????????????????????????????????????????????????????????GDBM???????????????????????????DBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

QDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? O(1) ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? O(log n) ?????????????????????

+ +

QDBM??????????????????????????????RAM??????????????????????????????????????????????????????????????????????????????????????????RAM????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `read' ????????????RAM????????????????????????????????????`mmap' ????????????RAM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????56.7%??????????????????????????????36.8%???2?????????21.3%???4?????????11.5%???8?????????6.0%??????????????????????????????????????????2???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????100????????????????????????????????????????????????50????????????????????????????????????????????????????????????????????????????????????4????????????????????????????????????2M????????????RAM?????????????????????100?????????????????????????????????????????????????????????

+ +

QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

????????????DBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????DBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

??????????????????????????????????????????2GB????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1TB???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????RAID-0????????????????????????????????????????????????????????????????????????????????????????????????NFS???????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

?????????B+??????????????????????????????

+ +

B+?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? O(log n) ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? O(1) ????????????

+ +

B+???????????????????????????????????????????????????????????????????????????????????????????????????B+????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????B+?????????????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1????????????????????????

+ +

B+??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

?????????????????????????????????????????????ZLIB???LZO???BZIP2??????????????????QDBM????????????????????????B+?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Lempel-Ziv??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????25%?????????????????????????????????????????????????????????????????????I/O?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

?????????????????????????????????????????????

+ +

QDBM???API??????????????????????????????ANSI C?????????????????? `FILE' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????API???????????????????????????????????????????????????????????????????????????????????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

NDBM?????????GDBM???????????????API?????????????????????NDBM???GDBM??????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????#include??????????????????????????????????????????????????????????????????????????????????????????NDBM???GDBM????????????????????????????????????????????????QDBM?????????????????????????????????

+ +

??????????????????????????????????????????????????????????????????????????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????C????????????Perl???Ruby?????????????????????????????????????????????????????????????????????????????????????????????

+ +

B+??????????????????????????????API?????????????????????????????????API?????????API????????????????????????API???????????????????????????????????????API?????????API?????????API????????????????????????????????????????????????????????????????????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

QDBM???C?????????????????????C++???Java???Perl?????????Ruby???API??????????????????C?????????API???????????????API?????????API???NDBM??????API???GDBM??????API????????????????????????API?????????API???????????????API???????????????????????????API???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????C++???API?????????API?????????API?????????API???????????????????????????????????????C++????????????????????????????????????????????????????????????Java???API???Java Native Interface??????????????????API?????????API?????????API?????????????????????????????????Perl???API???XS????????????????????????API?????????API?????????API?????????????????????????????????Ruby???API???Ruby?????????????????????????????????API?????????API?????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????CGI???????????? ????????????????????????

+ +

??????????????????

+ +

QDBM???ANSI C???C89????????????????????????ANSI C?????????POSIX??????????????????API?????????????????????????????????????????????????????????????????????UNIX?????????????????????????????????OS???????????????????????????????????????C?????????API???????????????????????????????????????????????????????????????????????????????????????????????????

+ +
    +
  • Linux (2.2, 2.4, 2.6) (IA32, IA64, AMD64, PA-RISC, Alpha, PowerPC, M68000, ARM)
  • +
  • FreeBSD (4.9, 5.0, 5.1, 5.2, 5.3) (IA32, IA64, SPARC, Alpha)
  • +
  • NetBSD (1.6) (IA32)
  • +
  • OpenBSD (3.4) (IA32)
  • +
  • SunOS (5.6, 5.7, 5.8, 5.9, 5.10) (IA32, SPARC)
  • +
  • HP-UX (11.11, 11.23) (IA64, PA-RISC)
  • +
  • AIX (5.2) (POWER)
  • +
  • Windows (2000, XP) (IA32, IA64, AMD64) (Cygwin, MinGW, Visual C++)
  • +
  • Mac OS X (10.2, 10.3, 10.4) (IA32, PowerPC)
  • +
  • Tru64 (5.1) (Alpha)
  • +
  • RISC OS (5.03) (ARM)
  • +
+ +

QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+ +

??????????????????

+ +

??????

+ +

????????????????????????????????????QDBM????????????????????????????????????GCC??????????????????2.8????????? `make' ?????????????????????

+ +

QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????????

+ +

Linux???BSD???SunOS?????????????????????????????????

+ +

?????????????????????????????????

+ +
./configure
+
+ +

????????????????????????????????????

+ +
make
+
+ +

???????????????????????????????????????????????????

+ +
make check
+
+ +

?????????????????????????????????????????????????????? `root' ?????????????????????

+ +
make install
+
+ +

GNU Libtool???????????????

+ +

????????????????????????????????????????????????????????????????????????????????????????????????GNU Libtool??????????????????1.5???????????????????????????

+ +

?????????????????????????????????

+ +
./configure
+
+ +

????????????????????????????????????

+ +
make -f LTmakefile
+
+ +

???????????????????????????????????????????????????

+ +
make -f LTmakefile check
+
+ +

?????????????????????????????????????????????????????? `root' ?????????????????????

+ +
make -f LTmakefile install
+
+ +

??????

+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `/usr/local/man/man1' ??? `/usr/local/man/man3' ?????????????????????????????? `/usr/local/share/qdbm' ??????`pkg-config' ??????????????????????????? `/usr/local/lib/pkgconfig' ?????????????????????????????????

+ +
/usr/local/include/depot.h
+/usr/local/include/curia.h
+/usr/local/include/relic.h
+/usr/local/include/hovel.h
+/usr/local/include/cabin.h
+/usr/local/include/villa.h
+/usr/local/include/vista.h
+/usr/local/include/odeum.h
+/usr/local/lib/libqdbm.a
+/usr/local/lib/libqdbm.so.14.13.0
+/usr/local/lib/libqdbm.so.14
+/usr/local/lib/libqdbm.so
+/usr/local/bin/dpmgr
+/usr/local/bin/dptest
+/usr/local/bin/dptsv
+/usr/local/bin/crmgr
+/usr/local/bin/crtest
+/usr/local/bin/crtsv
+/usr/local/bin/rlmgr
+/usr/local/bin/rltest
+/usr/local/bin/hvmgr
+/usr/local/bin/hvtest
+/usr/local/bin/cbtest
+/usr/local/bin/cbcodec
+/usr/local/bin/vlmgr
+/usr/local/bin/vltest
+/usr/local/bin/vltsv
+/usr/local/bin/odmgr
+/usr/local/bin/odtest
+/usr/local/bin/odidx
+/usr/local/bin/qmttest
+
+ +

`libqdbm.so' ?????????????????????????????????????????????????????????????????????????????????????????????????????? `/usr/local/lib' ?????????????????????????????????????????? `LD_LIBRARY_PATH' ?????????????????????????????????????????????????????????????????????

+ +

QDBM??????????????????????????????????????????`./configure' ???????????????????????????????????????????????????????????????????????? `root' ?????????????????????

+ +
make uninstall
+
+ +

QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

C???????????????API???CGI????????????????????????????????????????????????????????????????????????C++???API????????????????????????????????????????????????????????????????????? `plus' ????????? `xspex-ja.html' ????????????????????????JAVA???API????????????????????????????????????????????????????????????????????? `java' ????????? `jspex-ja.html' ????????????????????????Perl???API????????????????????????????????????????????????????????????????????? `perl' ????????? `plspex-ja.html' ????????????????????????Ruby???API????????????????????????????????????????????????????????????????????? `ruby' ????????? `rbspex-ja.html' ????????????????????????CGI???????????????????????????????????????????????????????????????????????????????????? `cgi' ????????? `cgispex.html' ????????????????????????

+ +

RPM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????RPM?????????????????????????????????????????????????????? `root' ???????????????????????????

+ +
rpm -ivh qdbm-1.x.x-x.i386.rpm
+
+ +

Windows?????????

+ +

Windows???Cygwin??????????????????????????????????????????????????????????????????

+ +

?????????????????????????????????

+ +
./configure
+
+ +

????????????????????????????????????

+ +
make win
+
+ +

???????????????????????????????????????????????????

+ +
make check-win
+
+ +

????????????????????????????????????????????????????????????????????????????????????????????? `make uninstall-win' ????????????

+ +
make install-win
+
+ +

Windows?????????????????????????????? `libqdbm.a' ?????????????????????????????????????????? `libqdbm.dll.a' ??????????????????????????????????????? `libqdbm.so' ???????????????????????????????????????????????????????????? `qdbm.dll' ?????????????????????`qdbm.dll' ??? `/usr/local/bin' ?????????????????????????????????

+ +

Cygwin?????????MinGW????????????????????????????????????`make win' ??????????????? `make mingw' ???????????????Cygwin???UNIX????????????????????????????????????????????????????????????????????????????????? `cygwin1.dll' ?????????????????????????????????GNU GPL???????????????????????????MinGW????????????Win32??????????????????DLL?????????????????????????????????????????????????????????

+ +

Visual C++????????????????????????????????????`VCmakefile' ?????????????????????????????????????????????????????????????????????????????????`nmake /f VCMakefile' ???????????????????????????????????? `qdbm.dll' ?????????????????????????????????????????????????????????????????? `/MD' ????????? `/MDd' ??????????????????????????? `msvcrt.dll' ?????????????????????????????????????????????????????????????????? `VCmakefile' ?????????????????????

+ +

Mac OS X?????????

+ +

Mac OS X???Darwin??????????????????????????????????????????????????????????????????

+ +

?????????????????????????????????

+ +
./configure
+
+ +

????????????????????????????????????

+ +
make mac
+
+ +

???????????????????????????????????????????????????

+ +
make check-mac
+
+ +

????????????????????????????????????????????????????????????????????????????????????????????? `make uninstall-mac' ????????????

+ +
make install-mac
+
+ +

Mac OS X?????????`libqdbm.so' ?????????????????? `libqdbm.dylib' ?????????????????????????????????????????????????????????????????????????????? `DYLD_LIBRARY_PATH' ??????????????????????????????

+ +

HP-UX?????????

+ +

HP-UX???????????????????????????????????????????????????????????????

+ +

?????????????????????????????????

+ +
./configure
+
+ +

????????????????????????????????????

+ +
make hpux
+
+ +

???????????????????????????????????????????????????

+ +
make check-hpux
+
+ +

????????????????????????????????????????????????????????????????????????????????????????????? `make uninstall-hpux' ????????????

+ +
make install-hpux
+
+ +

HP-UX?????????`libqdbm.so' ?????????????????? `libqdbm.sl' ??????????????????????????????????????????????????????????????????????????? `SHLIB_PATH' ??????????????????????????????

+ +

RISC OS?????????

+ +

RISC OS???????????????????????????????????????????????????????????????

+ +

??????????????????????????????????????????????????????????????????????????? `cc' ??????????????????????????????????????????`gcc' ????????????????????? `CC=gcc' ???????????????????????????????????????

+ +
make -f RISCmakefile
+
+ +

??????????????????????????????`libqdbm' ??????????????????????????????????????? `dpmgr' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`depot.h' ?????????????????????????????????????????????????????????????????????????????????

+ +

????????????

+ +

`./configure' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
    +
  • --enable-debug : ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
  • +
  • --enable-devel : ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
  • +
  • --enable-stable : ????????????????????????????????????????????????????????????????????????????????????????????????????????????
  • +
  • --enable-pthread : POSIX?????????????????????????????????????????????????????????????????????????????????????????????
  • +
  • --disable-lock : ????????????????????????????????????????????????????????????????????????????????????
  • +
  • --disable-mmap : ?????????????????????????????????????????????????????????????????????????????????
  • +
  • --enable-zlib : ZLIB?????????B+????????????????????????????????????????????????????????????????????????
  • +
  • --enable-lzo : LZO?????????B+????????????????????????????????????????????????????????????????????????
  • +
  • --enable-bzip : BZIP2?????????B+????????????????????????????????????????????????????????????????????????
  • +
  • --enable-iconv : ICONV????????????????????????????????????????????????????????????????????????
  • +
+ +

?????????QDBM???????????????????????????????????? `libqdbm.*' ????????????????????????????????????????????????????????????????????????????????????????????????????????????POSIX??????????????????????????????????????? `libpthread.*' ???????????????ZLIB??????????????????????????? `libz.*' ???????????????LZO??????????????????????????? `liblzo2.*' ???????????????BZIP2??????????????????????????? `libbz2.*' ???????????????ICONV??????????????????????????? `libiconv.*' ?????????????????????????????????

+ +

LZO?????????????????????GNU GPL????????????`liblzo2.*' ?????????????????????????????????????????????GNU GPL???????????????????????????????????????????????????

+ +
+ +

Depot: ??????API

+ +

??????

+ +

Depot???QDBM?????????API????????????QDBM???????????????????????????????????????????????????????????????Depot??????????????????????????????????????????API???Depot???????????????????????????????????????????????????QDBM???API?????????Depot?????????????????????????????????

+ +

Depot????????????????????????`depot.h' ??? `stdlib.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+
#include <depot.h>
+
#include <stdlib.h>
+
+ +

Depot??????????????????????????????????????????`DEPOT' ?????????????????????????????????????????????????????????????????????`stdio.h' ???????????????????????????????????????????????? `FILE' ?????????????????????????????????????????????????????????????????????????????? `dpopen' ?????????????????? `dpclose' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dpclose' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

API

+ +

???????????? `dpversion' ????????????????????????????????????????????????

+ +
+
extern const char *dpversion;
+
????????????????????????????????????????????????????????????
+
+ +

???????????? `dpecode' ???????????????????????????????????????????????????????????????????????????????????????????????? `depot.h' ????????????????????????

+ +
+
extern int dpecode;
+
??????????????????????????? `DP_ENOERR' ???????????????????????????????????????`DP_EFATAL'???`DP_EMODE'???`DP_EBROKEN'???`DP_EKEEP'???`DP_ENOITEM'???`DP_EALLOC'???`DP_EMAP'???`DP_EOPEN'???`DP_ECLOSE'???`DP_ETRUNC'???`DP_ESYNC'???`DP_ESTAT'???`DP_ESEEK'???`DP_EREAD'???`DP_EWRITE'???`DP_ELOCK'???`DP_EUNLINK'???`DP_EMKDIR'???`DP_ERMDIR' ????????? `DP_EMISC' ????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????? `dperrmsg' ???????????????

+ +
+
const char *dperrmsg(int ecode);
+
`ecode' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `dpopen' ???????????????

+ +
+
DEPOT *dpopen(const char *name, int omode, int bnum);
+
`name' ????????????????????????????????????????????????????????????`omode' ?????????????????????????????????`DP_OREADER' ??????????????????`DP_OWRITER' ???????????????????????????`DP_OWRITER' ????????????`DP_OCREAT' ????????? `DP_OTRUNC' ??????????????????????????????????????????????????????`DP_OCREAT' ????????????????????????????????????????????????????????????????????????`DP_OTRUNC' ?????????????????????????????????????????????????????????????????????`DP_OREADER' ??? `DP_OWRITER' ???????????? `DP_ONOLCK' ????????? `DP_OLCKNB' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`DP_OCREAT' ??? `DP_OSPARSE' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`bnum' ????????????????????????????????????????????????? ??????????????0 ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`DP_ONOLCK' ??????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `dpclose' ???????????????

+ +
+
int dpclose(DEPOT *depot);
+
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `dpput' ???????????????

+ +
+
int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+
`depot' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`dmode' ???????????????????????????????????????????????????????????????????????????`DP_DOVER' ????????????????????????????????????????????????`DP_DKEEP' ?????????????????????????????????????????????????????????`DP_DCAT' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `dpout' ???????????????

+ +
+
int dpout(DEPOT *depot, const char *kbuf, int ksiz);
+
`depot' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `dpget' ???????????????

+ +
+
char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp);
+
`depot' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `mall oc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `dpgetwb' ???????????????

+ +
+
int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf);
+
`depot' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`vbuf' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ??????????????????????????????????????????????????? -1 ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `dpvsiz' ???????????????

+ +
+
int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz);
+
`depot' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????????????????`dpget' ?????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `dpiterinit' ???????????????

+ +
+
int dpiterinit(DEPOT *depot);
+
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????????????????????????????? `dpiternext' ???????????????

+ +
+
char *dpiternext(DEPOT *depot, int *sp);
+
`depot' ???????????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????
+
+ +

???????????????????????????????????????????????????????????????????????? `dpsetalign' ???????????????

+ +
+
int dpsetalign(DEPOT *depot, int align);
+
`depot' ???????????????????????????????????????????????????????????????????????????`align' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`vsiz' ???????????????????????????????????????????????????????????? `(vsiz / pow(2, abs(align) - 1))' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `dpsetfbpsiz' ???????????????

+ +
+
int dpsetfbpsiz(DEPOT *depot, int size);
+
`depot' ???????????????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????16?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????? `dpsync' ???????????????

+ +
+
int dpsync(DEPOT *depot);
+
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `dpoptimize' ???????????????

+ +
+
int dpoptimize(DEPOT *depot, int bnum);
+
`depot' ???????????????????????????????????????????????????????????????????????????`bnum' ???????????????????????????????????????????????????????????????0 ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `dpname' ???????????????

+ +
+
char *dpname(DEPOT *depot);
+
`depot' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `dpfsiz' ???????????????

+ +
+
int dpfsiz(DEPOT *depot);
+
`depot' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

??????????????????????????????????????????????????????????????????????????? `dpbnum' ???????????????

+ +
+
int dpbnum(DEPOT *depot);
+
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `dpbusenum' ???????????????

+ +
+
int dpbusenum(DEPOT *depot);
+
`depot' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ?????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `dprnum' ???????????????

+ +
+
int dprnum(DEPOT *depot);
+
`depot' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????? `dpwritable' ???????????????

+ +
+
int dpwritable(DEPOT *depot);
+
`depot' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `dpfatalerror' ???????????????

+ +
+
int dpfatalerror(DEPOT *depot);
+
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????inode?????????????????????????????? `dpinode' ???????????????

+ +
+
int dpinode(DEPOT *depot);
+
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????inode??????????????????
+
+ +

??????????????????????????????????????????????????????????????? `dpmtime' ???????????????

+ +
+
time_t dpmtime(DEPOT *depot);
+
`depot' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `dpfdesc' ???????????????

+ +
+
int dpfdesc(DEPOT *depot);
+
`depot' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `dpremove' ???????????????

+ +
+
int dpremove(const char *name);
+
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `dprepair' ???????????????

+ +
+
int dprepair(const char *name);
+
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????? `dpexportdb' ???????????????

+ +
+
int dpexportdb(DEPOT *depot, const char *name);
+
`depot' ???????????????????????????????????????????????????`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????????????????? `dpimportdb' ???????????????

+ +
+
int dpimportdb(DEPOT *depot, const char *name);
+
`depot' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `dpsnaffle' ???????????????

+ +
+
char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
+
`name' ????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????1?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????? `dpinnerhash' ????????????

+ +
+
int dpinnerhash(const char *kbuf, int ksiz);
+
`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????????????????????????????31??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????? `dpouterhash' ????????????

+ +
+
int dpouterhash(const char *kbuf, int ksiz);
+
`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????????????????????????????31??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `dpprimenum' ???????????????

+ +
+
int dpprimenum(int num);
+
`num' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NAME     "mikio"
+#define NUMBER   "000-1234-5678"
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  DEPOT *depot;
+  char *val;
+
+  /* ??????????????????????????? */
+  if(!(depot = dpopen(DBNAME, DP_OWRITER | DP_OCREAT, -1))){
+    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* ??????????????????????????? */
+  if(!dpput(depot, NAME, -1, NUMBER, -1, DP_DOVER)){
+    fprintf(stderr, "dpput: %s\n", dperrmsg(dpecode));
+  }
+
+  /* ??????????????????????????? */
+  if(!(val = dpget(depot, NAME, -1, 0, -1, NULL))){
+    fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
+  } else {
+    printf("Name: %s\n", NAME);
+    printf("Number: %s\n", val);
+    free(val);
+  }
+
+  /* ?????????????????????????????? */
+  if(!dpclose(depot)){
+    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  DEPOT *depot;
+  char *key, *val;
+
+  /* ??????????????????????????? */
+  if(!(depot = dpopen(DBNAME, DP_OREADER, -1))){
+    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* ????????????????????????????????? */
+  if(!dpiterinit(depot)){
+    fprintf(stderr, "dpiterinit: %s\n", dperrmsg(dpecode));
+  }
+
+  /* ?????????????????????????????? */
+  while((key = dpiternext(depot, NULL)) != NULL){
+    if(!(val = dpget(depot, key, -1, 0, -1, NULL))){
+      fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
+      free(key);
+      break;
+    }
+    printf("%s: %s\n", key, val);
+    free(val);
+    free(key);
+  }
+
+  /* ?????????????????????????????? */
+  if(!dpclose(depot)){
+    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

??????

+ +

Depot???????????????????????????????????????????????????????????????????????? `libqdbm.a' ????????? `libqdbm.so' ????????????????????????????????????????????????????????????`sample.c' ?????? `sample' ?????????????????????????????????????????????????????????

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

POSIX??????????????????????????????QDBM??????????????????????????????????????? `dpecode' ???????????????????????????????????????????????????????????????Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

+ +
+ +

Depot???????????????

+ +

Depot???????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `dpmgr' ???Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`key' ???????????????????????????`val' ???????????????????????????????????????

+ +
+
dpmgr create [-s] [-bnum num] name
+
????????????????????????????????????????????????
+
dpmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-na] name key val
+
?????????????????????????????????????????????????????????
+
dpmgr out [-kx|-ki] name key
+
???????????????????????????????????????????????????
+
dpmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-n] name key
+
???????????????????????????????????????????????????????????????????????????
+
dpmgr list [-nl] [-k|-v] [-ox] name
+
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
dpmgr optimize [-bnum num] [-na] name
+
???????????????????????????????????????
+
dpmgr inform [-nl] name
+
??????????????????????????????????????????????????????
+
dpmgr remove name
+
????????????????????????????????????????????????
+
dpmgr repair name
+
?????????????????????????????????????????????????????????
+
dpmgr exportdb name file
+
??????????????????????????????????????????????????????????????????????????????????????????
+
dpmgr importdb [-bnum num] name file
+
????????????????????????????????????????????????????????????????????????????????????
+
dpmgr snaffle [-kx|-ki] [-ox] [-n] name key
+
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
dpmgr version
+
QDBM????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -s : ???????????????????????????????????????
  • +
  • -bnum num : ????????????????????????????????? `num' ??????????????????
  • +
  • -kx : 2????????????16?????????????????????????????????????????? `key' ????????????
  • +
  • -ki : 10???????????????????????????????????? `key' ????????????
  • +
  • -vx : 2????????????16?????????????????????????????????????????? `val' ????????????
  • +
  • -vi : 10???????????????????????????????????? `val' ????????????
  • +
  • -vf : ????????? `val' ?????????????????????????????????????????????????????????
  • +
  • -keep : ????????????????????????????????????????????????????????????????????????????????????
  • +
  • -cat : ???????????????????????????????????????????????????????????????????????????
  • +
  • -na : ??????????????????????????????????????????
  • +
  • -nl : ??????????????????????????????????????????????????????????????????
  • +
  • -start : ????????????????????????????????????????????????????????????????????????
  • +
  • -max : ??????????????????????????????????????????????????????????????????
  • +
  • -ox : 2????????????16??????????????????????????????????????????????????????????????????
  • +
  • -n : ??????????????????????????????????????????????????????????????????????????????
  • +
  • -k : ??????????????????????????????
  • +
  • -v : ???????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `dptest' ???Depot??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dpmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`rnum' ?????????????????????`bnum' ????????????????????????????????????`pnum' ??????????????????????????????`align' ?????????????????????????????????????????????`fbpsiz' ???????????????????????????????????????????????????????????????

+ +
+
dptest write [-s] name rnum bnum
+
`00000001'???`00000002' ????????????????????????8??????????????????????????????8??????????????????????????????????????????????????????????????????
+
dptest read [-wb] name
+
???????????????????????????????????????????????????????????????????????????
+
dptest rcat [-c] name rnum bnum pnum align fbpsiz
+
????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
dptest combo name
+
???????????????????????????????????????????????????
+
dptest wicked [-c] name rnum
+
????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -s : ???????????????????????????????????????
  • +
  • -wb : ?????? `dpget' ????????????????????? `dpgetwb' ???????????????
  • +
  • -c : Cabin???????????????????????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `dptsv' ???????????????????????????????????????????????????????????????TSV???????????????Depot?????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????DBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ??????????????????????????????????????????`export' ????????????????????????TSV????????????????????????????????????????????????????????????????????????????????????????????????????????????`-bnum' ???????????????????????? `num' ???????????????????????????????????????????????????`import' ????????????????????????TSV???????????????????????????????????????????????????

+ +
+
dptsv import [-bnum num] [-bin] name
+
TSV??????????????????????????????????????????????????????????????????
+
dptsv export [-bin] name
+
?????????????????????????????????????????????TSV????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -bnum num : ????????????????????????????????? `num' ??????????????????
  • +
  • -bin : Base64?????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +

Depot???????????????????????????????????????????????????????????????????????????????????????????????????????????? `/etc/password' ????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
cat /etc/passwd | tr ':' '\t' | dptsv import casket
+
+ +

????????????`mikio' ??????????????????????????????????????????????????????????????????????????????

+ +
dpmgr get casket mikio
+
+ +

?????????????????????????????????????????????Depot???API???????????????????????????????????????????????????

+ +
+ +

Curia: ??????API

+ +

??????

+ +

Curia???QDBM?????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Depot???????????????????????????????????????????????????????????????????????????Curia??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`depot' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4??????10?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `depot' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`casket' ???????????????????????????????????????????????????????????????3??????????????????`casket/depot'???`casket/0001/depot'???`casket/0002/depot'???`casket/0003/depot' ???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Curia???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `lob' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????

+ +

Curia????????????????????????`depot.h' ??? `curia.h' ??? `stdlib.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+
#include <depot.h>
+
#include <curia.h>
+
#include <stdlib.h>
+
+ +

Curia??????????????????????????????????????????`CURIA' ?????????????????????????????????????????????????????????????????????`stdio.h' ???????????????????????????????????????????????? `FILE' ?????????????????????????????????????????????????????????????????????????????? `cropen' ?????????????????? `crclose' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `crclose' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Curia??????Depot???????????????????????? `dpecode' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dperrmsg' ???????????????

+ +

API

+ +

??????????????????????????????????????????????????????????????? `cropen' ???????????????

+ +
+
CURIA *cropen(const char *name, int omode, int bnum, int dnum);
+
`name' ??????????????????????????????????????????????????????????????????`omode' ?????????????????????????????????`CR_OREADER' ??????????????????`CR_OWRITER' ???????????????????????????`CR_OWRITER' ????????????`CR_OCREAT' ????????? `CR_OTRUNC' ??????????????????????????????????????????????????????`CR_OCREAT' ????????????????????????????????????????????????????????????????????????`CR_OTRUNC' ?????????????????????????????????????????????????????????????????????`CR_OREADER' ??? `CR_OWRITER' ???????????? `CR_ONOLCK' ????????? `CR_OLCKNB' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`CR_OCREAT' ??? `CR_OSPARSE' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`bnum' ??????????????????????????????????????????? ????????????????????0 ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4?????????????????????????????????`dnum' ??????????????????????????????????????????????????????0 ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 512 ??????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????????????????????????????????`CR_ONOLCK' ??????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `crclose' ???????????????

+ +
+
int crclose(CURIA *curia);
+
`curia' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `crput' ???????????????

+ +
+
int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+
`curia' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`dmode' ???????????????????????????????????????????????????????????????????????????`CR_DOVER' ????????????????????????????????????????????????`CR_DKEEP' ?????????????????????????????????????????????????????????`DP_DCAT' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `crout' ???????????????

+ +
+
int crout(CURIA *curia, const char *kbuf, int ksiz);
+
`curia' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `crget' ???????????????

+ +
+
char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
+
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `mall oc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `crgetwb' ???????????????

+ +
+
int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf);
+
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`vbuf' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ??????????????????????????????????????????????????? -1 ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `crvsiz' ???????????????

+ +
+
int crvsiz(CURIA *curia, const char *kbuf, int ksiz);
+
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????????????????`crget' ?????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `criterinit' ???????????????

+ +
+
int criterinit(CURIA *curia);
+
`curia' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????????????????????????????? `criternext' ???????????????

+ +
+
char *criternext(CURIA *curia, int *sp);
+
`curia' ???????????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????
+
+ +

???????????????????????????????????????????????????????????????????????? `crsetalign' ???????????????

+ +
+
int crsetalign(CURIA *curia, int align);
+
`curia' ???????????????????????????????????????????????????????????????????????????`align' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`vsiz' ???????????????????????????????????????????????????????????? `(vsiz / pow(2, abs(align) - 1))' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `crsetfbpsiz' ???????????????

+ +
+
int crsetfbpsiz(CURIA *curia, int size);
+
`curia' ???????????????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????16?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????? `crsync' ???????????????

+ +
+
int crsync(CURIA *curia);
+
`curia' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `croptimize' ???????????????

+ +
+
int croptimize(CURIA *curia, int bnum);
+
`curia' ???????????????????????????????????????????????????????????????????????????`bnum' ???????????????????????????????????????????????????????????????0 ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `crname' ???????????????

+ +
+
char *crname(CURIA *curia);
+
`curia' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????? `crfsiz' ???????????????

+ +
+
int crfsiz(CURIA *curia);
+
`curia' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????????????????2GB?????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????? `crfsizd' ???????????????

+ +
+
double crfsizd(CURIA *curia);
+
`curia' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `crbnum' ???????????????

+ +
+
int crbnum(CURIA *curia);
+
`curia' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

??????????????????????????????????????????????????????????????????????????????????????????????????? `crbusenum' ???????????????

+ +
+
int crbusenum(CURIA *curia);
+
`curia' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ?????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `crrnum' ???????????????

+ +
+
int crrnum(CURIA *curia);
+
`curia' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????? `crwritable' ???????????????

+ +
+
int crwritable(CURIA *curia);
+
`curia' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `crfatalerror' ???????????????

+ +
+
int crfatalerror(CURIA *curia);
+
`curia' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????inode?????????????????????????????? `crinode' ???????????????

+ +
+
int crinode(CURIA *curia);
+
`curia' ??????????????????????????????????????????????????????????????????????????????????????????????????????inode??????????????????
+
+ +

??????????????????????????????????????????????????????????????? `crmtime' ???????????????

+ +
+
time_t crmtime(CURIA *curia);
+
`curia' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `crremove' ???????????????

+ +
+
int crremove(const char *name);
+
`name' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????? `crrepair' ???????????????

+ +
+
int crrepair(const char *name);
+
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????? `crexportdb' ???????????????

+ +
+
int crexportdb(CURIA *curia, const char *name);
+
`curia' ???????????????????????????????????????????????????`name' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????????????????? `crimportdb' ???????????????

+ +
+
int crimportdb(CURIA *curia, const char *name);
+
`curia' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `crsnaffle' ???????????????

+ +
+
char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
+
`name' ??????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????????????????? `crputlob' ???????????????

+ +
+
int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+
`curia' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`dmode' ???????????????????????????????????????????????????????????????????????????`CR_DOVER' ????????????????????????????????????????????????`CR_DKEEP' ?????????????????????????????????????????????????????????`DP_DCAT' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????????????????? `croutlob' ???????????????

+ +
+
int croutlob(CURIA *curia, const char *kbuf, int ksiz);
+
`curia' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????? `crgetlob' ???????????????

+ +
+
char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
+
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`start' ???????????????????????????????????????????????????????????????????????????????????????`max' ????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????? `start' ????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `mall oc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `crgetlobfd' ???????????????

+ +
+
int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz);
+
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ??????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????? `open' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????O_RDWR????????????????????????????????????????????????????????????O_RDONLY???????????????????????????????????????????????????????????? `close' ??????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `crvsizlob' ???????????????

+ +
+
int crvsizlob(CURIA *curia, const char *kbuf, int ksiz);
+
`curia' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????????????????`crgetlob' ?????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????????????????????????????? `crrnumlob' ???????????????

+ +
+
int crrnumlob(CURIA *curia);
+
`curia' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

?????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <curia.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NAME     "mikio"
+#define NUMBER   "000-1234-5678"
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  CURIA *curia;
+  char *val;
+
+  /* ??????????????????????????? */
+  if(!(curia = cropen(DBNAME, CR_OWRITER | CR_OCREAT, -1, -1))){
+    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* ??????????????????????????? */
+  if(!crput(curia, NAME, -1, NUMBER, -1, CR_DOVER)){
+    fprintf(stderr, "crput: %s\n", dperrmsg(dpecode));
+  }
+
+  /* ??????????????????????????? */
+  if(!(val = crget(curia, NAME, -1, 0, -1, NULL))){
+    fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
+  } else {
+    printf("Name: %s\n", NAME);
+    printf("Number: %s\n", val);
+    free(val);
+  }
+
+  /* ?????????????????????????????? */
+  if(!crclose(curia)){
+    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <curia.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  CURIA *curia;
+  char *key, *val;
+
+  /* ??????????????????????????? */
+  if(!(curia = cropen(DBNAME, CR_OREADER, -1, -1))){
+    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* ????????????????????????????????? */
+  if(!criterinit(curia)){
+    fprintf(stderr, "criterinit: %s\n", dperrmsg(dpecode));
+  }
+
+  /* ?????????????????????????????? */
+  while((key = criternext(curia, NULL)) != NULL){
+    if(!(val = crget(curia, key, -1, 0, -1, NULL))){
+      fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
+      free(key);
+      break;
+    }
+    printf("%s: %s\n", key, val);
+    free(val);
+    free(key);
+  }
+
+  /* ?????????????????????????????? */
+  if(!crclose(curia)){
+    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

??????

+ +

Curia????????????????????????????????????????????????????????????Depot????????????????????????????????????

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

POSIX??????????????????????????????QDBM??????????????????????????????????????? `dpecode' ???????????????????????????????????????????????????????????????Curia?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

+ +
+ +

Curia???????????????

+ +

Curia???????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `crmgr' ???Curia?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`key' ???????????????????????????`val' ???????????????????????????????????????

+ +
+
crmgr create [-s] [-bnum num] [-dnum num] name
+
??????????????????????????????????????????????????????
+
crmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] name key val
+
?????????????????????????????????????????????????????????
+
crmgr out [-kx|-ki] [-lob] name key
+
???????????????????????????????????????????????????
+
crmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-lob] [-n] name key
+
???????????????????????????????????????????????????????????????????????????
+
crmgr list [-nl] [-k|-v] [-ox] name
+
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
crmgr optimize [-bnum num] [-na] name
+
???????????????????????????????????????
+
crmgr inform [-nl] name
+
??????????????????????????????????????????????????????
+
crmgr remove name
+
??????????????????????????????????????????????????????
+
crmgr repair name
+
???????????????????????????????????????????????????????????????
+
crmgr exportdb name dir
+
??????????????????????????????????????????????????????????????????????????????????????????
+
crmgr importdb [-bnum num] [-dnum num] name dir
+
????????????????????????????????????????????????????????????????????????????????????
+
crmgr snaffle [-kx|-ki] [-ox] [-n] name key
+
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
crmgr version
+
QDBM????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -s : ???????????????????????????????????????
  • +
  • -bnum num : ????????????????????????????????? `num' ??????????????????
  • +
  • -dnum num : ????????????????????????????????????????????? `num' ??????????????????
  • +
  • -kx : 2????????????16?????????????????????????????????????????? `key' ????????????
  • +
  • -ki : 10???????????????????????????????????? `key' ????????????
  • +
  • -vx : 2????????????16?????????????????????????????????????????? `val' ????????????
  • +
  • -vi : 10???????????????????????????????????? `val' ????????????
  • +
  • -vf : ????????? `val' ?????????????????????????????????????????????????????????
  • +
  • -keep : ????????????????????????????????????????????????????????????????????????????????????
  • +
  • -cat : ???????????????????????????????????????????????????????????????????????????
  • +
  • -na : ??????????????????????????????????????????
  • +
  • -nl : ??????????????????????????????????????????????????????????????????
  • +
  • -start : ????????????????????????????????????????????????????????????????????????
  • +
  • -max : ??????????????????????????????????????????????????????????????????
  • +
  • -ox : 2????????????16??????????????????????????????????????????????????????????????????
  • +
  • -lob : ???????????????????????????????????????
  • +
  • -n : ??????????????????????????????????????????????????????????????????????????????
  • +
  • -k : ??????????????????????????????
  • +
  • -v : ???????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `crtest' ???Curia?????????????????????????????????????????????????????????????????????`crtest' ?????????????????????????????????????????????????????????????????? `crmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`rnum' ?????????????????????`bnum' ????????????????????????????????????`dnum' ????????????????????????????????????????????????`pnum' ??????????????????????????????`align' ?????????????????????????????????????????????`fbpsiz' ???????????????????????????????????????????????????????????????

+ +
+
crtest write [-s] [-lob] name rnum bnum dnum
+
`00000001'???`00000002' ????????????????????????8??????????????????????????????8??????????????????????????????????????????????????????????????????
+
crtest read [-wb] [-lob] name
+
???????????????????????????????????????????????????????????????????????????
+
crtest rcat [-c] name rnum bnum dnum pnum align fbpsiz
+
????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
crtest combo name
+
???????????????????????????????????????????????????
+
crtest wicked [-c] name rnum
+
????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -s : ???????????????????????????????????????
  • +
  • -lob : ???????????????????????????????????????
  • +
  • -wb : ?????? `crget' ????????????????????? `crgetwb' ???????????????
  • +
  • -c : Cabin???????????????????????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `crtsv' ???????????????????????????????????????????????????????????????TSV???????????????Curia?????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????DBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ??????????????????????????????????????????`export' ????????????????????????TSV????????????????????????????????????????????????????????????????????????????????????????????????????????????`-bnum' ???????????????????????? `num' ???????????????????????????????????????????????????`-dnum' ???????????????????????? `num' ???????????????????????????????????????????????????`import' ????????????????????????TSV???????????????????????????????????????????????????

+ +
+
crtsv import [-bnum num] [-dnum num] [-bin] name
+
TSV??????????????????????????????????????????????????????????????????
+
crtsv export [-bin] name
+
?????????????????????????????????????????????TSV????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -bnum num : ????????????????????????????????? `num' ??????????????????
  • +
  • -dnum num : ????????????????????????????????????????????? `num' ??????????????????
  • +
  • -bin : Base64?????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +

Curia???????????????????????????????????????????????????????????????????????????????????????????????????????????? `/etc/password' ????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
cat /etc/passwd | tr ':' '\t' | crtsv import casket
+
+ +

????????????`mikio' ??????????????????????????????????????????????????????????????????????????????

+ +
crmgr get casket mikio
+
+ +

?????????????????????????????????????????????Curia???API???????????????????????????????????????????????????

+ +
+ +

Relic: NDBM??????API

+ +

??????

+ +

Relic??????NDBM???????????????API???????????????????????????Depot???????????????NDBM???API??????????????????????????????Relic????????????NDBM??????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????? `ndbm.h' ?????? `relic.h' ????????????????????????????????????????????????????????? `-lndbm' ?????? `-lqdbm' ??????????????????????????????

+ +

??????????????????NDBM???????????????????????????????????????????????????????????????????????????????????????????????? `.dir' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `.pag' ?????????????????????????????????????????????????????????????????????????????????????????????Relic????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Relic????????????????????????NDBM?????????????????????????????????????????????????????????????????????????????????????????????NDBM????????????????????????????????????????????????Relic?????????????????????????????????

+ +

Relic????????????????????????`relic.h' ??? `stdlib.h' ??? `sys/types.h' ??? `sys/stat.h' ??? `fcntl.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+
#include <relic.h>
+
#include <stdlib.h>
+
#include <sys/types.h>
+
#include <sys/stat.h>
+
#include <fcntl.h>
+
+ +

Relic??????????????????????????????????????????`DBM' ????????????????????????????????????????????????????????????????????????????????? `dbm_open' ?????????????????? `dbm_close' ??????????????????????????????????????????????????????????????????????????????????????????

+ +

API

+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `datum' ??????????????????????????????

+ +
+
typedef struct { void *dptr; size_t dsize; } datum;
+
`dptr' ????????????????????????????????????????????????`dsize' ??????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `dbm_open' ???????????????

+ +
+
DBM *dbm_open(char *name, int flags, int mode);
+
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`flags' ??? `open' ??????????????????????????????????????????`O_WRONLY' ??? `O_RDWR' ?????????????????????????????????????????? `O_CREAT' ??? `O_TRUNC' ???????????????????????????`mode' ??? `open' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `dbm_close' ???????????????

+ +
+
void dbm_close(DBM *db);
+
`db' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `dbm_store' ???????????????

+ +
+
int dbm_store(DBM *db, datum key, datum content, int flags);
+
`db' ???????????????????????????????????????????????????`key' ???????????????????????????????????????`content' ????????????????????????????????????`frags' ??? `DBM_INSERT' ??????????????????????????????????????????????????????`DBM_REPLACE' ??????????????????????????????????????????????????? 0 ???????????????????????????????????? 1 ??????????????????????????????????????? -1 ????????????
+
+ +

?????????????????????????????????????????? `dbm_delete' ???????????????

+ +
+
int dbm_delete(DBM *db, datum key);
+
`db' ???????????????????????????????????????????????????`key' ??????????????????????????????????????????????????????????????? 0 ??????????????????????????? -1 ????????????
+
+ +

?????????????????????????????????????????? `dbm_fetch' ???????????????

+ +
+
datum dbm_fetch(DBM *db, datum key);
+
`db' ???????????????????????????????????????????????????`key' ????????????????????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????????????? `dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????`dptr' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `dbm_firstkey' ???????????????

+ +
+
datum dbm_firstkey(DBM *db);
+
`db' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????`dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????`dptr' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dbm_nextkey' ??????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????? `dbm_nextkey' ???????????????

+ +
+
datum dbm_nextkey(DBM *db);
+
`db' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????`dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????`dptr' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dbm_firstkey' ??????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `dbm_error' ???????????????

+ +
+
int dbm_error(DBM *db);
+
`db' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????? `dbm_clearerr' ?????????????????????

+ +
+
int dbm_clearerr(DBM *db);
+
`db' ??????????????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????? `dbm_rdonly' ???????????????

+ +
+
int dbm_rdonly(DBM *db);
+
`db' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `dbm_dirfno' ???????????????

+ +
+
int dbm_dirfno(DBM *db);
+
`db' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????? `dbm_pagfno' ???????????????

+ +
+
int dbm_pagfno(DBM *db);
+
`db' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <relic.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+
+#define NAME     "mikio"
+#define NUMBER   "000-1234-5678"
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  DBM *db;
+  datum key, val;
+  int i;
+
+  /* ??????????????????????????? */
+  if(!(db = dbm_open(DBNAME, O_RDWR | O_CREAT, 00644))){
+    perror("dbm_open");
+    return 1;
+  }
+
+  /* ??????????????????????????? */
+  key.dptr = NAME;
+  key.dsize = strlen(NAME);
+  val.dptr = NUMBER;
+  val.dsize = strlen(NUMBER);
+
+  /* ??????????????????????????? */
+  if(dbm_store(db, key, val, DBM_REPLACE) != 0){
+    perror("dbm_store");
+  }
+
+  /* ??????????????????????????? */
+  val = dbm_fetch(db, key);
+  if(val.dptr){
+    printf("Name: %s\n", NAME);
+    printf("Number: ");
+    for(i = 0; i < val.dsize; i++){
+      putchar(((char *)val.dptr)[i]);
+    }
+    putchar('\n');
+  } else {
+    perror("dbm_fetch");
+  }
+
+  /* ?????????????????????????????? */
+  dbm_close(db);
+
+  return 0;
+}
+
+ +

??????

+ +

Relic????????????????????????????????????????????????????????????Depot???????????????????????????????????????????????????????????????????????? `-lndbm' ???????????? `-lqdbm' ????????????

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

?????????????????????????????????????????????????????????????????????????????????Relic????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

+ +
+ +

Relic???????????????

+ +

Relic???????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `rlmgr' ???Relic?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`key' ???????????????????????????`val' ???????????????????????????????????????

+ +
+
rlmgr create name
+
????????????????????????????????????????????????
+
rlmgr store [-kx] [-vx|-vf] [-insert] name key val
+
?????????????????????????????????????????????????????????
+
rlmgr delete [-kx] name key
+
???????????????????????????????????????????????????
+
rlmgr fetch [-kx] [-ox] [-n] name key
+
???????????????????????????????????????????????????????????????????????????
+
rlmgr list [-ox] name
+
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -kx : 2????????????16?????????????????????????????????????????? `key' ????????????
  • +
  • -vx : 2????????????16?????????????????????????????????????????? `val' ????????????
  • +
  • -vf : ????????? `val' ?????????????????????????????????????????????????????????
  • +
  • -insert : ????????????????????????????????????????????????????????????????????????????????????
  • +
  • -ox : 2????????????16??????????????????????????????????????????????????????????????????
  • +
  • -n : ??????????????????????????????????????????????????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +

???????????? `rltest' ???Relic??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `rlmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`rnum' ????????????????????????????????????

+ +
+
rltest write name rnum
+
`00000001'???`00000002' ????????????????????????8??????????????????????????????8??????????????????????????????????????????????????????????????????
+
rltest read name rnum
+
?????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +
+ +

Hovel: GDBM??????API

+ +

??????

+ +

Hovel??????GDBM???????????????API???????????????????????????Depot?????????Curia???????????????GDBM???API??????????????????????????????Hovel????????????GDBM??????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????? `gdbm.h' ?????? `hovel.h' ????????????????????????????????????????????????????????? `-lgdbm' ?????? `-lqdbm' ?????????????????????????????????????????????????????????GDBM????????????????????????????????????????????????Hovel?????????????????????????????????

+ +

Hovel????????????????????????`hovel.h' ??? `stdlib.h' ??? `sys/types.h' ??? `sys/stat.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+
#include <hovel.h>
+
#include <stdlib.h>
+
#include <sys/types.h>
+
#include <sys/stat.h>
+
+ +

Hovel??????????????????????????????????????????`GDBM_FILE' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `gdbm_open' ?????????????????? `gdbm_close' ??????????????????????????????????????????????????????????????????????????????????????????Hovel????????????Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `gdbm_open2' ??????????????????????????????Curia?????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

API

+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `datum' ??????????????????????????????

+ +
+
typedef struct { char *dptr; size_t dsize; } datum;
+
`dptr' ????????????????????????????????????????????????`dsize' ??????????????????????????????????????????
+
+ +

???????????? `gdbm_version' ????????????????????????????????????????????????

+ +
+
extern char *gdbm_version;
+
????????????????????????????????????????????????????????????
+
+ +

???????????? `gdbm_errno' ???????????????????????????????????????????????????????????????????????????????????????????????? `hovel.h' ????????????????????????

+ +
+
extern gdbm_error gdbm_errno;
+
??????????????????????????? `GDBM_NO_ERROR' ???????????????????????????????????????`GDBM_MALLOC_ERROR'???`GDBM_BLOCK_SIZE_ERROR'???`GDBM_FILE_OPEN_ERROR'???`GDBM_FILE_WRITE_ERROR'???`GDBM_FILE_SEEK_ERROR'???`GDBM_FILE_READ_ERROR'???`GDBM_BAD_MAGIC_NUMBER'???`GDBM_EMPTY_DATABASE'???`GDBM_CANT_BE_READER'???`GDBM_CANT_BE_WRITER'???`GDBM_READER_CANT_DELETE'???`GDBM_READER_CANT_STORE'???`GDBM_READER_CANT_REORGANIZE'???`GDBM_UNKNOWN_UPDATE'???`GDBM_ITEM_NOT_FOUND'???`GDBM_REORGANIZE_FAILED'???`GDBM_CANNOT_REPLACE'???`GDBM_ILLEGAL_DATA'???`GDBM_OPT_ALREADY_SET' ????????? `GDBM_OPT_ILLEGAL' ????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????? `gdbm_strerror' ???????????????

+ +
+
char *gdbm_strerror(gdbm_error gdbmerrno);
+
`gdbmerrno' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

GDBM????????????????????????????????????????????????????????????????????? `gdbm_open' ???????????????

+ +
+
GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, void (*fatal_func)(void));
+
`name' ????????????????????????????????????????????????`block_size' ?????????????????????`read_write' ?????????????????????????????????`GDBM_READER' ??????????????????`GDBM_WRITER' ??? `GDBM_WRCREAT' ??? `GDBM_NEWDB' ???????????????????????????`GDBM_WRCREAT' ??????????????????????????????????????????????????????????????????`GDBM_NEWDB' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????`GDBM_SYNC' ??? `GDBM_NOLOCK' ??? `GDBM_LOCKNB' ??? `GDBM_FAST' ??? `GDBM_SPARSE' ??????????????????????????????????????????????????????`GDBM_SYNC' ?????????????????????????????????????????????????????????????????????`GDBM_NOLOCK' ?????????????????????????????????????????????????????????????????????`GDBM_LOCKNB' ?????????????????????????????????????????????`GDBM_FAST' ?????????????????????`GDBM_SPARSE' ???QDBM??????????????????????????????????????????????????????????????????????????????`mode' ??? `open' ??????????????????????????? ???????????????????????????????????????????????????`fatal_func' ?????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????
+
+ +

QDBM????????????????????????????????????????????????????????????????????? `gdbm_open2' ???????????????

+ +
+
GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align);
+
`name' ????????????????????????????????????????????????`read_write' ?????????????????????????????????`GDBM_READER' ??????????????????`GDBM_WRITER' ??? `GDBM_WRCREAT' ??? `GDBM_NEWDB' ???????????????????????????`GDBM_WRCREAT' ??????????????????????????????????????????????????????????????????`GDBM_NEWDB' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????`GDBM_SYNC' ??? `GDBM_NOLOCK' ??? `GDBM_LOCKNB' ??? `GDBM_FAST' ??? `GDBM_SPARSE' ??????????????????????????????????????????????????????`GDBM_SYNC' ?????????????????????????????????????????????????????????????????????`GDBM_NOLOCK' ?????????????????????????????????????????????????????????????????????`GDBM_LOCKNB' ?????????????????????????????????????????????`GDBM_FAST' ?????????????????????`GDBM_SPARSE' ???QDBM??????????????????????????????????????????????????????????????????????????????`mode' ??? `open' ????????????????????? `mkdir' ??????????????????????????????? ????????????????????????????????????????????????????????????????????`bnum' ???????????????????????????????????????????????????????????????0 ????????????????????????????????????????????????`dnum' ??????????????????????????????????????????????????????0 ???????????????????????????????????????Depot????????????????????????????????????????????????????????????Curia???????????????????????????`align' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????Depot????????????Curia?????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `gdbm_close' ???????????????

+ +
+
void gdbm_close(GDBM_FILE dbf);
+
`dbf' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `gdbm_store' ???????????????

+ +
+
int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag);
+
`dbf' ???????????????????????????????????????????????????????????????????????????`key' ???????????????????????????????????????`content' ????????????????????????????????????`frags' ??? `GDBM_INSERT' ??????????????????????????????????????????????????????`GDBM_REPLACE' ??????????????????????????????????????????????????? 0 ??????????????????????????? 1 ?????????????????????????????? -1 ????????????
+
+ +

?????????????????????????????????????????? `gdbm_delete' ???????????????

+ +
+
int gdbm_delete(GDBM_FILE dbf, datum key);
+
`dbf' ???????????????????????????????????????????????????????????????????????????`key' ??????????????????????????????????????????????????????????????? 0 ?????????????????? -1 ????????????
+
+ +

?????????????????????????????????????????? `gdbm_fetch' ???????????????

+ +
+
datum gdbm_fetch(GDBM_FILE dbf, datum key);
+
`dbf' ???????????????????????????????????????????????????`key' ????????????????????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????`dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????????????????????????? `dptr' ?????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `gdbm_exists' ???????????????

+ +
+
int gdbm_exists(GDBM_FILE dbf, datum key);
+
`dbf' ???????????????????????????????????????????????????`key' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `gdbm_firstkey' ???????????????

+ +
+
datum gdbm_firstkey(GDBM_FILE dbf);
+
`dbf' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????`dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????????????????????????? `dptr' ?????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????????????????????????? gdbm_nextkey ???????????????

+ +
+
datum gdbm_nextkey(GDBM_FILE dbf, datum key);
+
`dbf' ???????????????????????????????????????????????????`key' ?????????????????????????????????????????????????????????????????????????????????????????? `dptr' ???????????????????????????`dsize' ??????????????????????????????????????????????????? `dptr' ????????? `NULL' ????????????????????????????????? `dptr' ?????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????? `gdbm_sync' ???????????????

+ +
+
void gdbm_sync(GDBM_FILE dbf);
+
`dbf' ???????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `gdbm_reorganize' ???????????????

+ +
+
int gdbm_reorganize(GDBM_FILE dbf);
+
`dbf' ??????????????????????????????????????????????????????????????????????????????????????????????????? 0 ??????????????????????????? -1 ????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `gdbm_fdesc' ???????????????

+ +
+
int gdbm_fdesc(GDBM_FILE dbf);
+
`dbf' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

?????? `gdbm_setopt' ?????????????????????

+ +
+
int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size);
+
`dbf' ???????????????????????????????????????????????????`option' ?????????????????????`value' ?????????????????????`size' ????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <hovel.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+
+#define NAME     "mikio"
+#define NUMBER   "000-1234-5678"
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  GDBM_FILE dbf;
+  datum key, val;
+  int i;
+
+  /* ??????????????????????????? */
+  if(!(dbf = gdbm_open(DBNAME, 0, GDBM_WRCREAT, 00644, NULL))){
+    fprintf(stderr, "gdbm_open: %s\n", gdbm_strerror(gdbm_errno));
+    return 1;
+  }
+
+  /* ??????????????????????????? */
+  key.dptr = NAME;
+  key.dsize = strlen(NAME);
+  val.dptr = NUMBER;
+  val.dsize = strlen(NUMBER);
+
+  /* ??????????????????????????? */
+  if(gdbm_store(dbf, key, val, GDBM_REPLACE) != 0){
+    fprintf(stderr, "gdbm_store: %s\n", gdbm_strerror(gdbm_errno));
+  }
+
+  /* ??????????????????????????? */
+  val = gdbm_fetch(dbf, key);
+  if(val.dptr){
+    printf("Name: %s\n", NAME);
+    printf("Number: ");
+    for(i = 0; i < val.dsize; i++){
+      putchar(val.dptr[i]);
+    }
+    putchar('\n');
+    free(val.dptr);
+  } else {
+    fprintf(stderr, "gdbm_fetch: %s\n", gdbm_strerror(gdbm_errno));
+  }
+
+  /* ?????????????????????????????? */
+  gdbm_close(dbf);
+
+  return 0;
+}
+
+ +

??????

+ +

Hovel????????????????????????????????????????????????????????????Depot???????????????????????????????????????????????????????????????????????? `-lgdbm' ???????????? `-lqdbm' ????????????

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

POSIX??????????????????????????????QDBM??????????????????????????????????????? `gdbm_errno' ???????????????????????????????????????????????????????????????Hovel?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

+ +
+ +

Hovel???????????????

+ +

Hovel???????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `hvmgr' ???Hovel??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`key' ???????????????????????????`val' ???????????????????????????????????????

+ +
+
hvmgr [-qdbm bnum dnum] [-s] create name
+
????????????????????????????????????????????????
+
hvmgr store [-qdbm] [-kx] [-vx|-vf] [-insert] name key val
+
?????????????????????????????????????????????????????????
+
hvmgr delete [-qdbm] [-kx] name key
+
???????????????????????????????????????????????????
+
hvmgr fetch [-qdbm] [-kx] [-ox] [-n] name key
+
???????????????????????????????????????????????????????????????????????????
+
hvmgr list [-qdbm] [-ox] name
+
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
hvmgr optimize [-qdbm] name
+
???????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -qdbm [bnum dnum] : `gdbm_open2' ?????????????????????????????????`bnum' ??? `dnum' ????????????????????????????????????????????????????????????????????????????????????
  • +
  • -s : ???????????????????????????????????????
  • +
  • -kx : 2????????????16?????????????????????????????????????????? `key' ????????????
  • +
  • -vx : 2????????????16?????????????????????????????????????????? `val' ????????????
  • +
  • -vf : ????????? `val' ?????????????????????????????????????????????????????????
  • +
  • -insert : ????????????????????????????????????????????????????????????????????????????????????
  • +
  • -ox : 2????????????16??????????????????????????????????????????????????????????????????
  • +
  • -n : ??????????????????????????????????????????????????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +

???????????? `hvtest' ???Hovel??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `hvmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`rnum' ????????????????????????????????????

+ +
+
hvtest write [-qdbm] [-s] name rnum
+
`00000001'???`00000002' ????????????????????????8??????????????????????????????8??????????????????????????????????????????????????????????????????
+
hvtest read [-qdbm] name rnum
+
?????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -qdbm : `gdbm_open2' ????????????Curia???????????????????????????
  • +
  • -s : ???????????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +
+ +

Cabin: ?????????????????????API

+ +

??????

+ +

Cabin??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API????????????MIME???CSV???XML????????????????????????????????????????????????????????????????????????????????????

+ +

Cabin????????????????????????`cabin.h' ??? `stdlib.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+
#include <cabin.h>
+
#include <stdlib.h>
+
+ +

?????????????????????????????????????????????`CBDATUM' ?????????????????????????????????????????????????????????????????????????????????????????? `cbdatumopen' ?????????????????? `cbdatumclose' ?????????????????????????????????????????????`CBLIST' ?????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ?????????????????? `cblistclose' ?????????????????????????????????????????????`CBMAP' ?????????????????????????????????????????????????????????????????????????????????????????? `cbmapopen' ?????????????????? `cbmapclose' ???????????????????????????????????????????????? `CBHEAP' ??????????????????????????????????????????????????????????????????????????????????????? `cbheapopen' ?????????????????? `cbheapclose' ????????????????????????????????????????????????????????????????????????????????????????????? + +

+ +

API

+ +

???????????? `cbfatalfunc' ????????????????????????????????????????????????????????????????????????????????????

+ +
+
extern void (*cbfatalfunc)(const char *message);
+
?????????????????????????????????????????????????????????????????????????????? `NULL' ????????????`NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbmalloc' ???????????????

+ +
+
void *cbmalloc(size_t size);
+
`size' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `cbrealloc' ???????????????

+ +
+
void *cbrealloc(void *ptr, size_t size);
+
`ptr' ?????????????????????????????????????????????`size' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `remalloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbmemdup' ???????????????

+ +
+
char *cbmemdup(const char *ptr, int size);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbfree' ???????????????

+ +
+
void cbfree(void *ptr);
+
`ptr' ????????????????????????????????????????????????`NULL' ????????????????????????????????????????????? `free' ????????????????????????????????????`malloc' ?????????????????????????????????????????????????????????????????????????????????QDBM????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbglobalgc' ???????????????

+ +
+
void cbglobalgc(void *ptr, void (*func)(void *));
+
`ptr' ?????????????????????????????????????????????????????????????????????`func' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`main' ?????????????????????????????? `exit' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `cbggcsweep' ???????????????

+ +
+
void cbggcsweep(void);
+
???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `cbvmemavail' ???????????????

+ +
+
int cbvmemavail(size_t size);
+
`size' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `cbisort' ???????????????

+ +
+
void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
`base' ??????????????????????????????????????????`nmemb' ???????????????????????????????????????`size' ??????????????????????????????????????????`compar' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `cbssort' ???????????????

+ +
+
void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
`base' ??????????????????????????????????????????`nmemb' ???????????????????????????????????????`size' ??????????????????????????????????????????`compar' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `cbhsort' ???????????????

+ +
+
void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
`base' ??????????????????????????????????????????`nmemb' ???????????????????????????????????????`size' ??????????????????????????????????????????`compar' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????? `cbqsort' ???????????????

+ +
+
void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
`base' ??????????????????????????????????????????`nmemb' ???????????????????????????????????????`size' ??????????????????????????????????????????`compar' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????????????????? `cbstricmp' ???????????????

+ +
+
int cbstricmp(const char *astr, const char *bstr);
+
`astr' ?????????????????????????????????????????????????????????`bstr' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ????????????ASCII????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `cbstrfwmatch' ???????????????

+ +
+
int cbstrfwmatch(const char *str, const char *key);
+
`str' ?????????????????????????????????????????????????????????`key' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbstrfwimatch' ???????????????

+ +
+
int cbstrfwimatch(const char *str, const char *key);
+
`str' ?????????????????????????????????????????????????????????`key' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ASCII????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `cbstrbwmatch' ???????????????

+ +
+
int cbstrbwmatch(const char *str, const char *key);
+
`str' ?????????????????????????????????????????????????????????`key' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbstrbwimatch' ???????????????

+ +
+
int cbstrbwimatch(const char *str, const char *key);
+
`str' ?????????????????????????????????????????????????????????`key' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ASCII????????????????????????????????????????????????????????????????????????????????????
+
+ +

KMP??????????????????????????????????????????????????????????????????????????? `cbstrstrkmp' ???????????????

+ +
+
char *cbstrstrkmp(const char *haystack, const char *needle);
+
`haystack' ????????????????????????????????????????????????`needle' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????? `strstr' ???????????????????????????
+
+ +

BM??????????????????????????????????????????????????????????????????????????? `cbstrstrbm' ???????????????

+ +
+
char *cbstrstrbm(const char *haystack, const char *needle);
+
`haystack' ????????????????????????????????????????????????`needle' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????? `strstr' ???????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `cbstrtoupper' ???????????????

+ +
+
char *cbstrtoupper(char *str);
+
`str' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `cbstrtolower' ???????????????

+ +
+
char *cbstrtolower(char *str);
+
`str' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????? `cbstrtrim' ???????????????

+ +
+
char *cbstrtrim(char *str);
+
`str' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `cbstrsqzcpc' ???????????????

+ +
+
char *cbstrsqzspc(char *str);
+
`str' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

UTF-8??????????????????????????????????????????????????????????????? `cbstrcountutf' ???????????????

+ +
+
int cbstrcountutf(const char *str);
+
`str' ???UTF-8???????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

UTF-8???????????????????????????????????????????????????????????? `cbstrcututf' ???????????????

+ +
+
char *cbstrcututf(char *str, int num);
+
`str' ???UTF-8????????????????????????????????????????????????`num' ???????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbdatumopen' ???????????????

+ +
+
CBDATUM *cbdatumopen(const char *ptr, int size);
+
`ptr' ???????????????????????????????????????????????????????????????`NULL' ???????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ???????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????? `cbdatumdup' ???????????????

+ +
+
CBDATUM *cbdatumdup(const CBDATUM *datum);
+
`datum' ????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbdatumclose' ???????????????

+ +
+
void cbdatumclose(CBDATUM *datum);
+
`datum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `cbdatumcat' ???????????????

+ +
+
void cbdatumcat(CBDATUM *datum, const char *ptr, int size);
+
`datum' ??????????????????????????????????????????`ptr' ?????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????
+
+ +

???????????????????????????????????????????????????????????? `cbdatumptr' ???????????????

+ +
+
const char *cbdatumptr(const CBDATUM *datum);
+
`datum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `cbdatumsize' ???????????????

+ +
+
int cbdatumsize(const CBDATUM *datum);
+
`datum' ????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `cbdatumsetsize' ???????????????

+ +
+
void cbdatumsetsize(CBDATUM *datum, int size);
+
`datum' ??????????????????????????????????????????`size' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbdatumprintf' ???????????????

+ +
+
void cbdatumprintf(CBDATUM *datum, const char *format, ...);
+
`format' ???printf??????????????????????????????????????????????????? `%' ??? `s'???`d'???`o'???`u'???`x'???`X'???`c'???`e'???`E'???`f'???`g'???`G'???`@'???`?'???`:'???`%' ?????????????????????????????????????????????`@' ??? `s' ??????????????????????????????XML??????????????????????????????????????????`?' ??? `s' ??????????????????????????????URL??????????????????????????????????????????`:' ??? `s' ??????????????????????????????UTF-8????????????MIME????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `cbdatumtomalloc' ???????????????

+ +
+
char *cbdatumtomalloc(CBDATUM *datum, int *sp);
+
`datum' ??????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cblistopen' ???????????????

+ +
+
CBLIST *cblistopen(void);
+
?????????????????????????????????????????????
+
+ +

??????????????????????????????????????? `cblistdup' ???????????????

+ +
+
CBLIST *cblistdup(const CBLIST *list);
+
`list' ????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cblistclose' ???????????????

+ +
+
void cblistclose(CBLIST *list);
+
`list' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `cblistnum' ???????????????

+ +
+
int cblistnum(const CBLIST *list);
+
`list' ??????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????? `cblistval' ???????????????

+ +
+
const char *cblistval(const CBLIST *list, int index, int *sp);
+
`list' ??????????????????????????????????????????`index' ????????????????????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????`index' ?????????????????????????????????????????? `NULL' ????????????
+
+ +

?????????????????????????????????????????????????????? `cblistpush' ???????????????

+ +
+
void cblistpush(CBLIST *list, const char *ptr, int size);
+
`list' ??????????????????????????????????????????`ptr' ??????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????
+
+ +

????????????????????????????????????????????????????????? `cblistpop' ???????????????

+ +
+
char *cblistpop(CBLIST *list, int *sp);
+
`list' ??????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????? `NULL' ????????????
+
+ +

?????????????????????????????????????????????????????? `cblistunshift' ???????????????

+ +
+
void cblistunshift(CBLIST *list, const char *ptr, int size);
+
`list' ??????????????????????????????????????????`ptr' ??????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????
+
+ +

????????????????????????????????????????????????????????? `cblistshift' ???????????????

+ +
+
char *cblistshift(CBLIST *list, int *sp);
+
`list' ??????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????? `NULL' ????????????
+
+ +

????????????????????????????????????????????????????????????????????? `cblistinsert' ???????????????

+ +
+
void cblistinsert(CBLIST *list, int index, const char *ptr, int size);
+
`list' ??????????????????????????????????????????`index' ????????????????????????????????????????????????????????????`ptr' ??????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `cblistremove' ???????????????

+ +
+
char *cblistremove(CBLIST *list, int index, int *sp);
+
`list' ??????????????????????????????????????????`index' ????????????????????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????`index' ????????????????????????????????????????????????????????????????????? `NULL' ????????????
+
+ +

??????????????????????????????????????????????????????????????????????????? `cblistover' ???????????????

+ +
+
void cblistover(CBLIST *list, int index, const char *ptr, int size);
+
`list' ??????????????????????????????????????????`index' ????????????????????????????????????????????????????????????`ptr' ???????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`index' ???????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `cblistsort' ???????????????

+ +
+
void cblistsort(CBLIST *list);
+
`list' ????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `cblistlsearch' ???????????????

+ +
+
int cblistlsearch(const CBLIST *list, const char *ptr, int size);
+
`list' ??????????????????????????????????????????`ptr' ????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ?????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `cblistbsearch' ???????????????

+ +
+
int cblistbsearch(const CBLIST *list, const char *ptr, int size);
+
`list' ????????????????????????????????????????????????????????????????????????????????????????????????????????????`ptr' ????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ?????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `cblistdump' ???????????????

+ +
+
char *cblistdump(const CBLIST *list, int *sp);
+
`list' ??????????????????????????????????????????`sp' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

????????????????????????????????????????????????????????? `cblistload' ???????????????

+ +
+
CBLIST *cblistload(const char *ptr, int size);
+
`ptr' ??????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbmapopen' ???????????????

+ +
+
CBMAP *cbmapopen(void);
+
?????????????????????????????????????????????
+
+ +

??????????????????????????????????????? `cbmapdup' ???????????????

+ +
+
CBMAP *cbmapdup(CBMAP *map);
+
`map' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbmapclose' ???????????????

+ +
+
void cbmapclose(CBMAP *map);
+
`map' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `cbmapput' ???????????????

+ +
+
int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over);
+
`map' ??????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`over' ????????????????????????????????????????????????????????????????????????`over' ????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `cbmapputcat' ???????????????

+ +
+
void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz);
+
`map' ??????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `cbmapout' ???????????????

+ +
+
int cbmapout(CBMAP *map, const char *kbuf, int ksiz);
+
`map' ??????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `cbmapget' ???????????????

+ +
+
const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp);
+
`map' ??????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `cbmapmove' ???????????????

+ +
+
int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head);
+
`map' ??????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`head' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `cbmapiterinit' ???????????????

+ +
+
void cbmapiterinit(CBMAP *map);
+
`map' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `cbmapiternext' ???????????????

+ +
+
const char *cbmapiternext(CBMAP *map, int *sp);
+
`map' ??????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????`cbmapiterval' ???????????????

+ +
+
const char *cbmapiterval(const char *kbuf, int *sp);
+
`kbuf' ??????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbmaprnum' ???????????????

+ +
+
int cbmaprnum(const CBMAP *map);
+
`map' ??????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????? `cbmapkeys' ???????????????

+ +
+
CBLIST *cbmapkeys(CBMAP *map);
+
`map' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????? `cbmapvals' ???????????????

+ +
+
CBLIST *cbmapvals(CBMAP *map);
+
`map' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `cbmapdump' ???????????????

+ +
+
char *cbmapdump(const CBMAP *map, int *sp);
+
`map' ??????????????????????????????????????????`sp' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

????????????????????????????????????????????????????????? `cbmapload' ???????????????

+ +
+
CBMAP *cbmapload(const char *ptr, int size);
+
`ptr' ??????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `cbmaploadone' ???????????????

+ +
+
char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp);
+
`ptr' ??????????????????????????????????????????????????????`size' ?????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbheapopen' ???????????????

+ +
+
CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *));
+
`size' ?????????????????????????????????????????????????????????`max' ?????????????????????????????????????????????????????????????????????`compar' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ???????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbheapdup' ???????????????

+ +
+
CBHEAP *cbheapdup(CBHEAP *heap);
+
`heap' ????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbheapclose' ???????????????

+ +
+
void cbheapclose(CBHEAP *heap);
+
`heap' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `cbheapnum' ???????????????

+ +
+
int cbheapnum(CBHEAP *heap);
+
`heap' ????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `cbheapinsert' ???????????????

+ +
+
int cbheapinsert(CBHEAP *heap, const void *ptr);
+
`heap' ??????????????????????????????????????????`ptr' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `cbheapget' ???????????????

+ +
+
void *cbheapval(CBHEAP *heap, int index);
+
`heap' ??????????????????????????????????????????`index' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`index' ?????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `cbheaptomalloc' ???????????????

+ +
+
void *cbheaptomalloc(CBHEAP *heap, int *np);
+
`heap' ??????????????????????????????????????????`np' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????? `cbsprintf' ???????????????

+ +
+
char *cbsprintf(const char *format, ...);
+
`format' ???printf??????????????????????????????????????????????????? `%' ?????????????????? `d'???`o'???`u'???`x'???`X'???`e'???`E'???`f'???`g'???`G'???`c'???`s' ????????? `%' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????10????????????`.'???`+'???`-' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

????????????????????????????????????????????????????????? `cbreplace' ???????????????

+ +
+
char *cbreplace(const char *str, CBMAP *pairs);
+
`str' ??????????????????????????????????????????`pairs' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `cbsplit' ???????????????

+ +
+
CBLIST *cbsplit(const char *ptr, int size, const char *delim);
+
`ptr' ??????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`delim' ?????????????????????????????????????????????????????????`NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
+
+ +

????????????????????????????????????????????????????????? `cbreadfile' ???????????????

+ +
+
char *cbreadfile(const char *name, int *sp);
+
`name' ?????????????????????????????????????????????`NULL' ????????????????????????????????????`sp' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `cbwritefile' ???????????????

+ +
+
int cbwritefile(const char *name, const char *ptr, int size);
+
`name' ???????????????????????????????????????`NULL' ??????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `cbreadlines' ???????????????

+ +
+
CBLIST *cbreadlines(const char *name);
+
`name' ?????????????????????????????????????????????`NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `cbdirlist' ???????????????

+ +
+
CBLIST *cbdirlist(const char *name);
+
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `cbfilestat' ???????????????

+ +
+
int cbfilestat(const char *name, int *isdirp, int *sizep, int *mtimep);
+
`name' ???????????????????????????????????????????????????????????????`dirp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????`sizep' ??? `NULL' ??????????????????????????????????????????????????????????????????????????????`mtimep' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????? `cbremove' ???????????????

+ +
+
int cbremove(const char *name);
+
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

URL????????????????????????????????????????????? `cburlbreak' ???????????????

+ +
+
CBMAP *cburlbreak(const char *str);
+
`str' ???URL???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? "self" ???URL???????????????????????????????????? "scheme" ???URL??????????????????????????????????????? "host" ??????????????????????????????????????????????????? "port" ?????????????????????????????????????????????????????? "authority" ??????????????????????????????????????? "path" ???????????????????????????????????????????????? "file" ?????????????????????????????????????????????????????????????????????????????? "query" ????????????????????????????????????????????? "fragment" ????????????????????????????????????????????????????????????????????????????????????HTTP???HTTPS???FTP???FILE??????????????????URL????????????URL?????????????????????????????????????????????????????? `cbmapopen' ????????????????????????????????????????????? `cbmapclose' ??????????????????????????????
+
+ +

??????URL?????????URL??????????????????????????????????????? `cburlresolve' ???????????????

+ +
+
char *cburlresolve(const char *base, const char *target);
+
`base' ???????????????????????????????????????URL??????????????????`target' ??????????????????URL?????????????????????????????????????????????URL???????????????????????????URL?????????URL???????????????????????????????????????????????????????????????URL???????????????????????????URL?????????URL???????????????????????????URL????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????URL????????????????????????????????????????????????????????? `cburlencode' ???????????????

+ +
+
char *cburlencode(const char *ptr, int size);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

URL???????????????????????????????????????????????????????????????????????????????????? `cburldecode' ???????????????

+ +
+
char *cburldecode(const char *str, int *sp);
+
`str' ??????????????????????????????????????????????????????????????????`sp' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????Base64????????????????????????????????????????????????????????? `cbbaseencode' ???????????????

+ +
+
char *cbbaseencode(const char *ptr, int size);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

Base64???????????????????????????????????????????????????????????????????????????????????? `cbbasedecode' ???????????????

+ +
+
char *cbbasedecode(const char *str, int *sp);
+
`str' ??????????????????????????????????????????????????????????????????`sp' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????quoted-printable????????????????????????????????????????????????????????? `cbquoteencode' ???????????????

+ +
+
char *cbquoteencode(const char *ptr, int size);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

quoted-printable???????????????????????????????????????????????????????????????????????????????????? `cbquotedecode' ???????????????

+ +
+
char *cbquotedecode(const char *str, int *sp);
+
`str' ??????????????????????????????????????????????????????????????????`sp' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

MIME?????????????????????????????????????????????????????????????????? `cbmimebreak' ???????????????

+ +
+
char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp);
+
`ptr' ???MIME?????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`attrs' ???????????????????????????????????????????????????????????????????????????`NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? "TYPE" ?????????????????????????????????????????????????????????????????????????????????????????? "CHARSET" ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? "BOUNDARY" ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? "DISPOSITION" ??????????????????????????? ???????????????????????????????????????????????????????????? "FILENAME" ????????????????????????????????????????????????????????????????????????????????? "NAME" ?????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

MIME??????????????????????????????????????????????????????????????????????????????????????? `cbmimeparts' ???????????????

+ +
+
CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary);
+
`ptr' ???MIME?????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`boundary' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
+
+ +

????????????MIME????????????????????????????????????????????????????????? `cbmimeencode' ???????????????

+ +
+
char *cbmimeencode(const char *str, const char *encname, int base);
+
`str' ????????????????????????????????????????????????`encname' ???????????????????????????????????????????????????`base' ???Base64??????????????????????????????????????????????????????????????????quoted-printable?????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

MIME???????????????????????????????????????????????????????????????????????????????????? `cbmimedecode' ???????????????

+ +
+
char *cbmimedecode(const char *str, char *enp);
+
`str' ??????????????????????????????????????????????????????????????????`enp' ??????????????????????????????????????????????????????????????????????????????????????????`NULL' ????????????????????????????????????????????????????????????32?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

CSV???????????????????????????????????????????????? `cbcsvrows' ???????????????

+ +
+
CBLIST *cbcsvrows(const char *str);
+
`str' ???CSV????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????????????????????????????????????????US-ASCII???UTF-8???ISO-8859-*???EUC-*???Shift_JIS???????????????????????????????????????MS-Excel???????????????????????????CSV?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

CSV????????????????????????????????????????????????????????? `cbcsvcells' ???????????????

+ +
+
CBLIST *cbcsvcells(const char *str);
+
`str' ???CSV??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
+
+ +

CSV???????????????????????????????????????????????????????????????????????? `cbcsvescape' ???????????????

+ +
+
char *cbcsvescape(const char *str);
+
`str' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

XML?????????????????????????????????????????????????????????????????????????????? `cbcsvunescape' ???????????????

+ +
+
char *cbcsvunescape(const char *str);
+
`str' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

XML????????????????????????????????????????????????????????????????????????????????? `cbxmlbreak' ???????????????

+ +
+
CBLIST *cbxmlbreak(const char *str, int cr);
+
`str' ???XML????????????????????????????????????????????????`cr' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????????????????????????????????????????US-ASCII???UTF-8???ISO-8859-*???EUC-*???Shift_JIS????????????????????????????????????????????????XML???????????????????????????????????????XML??????????????????????????????HTML???SGML??????????????????????????????
+
+ +

XML?????????????????????????????????????????????????????? `cbxmlattrs' ???????????????

+ +
+
CBMAP *cbxmlattrs(const char *str);
+
`str' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cbmapopen' ????????????????????????????????????????????? `cbmapclose' ??????????????????????????????
+
+ +

XML???????????????????????????????????????????????????????????????????????? `cbxmlescape' ???????????????

+ +
+
char *cbxmlescape(const char *str);
+
`str' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `&'??? `<'???`>'???`"' ????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

XML?????????????????????????????????????????????????????????????????????????????? `cbxmlunescape' ???????????????

+ +
+
char *cbxmlunescape(const char *str);
+
`str' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `&amp;'???`&lt;'???`&gt;'???`&quot;' ????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

ZLIB????????????????????????????????????????????????????????????????????? `cbdeflate' ???????????????

+ +
+
char *cbdeflate(const char *ptr, int size, int *sp);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`sp' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???ZLIB??????????????????????????????????????????????????????????????????
+
+ +

ZLIB??????????????????????????????????????????????????????????????????????????? `cbinflate' ???????????????

+ +
+
char *cbinflate(const char *ptr, int size, int *sp);
+
`ptr' ?????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???ZLIB??????????????????????????????????????????????????????????????????
+
+ +

GZIP????????????????????????????????????????????????????????????????????? `cbgzencode' ???????????????

+ +
+
char *cbgzencode(const char *ptr, int size, int *sp);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`sp' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???ZLIB??????????????????????????????????????????????????????????????????
+
+ +

GZIP??????????????????????????????????????????????????????????????????????????? `cbgzdecode' ???????????????

+ +
+
char *cbgzdecode(const char *ptr, int size, int *sp);
+
`ptr' ?????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???ZLIB??????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????CRC32?????????????????????????????????????????? `cbgetcrc' ???????????????

+ +
+
unsigned int cbgetcrc(const char *ptr, int size);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ???????????????????????????????????????????????????CRC32?????????????????????????????????????????????QDBM???ZLIB??????????????????????????????????????????????????????????????????
+
+ +

LZO????????????????????????????????????????????????????????????????????? `cblzoencode' ???????????????

+ +
+
char *cblzoencode(const char *ptr, int size, int *sp);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`sp' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???LZO??????????????????????????????????????????????????????????????????
+
+ +

LZO??????????????????????????????????????????????????????????????????????????? `cblzodecode' ???????????????

+ +
+
char *cblzodecode(const char *ptr, int size, int *sp);
+
`ptr' ?????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???LZO??????????????????????????????????????????????????????????????????
+
+ +

BZIP2????????????????????????????????????????????????????????????????????? `cbbzencode' ???????????????

+ +
+
char *cbbzencode(const char *ptr, int size, int *sp);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`sp' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???BZIP2??????????????????????????????????????????????????????????????????
+
+ +

BZIP2??????????????????????????????????????????????????????????????????????????? `cbbzdecode' ???????????????

+ +
+
char *cbbzdecode(const char *ptr, int size, int *sp);
+
`ptr' ?????????????????????????????????????????????`sp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???BZIP2??????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????? `cbiconv' ???????????????

+ +
+
char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`icode' ???????????????????????????????????????????????????????????????`outcode' ???????????????????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????`mp' ??? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ????????????????????????????????????????????????QDBM???ICONV??????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `cbencname' ???????????????

+ +
+
const char *cbencname(const char *str, int size);
+
`ptr' ?????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????? `strlen(ptr)' ??????????????????`icode' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????US-ASCII???ISO-2022-JP???Shift_JIS???CP932???EUC-JP???UTF-8???UTF-16???UTF-16BE?????????UTF-16LE???????????????????????????????????????????????????????????????ISO-8859-1?????????????????????????????????QDBM???ICONV??????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `cbjetlag' ???????????????

+ +
+
int cbjetlag(void);
+
???????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????? `cbcalendar' ???????????????

+ +
+
void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp);
+
`t' ?????????????????????????????????????????????????????????????????????????????????`jl' ??????????????????????????????????????????????????????`yearp' ??? `NULL' ?????????????????????????????????????????????????????????`monp' ??? `NULL' ?????????????????????????????????????????????????????????1???1??????????????????12???12?????????????????????`dayp' ??? `NULL' ?????????????????????????????????????????????????????????`hourp' ??? `NULL' ?????????????????????????????????????????????????????????`minp' ??? `NULL' ?????????????????????????????????????????????????????????`secp' ??? `NULL' ?????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????? `cbdayofweek' ???????????????

+ +
+
int cbdayofweek(int year, int mon, int day);
+
`year' ?????????????????????????????????`mon' ?????????????????????????????????`day' ?????????????????????????????????????????????????????????????????????0????????????????????????6???????????????????????????
+
+ +

???????????????W3CDTF?????????????????????????????????????????????????????? `cbdatestrwww' ???????????????

+ +
+
char *cbdatestrwww(time_t t, int jl);
+
`t' ?????????????????????????????????????????????????????????????????????????????????`jl' ??????????????????????????????????????????????????????????????????W3CDTF????????????YYYY-MM-DDThh:mm:ddTZD???????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

???????????????RFC 1123?????????????????????????????????????????????????????? `cbdatestrhttp' ???????????????

+ +
+
char *cbdatestrhttp(time_t t, int jl);
+
`t' ?????????????????????????????????????????????????????????????????????????????????`jl' ??????????????????????????????????????????????????????????????????RFC 1123????????????Wdy, DD-Mon-YYYY hh:mm:dd TZD???????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

10?????????16?????????W3CDTF???RFC 822???1123??????????????????????????????????????????????????????????????????????????? `cbstrmktime' ???????????????

+ +
+
time_t cbstrmktime(const char *str);
+
`str' ???10?????????16?????????W3CDTF???RFC 822???1123?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????10????????? "s" ??????????????????????????????????????????"m" ??????????????????????????????????????????"h" ??????????????????????????????????????????"d" ?????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `cbproctime' ???????????????

+ +
+
void cbproctime(double *usrp, double *sysp);
+
`usrp' ??? `NULL' ??????????????????????????????????????????????????????????????????????????????????????????????????????`sysp' ??? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `cbstdiobin' ???????????????

+ +
+
void cbstdiobin(void);
+
???????????????DOS????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????

+ +

??????????????????????????????????????????????????????????????????

+ +
#include <cabin.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int main(int argc, char **argv){
+  CBDATUM *datum;
+  CBLIST *list;
+  CBMAP *map;
+  char *buf1, *buf2;
+  int i;
+
+  /* ?????????????????????????????? */
+  datum = cbdatumopen("123", -1);
+  /* ???????????????????????? */
+  cbdatumcat(datum, "abc", -1);
+  /* ???????????????????????? */
+  printf("%s\n", cbdatumptr(datum));
+  /* ????????????????????????????????? */
+  cbdatumclose(datum);
+
+  /* ?????????????????????????????? */
+  list = cblistopen();
+  /* ????????????????????????????????? */
+  cblistpush(list, "apple", -1);
+  cblistpush(list, "orange", -1);
+  /* ?????????????????????????????? */
+  for(i = 0; i < cblistnum(list); i++){
+    printf("%s\n", cblistval(list, i, NULL));
+  }
+  /* ????????????????????????????????? */
+  cblistclose(list);
+
+  /* ?????????????????????????????? */
+  map = cbmapopen();
+  /* ??????????????????????????????????????? */
+  cbmapput(map, "dog", -1, "bowwow", -1, 1);
+  cbmapput(map, "cat", -1, "meow", -1, 1);
+  /* ?????????????????????????????? */
+  printf("%s\n", cbmapget(map, "dog", -1, NULL));
+  printf("%s\n", cbmapget(map, "cat", -1, NULL));
+  /* ????????????????????????????????? */
+  cbmapclose(map);
+
+  /* Base64????????????????????? */
+  buf1 = cbbaseencode("I miss you.", -1);
+  printf("%s\n", buf1);
+  /* Base64?????????????????? */
+  buf2 = cbbasedecode(buf1, NULL);
+  printf("%s\n", buf2);
+  /* ??????????????????????????? */
+  free(buf2);
+  free(buf1);
+
+  /* ?????????????????????????????????????????????????????????????????????????????? */
+  buf1 = cbmemdup("Take it easy.", -1);
+  cbglobalgc(buf1, free);
+  /* ???????????????????????????????????????????????????????????? */
+  printf("%s\n", buf1);
+
+  /* ?????????????????????????????????????????????????????????????????? */
+  list = cblistopen();
+  cbglobalgc(list, (void (*)(void *))cblistclose);
+  /* ????????????????????????????????????????????????????????? */
+  cblistpush(list, "Don't hesitate.", -1);
+  for(i = 0; i < cblistnum(list); i++){
+    printf("%s\n", cblistval(list, i, NULL));
+  }
+
+  return 0;
+}
+
+ +

??????

+ +

Cabin????????????????????????????????????????????????????????????Depot????????????????????????????????????

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

?????????????????????????????????????????????????????????????????????????????????`cbglobalgc' ????????????Cabin????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

+ +
+ +

Cabin???????????????

+ +

Cabin???????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `cbtest' ???Cabin?????????????????????????????????????????????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????`rnum' ????????????????????????????????????

+ +
+
cbtest sort [-d] rnum
+
???????????????????????????????????????????????????
+
cbtest strstr [-d] rnum
+
?????????????????????????????????????????????????????????
+
cbtest list [-d] rnum
+
?????????????????????????????????????????????
+
cbtest map [-d] rnum
+
?????????????????????????????????????????????
+
cbtest wicked rnum
+
????????????????????????????????????????????????????????????????????????????????????
+
cbtest misc
+
???????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -d : ???????????????????????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +

???????????? `cbcodec' ???Cabin??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`file' ??????????????????????????????????????????????????????????????????????????????????????????

+ +
+
cbcodec url [-d] [-br] [-rs base target] [-l] [-e expr] [file]
+
URL????????????????????????????????????????????????
+
cbcodec base [-d] [-l] [-c num] [-e expr] [file]
+
Base64????????????????????????????????????????????????
+
cbcodec quote [-d] [-l] [-c num] [-e expr] [file]
+
quoted-printable????????????????????????????????????????????????
+
cbcodec mime [-d] [-hd] [-bd] [-part num] [-l] [-ec code] [-qp] [-dc] [-e expr] [file]
+
MIME????????????????????????????????????????????????
+
cbcodec csv [-d] [-t] [-l] [-e expr] [-html] [file]
+
CSV????????????????????????????????????????????????????????????????????????????????????
+
cbcodec xml [-d] [-p] [-l] [-e expr] [-tsv] [file]
+
XML????????????????????????????????????????????????????????????????????????????????????
+
cbcodec zlib [-d] [-gz] [-crc] [file]
+
ZLIB????????????????????????????????????ZLIB??????????????????QDBM?????????????????????????????????????????????????????????
+
cbcodec lzo [-d] [file]
+
LZO????????????????????????????????????LZO??????????????????QDBM?????????????????????????????????????????????????????????
+
cbcodec bzip [-d] [file]
+
BZIP2????????????????????????????????????BZIP2??????????????????QDBM?????????????????????????????????????????????????????????
+
cbcodec iconv [-ic code] [-oc code] [-ol ltype] [-cn] [-um] [-wc] [file]
+
ICONV?????????????????????????????????????????????ICONV??????????????????QDBM?????????????????????????????????????????????????????????
+
cbcodec date [-wf] [-rf] [-utc] [str]
+
`str' ????????????????????????????????????????????????????????????????????????????????????UNIX????????????????????????`str' ????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -d : ??????????????????????????????????????????????????????????????????????????????????????????????????????
  • +
  • -br : URL?????????????????????????????????
  • +
  • -rs : ??????URL??????????????????
  • +
  • -l : ?????????????????????????????????????????????
  • +
  • -e expr : ???????????????????????????????????????
  • +
  • -c num : ??????????????????????????????????????????????????????
  • +
  • -hd : MIME???????????????????????????????????????TSV????????????????????????
  • +
  • -bd : MIME??????????????????????????????????????????????????????
  • +
  • -part num : MIME???????????????????????????????????????????????????????????????
  • +
  • -ec code : ????????????????????????????????????????????????????????????UTF-8????????????
  • +
  • -qp : quoted-printable????????????????????????????????????????????????Base64????????????
  • +
  • -dc : ??????????????????????????????????????????????????????????????????????????????
  • +
  • -t : CSV???????????????????????????TSV??????????????????????????????????????????????????????????????????????????????
  • +
  • -html : CSV???????????????????????????HTML??????????????????????????????
  • +
  • -p : XML??????????????????????????????????????????????????????????????????????????????????????????????????????
  • +
  • -tsv : XML????????????????????????????????????TSV????????????????????????????????????????????????????????????????????????URL???????????????????????????
  • +
  • -gz : GZIP?????????????????????
  • +
  • -crc : CRC32??????????????????????????????????????????????????????16????????????????????????
  • +
  • -ic code : ????????????????????????????????????????????????????????????????????????????????????
  • +
  • -oc code : ???????????????????????????????????????????????????????????????UTF-8????????????
  • +
  • -ol ltype : ??????????????????????????????`unix'(LF)???`dos'(CRLF)???`mac'(CR) ??????????????????????????????
  • +
  • -cn : ???????????????????????????????????????????????????????????????????????????
  • +
  • -wc : ???????????????????????????UTF-8????????????????????????????????????????????????
  • +
  • -um : UCS-2???????????????C??????????????????????????????UTF-16BE???UTF-8??????????????????????????????
  • +
  • -wf : W3CDTF???????????????????????????
  • +
  • -rf : RFC 1123???????????????????????????
  • +
  • -utc : ?????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +
+ +

Villa: ??????API

+ +

??????

+ +

Villa???QDBM?????????API????????????B+????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Villa???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Villa???Depot?????????Cabin????????????????????????????????????Villa????????????????????????????????????Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????Depot?????????????????????????????????????????????????????????????????????????????????

+ +

Villa????????????????????????`depot.h' ??? `cabin.h' ??? `villa.h' ??? `stdlib.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+
#include <depot.h>
+
#include <cabin.h>
+
#include <villa.h>
+
#include <stdlib.h>
+
+ +

Villa??????????????????????????????????????????`VILLA' ?????????????????????????????????????????????????????????????????????`stdio.h' ???????????????????????????????????????????????? `FILE' ?????????????????????????????????????????????????????????????????????????????? `vlopen' ?????????????????? `vlclose' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `vlclose' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `vlcurfirst' ??? `vlcurlast' ??? `vlcurjump' ????????????????????????????????????????????????`vlcurput' ??? `vlcurout' ?????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????

+ +

Villa??????Depot???????????????????????? `dpecode' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dperrmsg' ???????????????

+ +

API

+ +

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+
typedef int(*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz);
+
`aptr' ????????????????????????????????????????????????????????????????????????`asiz' ???????????????????????????????????????????????????????????????`bptr' ????????????????????????????????????????????????????????????????????????`bsiz' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ????????????
+
+ +

??????????????????????????????????????????????????????????????? `vlopen' ???????????????

+ +
+
VILLA *vlopen(const char *name, int omode, VLCFUNC cmp);
+
`name' ????????????????????????????????????????????????????????????`omode' ?????????????????????????????????`VL_OREADER' ??????????????????`VL_OWRITER' ???????????????????????????`VL_OWRITER' ????????????`VL_OCREAT' ????????? `VL_OTRUNC' ??????????????????????????????????????????????????????`VL_OCREAT' ????????????????????????????????????????????????????????????????????????`VL_OTRUNC' ??????????????????????????????????????????????????????????????????`VL_OZCOMP' ???????????????????????????????????????ZLIB????????????????????????????????????`VL_OYCOMP' ???????????????????????????????????????LZO????????????????????????????????????`VL_OXCOMP' ???????????????????????????????????????BZIP2???????????????????????????????????????`VL_OREADER' ??? `VL_OWRITER' ???????????? `VL_ONOLCK' ????????? `VL_OLCKNB' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????`cmp' ?????????????????????????????????`VL_CMPLEX' ???????????????????????????????????????`VL_CMPINT' ???????????? `int' ??????????????????????????????????????????????????????`VL_CMPNUM' ??????????????????????????????????????????????????????????????????????????????`VL_CMPDEC' ????????????10???????????????????????????????????????????????????????????????`VLCFUNC' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????`VL_OZCOMP' ??? `VL_OYCOMP' ??? `VL_OXCOMP' ???QDBM???????????????ZLIB???LZO???BZIP2?????????????????????????????????????????????????????????????????????`VL_ONOLCK' ??????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `vlclose' ???????????????

+ +
+
int vlclose(VILLA *villa);
+
`villa' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `vlput' ???????????????

+ +
+
int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+
`villa' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`dmode' ???????????????????????????????????????????????????????????????????????????`VL_DOVER' ????????????????????????????????????????????????`VL_DKEEP' ?????????????????????????????????????????????????????????`VL_DCAT' ?????????????????????????????????????????????????????????`VL_DDUP' ?????????????????????????????????????????????????????????????????????????????????`VL_DDUPR' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `vlout' ???????????????

+ +
+
int vlout(VILLA *villa, const char *kbuf, int ksiz);
+
`villa' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `vlget' ???????????????

+ +
+
char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp);
+
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `vlvsiz' ???????????????

+ +
+
int vlvsiz(VILLA *villa, const char *kbuf, int ksiz);
+
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `vlvnum' ???????????????

+ +
+
int vlvnum(VILLA *villa, const char *kbuf, int ksiz);
+
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0 ????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `vlputlist' ???????????????

+ +
+
int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals);
+
`villa' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`vals' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `vloutlist' ???????????????

+ +
+
int vloutlist(VILLA *villa, const char *kbuf, int ksiz);
+
`villa' ???????????????????????????????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `vlgetlist' ???????????????

+ +
+
CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz);
+
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `vlgetcat' ???????????????

+ +
+
char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp);
+
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `vlcurfirst' ???????????????

+ +
+
int vlcurfirst(VILLA *villa);
+
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `vlcurlast' ???????????????

+ +
+
int vlcurlast(VILLA *villa);
+
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `vlcurprev' ???????????????

+ +
+
int vlcurprev(VILLA *villa);
+
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `vlcurnext' ???????????????

+ +
+
int vlcurnext(VILLA *villa);
+
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????? `vlcurjump' ???????????????

+ +
+
int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode);
+
`villa' ???????????????????????????????????????????????????`kbuf' ???????????????????????????????????????????????????????????????`ksiz' ???????????????????????????????????????????????????????????????????????? `strlen(kbuf)' ??????????????????`jmode' ????????????????????????????????????`VL_JFORWARD' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`VL_JBACKWORD' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `vlcurkey' ???????????????

+ +
+
char *vlcurkey(VILLA *villa, int *sp);
+
`villa' ???????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `vlcurkey' ???????????????

+ +
+
char *vlcurval(VILLA *villa, int *sp);
+
`villa' ???????????????????????????????????????????????????`sp' ??? `NULL' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ??????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????????????????? `vlcurput' ???????????????

+ +
+
int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode);
+
`villa' ???????????????????????????????????????????????????????????????????????????`vbuf' ????????????????????????????????????????????????????????????`vsiz' ????????????????????????????????????????????????????????????????????? `strlen(vbuf)' ??????????????????`cpmode' ????????????????????????????????????`VL_CPCURRENT' ?????????????????????????????????????????????????????????????????????`VL_CPBEFORE' ???????????????????????????????????????????????????????????????????????????`VL_CPAFTER' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `vlcurout' ???????????????

+ +
+
int vlcurout(VILLA *villa);
+
`villa' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `vlsettuning' ???????????????

+ +
+
void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum);
+
`villa' ???????????????????????????????????????????????????`lrecmax' ???B+????????????????????????????????????????????????????????????????????????????????????0 ????????????????????????????????????????????????`nidxmax' ???B+??????????????????????????????????????????????????????????????????????????????????????????0 ????????????????????????????????????????????????`lcnum' ????????????????????????????????????????????????????????????????????????0 ????????????????????????????????????????????????`ncnum' ????????????????????????????????????????????????????????????????????????????????????0 ??????????????????????????????????????????????????????????????????????????? `vlsettuning(49, 192, 1024, 512)' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `vlsetfbpsiz' ???????????????

+ +
+
int vlsetfbpsiz(VILLA *villa, int size);
+
`villa' ???????????????????????????????????????????????????????????????????????????`size' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????256?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????? `vlsync' ???????????????

+ +
+
int vlsync(VILLA *villa);
+
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `vloptimize' ???????????????

+ +
+
int vloptimize(VILLA *villa);
+
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `vlname' ???????????????

+ +
+
char *vlname(VILLA *villa);
+
`villa' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `vlfsiz' ???????????????

+ +
+
int vlfsiz(VILLA *villa);
+
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????I/O?????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

B+?????????????????????????????????????????????????????? `vllnum' ???????????????

+ +
+
int vllnum(VILLA *villa);
+
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

B+????????????????????????????????????????????????????????? `vlnnum' ???????????????

+ +
+
int vlnnum(VILLA *villa);
+
`villa' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

???????????????????????????????????????????????????????????? `vlrnum' ???????????????

+ +
+
int vlrnum(VILLA *villa);
+
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????? `vlwritable' ???????????????

+ +
+
int vlwritable(VILLA *villa);
+
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `vlfatalerror' ???????????????

+ +
+
int vlfatalerror(VILLA *villa);
+
`villa' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????inode?????????????????????????????? `vlinode' ???????????????

+ +
+
int vlinode(VILLA *villa);
+
`villa' ????????????????????????????????????????????????????????????????????????????????????????????????inode??????????????????
+
+ +

??????????????????????????????????????????????????????????????? `vlmtime' ???????????????

+ +
+
time_t vlmtime(VILLA *villa);
+
`villa' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `vltranbegin' ???????????????

+ +
+
int vltranbegin(VILLA *villa);
+
`villa' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `vltrancommit' ???????????????

+ +
+
int vltrancommit(VILLA *villa);
+
`villa' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? `vltranabort' ???????????????

+ +
+
int vltranabort(VILLA *villa);
+
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `vlremove' ???????????????

+ +
+
int vlremove(const char *name);
+
`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `vlrepair' ???????????????

+ +
+
int vlrepair(const char *name, VLCFUNC cmp);
+
`name' ????????????????????????????????????????????????????????????`cmp' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????? `vlexportdb' ???????????????

+ +
+
int vlexportdb(VILLA *villa, const char *name);
+
`villa' ???????????????????????????????????????????????????`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????????????????? `vlimportdb' ???????????????

+ +
+
int vlimportdb(VILLA *villa, const char *name);
+
`villa' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????

+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <cabin.h>
+#include <villa.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NAME     "mikio"
+#define NUMBER   "000-1234-5678"
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  VILLA *villa;
+  char *val;
+
+  /* ??????????????????????????? */
+  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
+    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* ??????????????????????????? */
+  if(!vlput(villa, NAME, -1, NUMBER, -1, VL_DOVER)){
+    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
+  }
+
+  /* ??????????????????????????? */
+  if(!(val = vlget(villa, NAME, -1, NULL))){
+    fprintf(stderr, "vlget: %s\n", dperrmsg(dpecode));
+  } else {
+    printf("Name: %s\n", NAME);
+    printf("Number: %s\n", val);
+    free(val);
+  }
+
+  /* ?????????????????????????????? */
+  if(!vlclose(villa)){
+    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <cabin.h>
+#include <villa.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define DBNAME   "words"
+#define PREFIX   "apple"
+
+int main(int argc, char **argv){
+  VILLA *villa;
+  char *key, *val;
+
+  /* ??????????????????????????? */
+  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
+    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* ??????????????????????????? */
+  if(!vlput(villa, "applet", -1, "little application", -1, VL_DDUP) ||
+     !vlput(villa, "aurora", -1, "polar wonderwork", -1, VL_DDUP) ||
+     !vlput(villa, "apple", -1, "delicious fruit", -1, VL_DDUP) ||
+     !vlput(villa, "amigo", -1, "good friend", -1, VL_DDUP) ||
+     !vlput(villa, "apple", -1, "big city", -1, VL_DDUP)){
+    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
+  }
+
+  /* ??????????????????????????????????????? */
+  vlcurjump(villa, PREFIX, -1, VL_JFORWARD);
+
+  /* ??????????????????????????? */
+  while((key = vlcurkey(villa, NULL)) != NULL){
+    if(strstr(key, PREFIX) != key){
+      free(key);
+      break;
+    }
+    if(!(val = vlcurval(villa, NULL))){
+      fprintf(stderr, "vlcurval: %s\n", dperrmsg(dpecode));
+      free(key);
+      break;
+    }
+    printf("%s: %s\n", key, val);
+    free(val);
+    free(key);
+    vlcurnext(villa);
+  }
+
+  /* ?????????????????????????????? */
+  if(!vlclose(villa)){
+    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

??????

+ +

Villa????????????????????????????????????????????????????????????Depot????????????????????????????????????

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

POSIX??????????????????????????????QDBM??????????????????????????????????????? `dpecode' ???????????????????????????????????????????????????????????????Villa?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

+ +

Vista: ????????????API

+ +

Vista???Villa???????????????API????????????Villa???2GB???????????????????????????????????????????????????????????????????????????????????????Vista??????Depot????????????Curia??????????????????????????????????????????????????????Vista???Villa????????????B+???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Vista??????????????????`villa.h' ??????????????? `vista.h' ???????????????????????????????????????Vista???Villa???????????????????????????????????????????????????????????????????????????????????????Villa??????????????????API?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Vista????????????????????????????????????????????????????????????Villa???????????????????????????????????????`villa.h' ????????????????????????????????????????????????

+ +
+ +

Villa???????????????

+ +

Villa???????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `vlmgr' ???Villa?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`key' ???????????????????????????`val' ???????????????????????????????????????

+ +
+
vlmgr create [-cz|-cy|-cx] name
+
????????????????????????????????????????????????
+
vlmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat|-dup] name key val
+
?????????????????????????????????????????????????????????
+
vlmgr out [-l] [-kx|-ki] name key
+
???????????????????????????????????????????????????
+
vlmgr get [-nl] [-l] [-kx|-ki] [-ox] [-n] name key
+
???????????????????????????????????????????????????????????????????????????
+
vlmgr list [-nl] [-k|-v] [-kx|-ki] [-ox] [-top key] [-bot key] [-gt] [-lt] [-max num] [-desc] name
+
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
vlmgr optimize name
+
???????????????????????????????????????
+
vlmgr inform [-nl] name
+
??????????????????????????????????????????????????????
+
vlmgr remove name
+
????????????????????????????????????????????????
+
vlmgr repair [-ki] name
+
?????????????????????????????????????????????????????????
+
vlmgr exportdb [-ki] name file
+
??????????????????????????????????????????????????????????????????????????????????????????
+
vlmgr importdb [-ki] name file
+
????????????????????????????????????????????????????????????????????????????????????
+
vlmgr version
+
QDBM????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -cz : ?????????????????????????????????ZLIB??????????????????
  • +
  • -cy : ?????????????????????????????????LZO??????????????????
  • +
  • -cx : ?????????????????????????????????BZIP2??????????????????
  • +
  • -l : ?????????????????????????????????????????????????????????????????????
  • +
  • -kx : 2????????????16?????????????????????????????????????????? `key' ????????????
  • +
  • -ki : 10???????????????????????????????????? `key' ????????????
  • +
  • -vx : 2????????????16?????????????????????????????????????????? `val' ????????????
  • +
  • -vi : 10???????????????????????????????????? `val' ????????????
  • +
  • -vf : ????????? `val' ?????????????????????????????????????????????????????????
  • +
  • -keep : ????????????????????????????????????????????????????????????????????????????????????
  • +
  • -cat : ???????????????????????????????????????????????????????????????????????????
  • +
  • -dup : ???????????????????????????????????????????????????
  • +
  • -nl : ??????????????????????????????????????????????????????????????????
  • +
  • -top key : ?????????????????????????????????????????????
  • +
  • -bot key : ?????????????????????????????????????????????
  • +
  • -gt : ?????????????????????????????????????????????
  • +
  • -lt : ?????????????????????????????????????????????
  • +
  • -max num : ??????????????????????????????????????????
  • +
  • -desc : ??????????????????????????????
  • +
  • -ox : 2????????????16??????????????????????????????????????????????????????????????????
  • +
  • -n : ??????????????????????????????????????????????????????????????????????????????
  • +
  • -k : ??????????????????????????????
  • +
  • -v : ???????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `vltest' ???Villa??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `vlmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`rnum' ?????????????????????`pnum' ?????????????????????????????????????????????

+ +
+
vltest write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum
+
`00000001'???`00000002' ????????????????????????8??????????????????????????????8??????????????????????????????????????????????????????????????????
+
vltest read [-int] [-vc] name
+
???????????????????????????????????????????????????????????????????????????
+
vltest rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum pnum
+
????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
vltest combo [-cz|-cy|-cx] name
+
???????????????????????????????????????????????????
+
vltest wicked [-cz|-cy|-cx] name rnum
+
????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -int : `int' ??????????????????????????????????????????????????????????????????????????????????????????
  • +
  • -cz : ?????????????????????????????????ZLIB??????????????????
  • +
  • -cy : ?????????????????????????????????LZO??????????????????
  • +
  • -cx : ?????????????????????????????????BZIP2??????????????????
  • +
  • -vc : ??????????????????????????????????????????
  • +
  • -cc : ???????????????????????????????????????????????????????????????
  • +
  • -tune lrecmax nidxmax lcnum ncnum : ???????????????????????????????????????
  • +
  • -fbp num : ????????????????????????????????????????????????????????????
  • +
  • -c : Cabin???????????????????????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `vltsv' ???????????????????????????????????????????????????????????????TSV???????????????Villa?????????????????????????????????????????????????????????????????????QDBM?????????????????????????????????DBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ??????????????????????????????????????????`export' ????????????????????????TSV????????????????????????????????????????????????`import' ????????????????????????TSV???????????????????????????????????????????????????

+ +
+
vltsv import [-bin] name
+
TSV??????????????????????????????????????????????????????????????????
+
vltsv export [-bin] name
+
?????????????????????????????????????????????TSV????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -bin : Base64?????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +

Villa???????????????????????????????????????????????????????????????????????????????????????????????????????????? `/etc/password' ????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
cat /etc/passwd | tr ':' '\t' | vltsv import casket
+
+ +

????????????`mikio' ??????????????????????????????????????????????????????????????????????????????

+ +
vlmgr get casket mikio
+
+ +

?????????????????????????????????????????????Villa???API???????????????????????????????????????????????????

+ +

???????????? `qmttest' ???Depot???Curia???Villa????????????????????????????????????????????????????????????????????????????????????POSIX??????????????????????????????QDBM??????????????????????????????????????????????????????????????????????????????????????????????????????`name' ??????????????????????????????????????????????????????`rnum' ????????????????????????????????????????????????????????????????????????`tnum' ????????????????????????????????????

+ +
+
qmttest name rnum tnum
+
????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +
+ +

Odeum: ??????API

+ +

??????

+ +

Odeum????????????????????????????????????API????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Odeum?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????N-gram??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????

+ +

Odeum???Curia???Cabin???Villa????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Curia???Villa???????????????????????????????????????????????????`casket' ????????????????????????????????????????????????????????????`casket/docs'???`casket/index' ????????? `casket/rdocs' ?????????????????????`docs' ???Curia?????????????????????????????????????????????????????????????????????ID????????????????????????URI??????????????????????????????`index' ???Curia????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ID????????????????????????????????????????????????????????????`rdocs' ???Villa???????????????????????????????????????????????????????????????URI???????????????????????????ID??????????????????

+ +

Odeum????????????????????????`depot.h' ??? `cabin.h' ??? `odeum.h' ??? `stdlib.h' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+
#include <depot.h>
+
#include <cabin.h>
+
#include <odeum.h>
+
#include <stdlib.h>
+
+ +

Odeum??????????????????????????????????????????`ODEUM' ????????????????????????????????????????????????????????????????????????????????? `odopen' ?????????????????? `odclose' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `odclose' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

??????????????????????????????`ODDOC' ????????????????????????????????????????????????????????????????????????????????? `oddocopen' ?????????????????? `oddocclose' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Odeum??????Depot???????????????????????? `dpecode' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `dperrmsg' ???????????????

+ +

API

+ +

????????????????????????????????????`ODPAIR' ??????????????????????????????

+ +
+
typedef struct { int id; int score; } ODPAIR;
+
`id' ????????????ID??????????????????`score' ????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????? `odopen' ???????????????

+ +
+
ODEUM *odopen(const char *name, int omode);
+
`name' ??????????????????????????????????????????????????????????????????`omode' ?????????????????????????????????`OD_OREADER' ??????????????????`OD_OWRITER' ???????????????????????????`OD_OWRITER' ????????????`OD_OCREAT' ????????? `OD_OTRUNC' ??????????????????????????????????????????????????????`OD_OCREAT' ????????????????????????????????????????????????????????????????????????`OD_OTRUNC' ?????????????????????????????????????????????????????????????????????`OD_OREADER' ??? `OD_OWRITER' ???????????? `OD_ONOLCK' ??? `OD_OLCKNB' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`OD_ONOLCK' ??????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `odclose' ???????????????

+ +
+
int odclose(ODEUM *odeum);
+
`odeum' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????? `odput' ???????????????

+ +
+
int odput(ODEUM *odeum, const ODDOC *doc, int wmax, int over);
+
`odeum' ???????????????????????????????????????????????????????????????????????????`doc' ???????????????????????????????????????`wmax' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????`over' ?????????????????????????????????????????????????????????????????????????????????????????????URI??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

URI??????????????????????????????????????????????????? `odout' ???????????????

+ +
+
int odout(ODEUM *odeum, const char *uri);
+
`odeum' ???????????????????????????????????????????????????????????????????????????`uri' ????????????URI??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

ID????????????????????????????????????????????????????????? `odoutbyid' ???????????????

+ +
+
int odoutbyid(ODEUM *odeum, int id);
+
`odeum' ???????????????????????????????????????????????????????????????????????????`id' ????????????ID????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

URI??????????????????????????????????????????????????? `odget' ???????????????

+ +
+
ODDOC *odget(ODEUM *odeum, const char *uri);
+
`odeum' ???????????????????????????????????????????????????`uri' ????????????URI??????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????? `NULL' ???????????????????????????????????????????????? `oddocopen' ????????????????????????????????????????????? `oddocclose' ??????????????????????????????
+
+ +

ID????????????????????????????????????????????????????????? `odgetbyid' ???????????????

+ +
+
ODDOC *odgetbyid(ODEUM *odeum, int id);
+
`odeum' ???????????????????????????????????????????????????`id' ????????????ID????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????? `NULL' ???????????????????????????????????????????????? `oddocopen' ????????????????????????????????????????????? `oddocclose' ??????????????????????????????
+
+ +

URI????????????????????????ID?????????????????????????????? `odgetidbyuri' ???????????????

+ +
+
int odgetidbyuri(ODEUM *odeum, const char *uri);
+
`odeum' ???????????????????????????????????????????????????`uri' ????????????URI????????????????????????????????????????????????????????????????????????ID??????????????????????????? -1 ????????????????????????????????????????????? -1 ????????????
+
+ +

ID??????????????????????????????????????????????????????????????????????????? `odcheck' ???????????????

+ +
+
int odcheck(ODEUM *odeum, int id);
+
`odeum' ???????????????????????????????????????????????????`id' ????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????????????????? `odsearch' ???????????????

+ +
+
ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np);
+
`odeum' ???????????????????????????????????????????????????`word' ??????????????????????????????`max' ???????????????????????????????????????????????????`np' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????? `odsearchdnum' ???????????????

+ +
+
int odsearchdnum(ODEUM *odeum, const char *word);
+
`odeum' ???????????????????????????????????????????????????`word' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ???????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `oditerinit' ???????????????

+ +
+
int oditerinit(ODEUM *odeum);
+
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????? `oditernext' ???????????????

+ +
+
ODDOC *oditernext(ODEUM *odeum);
+
`odeum' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????????????????????????????????????? `NULL' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `oddocopen' ????????????????????????????????????????????? `oddocclose' ??????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????????????????? `odsync' ???????????????

+ +
+
int odsync(ODEUM *odeum);
+
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `odoptimize' ???????????????

+ +
+
int odoptimize(ODEUM *odeum);
+
`odeum' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????? `odname' ???????????????

+ +
+
char *odname(ODEUM *odeum);
+
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????? `odfsiz' ???????????????

+ +
+
double odfsiz(ODEUM *odeum);
+
`odeum' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1.0 ????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????????????????? `odbnum' ???????????????

+ +
+
int odbnum(ODEUM *odeum);
+
`odeum' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????? `odbusenum' ???????????????

+ +
+
int odbusenum(ODEUM *odeum);
+
`odeum' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ + +

????????????????????????????????????????????????????????????????????? `oddnum' ???????????????

+ +
+
int oddnum(ODEUM *odeum);
+
`odeum' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????
+
+ +

????????????????????????????????????????????????????????????????????? `odwnum' ???????????????

+ +
+
int odwnum(ODEUM *odeum);
+
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? -1 ????????????I/O?????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????? `odwritable' ???????????????

+ +
+
int odwritable(ODEUM *odeum);
+
`odeum' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `odfatalerror' ???????????????

+ +
+
int odfatalerror(ODEUM *odeum);
+
`odeum' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????inode?????????????????????????????? `odinode' ???????????????

+ +
+
int odinode(ODEUM *odeum);
+
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????inode??????????????????
+
+ +

??????????????????????????????????????????????????????????????? `odmtime' ???????????????

+ +
+
time_t odmtime(ODEUM *odeum);
+
`odeum' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `odmerge' ???????????????

+ +
+
int odmerge(const char *name, const CBLIST *elemnames);
+
`name' ??????????????????????????????????????????????????????????????????????????????`elemnames' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????URL??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `odremove' ???????????????

+ +
+
int odremove(const char *name);
+
`name' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????API??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????? `oddocopen' ???????????????

+ +
+
ODDOC *oddocopen(const char *uri);
+
`uri' ????????????URI??????????????????????????????????????????????????????????????????????????????ID????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????? `oddocclose' ???????????????

+ +
+
void oddocclose(ODDOC *doc);
+
`doc' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????? `oddocaddattr' ???????????????

+ +
+
void oddocaddattr(ODDOC *doc, const char *name, const char *value);
+
`doc' ???????????????????????????????????????`name' ??????????????????????????????????????????`value' ??????????????????????????????????????????
+
+ +

?????????????????????????????????????????? `oddocaddword' ???????????????

+ +
+
void oddocaddword(ODDOC *doc, const char *normal, const char *asis);
+
`doc' ???????????????????????????????????????`normal' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`asis' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????ID???????????????????????? `oddocid' ???????????????

+ +
+
int oddocid(const ODDOC *doc);
+
`doc' ????????????????????????????????????????????????????????????ID??????????????????
+
+ +

?????????URI???????????????????????? `oddocuri' ???????????????

+ +
+
const char *oddocuri(const ODDOC *doc);
+
`doc' ????????????????????????????????????????????????????????????URI????????????????????????
+
+ +

?????????????????????????????????????????? `oddocgetattr' ???????????????

+ +
+
const char *oddocgetattr(const ODDOC *doc, const char *name);
+
`doc' ???????????????????????????????????????`name' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????
+
+ +

?????????????????????????????????????????????????????????????????? `oddocnwords' ???????????????

+ +
+
const CBLIST *oddocnwords(const ODDOC *doc);
+
`doc' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `oddocawords' ???????????????

+ +
+
const CBLIST *oddocawords(const ODDOC *doc);
+
`doc' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????????????????? `oddocscores' ???????????????

+ +
+
CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum);
+
`doc' ???????????????????????????????????????`max' ????????????????????????????????????????????????????????????`odeum' ??? `NULL' ????????????????????????????????????????????????????????????IDF??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????10???????????????????????????????????????????????????????????????????????? `cbmapopen' ????????????????????????????????????????????? `cbmapclose' ??????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????????????????? `odbreaktext' ???????????????

+ +
+
CBLIST *odbreaktext(const char *text);
+
`text' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `cblistopen' ????????????????????????????????????????????? `cblistclose' ??????????????????????????????
+
+ +

????????????????????????????????????????????? `odnormalizeword' ???????????????

+ +
+
char *odnormalizeword(const char *asis);
+
`asis' ???????????????????????????????????????????????????????????????????????????????????????????????????ASCII????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

????????????????????????????????????????????????????????????????????? `odpairsand' ???????????????

+ +
+
ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
+
`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`np' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `odpairsor' ???????????????

+ +
+
ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
+
`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`np' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `odpairsnotand' ???????????????

+ +
+
ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
+
`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`apairs' ???????????????????????????????????????????????????`anum' ????????????????????????????????????????????????`np' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ?????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????? `odpairssort' ???????????????

+ +
+
void odpairssort(ODPAIR *pairs, int pnum);
+
`pairs' ??????????????????????????????????????????`pnum' ?????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????? `odlogarithm' ???????????????

+ +
+
double odlogarithm(double x);
+
`x' ???????????????????????????????????????????????????????????????????????????????????????????????? 1.0 ????????????????????????????????? 0.0 ?????????????????????????????????????????????????????????????????????IDF???????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????? `odvectorcosine' ???????????????

+ +
+
double odvectorcosine(const int *avec, const int *bvec, int vnum);
+
`avec' ??????????????????????????????????????????`bvec' ??????????????????????????????????????????`vnum' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????????????????????????????????????????????????????????????? `odsettuning' ???????????????

+ +
+
void odsettuning(int ibnum, int idnum, int cbnum, int csiz);
+
`ibnum' ???????????????????????????????????????????????????????????????`idnum' ?????????????????????????????????????????????????????????`cbnum' ???????????????????????????????????????????????????????????????`csiz' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????? `odsettuning(32749, 7, 262139, 8388608)' ??????????????????????????????????????????????????????????????????????????????????????????
+
+ +

??????????????????????????????????????????????????????????????????????????????????????????????????? `odanalyzetext' ???????????????

+ +
+
void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords);
+
`odeum' ???????????????????????????????????????????????????`text' ?????????????????????????????????????????????`awords' ??????????????????????????????????????????????????????????????????`nwords' ?????????????????????????????????????????????????????????????????????`NULL' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????? `odanalyzetext' ???????????????????????????????????????????????????????????? `odsetcharclass' ???????????????

+ +
+
void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars);
+
`odeum' ???????????????????????????????????????????????????`spachechars' ???????????????????????????????????????????????????`delimchars' ??????????????????????????????????????????????????????`gluechars' ???????????????????????????????????????????????????
+
+ +

???????????????????????????????????????????????????????????????????????? `odquery' ???????????????

+ +
+
ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors);
+
`odeum' ???????????????????????????????????????????????????`query' ??????????????????????????????????????????????????????`np' ????????????????????????????????????????????????????????????????????????`error' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `NULL' ????????????????????????????????????????????????ID??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `malloc' ???????????????????????????????????????????????? `free' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +

?????????????????????

+ +

????????????????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <cabin.h>
+#include <odeum.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define DBNAME   "index"
+
+int main(int argc, char **argv){
+  ODEUM *odeum;
+  ODDOC *doc;
+  CBLIST *awords;
+  const char *asis;
+  char *normal;
+  int i;
+
+  /* ??????????????????????????? */
+  if(!(odeum = odopen(DBNAME, OD_OWRITER | OD_OCREAT))){
+    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* ????????????????????????????????? */
+  doc = oddocopen("http://www.foo.bar/baz.txt");
+
+  /* ?????????????????????????????? */
+  oddocaddattr(doc, "title", "Balcony Scene");
+  oddocaddattr(doc, "author", "Shakespeare");
+
+  /* ??????????????????????????????????????????????????? */
+  awords = odbreaktext("Parting is such sweet sorrow.");
+
+  /* ?????????????????????????????????????????? */
+  for(i = 0; i < cblistnum(awords); i++){
+    /* ?????????????????????????????????????????? */
+    asis = cblistval(awords, i, NULL);
+    /* ??????????????????????????????????????? */
+    normal = odnormalizeword(asis);
+    /* ??????????????????????????????????????? */
+    oddocaddword(doc, normal, asis);
+    /* ????????????????????????????????? */
+    free(normal);
+  }
+
+  /* ?????????????????????????????????????????? */
+  if(!odput(odeum, doc, -1, 1)){
+    fprintf(stderr, "odput: %s\n", dperrmsg(dpecode));
+  }
+
+  /* ?????????????????????????????? */
+  cblistclose(awords);
+
+  /* ????????????????????????????????? */
+  oddocclose(doc);
+
+  /* ?????????????????????????????? */
+  if(!odclose(odeum)){
+    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

???????????????????????????????????????????????????????????????????????????????????????

+ +
#include <depot.h>
+#include <cabin.h>
+#include <odeum.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define DBNAME   "index"
+
+int main(int argc, char **argv){
+  ODEUM *odeum;
+  ODPAIR *pairs;
+  ODDOC *doc;
+  const CBLIST *words;
+  const char *title, *author, *asis;
+  int i, j, pnum;
+
+  /* ????????????????????????????????? */
+  if(!(odeum = odopen(DBNAME, OD_OREADER))){
+    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* ???????????????????????? */
+  if((pairs = odsearch(odeum, "sorrow", -1, &pnum)) != NULL){
+
+    /* ?????????????????????????????? */
+    for(i = 0; i < pnum; i++){
+      /* ????????????????????????????????? */
+      if(!(doc = odgetbyid(odeum, pairs[i].id))) continue;
+      /* ?????????????????????????????? */
+      printf("URI: %s\n", oddocuri(doc));
+      title = oddocgetattr(doc, "title");
+      if(title) printf("TITLE: %s\n", title);
+      author = oddocgetattr(doc, "author");
+      if(author) printf("AUTHOR: %s\n", author);
+      /* ?????????????????????????????????????????? */
+      printf("WORDS:");
+      words = oddocawords(doc);
+      for(j = 0; j < cblistnum(words); j++){
+        asis = cblistval(words, j, NULL);
+        printf(" %s", asis);
+      }
+      putchar('\n');
+      /* ????????????????????????????????? */
+      oddocclose(doc);
+    }
+
+    /* ?????????????????????????????? */
+    free(pairs);
+
+  } else {
+    fprintf(stderr, "odsearch: %s\n", dperrmsg(dpecode));
+  }
+
+  /* ?????????????????????????????? */
+  if(!odclose(odeum)){
+    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

??????

+ +

Odeum????????????????????????????????????????????????????????????Depot????????????????????????????????????

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

POSIX??????????????????????????????QDBM??????????????????????????????????????? `dpecode' ???????????????????????????????????????????????????????????????Odeum?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`errno' ??? `malloc' ???????????????????????????????????????????????????????????????????????????

+ +

ZLIB??????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????30%????????????????????????????????????Odeum????????????????????????ZLIB?????????????????????????????????ZLIB??????????????????????????????Odeum???????????????????????????ZLIB?????????????????????????????????????????????????????????????????????????????????????????????????????????ZLIB??????????????????LZO????????????????????????ZLIB???????????????LZO?????????????????????

+ +

?????????????????????

+ +

?????? `odquery' ?????????????????????????????????????????????????????????

+ +
expr ::= subexpr ( op subexpr )*
+subexpr ::= WORD
+subexpr ::= LPAREN expr RPAREN
+
+ +

????????????????????? "&"???AND?????? "|"???OR?????? "!"???NOTAND??????????????????????????????????????? "()" ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `odanalyzetext' ????????????????????????????????????"&"???"|"???"!"???"("???")" ???????????????????????????????????????????????????????????????????????????????????????????????????????????? "&" ?????????????????????????????????????????????????????? "joe blow" ??? "joe & blow" ?????????????????????

+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1?????????????????????????????????

+ +
+ +

Odeum???????????????

+ +

Odeum???????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `odmgr' ???Odeum???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`file' ?????????????????????`expr' ????????????URI???ID?????????`words' ???????????????`elems' ?????????????????????????????????????????????

+ +
+
odmgr create name
+
????????????????????????????????????????????????
+
odmgr put [-uri str] [-title str] [-author str] [-date str] [-wmax num] [-keep] name [file]
+
??????????????????????????????????????????????????????`file' ??????????????????????????????????????????????????????????????????URI??????????????????????????????
+
odmgr out [-id] name expr
+
URI???????????????????????????????????????
+
odmgr get [-id] [-t|-h] name expr
+
URI?????????????????????????????????????????????????????????ID?????????URI??????????????????????????????????????????????????????
+
odmgr search [-max num] [-or] [-idf] [-t|-h|-n] name words...
+
????????????????????????????????????????????????????????????1????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????2????????????????????????????????????ID?????????URI??????????????????????????????????????????????????????
+
odmgr list [-t|-h] name
+
????????????????????????????????????????????????????????????????????????????????????ID?????????URI??????????????????????????????????????????????????????
+
odmgr optimize name
+
???????????????????????????????????????
+
odmgr inform name
+
??????????????????????????????????????????????????????
+
odmgr merge name elems...
+
????????????????????????????????????????????????
+
odmgr remove name
+
??????????????????????????????????????????????????????
+
odmgr break [-h|-k|-s] [file]
+
???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
odmgr version
+
QDBM??????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -uri str : ?????????URI??????????????????????????????
  • +
  • -title str : ???????????????????????????????????????
  • +
  • -author str : ????????????????????????????????????
  • +
  • -date str : ???????????????????????????????????????
  • +
  • -wmax num : ?????????????????????????????????????????????
  • +
  • -keep : ??????URI?????????????????????????????????????????????????????????
  • +
  • -id : URI?????????ID?????????????????????????????????
  • +
  • -t : ?????????????????????????????????????????????????????????
  • +
  • -h : ????????????????????????????????????????????????????????????????????????
  • +
  • -k : ????????????????????????????????????????????????
  • +
  • -s : ???????????????????????????????????????
  • +
  • -max num : ????????????????????????????????????????????????
  • +
  • -or : AND???????????????OR??????????????????
  • +
  • -idf : IDF????????????????????????????????????
  • +
  • -n : ?????????ID????????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `odtest' ???Odeum????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `odmgr' ??????????????????????????????`time' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`name' ???????????????????????????`dnum' ???????????????`wnum' ????????????????????????`pnum' ??????????????????????????????????????????

+ +
+
odtest write [-tune ibnum idnum cbnum csiz] name dnum wnum pnum
+
??????????????????????????????????????????????????????????????????????????????????????????
+
odtest read name
+
?????????????????????????????????????????????????????????????????????
+
odtest combo name
+
???????????????????????????????????????????????????
+
odtest wicked name dnum
+
????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -tune ibnum idnum cbnum csiz : ???????????????????????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ?????????????????????????????????????????????????????????????????????????????????????????? `QDBMDBGFD' ???????????????????????? `dpecode' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????? `odidx' ???????????????????????????????????????????????????????????????????????????Odeum??????????????????????????????????????????????????????????????????????????????????????????Web??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????HTML???????????????????????????????????????????????????US-ASCII???ISO-8859-1????????????????????????URI??????????????????????????????????????????????????????????????????`title' ??? `date' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? '_mtime' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `_score' ??????????????????????????????????????????????? ?????????????????????????????????????`name' ???????????????????????????`dir' ??????????????????????????????????????????

+ +
+
odidx register [-l file] [-wmax num] [-tsuf sufs] [-hsuf sufs] name [dir]
+
???????????????????????????????????????????????????????????????????????????????????????`dir' ??????????????????????????????????????????????????????????????????????????????
+
odidx relate name
+
????????????????????????????????????????????????????????????????????????????????????????????????
+
odidx purge name
+
??????????????????????????????????????????????????????????????????????????????????????????
+
+ +

????????????????????????????????????????????????

+ +
    +
  • -l file : ????????????????????????????????????????????????????????????????????????????????????`-' ????????????????????????????????????????????????????????????
  • +
  • -wmax num : ??????????????????????????????????????????????????????????????????
  • +
  • -tsuf sufs : ????????????????????????????????????????????????????????????????????????????????????????????????????????? `-tsuf .txt,.text' ?????????????????????
  • +
  • -hsuf sufs : HTML????????????????????????????????????????????????????????????????????????????????? `-hsuf .html,.htm' ?????????????????????
  • +
+ +

?????????????????????????????????????????????????????? 0 ??????????????????????????????????????????????????????????????????????????????

+ +

Odeum????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `/home/mikio' ???????????????????????? `.txt' ??? `.c' ??? `.h' ????????????????????????????????????????????? `casket' ???????????????????????????????????????????????????????????????????????????????????????

+ +
odidx register -tsuf ".txt,.c,.h" -hsuf "" casket /home/mikio
+
+ +

????????????`unix' ????????? `posix' ????????????????????????????????????????????????8??????????????????????????????????????????????????????

+ +
odmgr search -max 8 -h casket "unix posix"
+
+ +

`odidx' ???????????????????????????????????????QDBM??????????????????????????????????????????CGI??????????????? `qfts.cgi' ????????????????????????????????????????????????

+ +
+ +

??????????????????????????????

+ +

Depot?????????????????????????????????

+ +

Depot??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

?????????????????????????????????????????? 48 ????????????????????????????????????????????????????????????????????????

+ +
    +
  1. ????????????????????? : ??????????????? 0 ??????????????????????????????????????????????????????????????? "[DEPOT]\n\f" ??????????????????????????????????????????????????????????????? "[depot]\n\f" ?????????????????????
  2. +
  3. ????????????????????? : ??????????????? 12 ????????????????????????????????????????????????????????????10???????????????????????????????????????????????????
  4. +
  5. ???????????????????????? : ??????????????? 16 ??????????????????`int' ????????????????????????
  6. +
  7. ????????????????????? : ??????????????? 24 ??????????????????`int' ????????????????????????
  8. +
  9. ?????????????????????????????? : ??????????????? 32 ??????????????????`int' ????????????????????????
  10. +
  11. ??????????????? : ??????????????? 40 ??????????????????`int' ????????????????????????
  12. +
+ +

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
    +
  1. ????????? : `int' ????????????????????????
  2. +
  3. ?????????????????????????????? : `int' ????????????????????????
  4. +
  5. ?????????????????? : `int' ????????????????????????
  6. +
  7. ??????????????? : `int' ????????????????????????
  8. +
  9. ??????????????????????????? : `int' ????????????????????????
  10. +
  11. ?????????????????? : `int' ????????????????????????
  12. +
  13. ?????????????????? : `int' ????????????????????????
  14. +
  15. ????????????????????? : ?????????????????????????????????????????????????????????????????????????????????
  16. +
  17. ?????????????????? : ??????????????????????????????????????????????????????????????????????????????
  18. +
  19. ??????????????? : ????????????????????????????????????????????????????????????????????????????????????????????????????????????
  20. +
+ +

Villa?????????????????????????????????

+ +

Villa??????????????????????????????Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `int' ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Villa?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????BER??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????128?????????????????????????????????

+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
    +
  1. ?????????????????? : ??????????????????????????????
  2. +
  3. ????????????????????? : ?????????????????????????????????????????????????????????????????????????????????
  4. +
  5. ????????? : ??????????????????????????????
  6. +
  7. ??????????????? : ??????????????????????????????????????????????????????????????????????????????
      +
    1. ????????? : ??????????????????????????????
    2. +
    3. ???????????? : ????????????????????????????????????????????????????????????????????????
    4. +
  8. +
+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `int' ??????ID????????????????????????????????????????????????????????????Depot????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
    +
  1. ??????????????????ID : ??????????????????????????????
  2. +
  3. ??????????????????ID : ??????????????????????????????
  4. +
  5. ???????????????????????? : ???????????????????????????????????????????????????
  6. +
+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
    +
  1. ????????????????????????ID : ??????????????????????????????
  2. +
  3. ?????????????????? : ??????????????????????????????
  4. +
  5. ????????????????????? : ?????????????????????????????????????????????????????????????????????????????????
  6. +
+ +

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `int' ??????ID????????????????????????????????????????????????????????????Depot??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
    +
  1. ????????????????????????ID : ??????????????????????????????
  2. +
  3. ?????????????????????????????? : ?????????????????????????????????????????????????????????
  4. +
+ +

??????

+ +

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Depot?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

Depot???Villa?????????????????????????????????????????????????????????????????????????????????MIME???????????? `application/x-qdbm' ??????????????????????????????????????????????????? `.qdb' ?????????????????????Curia???????????????????????????????????????????????????????????????????????????????????????TAR??????????????????????????????????????????????????????????????????????????????

+ +

????????????????????????????????????????????????????????? `file' ?????????????????????????????????????????????`magic' ??????????????????????????????????????????????????????

+ +
0       string          [DEPOT]\n\f     QDBM, big endian
+>12     string          x               \b, version=%s
+>19     byte            ^1              \b, Hash
+>19     byte            &1              \b, B+ tree
+>19     byte            &2              \b (deflated:ZLIB)
+>19     byte            &4              \b (deflated:LZO)
+>19     byte            &8              \b (deflated:BZIP2)
+>24     belong          x               \b, filesize=%d
+>32     belong          x               \b, buckets=%d
+>40     belong          x               \b, records=%d
+0       string          [depot]\n\f     QDBM, little endian
+>12     string          x               \b, version=%s
+>16     byte            ^1              \b, Hash
+>16     byte            &1              \b, B+ tree
+>16     byte            &2              \b (deflated:ZLIB)
+>16     byte            &4              \b (deflated:LZO)
+>16     byte            &8              \b (deflated:BZIP2)
+>24     lelong          x               \b, filesize=%d
+>32     lelong          x               \b, buckets=%d
+>40     lelong          x               \b, records=%d
+
+ +
+ +

????????????

+ +

QDBM???POSIX?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????API??????????????????????????????????????????????????????????????????????????????????????????????????????GCC????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? `Makefile' ?????????????????????????????????????????????????????????????????????????????????????????????????????????C?????????API???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
    +
  • Makefile.in : `./configure' ??????????????????`Makefile' ????????????????????????
  • +
  • myconf.h : ??????????????????????????????????????????
  • +
  • depot.h : ??????API???????????????
  • +
  • curia.h : ??????API???????????????
  • +
  • relic.h : NDBM??????API???????????????
  • +
  • hovel.h : GDBM??????API???????????????
  • +
  • cabin.h : ?????????????????????API???????????????
  • +
  • villa.h : ??????API???????????????
  • +
  • vista.h : ????????????API???????????????
  • +
  • odeum.h : ??????API???????????????
  • +
  • myconf.c : ??????????????????????????????
  • +
  • depot.c : ??????API????????????
  • +
  • curia.c : ??????API????????????
  • +
  • relic.c : NDBM??????API????????????
  • +
  • hovel.c : GDBM??????API????????????
  • +
  • cabin.c : ?????????????????????API????????????
  • +
  • villa.c : ??????API????????????
  • +
  • vista.c : ????????????API????????????
  • +
  • odeum.c : ??????API????????????
  • +
+ +

`fcntl' ?????????????????????????????????????????????????????????????????????????????????????????????????????????`Makefile' ?????????????????? `CFLAGS' ???????????? `-DMYNOLOCK' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`mmap' ???????????????????????????????????????????????????`CFLAGS' ??? `-DMYNOMMAP' ???????????????????????????`mmap' ??????????????? `malloc' ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`myconf.h' ??? `myconf.c' ?????????????????????????????????????????????????????????????????????????????????????????????

+ +

C++??????API??????POSIX???????????????????????????????????????????????????????????????????????????????????????????????????C++???API????????????????????????Java??????API??????JNI????????????????????????????????????????????????????????????????????????????????????????????????????????????`long long' ??? `int64' ??????????????????????????????????????????????????????Perl???Ruby??????API??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +
+ +

??????

+ +

QDBM?????????????????????????????????????????????????????????????????????????????????????????????

+ +

segmentation fault???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

+ +

???????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????OS????????????????????????????????????????????????????????????

+ +

1.7.13??????????????????????????????QDBM?????????????????????????????????????????????????????????????????????????????????????????????

+ +
+ +

????????????????????????

+ +
+
Q. : QDBM???SQL???????????????????????????
+
A. : QDBM???SQL???????????????????????????QDBM???RDBMS??????????????????????????????????????????????????????????????????????????????RDBMS?????????????????????SQLite?????????????????????????????????
+
Q. : ?????????????????????GDBM???NDBM???SDBM???Berkeley DB???????????????????????????
+
A. : ???????????????????????????????????????????????????????????????API??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????100???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????DBM???DBMS????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
Q. : ????????????????????????
+
A. : QDBM???????????????????????????????????????Aho?????? `Data Structures and Algorithms'??????????????????????????????????????????????????????????????????Sedgewick??? `Algorithms in C'?????????????????????????????????C?????????????????????????????????????????????
+
Q. : ??????API???????????????????????????
+
A. : ???????????????????????????????????????????????????????????????Depot??????????????????????????????????????????????????????Curia?????????????????????????????????????????????????????????????????????????????????Villa??????????????????????????????????????????????????????Vista?????????????????????????????????????????????????????????????????????ZLIB???LZO??????????????????QDBM??????????????????????????????Vista???????????????????????????
+
Q. : ?????????????????????????????????????????????????????????????????????
+
A. : ???API??????????????????????????????????????????????????????????????????`dptsv.c' ??? `crtsv.c' ??? `vltsv.c' ???????????????????????????
+
Q. : ????????????????????????????????????????????????????????????
+
A. : ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????CGI??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????CGI??????????????????SIGPIPE???SIGTERM??????????????????????????????????????????????????????????????????????????????
+
Q. : QDBM?????????????????????????????????????????????????????????
+
A. : QDBM????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Villa?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM???????????????????????????????????????????????????????????????????????????????????????
+
Q. : Depot???Curia??????????????????????????????????????????????????????????????????
+
A. : ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????32????????????????????????????????????
+
Q. : Villa???????????????????????????????????????????????????????????????
+
A. : ???????????????????????????????????????????????????????????????`lrecmax' ??? `nidxmax' ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????RAM??????????????????????????????`lcnum' ??? `ncnum' ????????????????????????????????????????????????ZLIB???LZO???BZIP2???????????????????????????`lrecmax' ??????????????????????????????????????????????????????
+
Q. : Villa???????????????????????????ZLIB???LZO???BZIP2???????????????????????????
+
A. : ??????????????????????????????BZIP2???????????????????????????????????????LZO??????ZLIB?????????????????????????????????????????????????????????????????????ZLIB???????????????????????????????????????????????????????????????????????????LZO???????????????????????????????????????????????????BZIP2???????????????????????????????????????????????????????????????LZO????????????????????????LZO?????????????????????GNU GPL???????????????????????????????????????
+
Q. : ???????????????????????????????????????
+
A. : ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM?????????DP_OSPARSE?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
Q. : ??????Depot???Curia??????????????????????????????????????????????????????
+
A. : ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Cabin???????????????????????????????????????????????????
+
Q. : ??????????????????????????????????????????????????????????????????
+
A. : ????????????????????????????????????????????????RAM???????????????????????????????????????????????????????????????I/O?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Linux?????????????????????EXT2???????????????????????????EXT3??? `writeback' ??????????????????????????????????????????ReiserFS???????????????????????????EXT3?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
Q. : `gcc' ??????????????? `cc' ????????????????????????????????????
+
A. : `LTmakefile' ????????????????????????
+
Q. : Visual C++????????????????????????????????????
+
A. : ????????????`Makefile' ??????????????? `VCmakefile' ??????????????????
+
Q. : ??????QDBM???????????????????????????????????????
+
A. : PHP???Scheme???Gauche??????OCaml????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
Q. : ???QDBM???????????????????????????????????????
+
A. : ???QDBM?????????Quick Database Manager???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
Q. : ???API?????????????????????????????????????????????????????????????????????
+
A. : 5?????????????????????????????????????????????????????????????????????????????????????????????depot????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????curia?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????relic????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????hovel?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????cabin??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????villa???????????????? ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????vista?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????odeum??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+ +
+ +

???????????????

+ +

QDBM?????????????????????????????????????????????????????????Free Software Foundation???????????????GNU Lesser General Public License??????????????????2.1???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????QDBM??????????????????????????????????????????????????????

+ +

QDBM???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????GNU Lesser General Public License????????????????????????

+ +

???????????????QDBM????????????GNU Lesser General Public License???????????????????????????????????????????????????`COPYING' ??????????????????????????????????????????????????????Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ???????????????????????????

+ +

QDBM??????????????????????????????????????????????????????????????????`mikio at users.sourceforge.net' ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????`http://lists.sourceforge.net/lists/listinfo/qdbm-users' ????????????????????????

+ +
+ + + + + + Deleted: box/trunk/qdbm/spex.html =================================================================== --- box/trunk/qdbm/spex.html 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/spex.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,4343 +0,0 @@ - - - - - - - - - - - - - - - -Specifications of QDBM Version 1 - - - - - -

Fundamental Specifications of QDBM Version 1

- -
Copyright (C) 2000-2007 Mikio Hirabayashi
-
Last Update: Thu, 26 Oct 2006 15:00:20 +0900
- - -
- -

Table of Contents

- -
    -
  1. Overview
  2. -
  3. Features
  4. -
  5. Installation
  6. -
  7. Depot: Basic API
  8. -
  9. Commands for Depot
  10. -
  11. Curia: Extended API
  12. -
  13. Commands for Curia
  14. -
  15. Relic: NDBM-compatible API
  16. -
  17. Commands for Relic
  18. -
  19. Hovel: GDBM-compatible API
  20. -
  21. Commands for Hovel
  22. -
  23. Cabin: Utility API
  24. -
  25. Commands for Cabin
  26. -
  27. Villa: Advanced API
  28. -
  29. Commands for Villa
  30. -
  31. Odeum: Inverted API
  32. -
  33. Commands for Odeum
  34. -
  35. File Format
  36. -
  37. Porting
  38. -
  39. Bugs
  40. -
  41. Frequently Asked Questions
  42. -
  43. Copying
  44. -
- -
- -

Overview

- -

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organized in hash table or B+ tree.

- -

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers: NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

- -

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting, and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

- -

QDBM is written in C, and provided as APIs of C, C++, Java, Perl, and Ruby. QDBM is available on platforms which have API conforming to POSIX. QDBM is a free software licensed under the GNU Lesser General Public License.

- -
- -

Features

- -

Effective Implementation of Hash Database

- -

QDBM is developed referring to GDBM for the purpose of the following three points: higher processing speed, smaller size of a database file, and simpler API. They have been achieved. Moreover, as with GDBM, the following three restrictions of traditional DBM: a process can handle only one database, the size of a key and a value is bounded, a database file is sparse, are cleared.

- -

QDBM uses hash algorithm to retrieve records. If a bucket array has sufficient number of elements, the time complexity of retrieval is `O(1)'. That is, time required for retrieving a record is constant, regardless of the scale of a database. It is also the same about storing and deleting. Collision of hash values is managed by separate chaining. Data structure of the chains is binary search tree. Even if a bucket array has unusually scarce elements, the time complexity of retrieval is `O(log n)'.

- -

QDBM attains improvement in retrieval by loading RAM with the whole of a bucket array. If a bucket array is on RAM, it is possible to access a region of a target record by about one path of file operations. A bucket array saved in a file is not read into RAM with the `read' call but directly mapped to RAM with the `mmap' call. Therefore, preparation time on connecting to a database is very short, and two or more processes can share the same memory map.

- -

If the number of elements of a bucket array is about half of records stored within a database, although it depends on characteristic of the input, the probability of collision of hash values is about 56.7% (36.8% if the same, 21.3% if twice, 11.5% if four times, 6.0% if eight times). In such case, it is possible to retrieve a record by two or less paths of file operations. If it is made into a performance index, in order to handle a database containing one million of records, a bucket array with half a million of elements is needed. The size of each element is 4 bytes. That is, if 2M bytes of RAM is available, a database containing one million records can be handled.

- -

QDBM provides two modes to connect to a database: `reader' and `writer'. A reader can perform retrieving but neither storing nor deleting. A writer can perform all access methods. Exclusion control between processes is performed when connecting to a database by file locking. While a writer is connected to a database, neither readers nor writers can be connected. While a reader is connected to a database, other readers can be connect, but writers can not. According to this mechanism, data consistency is guaranteed with simultaneous connections in multitasking environment.

- -

Traditional DBM provides two modes of the storing operations: `insert' and `replace'. In the case a key overlaps an existing record, the insert mode keeps the existing value, while the replace mode transposes it to the specified value. In addition to the two modes, QDBM provides `concatenate' mode. In the mode, the specified value is concatenated at the end of the existing value and stored. This feature is useful when adding a element to a value as an array. Moreover, although DBM has a method to fetch out a value from a database only by reading the whole of a region of a record, QDBM has a method to fetch out a part of a region of a value. When a value is treated as an array, this feature is also useful.

- -

Generally speaking, while succession of updating, fragmentation of available regions occurs, and the size of a database grows rapidly. QDBM deal with this problem by coalescence of dispensable regions and reuse of them, and featuring of optimization of a database. When overwriting a record with a value whose size is greater than the existing one, it is necessary to remove the region to another position of the file. Because the time complexity of the operation depends on the size of the region of a record, extending values successively is inefficient. However, QDBM deal with this problem by alignment. If increment can be put in padding, it is not necessary to remove the region.

- -

As for many file systems, it is impossible to handle a file whose size is more than 2GB. To deal with this problem, QDBM provides a directory database containing multiple database files. Due to this feature, it is possible to handle a database whose total size is up to 1TB in theory. Moreover, because database files can be deployed on multiple disks, the speed of updating operations can be improved as with RAID-0 (striping). It is also possible for the database files to deploy on multiple file servers using NFS and so on.

- -

Useful Implementation of B+ Tree Database

- -

Although B+ tree database is slower than hash database, it features ordering access to each record. The order can be assigned by users. Records of B+ tree are sorted and arranged in logical pages. Sparse index organized in B tree that is multiway balanced tree are maintained for each page. Thus, the time complexity of retrieval and so on is `O(log n)'. Cursor is provided to access each record in order. The cursor can jump to a position specified by a key and can step forward or backward from the current position. Because each page is arranged as double linked list, the time complexity of stepping cursor is `O(1)'.

- -

B+ tree database is implemented, based on above hash database. Because each page of B+ tree is stored as each record of hash database, B+ tree database inherits efficiency of storage management of hash database. Because the header of each record is smaller and alignment of each page is adjusted according to the page size, in most cases, the size of database file is cut by half compared to one of hash database. Although operation of many pages are required to update B+ tree, QDBM expedites the process by caching pages and reducing file operations. In most cases, because whole of the sparse index is cached on memory, it is possible to retrieve a record by one or less path of file operations.

- -

B+ tree database features transaction mechanism. It is possible to commit a series of operations between the beginning and the end of the transaction in a lump, or to abort the transaction and perform rollback to the state before the transaction. Even if the process of an application is crashed while the transaction, the database file is not broken.

- -

In case that QDBM was built with ZLIB, LZO, or BZIP2 enabled, a lossless data-compression library, the content of each page of B+ tree is compressed and stored in a file. Because each record in a page has similar patterns, high efficiency of compression is expected due to the Lempel-Ziv algorithm and the like. In case handling text data, the size of a database is reduced to about 25%. If the scale of a database is large and disk I/O is the bottleneck, featuring compression makes the processing speed improved to a large extent.

- -

Simple but Various Interfaces

- -

QDBM provides very simple APIs. You can perform database I/O as usual file I/O with `FILE' pointer defined in ANSI C. In the basic API of QDBM, entity of a database is recorded as one file. In the extended API, entity of a database is recorded as several files in one directory. Because the two APIs are very similar with each other, porting an application from one to the other is easy.

- -

APIs which are compatible with NDBM and GDBM are also provided. As there are a lot of applications using NDBM or GDBM, it is easy to port them onto QDBM. In most cases, it is completed only by replacement of header including (#include) and re-compiling. However, QDBM can not handle database files made by the original NDBM or GDBM.

- -

In order to handle records on memory easily, the utility API is provided. It implements memory allocating functions, sorting functions, extensible datum, array list, hash map, and so on. Using them, you can handle records in C language cheaply as in such script languages as Perl or Ruby.

- -

B+ tree database is used with the advanced API. The advanced API is implemented using the basic API and the utility API. Because the advanced API is also similar to the basic API and the extended API, it is easy to learn how to use it.

- -

In order to handle an inverted index which is used by full-text search systems, the inverted API is provided. If it is easy to handle an inverted index of documents, an application can focus on text processing and natural language processing. Because this API does not depend on character codes nor languages, it is possible to implement a full-text search system which can respond to various requests from users.

- -

Along with APIs for C, QDBM provides APIs for C++, Java, Perl, and Ruby. APIs for C are composed of seven kinds: the basic API, the extended API, the NDBM-compatible API, the GDBM-compatible API, the utility API, the advanced API, and the inverted API. Command line interfaces corresponding to each API are also provided. They are useful for prototyping, testing, debugging, and so on. The C++ API encapsulates database handling functions of the basic API, the extended API, and the advanced API with class mechanism of C++. The Java API has native methods calling the basic API, the extended API, and the advanced API with Java Native Interface. The Perl API has methods calling the basic API, the extended API, and the advanced API with XS language. The Ruby API has method calling the basic API, the extended API, and the advanced API as modules of Ruby. Moreover, CGI scripts for administration of databases, file uploading, and full-text search are provided.

- -

Wide Portability

- -

QDBM is implemented being based on syntax of ANSI C (C89) and using only APIs defined in ANSI C or POSIX. Thus, QDBM works on most UNIX and its compatible OSs. As for C API, checking operations have been done at least on the following platforms.

- -
    -
  • Linux (2.2, 2.4, 2.6) (IA32, IA64, AMD64, PA-RISC, Alpha, PowerPC, M68000, ARM)
  • -
  • FreeBSD (4.9, 5.0, 5.1, 5.2, 5.3) (IA32, IA64, SPARC, Alpha)
  • -
  • NetBSD (1.6) (IA32)
  • -
  • OpenBSD (3.4) (IA32)
  • -
  • SunOS (5.6, 5.7, 5.8, 5.9, 5.10) (IA32, SPARC)
  • -
  • HP-UX (11.11, 11.23) (IA64, PA-RISC)
  • -
  • AIX (5.2) (POWER)
  • -
  • Windows (2000, XP) (IA32, IA64, AMD64) (Cygwin, MinGW, Visual C++)
  • -
  • Mac OS X (10.2, 10.3, 10.4) (IA32, PowerPC)
  • -
  • Tru64 (5.1) (Alpha)
  • -
  • RISC OS (5.03) (ARM)
  • -
- -

Although a database file created by QDBM depends on byte order of the processor, to do with it, utilities to dump data in format which is independent to byte orders are provided.

- -
- -

Installation

- -

Preparation

- -

To install QDBM from a source package, GCC of 2.8 or later version and `make' are required.

- -

When an archive file of QDBM is extracted, change the current working directory to the generated directory and perform installation.

- -

Usual Steps

- -

Follow the procedures below on Linux, BSD, or SunOS.

- -

Run the configuration script.

- -
./configure
-
- -

Build programs.

- -
make
-
- -

Perform self-diagnostic test.

- -
make check
-
- -

Install programs. This operation must be carried out by the root user.

- -
make install
-
- -

Using GNU Libtool

- -

If above steps do not work, try the following steps. This way needs GNU Libtool of 1.5 or later version.

- -

Run the configuration script.

- -
./configure
-
- -

Build programs.

- -
make -f LTmakefile
-
- -

Perform self-diagnostic test.

- -
make -f LTmakefile check
-
- -

Install programs. This operation must be carried out by the root user.

- -
make -f LTmakefile install
-
- -

Result

- -

When a series of work finishes, the following files will be installed. As for the rest, manuals will be installed under `/usr/local/man/man1' and '/usr/local/man/man3', other documents will be installed under `/usr/local/share/qdbm'. A configuration file for `pkg-config' will be installed under `/usr/local/lib/pkgconfig'.

- -
/usr/local/include/depot.h
-/usr/local/include/curia.h
-/usr/local/include/relic.h
-/usr/local/include/hovel.h
-/usr/local/include/cabin.h
-/usr/local/include/villa.h
-/usr/local/include/vista.h
-/usr/local/include/odeum.h
-/usr/local/lib/libqdbm.a
-/usr/local/lib/libqdbm.so.14.13.0
-/usr/local/lib/libqdbm.so.14
-/usr/local/lib/libqdbm.so
-/usr/local/bin/dpmgr
-/usr/local/bin/dptest
-/usr/local/bin/dptsv
-/usr/local/bin/crmgr
-/usr/local/bin/crtest
-/usr/local/bin/crtsv
-/usr/local/bin/rlmgr
-/usr/local/bin/rltest
-/usr/local/bin/hvmgr
-/usr/local/bin/hvtest
-/usr/local/bin/cbtest
-/usr/local/bin/cbcodec
-/usr/local/bin/vlmgr
-/usr/local/bin/vltest
-/usr/local/bin/vltsv
-/usr/local/bin/odmgr
-/usr/local/bin/odtest
-/usr/local/bin/odidx
-/usr/local/bin/qmttest
-
- -

When you run a program linked dynamically to `libqdbm.so', the library search path should include `/usr/local/lib'. You can set the library search path with the environment variable `LD_LIBRARY_PATH'.

- -

To uninstall QDBM, execute the following command after `./configure'. This operation must be carried out by the root user.

- -
make uninstall
-
- -

If an old version of QDBM is installed on your system, uninstall it before installation of a new one.

- -

The other APIs except for C nor CGI scripts are not installed by default. Refer to `plus/xspex.html' to know how to install the C++ API. Refer to `java/jspex.html' to know how to install the Java API. Refer to `perl/plspex.html' to know how to install the Perl API. Refer to `ruby/rbspex.html' to know how to install the Ruby API. Refer to `cgi/cgispex.html' to know how to install the CGI script.

- -

To install QDBM from such a binary package as RPM, refer to the manual of the package manager. For example, if you use RPM, execute like the following command by the root user.

- -
rpm -ivh qdbm-1.x.x-x.i386.rpm
-
- -

For Windows

- -

On Windows (Cygwin), you should follow the procedures below for installation.

- -

Run the configuration script.

- -
./configure
-
- -

Build programs.

- -
make win
-
- -

Perform self-diagnostic test.

- -
make check-win
-
- -

Install programs. As well, perform `make uninstall-win' to uninstall them.

- -
make install-win
-
- -

On Windows, the import library `libqdbm.dll.a' is created as well as the static library `libqdbm.a', and the dynamic linking library `qdbm.dll' is created instead of such shared libraries as `libqdbm.so'. `qdbm.dll' is installed into `/usr/local/bin'.

- -

In order to build QDBM using MinGW on Cygwin, you should perform `make mingw' instead of `make win'. With the UNIX emulation layer of Cygwin, generated programs depend on `cygwin1.dll' (they come under GNU GPL). This problem is solved by linking them to the Win32 native DLL with MinGW.

- -

In order to build QDBM using Visual C++, you should edit `VCmakefile' and set the search paths for libraries and headers. And perform `nmake /f VCMakefile'. Applications linking to `qdbm.dll' should link to `msvcrt.dll' by `/MD' or `/MDd' option of the compiler. Refer to `VCmakefile' for detail configurations.

- -

For Mac OS X

- -

On Mac OS X (Darwin), you should follow the procedures below for installation.

- -

Run the configuration script.

- -
./configure
-
- -

Build programs.

- -
make mac
-
- -

Perform self-diagnostic test.

- -
make check-mac
-
- -

Install programs. As well, perform `make uninstall-mac' to uninstall them.

- -
make install-mac
-
- -

On Mac OS X, `libqdbm.dylib' and so on are created instead of `libqdbm.so' and so on. You can set the library search path with the environment variable `DYLD_LIBRARY_PATH'.

- -

For HP-UX

- -

On HP-UX, you should follow the procedures below for installation.

- -

Run the configuration script.

- -
./configure
-
- -

Build programs.

- -
make hpux
-
- -

Perform self-diagnostic test.

- -
make check-hpux
-
- -

Install programs. As well, perform `make uninstall-hpux' to uninstall them.

- -
make install-hpux
-
- -

On HP-UX, `libqdbm.sl' is created instead of `libqdbm.so' and so on. You can set the library search path with the environment variable `SHLIB_PATH'.

- -

For RISC OS

- -

On RISC OS, you should follow the procedures below for installation.

- -

Build programs. As `cc' is used for compilation by default, if you want to use `gcc', add the argument `CC=gcc'.

- -
make -f RISCmakefile
-
- -

When a series of work finishes, the library file `libqdbm' and such commands as `dpmgr' are generated. Because how to install them is not defined, copy them manually for installation. As with it, such header files as `depot.h' should be installed manually.

- -

Detail Configurations

- -

You can configure building processes by the following optional arguments of `./configure'.

- -
    -
  • --enable-debug : build for debugging. Enable debugging symbols, do not perform optimization, and perform static linking.
  • -
  • --enable-devel : build for development. Enable debugging symbols, perform optimization, and perform dynamic linking.
  • -
  • --enable-stable : build for stable release. Perform conservative optimization, and perform dynamic linking.
  • -
  • --enable-pthread : feature POSIX thread and treat global variables as thread specific data.
  • -
  • --disable-lock : build for environments without file locking.
  • -
  • --disable-mmap : build for environments without memory mapping.
  • -
  • --enable-zlib : feature ZLIB compression for B+ tree and inverted index.
  • -
  • --enable-lzo : feature LZO compression for B+ tree and inverted index.
  • -
  • --enable-bzip : feature BZIP2 compression for B+ tree and inverted index.
  • -
  • --enable-iconv : feature ICONV utilities for conversion of character encodings.
  • -
- -

Usually, QDBM and its applications can be built without any dependency on non-standard libraries except for `libqdbm.*'. However, they depend on `libpthread.*' if POSIX thread is enabled, and they depend on `libz.*' if ZLIB is enabled, and they depend on `liblzo2.*' if LZO is enabled, and they depend on `libbz2.*' if BZIP2 is enabled, and they depend on `libiconv.*' if ICONV is enabled.

- -

Because the license of LZO is GNU GPL, note that applications linking to `liblzo2.*' should meet commitments of GNU GPL.

- -
- -

Depot: Basic API

- -

Overview

- -

Depot is the basic API of QDBM. Almost all features for managing a database provided by QDBM are implemented by Depot. Other APIs are no more than wrappers of Depot. Depot is the fastest in all APIs of QDBM.

- -

In order to use Depot, you should include `depot.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

- -
-
#include <depot.h>
-
#include <stdlib.h>
-
- -

A pointer to `DEPOT' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `dpopen' and closed with `dpclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `dpclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used.

- -

API

- -

The external variable `dpversion' is the string containing the version information.

- -
-
extern const char *dpversion;
-
- -

The external variable `dpecode' is assigned with the last happened error code. Refer to `depot.h' for details of the error codes.

- -
-
extern int dpecode;
-
The initial value of this variable is `DP_ENOERR'. The other values are `DP_EFATAL', `DP_EMODE', `DP_EBROKEN', `DP_EKEEP', `DP_ENOITEM', `DP_EALLOC', `DP_EMAP', `DP_EOPEN', `DP_ECLOSE', `DP_ETRUNC', `DP_ESYNC', `DP_ESTAT', `DP_ESEEK', `DP_EREAD', `DP_EWRITE', `DP_ELOCK', `DP_EUNLINK', `DP_EMKDIR', `DP_ERMDIR', and `DP_EMISC'.
-
- -

The function `dperrmsg' is used in order to get a message string corresponding to an error code.

- -
-
const char *dperrmsg(int ecode);
-
`ecode' specifies an error code. The return value is the message string of the error code. The region of the return value is not writable.
-
- -

The function `dpopen' is used in order to get a database handle.

- -
-
DEPOT *dpopen(const char *name, int omode, int bnum);
-
`name' specifies the name of a database file. `omode' specifies the connection mode: `DP_OWRITER' as a writer, `DP_OREADER' as a reader. If the mode is `DP_OWRITER', the following may be added by bitwise or: `DP_OCREAT', which means it creates a new database if not exist, `DP_OTRUNC', which means it creates a new database regardless if one exists. Both of `DP_OREADER' and `DP_OWRITER' can be added to by bitwise or: `DP_ONOLCK', which means it opens a database file without file locking, or `DP_OLCKNB', which means locking is performed without blocking. `DP_OCREAT' can be added to by bitwise or: `DP_OSPARSE', which means it creates a database file as a sparse file. `bnum' specifies the number of elements of the bucket array. If it is not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. If `DP_ONOLCK' is used, the application is responsible for exclusion control.
-
- -

The function `dpclose' is used in order to close a database handle.

- -
-
int dpclose(DEPOT *depot);
-
`depot' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.
-
- -

The function `dpput' is used in order to store a record.

- -
-
int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
-
`depot' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `DP_DOVER', which means the specified value overwrites the existing one, `DP_DKEEP', which means the existing value is kept, `DP_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false.
-
- -

The function `dpout' is used in order to delete a record.

- -
-
int dpout(DEPOT *depot, const char *kbuf, int ksiz);
-
`depot' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key.
-
- -

The function `dpget' is used in order to retrieve a record.

- -
-
char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp);
-
`depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return valu e is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `dpgetwb' is used in order to retrieve a record and write the value into a buffer.

- -
-
int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf);
-
`depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be equal to or less than the size of the writing buffer. `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is written. If successful, the return value is the size of the written data, else, it is -1. -1 is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Note that no additional zero code is appended at the end of the region of the writing buffer.
-
- -

The function `dpvsiz' is used in order to get the size of the value of a record.

- -
-
int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz);
-
`depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. Because this function does not read the entity of a record, it is faster than `dpget'.
-
- -

The function `dpiterinit' is used in order to initialize the iterator of a database handle.

- -
-
int dpiterinit(DEPOT *depot);
-
`depot' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database.
-
- -

The function `dpiternext' is used in order to get the next key of the iterator.

- -
-
char *dpiternext(DEPOT *depot, int *sp);
-
`depot' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.
-
- -

The function `dpsetalign' is used in order to set alignment of a database handle.

- -
-
int dpsetalign(DEPOT *depot, int align);
-
`depot' specifies a database handle connected as a writer. `align' specifies the size of alignment. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.
-
- -

The function `dpsetfbpsiz' is used in order to set the size of the free block pool of a database handle.

- -
-
int dpsetfbpsiz(DEPOT *depot, int size);
-
`depot' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
-
- -

The function `dpsync' is used in order to synchronize updating contents with the file and the device.

- -
-
int dpsync(DEPOT *depot);
-
`depot' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database file.
-
- -

The function `dpoptimize' is used in order to optimize a database.

- -
-
int dpoptimize(DEPOT *depot, int bnum);
-
`depot' specifies a database handle connected as a writer. `bnum' specifies the number of the elements of the bucket array. If it is not more than 0, the default value is specified. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them.
-
- -

The function `dpname' is used in order to get the name of a database.

- -
-
char *dpname(DEPOT *depot);
-
`depot' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `dpfsiz' is used in order to get the size of a database file.

- -
-
int dpfsiz(DEPOT *depot);
-
`depot' specifies a database handle. If successful, the return value is the size of the database file, else, it is -1.
-
- -

The function `dpbnum' is used in order to get the number of the elements of the bucket array.

- -
-
int dpbnum(DEPOT *depot);
-
`depot' specifies a database handle. If successful, the return value is the number of the elements of the bucket array, else, it is -1.
-
- -

The function `dpbusenum' is used in order to get the number of the used elements of the bucket array.

- -
-
int dpbusenum(DEPOT *depot);
-
`depot' specifies a database handle. If successful, the return value is the number of the used elements of the bucket array, else, it is -1. This function is inefficient because it accesses all elements of the bucket array.
-
- -

The function `dprnum' is used in order to get the number of the records stored in a database.

- -
-
int dprnum(DEPOT *depot);
-
`depot' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1.
-
- -

The function `dpwritable' is used in order to check whether a database handle is a writer or not.

- -
-
int dpwritable(DEPOT *depot);
-
`depot' specifies a database handle. The return value is true if the handle is a writer, false if not.
-
- -

The function `dpfatalerror' is used in order to check whether a database has a fatal error or not.

- -
-
int dpfatalerror(DEPOT *depot);
-
`depot' specifies a database handle. The return value is true if the database has a fatal error, false if not.
-
- -

The function `dpinode' is used in order to get the inode number of a database file.

- -
-
int dpinode(DEPOT *depot);
-
`depot' specifies a database handle. The return value is the inode number of the database file.
-
- -

The function `dpmtime' is used in order to get the last modified time of a database.

- -
-
time_t dpmtime(DEPOT *depot);
-
`depot' specifies a database handle. The return value is the last modified time of the database.
-
- -

The function `dpfdesc' is used in order to get the file descriptor of a database file.

- -
-
int dpfdesc(DEPOT *depot);
-
`depot' specifies a database handle. The return value is the file descriptor of the database file. Handling the file descriptor of a database file directly is not suggested.
-
- -

The function `dpremove' is used in order to remove a database file.

- -
-
int dpremove(const char *name);
-
`name' specifies the name of a database file. If successful, the return value is true, else, it is false.
-
- -

The function `dprepair' is used in order to repair a broken database file.

- -
-
int dprepair(const char *name);
-
`name' specifies the name of a database file. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database file correspond to the original or expected state.
-
- -

The function `dpexportdb' is used in order to dump all records as endian independent data.

- -
-
int dpexportdb(DEPOT *depot, const char *name);
-
`depot' specifies a database handle. `name' specifies the name of an output file. If successful, the return value is true, else, it is false.
-
- -

The function `dpimportdb' is used in order to load all records from endian independent data.

- -
-
int dpimportdb(DEPOT *depot, const char *name);
-
`depot' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input file. If successful, the return value is true, else, it is false.
-
- -

The function `dpsnaffle' is used in order to retrieve a record directly from a database file.

- -
-
char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
-
`name' specifies the name of a database file. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Although this function can be used even while the database file is locked by another process, it is not assured that recent updated is reflect ed.
-
- -

The function `dpinnerhash' is a hash function used inside Depot.

- -
-
int dpinnerhash(const char *kbuf, int ksiz);
-
`kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the hash value of 31 bits length computed from the key. This function is useful when an application calculates the state of the inside bucket array.
-
- -

The function `dpouterhash' is a hash function which is independent from the hash functions used inside Depot.

- -
-
int dpouterhash(const char *kbuf, int ksiz);
-
`kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the hash value of 31 bits length computed from the key. This function is useful when an application uses its own hash algorithm outside Depot.
-
- -

The function `dpprimenum' is used in order to get a natural prime number not less than a number.

- -
-
int dpprimenum(int num);
-
`num' specified a natural number. The return value is a natural prime number not less than the specified number. This function is useful when an application determines the size of a bucket array of its own hash algorithm.
-
- -

Examples

- -

The following example stores and retrieves a phone number, using the name as the key.

- -
#include <depot.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define NAME     "mikio"
-#define NUMBER   "000-1234-5678"
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  DEPOT *depot;
-  char *val;
-
-  /* open the database */
-  if(!(depot = dpopen(DBNAME, DP_OWRITER | DP_OCREAT, -1))){
-    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* store the record */
-  if(!dpput(depot, NAME, -1, NUMBER, -1, DP_DOVER)){
-    fprintf(stderr, "dpput: %s\n", dperrmsg(dpecode));
-  }
-
-  /* retrieve the record */
-  if(!(val = dpget(depot, NAME, -1, 0, -1, NULL))){
-    fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
-  } else {
-    printf("Name: %s\n", NAME);
-    printf("Number: %s\n", val);
-    free(val);
-  }
-
-  /* close the database */
-  if(!dpclose(depot)){
-    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

The following example shows all records of the database.

- -
#include <depot.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  DEPOT *depot;
-  char *key, *val;
-
-  /* open the database */
-  if(!(depot = dpopen(DBNAME, DP_OREADER, -1))){
-    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* initialize the iterator */
-  if(!dpiterinit(depot)){
-    fprintf(stderr, "dpiterinit: %s\n", dperrmsg(dpecode));
-  }
-
-  /* scan with the iterator */
-  while((key = dpiternext(depot, NULL)) != NULL){
-    if(!(val = dpget(depot, key, -1, 0, -1, NULL))){
-      fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
-      free(key);
-      break;
-    }
-    printf("%s: %s\n", key, val);
-    free(val);
-    free(key);
-  }
-
-  /* close the database */
-  if(!dpclose(depot)){
-    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

Notes

- -

For building a program using Depot, the program should be linked with a library file `libqdbm.a' or `libqdbm.so'. For example, the following command is executed to build `sample' from `sample.c'.

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Depot are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

- -
- -

Commands for Depot

- -

Depot has the following command line interfaces.

- -

The command `dpmgr' is a utility for debugging Depot and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

- -
-
dpmgr create [-s] [-bnum num] name
-
Create a database file.
-
dpmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-na] name key val
-
Store a record with a key and a value.
-
dpmgr out [-kx|-ki] name key
-
Delete a record with a key.
-
dpmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-n] name key
-
Retrieve a record with a key and output it to the standard output.
-
dpmgr list [-nl] [-k|-v] [-ox] name
-
List all keys and values delimited with tab and line-feed to the standard output.
-
dpmgr optimize [-bnum num] [-na] name
-
Optimize a database.
-
dpmgr inform [-nl] name
-
Output miscellaneous information to the standard output.
-
dpmgr remove name
-
Remove a database file.
-
dpmgr repair name
-
Repair a broken database file.
-
dpmgr exportdb name file
-
Dump all records as endian independent data.
-
dpmgr importdb [-bnum num] name file
-
Load all records from endian independent data.
-
dpmgr snaffle [-kx|-ki] [-ox] [-n] name key
-
Retrieve a record from a locked database with a key and output it to the standard output.
-
dpmgr version
-
Output version information of QDBM to the standard output.
-
- -

Options feature the following.

- -
    -
  • -s : make the file sparse.
  • -
  • -bnum num : specify the number of the elements of the bucket array.
  • -
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • -
  • -ki : treat `key' as an integer expression of decimal notation.
  • -
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • -
  • -vi : treat `val' as an integer expression of decimal notation.
  • -
  • -vf : read the value from a file specified with `val'.
  • -
  • -keep : specify the storing mode for `DP_DKEEP'.
  • -
  • -cat : specify the storing mode for `DP_DCAT'.
  • -
  • -na : do not set alignment.
  • -
  • -nl : open the database without file locking.
  • -
  • -start : specify the beginning offset of a value to fetch.
  • -
  • -max : specify the max size of a value to fetch.
  • -
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • -
  • -n : do not output the tailing newline.
  • -
  • -k : output keys only.
  • -
  • -v : output values only.
  • -
- -

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

- -

The command `dptest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of the records. `bnum' specifies the number of the elements of the bucket array. `pnum' specifies the number of patterns of the keys. `align' specifies the basic size of alignment. `fbpsiz' specifies the size of the free block pool.

- -
-
dptest write [-s] name rnum bnum
-
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
-
dptest read [-wb] name
-
Retrieve all records of the database above.
-
dptest rcat [-c] name rnum bnum pnum align fbpsiz
-
Store records with partway duplicated keys using concatenate mode.
-
dptest combo name
-
Perform combination test of various operations.
-
dptest wicked [-c] name rnum
-
Perform updating operations selected at random.
-
- -

Options feature the following.

- -
    -
  • -s : make the file sparse.
  • -
  • -wb : use the function `dpgetwb' instead of the function `dpget'.
  • -
  • -c : perform comparison test with map of Cabin.
  • -
- -

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

- -

The command `dptsv' features mutual conversion between a database of Depot and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the following format. `name' specifies a database name. The subcommand `export' reads TSV data from the standard input. If a key overlaps, the latter is adopted. `-bnum' specifies the number of the elements of the bucket array. The subcommand `import' writes TSV data to the standard output.

- -
-
dptsv import [-bnum num] [-bin] name
-
Create a database from TSV.
-
dptsv export [-bin] name
-
Write TSV data of a database.
-
- -

Options feature the following.

- -
    -
  • -bnum num : specify the number of the elements of the bucket array.
  • -
  • -bin : treat records as Base64 format.
  • -
- -

This command returns 0 on success, another on failure.

- -

Commands of Depot realize a simple database system. For example, to make a database to search `/etc/password' by a user name, perform the following command.

- -
cat /etc/passwd | tr ':' '\t' | dptsv import casket
-
- -

Thus, to retrieve the information of a user `mikio', perform the following command.

- -
dpmgr get casket mikio
-
- -

It is easy to implement functions upsides with these commands, using the API of Depot.

- -
- -

Curia: Extended API

- -

Overview

- -

Curia is the extended API of QDBM. It provides routines for managing multiple database files in a directory. Restrictions of some file systems that the size of each file is limited are escaped by dividing a database file into two or more. If the database files deploy on multiple devices, the scalability is improved.

- -

Although Depot creates a database with a file name, Curia creates a database with a directory name. A database file named as `depot' is placed in the specified directory. Although it keeps the attribute of the database, it does not keep the entities of the records. Besides, sub directories are created by the number of division of the database, named with 4 digits. The database files are placed in the subdirectories. The entities of the records are stored in the database file. For example, in the case that a database directory named as `casket' and the number of division is 3, `casket/depot', `casket/0001/depot', `casket/0002/depot' and `casket/0003/depot' are created. No error occurs even if the namesake directory exists when creating a database. So, if sub directories exists and some devices are mounted on the sub directories, the database files deploy on the multiple devices.

- -

Curia features managing large objects. Although usual records are stored in some database files, records of large objects are stored in individual files. Because the files of large objects are deployed in different directories named with the hash values, the access speed is part-way robust although it is slower than the speed of usual records. Large and not often accessed data should be secluded as large objects. By doing this, the access speed of usual records is improved. The directory hierarchies of large objects are placed in the directory named as `lob' in the sub directories of the database. Because the key spaces of the usual records and the large objects are different, the operations keep out of each other.

- -

In order to use Curia, you should include `depot.h', `curia.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

- -
-
#include <depot.h>
-
#include <curia.h>
-
#include <stdlib.h>
-
- -

A pointer to `CURIA' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `cropen' and closed with `crclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `crclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database directory should not be used.

- -

Curia also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code.

- -

API

- -

The function `cropen' is used in order to get a database handle.

- -
-
CURIA *cropen(const char *name, int omode, int bnum, int dnum);
-
`name' specifies the name of a database directory. `omode' specifies the connection mode: `CR_OWRITER' as a writer, `CR_OREADER' as a reader. If the mode is `CR_OWRITER', the following may be added by bitwise or: `CR_OCREAT', which means it creates a new database if not exist, `CR_OTRUNC', which means it creates a new database regardless if one exists. Both of `CR_OREADER' and `CR_OWRITER' can be added to by bitwise or: `CR_ONOLCK', which means it opens a database directory without file locking, or `CR_OLCKNB', which means locking is performed without blocking. `CR_OCREAT' can be added to by bitwise or: `CR_OSPARSE', which means it creates database files as sparse files. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. The size of each bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of each bucket array is about from 0.5 to 4 times of the number of all records to store. `dnum' specifies the number of division of the database. If it is not more than 0, the default value is specified. The number of division can not be changed from the initial value. The max number of division is 512. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `CR_ONOLCK' is used, the application is responsible for exclusion control.
-
- -

The function `crclose' is used in order to close a database handle.

- -
-
int crclose(CURIA *curia);
-
`curia' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.
-
- -

The function `crput' is used in order to store a record.

- -
-
int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
-
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', which means the specified value overwrites the existing one, `CR_DKEEP', which means the existing value is kept, `CR_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false.
-
- -

The function `crout' is used in order to delete a record.

- -
-
int crout(CURIA *curia, const char *kbuf, int ksiz);
-
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key.
-
- -

The function `crget' is used in order to retrieve a record.

- -
-
char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
-
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return valu e is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `crgetwb' is used in order to retrieve a record and write the value into a buffer.

- -
-
int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf);
-
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be equal to or less than the size of the writing buffer. `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is written. If successful, the return value is the size of the written data, else, it is -1. -1 is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Note that no additional zero code is appended at the end of the region of the writing buffer.
-
- -

The function `crvsiz' is used in order to get the size of the value of a record.

- -
-
int crvsiz(CURIA *curia, const char *kbuf, int ksiz);
-
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. Because this function does not read the entity of a record, it is faster than `crget'.
-
- -

The function `criterinit' is used in order to initialize the iterator of a database handle.

- -
-
int criterinit(CURIA *curia);
-
`curia' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database.
-
- -

The function `criternext' is used in order to get the next key of the iterator.

- -
-
char *criternext(CURIA *curia, int *sp);
-
`curia' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.
-
- -

The function `crsetalign' is used in order to set alignment of a database handle.

- -
-
int crsetalign(CURIA *curia, int align);
-
`curia' specifies a database handle connected as a writer. `align' specifies the size of alignment. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.
-
- -

The function `crsetfbpsiz' is used in order to set the size of the free block pool of a database handle.

- -
-
int crsetfbpsiz(CURIA *curia, int size);
-
`curia' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
-
- -

The function `crsync' is used in order to synchronize updating contents with the files and the devices.

- -
-
int crsync(CURIA *curia);
-
`curia' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database directory.
-
- -

The function `croptimize' is used in order to optimize a database.

- -
-
int croptimize(CURIA *curia, int bnum);
-
`curia' specifies a database handle connected as a writer. `bnum' specifies the number of the elements of each bucket array. If it is not more than 0, the default value is specified. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them.
-
- -

The function `crname' is used in order to get the name of a database.

- -
-
char *crname(CURIA *curia);
-
`curia' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `crfsiz' is used in order to get the total size of database files.

- -
-
int crfsiz(CURIA *curia);
-
`curia' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1. If the total size is more than 2GB, the return value overflows.
-
- -

The function `crfsizd' is used in order to get the total size of database files as double-precision floating-point number.

- -
-
double crfsizd(CURIA *curia);
-
`curia' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1.0.
-
- -

The function `crbnum' is used in order to get the total number of the elements of each bucket array.

- -
-
int crbnum(CURIA *curia);
-
`curia' specifies a database handle. If successful, the return value is the total number of the elements of each bucket array, else, it is -1.
-
- -

The function `crbusenum' is used in order to get the total number of the used elements of each bucket array.

- -
-
int crbusenum(CURIA *curia);
-
`curia' specifies a database handle. If successful, the return value is the total number of the used elements of each bucket array, else, it is -1. This function is inefficient because it accesses all elements of each bucket array.
-
- -

The function `crrnum' is used in order to get the number of the records stored in a database.

- -
-
int crrnum(CURIA *curia);
-
`curia' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1.
-
- -

The function `crwritable' is used in order to check whether a database handle is a writer or not.

- -
-
int crwritable(CURIA *curia);
-
`curia' specifies a database handle. The return value is true if the handle is a writer, false if not.
-
- -

The function `crfatalerror' is used in order to check whether a database has a fatal error or not.

- -
-
int crfatalerror(CURIA *curia);
-
`curia' specifies a database handle. The return value is true if the database has a fatal error, false if not.
-
- -

The function `crinode' is used in order to get the inode number of a database directory.

- -
-
int crinode(CURIA *curia);
-
`curia' specifies a database handle. The return value is the inode number of the database directory.
-
- -

The function `crmtime' is used in order to get the last modified time of a database.

- -
-
time_t crmtime(CURIA *curia);
-
`curia' specifies a database handle. The return value is the last modified time of the database.
-
- -

The function `crremove' is used in order to remove a database directory.

- -
-
int crremove(const char *name);
-
`name' specifies the name of a database directory. If successful, the return value is true, else, it is false.
-
- -

The function `crrepair' is used in order to repair a broken database directory.

- -
-
int crrepair(const char *name);
-
`name' specifies the name of a database directory. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database directory correspond to the original or expected state.
-
- -

The function `crexportdb' is used in order to dump all records as endian independent data.

- -
-
int crexportdb(CURIA *curia, const char *name);
-
`curia' specifies a database handle. `name' specifies the name of an output directory. If successful, the return value is true, else, it is false. Note that large objects are ignored.
-
- -

The function `crimportdb' is used in order to load all records from endian independent data.

- -
-
int crimportdb(CURIA *curia, const char *name);
-
`curia' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input directory. If successful, the return value is true, else, it is false. Note that large objects are ignored.
-
- -

The function `crsnaffle' is used in order to retrieve a record directly from a database directory.

- -
-
char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
-
`name' specifies the name of a database directory. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Although this function can be used even while the database directory is locked by another process, it is not assured that recent updated is reflected.
-
- -

The function `crputlob' is used in order to store a large object.

- -
-
int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
-
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', which means the specified value overwrites the existing one, `CR_DKEEP', which means the existing value is kept, `CR_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false.
-
- -

The function `croutlob' is used in order to delete a large object.

- -
-
int croutlob(CURIA *curia, const char *kbuf, int ksiz);
-
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. false is returned when no large object corresponds to the specified key.
-
- -

The function `crgetlob' is used in order to retrieve a large object.

- -
-
char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
-
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding large object, else, it is `NULL'. `NULL' is returned when no large object corresponds to the specified key or the size of the value of the corresponding large object is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `crgetlobfd' is used in order to get the file descriptor of a large object.

- -
-
int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz);
-
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the file descriptor of the corresponding large object, else, it is -1. -1 is returned when no large object corresponds to the specified key. The returned file descriptor is opened with the `open' call. If the database handle was opened as a writer, the descriptor is writable (O_RDWR), else, it is not writable (O_RDONLY). The descriptor should be closed with the `close' call if it is no longer in use.
-
- -

The function `crvsizlob' is used in order to get the size of the value of a large object.

- -
-
int crvsizlob(CURIA *curia, const char *kbuf, int ksiz);
-
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding large object, else, it is -1. Because this function does not read the entity of a large object, it is faster than `crgetlob'.
-
- -

The function `crrnumlob' is used in order to get the number of the large objects stored in a database.

- -
-
int crrnumlob(CURIA *curia);
-
`curia' specifies a database handle. If successful, the return value is the number of the large objects stored in the database, else, it is -1.
-
- -

Examples

- -

The following example stores and retrieves a phone number, using the name as the key.

- -
#include <depot.h>
-#include <curia.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define NAME     "mikio"
-#define NUMBER   "000-1234-5678"
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  CURIA *curia;
-  char *val;
-
-  /* open the database */
-  if(!(curia = cropen(DBNAME, CR_OWRITER | CR_OCREAT, -1, -1))){
-    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* store the record */
-  if(!crput(curia, NAME, -1, NUMBER, -1, CR_DOVER)){
-    fprintf(stderr, "crput: %s\n", dperrmsg(dpecode));
-  }
-
-  /* retrieve the record */
-  if(!(val = crget(curia, NAME, -1, 0, -1, NULL))){
-    fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
-  } else {
-    printf("Name: %s\n", NAME);
-    printf("Number: %s\n", val);
-    free(val);
-  }
-
-  /* close the database */
-  if(!crclose(curia)){
-    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

The following example shows all records of the database.

- -
#include <depot.h>
-#include <curia.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  CURIA *curia;
-  char *key, *val;
-
-  /* open the database */
-  if(!(curia = cropen(DBNAME, CR_OREADER, -1, -1))){
-    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* initialize the iterator */
-  if(!criterinit(curia)){
-    fprintf(stderr, "criterinit: %s\n", dperrmsg(dpecode));
-  }
-
-  /* scan with the iterator */
-  while((key = criternext(curia, NULL)) != NULL){
-    if(!(val = crget(curia, key, -1, 0, -1, NULL))){
-      fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
-      free(key);
-      break;
-    }
-    printf("%s: %s\n", key, val);
-    free(val);
-    free(key);
-  }
-
-  /* close the iterator */
-  if(!crclose(curia)){
-    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

Notes

- -

How to build programs using Curia is the same as the case of Depot.

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Curia are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

- -
- -

Commands for Curia

- -

Curia has the following command line interfaces.

- -

The command `crmgr' is a utility for debugging Curia and its applications. It features editing and checking of a database. It can be used for the database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

- -
-
crmgr create [-s] [-bnum num] [-dnum num] name
-
Create a database file.
-
crmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] name key val
-
Store a record with a key and a value.
-
crmgr out [-kx|-ki] [-lob] name key
-
Delete a record with a key.
-
crmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-lob] [-n] name key
-
Retrieve a record with a key and output it to the standard output.
-
crmgr list [-nl] [-k|-v] [-ox] name
-
List all keys and values delimited with tab and line-feed to the standard output.
-
crmgr optimize [-bnum num] [-na] name
-
Optimize a database.
-
crmgr inform [-nl] name
-
Output miscellaneous information to the standard output.
-
crmgr remove name
-
Remove a database directory.
-
crmgr repair name
-
Repair a broken database directory.
-
crmgr exportdb name dir
-
Dump all records as endian independent data.
-
crmgr importdb [-bnum num] [-dnum num] name dir
-
Load all records from endian independent data.
-
crmgr snaffle [-kx|-ki] [-ox] [-n] name key
-
Retrieve a record from a locked database with a key and output it to the standard output.
-
crmgr version
-
Output version information of QDBM to the standard output.
-
- -

Options feature the following.

- -
    -
  • -s : make the files sparse.
  • -
  • -bnum num : specify the number of elements of each bucket array.
  • -
  • -dnum num : specify the number of division of the database.
  • -
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • -
  • -ki : treat `key' as an integer expression of decimal notation.
  • -
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • -
  • -vi : treat `val' as an integer expression of decimal notation.
  • -
  • -vf : read the value from a file specified with `val'.
  • -
  • -keep : specify the storing mode for `CR_DKEEP'.
  • -
  • -cat : specify the storing mode for `CR_DCAT'.
  • -
  • -na : do not set alignment.
  • -
  • -nl : open the database without file locking.
  • -
  • -start : specify the beginning offset of a value to fetch.
  • -
  • -max : specify the max size of a value to fetch.
  • -
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • -
  • -lob : handle large objects.
  • -
  • -n : do not output the tailing newline.
  • -
  • -k : output keys only.
  • -
  • -v : output values only.
  • -
- -

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

- -

The command `crtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records. `bnum' specifies the number of elements of a bucket array. `dnum' specifies the number of division of a database. `pnum' specifies the number of patterns of the keys. `align' specifies the basic size of alignment. `fbpsiz' specifies the size of the free block pool.

- -
-
crtest write [-s] [-lob] name rnum bnum dnum
-
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
-
crtest read [-wb] [-lob] name
-
Retrieve all records of the database above.
-
crtest rcat [-c] name rnum bnum dnum pnum align fbpsiz
-
Store records with partway duplicated keys using concatenate mode.
-
crtest combo name
-
Perform combination test of various operations.
-
crtest wicked [-c] name rnum
-
Perform updating operations selected at random.
-
- -

Options feature the following.

- -
    -
  • -s : make the files sparse.
  • -
  • -lob : handle large objects.
  • -
  • -wb : use the function `crgetwb' instead of the function `crget'.
  • -
  • -c : perform comparison test with map of Cabin.
  • -
- -

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

- -

The command `crtsv' features mutual conversion between a database of Curia and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the following format. `name' specifies a database name. The subcommand `export' reads TSV data from the standard input. If a key overlaps, the latter is adopted. `-bnum' specifies the number of the elements of the bucket array. `-dnum' specifies the number of division of the database. The subcommand `import' writes TSV data to the standard output.

- -
-
crtsv import [-bnum num] [-dnum num] [-bin] name
-
Create a database from TSV.
-
crtsv export [-bin] name
-
Write TSV data of a database.
-
- -

Options feature the following.

- -
    -
  • -bnum num : specify the number of the elements of the bucket array.
  • -
  • -dnum num : specify the number of division of the database.
  • -
  • -bin : treat records as Base64 format.
  • -
- -

This command returns 0 on success, another on failure.

- -

Commands of Curia realize a simple database system. For example, to make a database to search `/etc/password' by a user name, perform the following command.

- -
cat /etc/passwd | tr ':' '\t' | crtsv import casket
-
- -

Thus, to retrieve the information of a user `mikio', perform the following command.

- -
crmgr get casket mikio
-
- -

It is easy to implement functions upsides with these commands, using the API of Curia.

- -
- -

Relic: NDBM-compatible API

- -

Overview

- -

Relic is the API which is compatible with NDBM. So, Relic wraps functions of Depot as API of NDBM. It is easy to port an application from NDBM to QDBM. In most cases, you should only replace the includings of `ndbm.h' with `relic.h' and replace the linking option `-lndbm' with `-lqdbm'.

- -

The original NDBM treats a database as a pair of files. One, `a directory file', has a name with suffix `.dir' and stores a bit map of keys. The other, `a data file', has a name with suffix `.pag' and stores entities of each records. Relic creates the directory file as a mere dummy file and creates the data file as a database. Relic has no restriction about the size of each record. Relic can not handle database files made by the original NDBM.

- -

In order to use Relic, you should include `relic.h', `stdlib.h', `sys/types.h', `sys/stat.h' and `fcntl.h' in the source files. Usually, the following description will be near the beginning of a source file.

- -
-
#include <relic.h>
-
#include <stdlib.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
- -

A pointer to `DBM' is used as a database handle. A database handle is opened with the function `dbm_open' and closed with `dbm_close'. You should not refer directly to any member of a handle.

- -

API

- -

Structures of `datum' type is used in order to give and receive data of keys and values with functions of Relic.

- -
-
typedef struct { void *dptr; size_t dsize; } datum;
-
`dptr' specifies the pointer to the region of a key or a value. `dsize' specifies the size of the region.
-
- -

The function `dbm_open' is used in order to get a database handle.

- -
-
DBM *dbm_open(char *name, int flags, int mode);
-
`name' specifies the name of a database. The file names are concatenated with suffixes. `flags' is the same as the one of `open' call, although `O_WRONLY' is treated as `O_RDWR' and additional flags except for `O_CREAT' and `O_TRUNC' have no effect. `mode' specifies the mode of the database file as the one of `open' call does. The return value is the database handle or `NULL' if it is not successful.
-
- -

The function `dbm_close' is used in order to close a database handle.

- -
-
void dbm_close(DBM *db);
-
`db' specifies a database handle. Because the region of the closed handle is released, it becomes impossible to use the handle.
-
- -

The function `dbm_store' is used in order to store a record.

- -
-
int dbm_store(DBM *db, datum key, datum content, int flags);
-
`db' specifies a database handle. `key' specifies a structure of a key. `content' specifies a structure of a value. `flags' specifies behavior when the key overlaps, by the following values: `DBM_REPLACE', which means the specified value overwrites the existing one, `DBM_INSERT', which means the existing value is kept. The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, -1 if other error occurs.
-
- -

The function `dbm_delete' is used in order to delete a record.

- -
-
int dbm_delete(DBM *db, datum key);
-
`db' specifies a database handle. `key' specifies a structure of a key. The return value is 0 if it is successful, -1 if some errors occur.
-
- -

The function `dbm_fetch' is used in order to retrieve a record.

- -
-
datum dbm_fetch(DBM *db, datum key);
-
`db' specifies a database handle. `key' specifies a structure of a key. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function with the same handle.
-
- -

The function `dbm_firstkey' is used in order to get the first key of a database.

- -
-
datum dbm_firstkey(DBM *db);
-
`db' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function or the function `dbm_nextkey' with the same handle.
-
- -

The function `dbm_nextkey' is used in order to get the next key of a database.

- -
-
datum dbm_nextkey(DBM *db);
-
`db' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function or the function `dbm_firstkey' with the same handle.
-
- -

The function `dbm_error' is used in order to check whether a database has a fatal error or not.

- -
-
int dbm_error(DBM *db);
-
`db' specifies a database handle. The return value is true if the database has a fatal error, false if not.
-
- -

The function `dbm_clearerr' has no effect.

- -
-
int dbm_clearerr(DBM *db);
-
`db' specifies a database handle. The return value is 0. The function is only for compatibility.
-
- -

The function `dbm_rdonly' is used in order to check whether a handle is read-only or not.

- -
-
int dbm_rdonly(DBM *db);
-
`db' specifies a database handle. The return value is true if the handle is read-only, or false if not read-only.
-
- -

The function `dbm_dirfno' is used in order to get the file descriptor of a directory file.

- -
-
int dbm_dirfno(DBM *db);
-
`db' specifies a database handle. The return value is the file descriptor of the directory file.
-
- -

The function `dbm_pagfno' is used in order to get the file descriptor of a data file.

- -
-
int dbm_pagfno(DBM *db);
-
`db' specifies a database handle. The return value is the file descriptor of the data file.
-
- -

Examples

- -

The following example stores and retrieves a phone number, using the name as the key.

- -
#include <relic.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <string.h>
-
-#define NAME     "mikio"
-#define NUMBER   "000-1234-5678"
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  DBM *db;
-  datum key, val;
-  int i;
-
-  /* open the database */
-  if(!(db = dbm_open(DBNAME, O_RDWR | O_CREAT, 00644))){
-    perror("dbm_open");
-    return 1;
-  }
-
-  /* prepare the record */
-  key.dptr = NAME;
-  key.dsize = strlen(NAME);
-  val.dptr = NUMBER;
-  val.dsize = strlen(NUMBER);
-
-  /* store the record */
-  if(dbm_store(db, key, val, DBM_REPLACE) != 0){
-    perror("dbm_store");
-  }
-
-  /* retrieve the record */
-  val = dbm_fetch(db, key);
-  if(val.dptr){
-    printf("Name: %s\n", NAME);
-    printf("Number: ");
-    for(i = 0; i < val.dsize; i++){
-      putchar(((char *)val.dptr)[i]);
-    }
-    putchar('\n');
-  } else {
-    perror("dbm_fetch");
-  }
-
-  /* close the database */
-  dbm_close(db);
-
-  return 0;
-}
-
- -

Notes

- -

How to build programs using Relic is the same as the case of Depot. Note that an option to be given to a linker is not `-lndbm', but `-lqdbm'.

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

Functions of Relic are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

- -
- -

Commands for Relic

- -

Relic has the following command line interfaces.

- -

The command `rlmgr' is a utility for debugging Relic and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

- -
-
rlmgr create name
-
Create a database file.
-
rlmgr store [-kx] [-vx|-vf] [-insert] name key val
-
Store a record with a key and a value.
-
rlmgr delete [-kx] name key
-
Delete a record with a key.
-
rlmgr fetch [-kx] [-ox] [-n] name key
-
Retrieve a record with a key and output to the standard output.
-
rlmgr list [-ox] name
-
List all keys and values delimited with tab and line-feed to the standard output.
-
- -

Options feature the following.

- -
    -
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • -
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • -
  • -vf : read the value from a file specified with `val'.
  • -
  • -insert : specify the storing mode for `DBM_INSERT'.
  • -
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • -
  • -n : do not output the tailing newline.
  • -
- -

This command returns 0 on success, another on failure.

- -

The command `rltest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records.

- -
-
rltest write name rnum
-
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
-
rltest read name rnum
-
Retrieve records of the database above.
-
- -

This command returns 0 on success, another on failure.

- -
- -

Hovel: GDBM-compatible API

- -

Overview

- -

Hovel is the API which is compatible with GDBM. So, Hovel wraps functions of Depot and Curia as API of GDBM. It is easy to port an application from GDBM to QDBM. In most cases, you should only replace the includings of `gdbm.h' with `hovel.h' and replace the linking option `-lgdbm' with `-lqdbm'. Hovel can not handle database files made by the original GDBM.

- -

In order to use Hovel, you should include `hovel.h', `stdlib.h', `sys/types.h' and `sys/stat.h' in the source files. Usually, the following description will be near the beginning of a source file.

- -
-
#include <hovel.h>
-
#include <stdlib.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
- -

An object of `GDBM_FILE' is used as a database handle. A database handle is opened with the function `gdbm_open' and closed with `gdbm_close'. You should not refer directly to any member of a handle. Although Hovel works as a wrapper of Depot and handles a database file usually, if you use the function `gdbm_open2' to open the handle, it is possible to make behavior of a handle as a wrapper of Curia and treat a database directory.

- -

API

- -

Structures of `datum' type is used in order to give and receive data of keys and values with functions of Hovel.

- -
-
typedef struct { char *dptr; size_t dsize; } datum;
-
`dptr' specifies the pointer to the region of a key or a value. `dsize' specifies the size of the region.
-
- -

The external variable `gdbm_version' is the string containing the version information.

- -
-
extern char *gdbm_version;
-
- -

The external variable `gdbm_errno' is assigned with the last happened error code. Refer to `hovel.h' for details of the error codes.

- -
-
extern gdbm_error gdbm_errno;
-
The initial value of this variable is `GDBM_NO_ERROR'. The other values are `GDBM_MALLOC_ERROR', `GDBM_BLOCK_SIZE_ERROR', `GDBM_FILE_OPEN_ERROR', `GDBM_FILE_WRITE_ERROR', `GDBM_FILE_SEEK_ERROR', `GDBM_FILE_READ_ERROR', `GDBM_BAD_MAGIC_NUMBER', `GDBM_EMPTY_DATABASE', `GDBM_CANT_BE_READER', `GDBM_CANT_BE_WRITER', `GDBM_READER_CANT_DELETE', `GDBM_READER_CANT_STORE', `GDBM_READER_CANT_REORGANIZE', `GDBM_UNKNOWN_UPDATE', `GDBM_ITEM_NOT_FOUND', `GDBM_REORGANIZE_FAILED', `GDBM_CANNOT_REPLACE', `GDBM_ILLEGAL_DATA', `GDBM_OPT_ALREADY_SET', and `GDBM_OPT_ILLEGAL'.
-
- -

The function `gdbm_strerror' is used in order to get a message string corresponding to an error code.

- -
-
char *gdbm_strerror(gdbm_error gdbmerrno);
-
`gdbmerrno' specifies an error code. The return value is the message string of the error code. The region of the return value is not writable.
-
- -

The function `gdbm_open' is used in order to get a database handle after the fashion of GDBM.

- -
-
GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, void (*fatal_func)(void));
-
`name' specifies the name of a database. `block_size' is ignored. `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', `GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. `GDBM_SPARSE' is an original mode of QDBM and makes database a sparse file. `mode' specifies mode of a database file as the one of `open' call does. `fatal_func' is ignored. The return value is the database handle or `NULL' if it is not successful.
-
- -

The function `gdbm_open2' is used in order to get a database handle after the fashion of QDBM.

- -
-
GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align);
-
`name' specifies the name of a database. `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', 'GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. `GDBM_SPARSE' is an original mode of QDBM and makes database sparse files. `mode' specifies a mode of a database file or a database directory as the one of `open' or `mkdir' call does. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. `dnum' specif ies the number of division of the database. If it is not more than 0, the returning handle is created as a wrapper of Depot, else, it is as a wrapper of Curia. `align' specifies the basic size of alignment. The return value is the database handle or `NULL' if it is not successful. If the database already exists, whether it is one of Depot or Curia is measured automatically.
-
- -

The function `gdbm_close' is used in order to close a database handle.

- -
-
void gdbm_close(GDBM_FILE dbf);
-
`dbf' specifies a database handle. Because the region of the closed handle is released, it becomes impossible to use the handle.
-
- -

The function `gdbm_store' is used in order to store a record.

- -
-
int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag);
-
`dbf' specifies a database handle connected as a writer. `key' specifies a structure of a key. `content' specifies a structure of a value. `flag' specifies behavior when the key overlaps, by the following values: `GDBM_REPLACE', which means the specified value overwrites the existing one, `GDBM_INSERT', which means the existing value is kept. The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, -1 if other error occurs.
-
- -

The function `gdbm_delete' is used in order to delete a record.

- -
-
int gdbm_delete(GDBM_FILE dbf, datum key);
-
`dbf' specifies a database handle connected as a writer. `key' specifies a structure of a key. The return value is 0 if it is successful, -1 if some errors occur.
-
- -

The function `gdbm_fetch' is used in order to retrieve a record.

- -
-
datum gdbm_fetch(GDBM_FILE dbf, datum key);
-
`dbf' specifies a database handle. `key' specifies a structure of a key. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `gdbm_exists' is used in order to check whether a record exists or not.

- -
-
int gdbm_exists(GDBM_FILE dbf, datum key);
-
`dbf' specifies a database handle. `key' specifies a structure of a key. The return value is true if a record corresponds and no error occurs, or false, else, it is false.
-
- -

The function `gdbm_firstkey' is used in order to get the first key of a database.

- -
-
datum gdbm_firstkey(GDBM_FILE dbf);
-
`dbf' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `gdbm_nextkey' is used in order to get the next key of a database.

- -
-
datum gdbm_nextkey(GDBM_FILE dbf, datum key);
-
`dbf' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `gdbm_sync' is used in order to synchronize updating contents with the file and the device.

- -
-
void gdbm_sync(GDBM_FILE dbf);
-
`dbf' specifies a database handle connected as a writer.
-
- -

The function `gdbm_reorganize' is used in order to reorganize a database.

- -
-
int gdbm_reorganize(GDBM_FILE dbf);
-
`dbf' specifies a database handle connected as a writer. If successful, the return value is 0, else -1.
-
- -

The function `gdbm_fdesc' is used in order to get the file descriptor of a database file.

- -
-
int gdbm_fdesc(GDBM_FILE dbf);
-
`dbf' specifies a database handle connected as a writer. The return value is the file descriptor of the database file. If the database is a directory the return value is -1.
-
- -

The function `gdbm_setopt' has no effect.

- -
-
int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size);
-
`dbf' specifies a database handle. `option' is ignored. `size' is ignored. The return value is 0. The function is only for compatibility.
-
- -

Examples

- -

The following example stores and retrieves a phone number, using the name as the key.

- -
#include <hovel.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <string.h>
-
-#define NAME     "mikio"
-#define NUMBER   "000-1234-5678"
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  GDBM_FILE dbf;
-  datum key, val;
-  int i;
-
-  /* open the database */
-  if(!(dbf = gdbm_open(DBNAME, 0, GDBM_WRCREAT, 00644, NULL))){
-    fprintf(stderr, "gdbm_open: %s\n", gdbm_strerror(gdbm_errno));
-    return 1;
-  }
-
-  /* prepare the record */
-  key.dptr = NAME;
-  key.dsize = strlen(NAME);
-  val.dptr = NUMBER;
-  val.dsize = strlen(NUMBER);
-
-  /* store the record */
-  if(gdbm_store(dbf, key, val, GDBM_REPLACE) != 0){
-    fprintf(stderr, "gdbm_store: %s\n", gdbm_strerror(gdbm_errno));
-  }
-
-  /* retrieve the record */
-  val = gdbm_fetch(dbf, key);
-  if(val.dptr){
-    printf("Name: %s\n", NAME);
-    printf("Number: ");
-    for(i = 0; i < val.dsize; i++){
-      putchar(val.dptr[i]);
-    }
-    putchar('\n');
-    free(val.dptr);
-  } else {
-    fprintf(stderr, "gdbm_fetch: %s\n", gdbm_strerror(gdbm_errno));
-  }
-
-  /* close the database */
-  gdbm_close(dbf);
-
-  return 0;
-}
-
- -

Notes

- -

How to build programs using Hovel is the same as the case of Depot. Note that an option to be given to a linker is not `-lgdbm', but `-lqdbm'.

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

If QDBM was built with POSIX thread enabled, the global variable `gdbm_errno' is treated as thread specific data, and functions of Hovel are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

- -
- -

Commands for Hovel

- -

Hovel has the following command line interfaces.

- -

The command `hvmgr' is a utility for debugging Hovel and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

- -
-
hvmgr create [-qdbm bnum dnum] [-s] name
-
Create a database file.
-
hvmgr store [-qdbm] [-kx] [-vx|-vf] [-insert] name key val
-
Store a record with a key and a value.
-
hvmgr delete [-qdbm] [-kx] name key
-
Delete a record with a key.
-
hvmgr fetch [-qdbm] [-kx] [-ox] [-n] name key
-
Retrieve a record with a key and output to the standard output.
-
hvmgr list [-qdbm] [-ox] name
-
List all keys and values delimited with tab and line-feed to the standard output.
-
hvmgr optimize [-qdbm] name
-
Optimize a database.
-
- -

Options feature the following.

- -
    -
  • -qdbm [bnum dnum] : use `gdbm_open2' to open the database. `bnum' specifies the number of the elements of the bucket array. `dnum' specifies the number of division of the database.
  • -
  • -s : make the file sparse.
  • -
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • -
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • -
  • -vf : read the value from a file specified with `val'.
  • -
  • -insert : specify the storing mode for `GDBM_INSERT'.
  • -
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • -
  • -n : do not output the trailing newline.
  • -
- -

This command returns 0 on success, another on failure.

- -

The command `hvtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records.

- -
-
hvtest write [-qdbm] [-s] name rnum
-
Store records with keys of 8 bytes. They changes as `00000001', `00000002'...
-
hvtest read [-qdbm] name rnum
-
Retrieve records of the database above.
-
- -

Options feature the following.

- -
    -
  • -qdbm : use `gdbm_open2' and open the handle as Curia.
  • -
  • -s : make the file sparse.
  • -
- -

This command returns 0 on success, another on failure.

- -
- -

Cabin: Utility API

- -

Overview

- -

Cabin is the utility API which provides memory allocating functions, sorting functions, extensible datum, array list, hash map, heap array, and so on for handling records easily on memory. This API features also parsing MIME, CSV, and XML, and features various types of encoding and decoding.

- -

In order to use Cabin, you should include `cabin.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

- -
-
#include <cabin.h>
-
#include <stdlib.h>
-
- -

A pointer to `CBDATUM' is used as a handle of an extensible datum. A datum handle is opened with the function `cbdatumopen' and closed with `cbdatumclose'. A pointer to `CBLIST' is used as a handle of an array list. A list handle is opened with the function `cblistopen' and closed with `cblistclose'. A pointer to `CBMAP' is used as a handle of a hash map. A map handle is opened with the function `cbmapopen' and closed with `cbmapclose'. A pointer to `CBHEAP' is used as a handle of a heap array. A heap handle is opened with the function `cbheapopen' and closed with `cbheapclose'. You should not refer directly to any member of each handles.

- -

API

- -

The external variable `cbfatalfunc' is the pointer to call back function for handling a fatal error.

- -
-
extern void (*cbfatalfunc)(const char *);
-
The argument specifies the error message. The initial value of this variable is `NULL'. If the value is `NULL', the default function is called when a fatal error occurs. A fatal error occurs when memory allocation is failed.
-
- -

The function `cbmalloc' is used in order to allocate a region on memory.

- -
-
void *cbmalloc(size_t size);
-
`size' specifies the size of the region. The return value is the pointer to the allocated region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbrealloc' is used in order to re-allocate a region on memory.

- -
-
void *cbrealloc(void *ptr, size_t size);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. The return value is the pointer to the re-allocated region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbmemdup' is used in order to duplicate a region on memory.

- -
-
char *cbmemdup(const char *ptr, int size);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the allocated region of the duplicate. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbfree' is used in order to free a region on memory.

- -
-
void cbfree(void *ptr);
-
`ptr' specifies the pointer to a region. If it is `NULL', this function has no effect. Although this function is just a wrapper of `free' call, this is useful in applications using another package of the `malloc' series.
-
- -

The function `cbglobalgc' is used in order to register the pointer or handle of an object to the global garbage collector.

- -
-
void cbglobalgc(void *ptr, void (*func)(void *));
-
`ptr' specifies the pointer or handle of an object. `func' specifies the pointer to a function to release resources of the object. Its argument is the pointer or handle of the object to release. This function assures that resources of an object are released when the process exits normally by returning from the `main' function or calling the `exit' function.
-
- -

The function `cbggcsweep' is used in order to exercise the global garbage collector explicitly.

- -
-
void cbggcsweep(void);
-
Note that you should not use objects registered to the global garbage collector any longer after calling this function. Because the global garbage collector is initialized and you can register new objects into it.
-
- -

The function `cbvmemavail' is used in order to check availability of allocation of the virtual memory.

- -
-
int cbvmemavail(size_t size);
-
`size' specifies the size of region to be allocated newly. The return value is true if allocation should be success, or false if not.
-
- -

The function `cbisort' is used in order to sort an array using insert sort.

- -
-
void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
-
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Insert sort is useful only if most elements have been sorted already.
-
- -

The function `cbssort' is used in order to sort an array using shell sort.

- -
-
void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
-
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. If most elements have been sorted, shell sort may be faster than heap sort or quick sort.
-
- -

The function `cbhsort' is used in order to sort an array using heap sort.

- -
-
void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
-
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Although heap sort is robust against bias of input, quick sort is faster in most cases.
-
- -

The function `cbqsort' is used in order to sort an array using quick sort.

- -
-
void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
-
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Being sensitive to bias of input, quick sort is the fastest sorting algorithm.
-
- -

The function `cbstricmp' is used in order to compare two strings with case insensitive evaluation.

- -
-
int cbstricmp(const char *astr, const char *bstr);
-
`astr' specifies the pointer of one string. `astr' specifies the pointer of the other string. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. Upper cases and lower cases of alphabets in ASCII code are not distinguished.
-
- -

The function `cbstrfwmatch' is used in order to check whether a string begins with a key.

- -
-
int cbstrfwmatch(const char *str, const char *key);
-
`str' specifies the pointer of a target string. `key' specifies the pointer of a forward matching key string. The return value is true if the target string begins with the key, else, it is false.
-
- -

The function `cbstrfwimatch' is used in order to check whether a string begins with a key, with case insensitive evaluation.

- -
-
int cbstrfwimatch(const char *str, const char *key);
-
`str' specifies the pointer of a target string. `key' specifies the pointer of a forward matching key string. The return value is true if the target string begins with the key, else, it is false. Upper cases and lower cases of alphabets in ASCII code are not distinguished.
-
- -

The function `cbstrbwmatch' is used in order to check whether a string ends with a key.

- -
-
int cbstrbwmatch(const char *str, const char *key);
-
`str' specifies the pointer of a target string. `key' specifies the pointer of a backward matching key string. The return value is true if the target string ends with the key, else, it is false.
-
- -

The function `cbstrbwimatch' is used in order to check whether a string ends with a key, with case insensitive evaluation.

- -
-
int cbstrbwimatch(const char *str, const char *key);
-
`str' specifies the pointer of a target string. `key' specifies the pointer of a backward matching key string. The return value is true if the target string ends with the key, else, it is false. Upper cases and lower cases of alphabets in ASCII code are not distinguished.
-
- -

The function `cbstrstrkmp' is used in order to locate a substring in a string using KMP method.

- -
-
char *cbstrstrkmp(const char *haystack, const char *needle);
-
`haystack' specifies the pointer of a target string. `needle' specifies the pointer of a substring to be found. The return value is the pointer to the beginning of the substring or `NULL' if the substring is not found. In most cases, `strstr' as a built-in function of the compiler is faster than this function.
-
- -

The function `cbstrstrkmp' is used in order to locate a substring in a string using BM method.

- -
-
char *cbstrstrbm(const char *haystack, const char *needle);
-
`haystack' specifies the pointer of a target string. `needle' specifies the pointer of a substring to be found. The return value is the pointer to the beginning of the substring or `NULL' if the substring is not found. In most cases, `strstr' as a built-in function of the compiler is faster than this function.
-
- -

The function `cbstrtoupper' is used in order to convert the letters of a string to upper case.

- -
-
char *cbstrtoupper(char *str);
-
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.
-
- -

The function `cbstrtolower' is used in order to convert the letters of a string to lower case.

- -
-
char *cbstrtolower(char *str);
-
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.
-
- -

The function `cbstrtrim' is used in order to cut space characters at head or tail of a string.

- -
-
char *cbstrtrim(char *str);
-
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.
-
- -

The function `cbstrsqzspc' is used in order to squeeze space characters in a string and trim it.

- -
-
char *cbstrsqzspc(char *str);
-
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.
-
- -

The function `cbstrcountutf' is used in order to count the number of characters in a string of UTF-8.

- -
-
int cbstrcountutf(const char *str);
-
`str' specifies the pointer of a string of UTF-8. The return value is the number of characters in the string.
-
- -

The function `cbstrcututf' is used in order to cut a string of UTF-8 at the specified number of characters.

- -
-
char *cbstrcututf(char *str, int num);
-
`str' specifies the pointer of a string of UTF-8. `num' specifies the number of characters to be kept. The return value is the pointer to the string.
-
- -

The function `cbdatumopen' is used in order to get a datum handle.

- -
-
CBDATUM *cbdatumopen(const char *ptr, int size);
-
`ptr' specifies the pointer to the region of the initial content. If it is `NULL', an empty datum is created. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is a datum handle.
-
- -

The function `cbdatumdup' is used in order to copy a datum.

- -
-
CBDATUM *cbdatumdup(const CBDATUM *datum);
-
`datum' specifies a datum handle. The return value is a new datum handle.
-
- -

The function `cbdatumclose' is used in order to free a datum handle.

- -
-
void cbdatumclose(CBDATUM *datum);
-
`datum' specifies a datum handle. Because the region of a closed handle is released, it becomes impossible to use the handle.
-
- -

The function `cbdatumcat' is used in order to concatenate a datum and a region.

- -
-
void cbdatumcat(CBDATUM *datum, const char *ptr, int size);
-
`datum' specifies a datum handle. `ptr' specifies the pointer to the region to be appended. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.
-
- -

The function `cbdatumptr' is used in order to get the pointer of the region of a datum.

- -
-
const char *cbdatumptr(const CBDATUM *datum);
-
`datum' specifies a datum handle. The return value is the pointer of the region of a datum. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.
-
- -

The function `cbdatumsize' is used in order to get the size of the region of a datum.

- -
-
int cbdatumsize(const CBDATUM *datum);
-
`datum' specifies a datum handle. The return value is the size of the region of a datum.
-
- -

The function `cbdatumsetsize' is used in order to change the size of the region of a datum.

- -
-
void cbdatumsetsize(CBDATUM *datum, int size);
-
`datum' specifies a datum handle. `size' specifies the new size of the region. If the new size is bigger than the one of old, the surplus region is filled with zero codes.
-
- -

The function `cbdatumprintf' is used in order to perform formatted output into a datum.

- -
-
void cbdatumprintf(CBDATUM *datum, const char *format, ...);
-
`format' specifies a printf-like format string. The conversion character `%' can be used with such flag characters as `s', `d', `o', `u', `x', `X', `c', `e', `E', `f', `g', `G', `@', `?', `:', `%'. `@' works as with `s' but escapes meta characters of XML. `?' works as with `s' but escapes meta characters of URL. `:' works as with `s' but performs MIME encoding as UTF-8. The other conversion character work as with each original.
-
- -

The function `cbdatumtomalloc' is used in order to convert a datum to an allocated region.

- -
-
char *cbdatumtomalloc(CBDATUM *datum, int *sp);
-
`datum' specifies a datum handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the datum. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Because the region of the original datum is released, it should not be released again.
-
- -

The function `cblistopen' is used in order to get a list handle.

- -
-
CBLIST *cblistopen(void);
-
The return value is a list handle.
-
- -

The function `cblistdup' is used in order to copy a list.

- -
-
CBLIST *cblistdup(const CBLIST *list);
-
`list' specifies a list handle. The return value is a new list handle.
-
- -

The function `cblistclose' is used in order to close a list handle.

- -
-
void cblistclose(CBLIST *list);
-
`list' specifies a list handle. Because the region of a closed handle is released, it becomes impossible to use the handle.
-
- -

The function `cblistnum' is used in order to get the number of elements of a list.

- -
-
int cblistnum(const CBLIST *list);
-
`list' specifies a list handle. The return value is the number of elements of the list.
-
- -

The function `cblistval' is used in order to get the pointer to the region of an element of a list.

- -
-
const char *cblistval(const CBLIST *list, int index, int *sp);
-
`list' specifies a list handle. `index' specifies the index of an element. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the element. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. If `index' is equal to or more than the number of elements, the return value is `NULL'.
-
- -

The function `cblistpush' is used in order to add an element at the end of a list.

- -
-
void cblistpush(CBLIST *list, const char *ptr, int size);
-
`list' specifies a list handle. `ptr' specifies the pointer to the region of an element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.
-
- -

The function `cblistpop' is used in order to remove an element of the end of a list.

- -
-
char *cblistpop(CBLIST *list, int *sp);
-
`list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If the list is empty, the return value is `NULL'.
-
- -

The function `cblistunshift' is used in order to add an element at the top of a list.

- -
-
void cblistunshift(CBLIST *list, const char *ptr, int size);
-
`list' specifies a list handle. `ptr' specifies the pointer to the region of an element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.
-
- -

The function `cblistshift' is used in order to remove an element of the top of a list.

- -
-
char *cblistshift(CBLIST *list, int *sp);
-
`list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If the list is empty, the return value is `NULL'.
-
- -

The function `cblistinsert' is used in order to add an element at the specified location of a list.

- -
-
void cblistinsert(CBLIST *list, int index, const char *ptr, int size);
-
`list' specifies a list handle. `index' specifies the index of an element. `ptr' specifies the pointer to the region of the element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.
-
- -

The function `cblistremove' is used in order to remove an element at the specified location of a list.

- -
-
char *cblistremove(CBLIST *list, int index, int *sp);
-
`list' specifies a list handle. `index' specifies the index of an element. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If `index' is equal to or more than the number of elements, no element is removed and the return value is `NULL'.
-
- -

The function `cblistover' is used in order to overwrite an element at the specified location of a list.

- -
-
void cblistover(CBLIST *list, int index, const char *ptr, int size);
-
`list' specifies a list handle. `index' specifies the index of an element. `ptr' specifies the pointer to the region of the new content. `size' specifies the size of the new content. If it is negative, the size is assigned with `strlen(ptr)'. If `index' is equal to or more than the number of elements, this function has no effect.
-
- -

The function `cblistsort' is used in order to sort elements of a list in lexical order.

- -
-
void cblistsort(CBLIST *list);
-
`list' specifies a list handle. Quick sort is used for sorting.
-
- -

The function `cblistlsearch' is used in order to search a list for an element using liner search.

- -
-
int cblistlsearch(const CBLIST *list, const char *ptr, int size);
-
`list' specifies a list handle. `ptr' specifies the pointer to the region of a key. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the index of a corresponding element or -1 if there is no corresponding element. If two or more elements corresponds, the former returns.
-
- -

The function `cblistbsearch' is used in order to search a list for an element using binary search.

- -
-
int cblistbsearch(const CBLIST *list, const char *ptr, int size);
-
`list' specifies a list handle. It should be sorted in lexical order. `ptr' specifies the pointer to the region of a key. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the index of a corresponding element or -1 if there is no corresponding element. If two or more elements corresponds, which returns is not defined.
-
- -

The function `cblistdump' is used in order to serialize a list into a byte array.

- -
-
char *cblistdump(const CBLIST *list, int *sp);
-
`list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. The return value is the pointer to the region of the result serial region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cblistload' is used in order to redintegrate a serialized list.

- -
-
CBLIST *cblistload(const char *ptr, int size);
-
`ptr' specifies the pointer to a byte array. `size' specifies the size of the region. The return value is a new list handle.
-
- -

The function `cbmapopen' is used in order to get a map handle.

- -
-
CBMAP *cbmapopen(void);
-
The return value is a map handle.
-
- -

The function `cbmapdup' is used in order to copy a map.

- -
-
CBMAP *cbmapdup(CBMAP *map);
-
`map' specifies a map handle. The return value is a new map handle. The iterator of the source map is initialized.
-
- -

The function `cbmapclose' is used in order to close a map handle.

- -
-
void cbmapclose(CBMAP *map);
-
`map' specifies a map handle. Because the region of a closed handle is released, it becomes impossible to use the handle.
-
- -

The function `cbmapput' is used in order to store a record into a map.

- -
-
int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over);
-
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `over' specifies whether the value of the duplicated record is overwritten or not. If `over' is false and the key duplicated, the return value is false, else, it is true.
-
- -

The function `cbmapputcat' is used in order to concatenate a value at the end of the value of the existing record.

- -
-
void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz);
-
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. If there is no corresponding record, a new record is created.
-
- -

The function `cbmapout' is used in order to delete a record of a map.

- -
-
int cbmapout(CBMAP *map, const char *kbuf, int ksiz);
-
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true. False is returned when no record corresponds to the specified key.
-
- -

The function `cbmapget' is used in order to retrieve a record of a map.

- -
-
const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp);
-
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record. `NULL' is returned when no record corresponds. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.
-
- -

The function `cbmapmove' is used in order to move a record to the edge of a map.

- -
-
int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head);
-
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `head' specifies the destination which is head if it is true or tail if else. If successful, the return value is true. False is returned when no record corresponds to the specified key.
-
- -

The function `cbmapiterinit' is used in order to initialize the iterator of a map.

- -
-
void cbmapiterinit(CBMAP *map);
-
`map' specifies a map handle. The iterator is used in order to access the key of every record stored in a map.
-
- -

The function `cbmapiternext' is used in order to get the next key of the iterator of a map.

- -
-
const char *cbmapiternext(CBMAP *map, int *sp);
-
`map' specifies a map handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. The order of iteration is assured to be the same of the one of storing.
-
- -

The function `cbmapiterval' is used in order to get the value binded to the key fetched from the iterator of a map.

- -
-
const char *cbmapiterval(const char *kbuf, int *sp);
-
`kbuf' specifies the pointer to the region of a iteration key. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value of the corresponding record. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.
-
- -

The function `cbmaprnum' is used in order to get the number of the records stored in a map.

- -
-
int cbmaprnum(const CBMAP *map);
-
`map' specifies a map handle. The return value is the number of the records stored in the map.
-
- -

The function `cbmapkeys' is used in order to get the list handle contains all keys in a map.

- -
-
CBLIST *cbmapkeys(CBMAP *map);
-
`map' specifies a map handle. The return value is the list handle contains all keys in the map. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
-
- -

The function `cbmapvals' is used in order to get the list handle contains all values in a map.

- -
-
CBLIST *cbmapvals(CBMAP *map);
-
`map' specifies a map handle. The return value is the list handle contains all values in the map. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
-
- -

The function `cbmapdump' is used in order to serialize a map into a byte array.

- -
-
char *cbmapdump(const CBMAP *map, int *sp);
-
`map' specifies a map handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. The return value is the pointer to the region of the result serial region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbmapload' is used in order to redintegrate a serialized map.

- -
-
CBMAP *cbmapload(const char *ptr, int size);
-
`ptr' specifies the pointer to a byte array. `size' specifies the size of the region. The return value is a new map handle.
-
- -

The function `cbmaploadone' is used in order to extract a record from a serialized map.

- -
-
char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp);
-
`ptr' specifies the pointer to a byte array. `size' specifies the size of the region. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record. `NULL' is returned when no record corresponds. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.
-
- - -

The function `cbheapopen' is used in order to get a heap handle.

- -
-
CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *));
-
`size' specifies the size of each record. `max' specifies the maximum number of records in the heap. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of records. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. The return value is a heap handle.
-
- -

The function `cbheapdup' is used in order to copy a heap.

- -
-
CBHEAP *cbheapdup(CBHEAP *heap);
-
`heap' specifies a heap handle. The return value is a new heap handle.
-
- -

The function `cbheapclose' is used in order to close a heap handle.

- -
-
void cbheapclose(CBHEAP *heap);
-
`heap' specifies a heap handle. Because the region of a closed handle is released, it becomes impossible to use the handle.
-
- -

The function `cbheapnum' is used in order to get the number of the records stored in a heap.

- -
-
int cbheapnum(CBHEAP *heap);
-
`heap' specifies a heap handle. The return value is the number of the records stored in the heap.
-
- -

The function `cbheapinsert' is used in order to insert a record into a heap.

- -
-
int cbheapinsert(CBHEAP *heap, const void *ptr);
-
`heap' specifies a heap handle. `ptr' specifies the pointer to the region of a record. The return value is true if the record is added, else false. If the new record is bigger than the biggest existing regord, the new record is not added. If the new record is added and the number of records exceeds the maximum number, the biggest existing record is removed.
-
- -

The function `cbheapval' is used in order to get the pointer to the region of a record in a heap.

- -
-
void *cbheapval(CBHEAP *heap, int index);
-
`heap' specifies a heap handle. `index' specifies the index of a record. The return value is the pointer to the region of the record. If `index' is equal to or more than the number of records, the return value is `NULL'. Note that records are organized by the nagative order the comparing function.
-
- -

The function `cbheaptomalloc' is used in order to convert a heap to an allocated region.

- -
-
void *cbheaptomalloc(CBHEAP *heap, int *np);
-
`heap' specifies a heap handle. `np' specifies the pointer to a variable to which the number of records of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the heap. Records are sorted. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Because the region of the original heap is released, it should not be released again.
-
- -

The function `cbsprintf' is used in order to allocate a formatted string on memory.

- -
-
char *cbsprintf(const char *format, ...);
-
`format' specifies a printf-like format string. The conversion character `%' can be used with such flag characters as `d', `o', `u', `x', `X', `e', `E', `f', `g', `G', `c', `s', and `%'. Specifiers of the field length and the precision can be put between the conversion characters and the flag characters. The specifiers consist of decimal characters, `.', `+', `-', and the space character. The other arguments are used according to the format string. The return value is the pointer to the allocated region of the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbreplace' is used in order to replace some patterns in a string.

- -
-
char *cbreplace(const char *str, CBMAP *pairs);
-
`str' specifies the pointer to a source string. `pairs' specifies the handle of a map composed of pairs of replacement. The key of each pair specifies a pattern before replacement and its value specifies the pattern after replacement. The return value is the pointer to the allocated region of the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbsplit' is used in order to make a list by splitting a serial datum.

- -
-
CBLIST *cbsplit(const char *ptr, int size, const char *delim);
-
`ptr' specifies the pointer to the region of the source content. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `delim' specifies a string containing delimiting characters. If it is `NULL', zero code is used as a delimiter. The return value is a list handle. If two delimiters are successive, it is assumed that an empty element is between the two. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose'.
-
- -

The function `cbreadfile' is used in order to read whole data of a file.

- -
-
char *cbreadfile(const char *name, int *sp);
-
`name' specifies the name of a file. If it is `NULL', the standard input is specified. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the allocated region of the read data. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbwritefile' is used in order to write a serial datum into a file.

- -
-
int cbwritefile(const char *name, const char *ptr, int size);
-
`name specifies the name of a file. If it is `NULL', the standard output is specified. `ptr' specifies the pointer to the region of the source content. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. If successful, the return value is true, else, it is false. If the file exists, it is overwritten. Else, a new file is created.
-
- -

The function `cbreadlines' is used in order to read every line of a file.

- -
-
CBLIST *cbreadlines(const char *name);
-
`name' specifies the name of a file. If it is `NULL', the standard input is specified. The return value is a list handle of the lines if successful, else it is NULL. Line separators are cut out. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
-
- -

The function `cbdirlist' is used in order to read names of files in a directory.

- -
-
CBLIST *cbdirlist(const char *name);
-
`name' specifies the name of a directory. The return value is a list handle of names if successful, else it is NULL. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
-
- -

The function `cbfilestat' is used in order to get the status of a file or a directory.

- -
-
int cbfilestat(const char *name, int *isdirp, int *sizep, int *mtimep);
-
`name' specifies the name of a file or a directory. `dirp' specifies the pointer to a variable to which whether the file is a directory is assigned. If it is `NULL', it is not used. `sizep' specifies the pointer to a variable to which the size of the file is assigned. If it is `NULL', it is not used. `mtimep' specifies the pointer to a variable to which the last modified time of the file is assigned. If it is `NULL', it is not used. If successful, the return value is true, else, false. False is returned when the file does not exist or the permission is denied.
-
- -

The function `cbremove' is used in order to remove a file or a directory and its sub ones recursively.

- -
-
int cbremove(const char *name);
-
`name' specifies the name of a file or a directory. If successful, the return value is true, else, false. False is returned when the file does not exist or the permission is denied.
-
- -

The function `cburlbreak' is used in order to break up a URL into elements.

- -
-
CBMAP *cburlbreak(const char *str);
-
`str' specifies the pointer to a string of URL. The return value is a map handle. Each key of the map is the name of an element. The key "self" specifies the URL itself. The key "scheme" specifies the scheme. The key "host" specifies the host of the server. The key "port" specifies the port number of the server. The key "authority" specifies the authority information. The key "path" specifies the path of the resource. The key "file" specifies the file name without the directory section. The key "query" specifies the query string. The key "fragment" specifies the fragment string. Supported schema are HTTP, HTTPS, FTP, and FILE. Absolute URL and relative URL are supported. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use.
-
- -

The runction `cburlresolve' is used in order to resolve a relative URL with another absolute URL.

- -
-
char *cburlresolve(const char *base, const char *target);
-
`base' specifies an absolute URL of a base location. `target' specifies a URL to be resolved. The return value is a resolved URL. If the target URL is relative, a new URL of relative location from the base location is returned. Else, a copy of the target URL is returned. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cburlencode' is used in order to encode a serial object with URL encoding.

- -
-
char *cburlencode(const char *ptr, int size);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cburldecode' is used in order to decode a string encoded with URL encoding.

- -
-
char *cburldecode(const char *str, int *sp);
-
`str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbbaseencode' is used in order to encode a serial object with Base64 encoding.

- -
-
char *cbbaseencode(const char *ptr, int size);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbbasedecode' is used in order to decode a string encoded with Base64 encoding.

- -
-
char *cbbasedecode(const char *str, int *sp);
-
`str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbquoteencode' is used in order to encode a serial object with quoted-printable encoding.

- -
-
char *cbquoteencode(const char *ptr, int size);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbquotedecode' is used in order to decode a string encoded with quoted-printable encoding.

- -
-
char *cbquotedecode(const char *str, int *sp);
-
`str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- - -

The function `cbmimebreak' is used in order to split a string of MIME into headers and the body.

- -
-
char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp);
-
`ptr' specifies the pointer to the region of MIME data. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `attrs' specifies a map handle to store attributes. If it is `NULL', it is not used. Each key of the map is an attribute name uncapitalized. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer of the body data. If the content type is defined, the attribute map has the key "TYPE" specifying the type. If the character encoding is defined, the key "CHARSET" specifies the encoding name. If the boundary string of multipart is defined, the key "BOUNDARY" specifies the string. If the content disposition is defined, the key "DISPOSITION" specifies the direction. If the file name is defined, the key "FILENAME" specifies the name. If the attribute name is defined, the key "NAME" specifies the nam e. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbmimeparts' is used in order to split multipart data of MIME into its parts.

- -
-
CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary);
-
`ptr' specifies the pointer to the region of multipart data of MIME. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `boundary' specifies the pointer to the region of the boundary string. The return value is a list handle. Each element of the list is the string of a part. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
-
- -

The function `cbmimeencode' is used in order to encode a string with MIME encoding.

- -
-
char *cbmimeencode(const char *str, const char *encname, int base);
-
`str' specifies the pointer to a string. `encname' specifies a string of the name of the character encoding. The return value is the pointer to the result string. `base' specifies whether to use Base64 encoding. If it is false, quoted-printable is used. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbmimedecode' is used in order to decode a string encoded with MIME encoding.

- -
-
char *cbmimedecode(const char *str, char *enp);
-
`str' specifies the pointer to an encoded string. `enp' specifies the pointer to a region into which the name of encoding is written. If it is `NULL', it is not used. The size of the buffer should be equal to or more than 32 bytes. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbcsvrows' is used in order to split a string of CSV into rows.

- -
-
CBLIST *cbcsvrows(const char *str);
-
`str' specifies the pointer to the region of an CSV string. The return value is a list handle. Each element of the list is a string of a row. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. The character encoding of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Being compatible with MS-Excel, these functions for CSV can handle cells including such meta characters as comma, between double quotation marks.
-
- -

The function `cbcsvcells' is used in order to split the string of a row of CSV into cells.

- -
-
CBLIST *cbcsvcells(const char *str);
-
`str' specifies the pointer to the region of a row of CSV. The return value is a list handle. Each element of the list is the unescaped string of a cell of the row. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
-
- -

The function `cbcsvescape' is used in order to escape a string with the meta characters of CSV.

- -
-
char *cbcsvescape(const char *str);
-
`str' specifies the pointer to the region of a string. The return value is the pointer to the escaped string sanitized of meta characters. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbcsvunescape' is used in order to unescape a string with the escaped meta characters of CSV.

- -
-
char *cbcsvunescape(const char *str);
-
`str' specifies the pointer to the region of a string with meta characters. The return value is the pointer to the unescaped string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbxmlbreak' is used in order to split a string of XML into tags and text sections.

- -
-
CBLIST *cbxmlbreak(const char *str, int cr);
-
`str' specifies the pointer to the region of an XML string. `cr' specifies whether to remove comments. The return value is a list handle. Each element of the list is the string of a tag or a text section. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. The character encoding of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Because these functions for XML are not XML parser with validation check, it can handle also HTML and SGML.
-
- -

The function `cbxmlattrs' is used in order to get the map of attributes of an XML tag.

- -
-
CBMAP *cbxmlattrs(const char *str);
-
`str' specifies the pointer to the region of a tag string. The return value is a map handle. Each key of the map is the name of an attribute. Each value is unescaped. You can get the name of the tag with the key of an empty string. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use.
-
- -

The function `cbxmlescape' is used in order to escape a string with the meta characters of XML.

- -
-
char *cbxmlescape(const char *str);
-
`str' specifies the pointer to the region of a string. The return value is the pointer to the escaped string sanitized of meta characters. This function converts only `&', `<', `>', and `"'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbxmlunescape' is used in order to unescape a string with the entity references of XML.

- -
-
char *cbxmlunescape(const char *str);
-
`str' specifies the pointer to the region of a string. The return value is the pointer to the unescaped string. This function restores only `&amp;', `&lt;', `&gt;', and `&quot;'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbdeflate' is used in order to compress a serial object with ZLIB.

- -
-
char *cbdeflate(const char *ptr, int size, int *sp);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.
-
- -

The function `cbinflate' is used in order to decompress a serial object compressed with ZLIB.

- -
-
char *cbinflate(const char *ptr, int size, int *sp);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.
-
- -

The function `cbgzencode' is used in order to compress a serial object with GZIP.

- -
-
char *cbgzencode(const char *ptr, int size, int *sp);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.
-
- -

The function `cbgzdecode' is used in order to decompress a serial object compressed with GZIP.

- -
-
char *cbgzdecode(const char *ptr, int size, int *sp);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.
-
- -

The function `cbgetcrc' is used in order to get the CRC32 checksum of a serial object.

- -
-
unsigned int cbgetcrc(const char *ptr, int size);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the CRC32 checksum of the object. This function is available only if QDBM was built with ZLIB enabled.
-
- -

The function `cblzoencode' is used in order to compress a serial object with LZO.

- -
-
char *cblzoencode(const char *ptr, int size, int *sp);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled.
-
- -

The function `cblzodecode' is used in order to decompress a serial object compressed with LZO.

- -
-
char *cblzodecode(const char *ptr, int size, int *sp);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled.
-
- -

The function `cbbzencode' is used in order to compress a serial object with BZIP2.

- -
-
char *cbbzencode(const char *ptr, int size, int *sp);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with BZIP2 enabled.
-
- -

The function `cbbzdecode' is used in order to decompress a serial object compressed with BZIP2.

- -
-
char *cbbzdecode(const char *ptr, int size, int *sp);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with BZIP2 enabled.
-
- -

The function `cbiconv' is used in order to convert the character encoding of a string.

- -
-
char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `icode' specifies the name of encoding of the input string. `ocode' specifies the name of encoding of the output string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. `mp' specifies the pointer to a variable to which the number of missing characters by failure of conversion is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QD BM was built with ICONV enabled.
-
- -

The function `cbencname' is used in order to detect the encoding of a string automatically.

- -
-
const char *cbencname(const char *ptr, int size);
-
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the string of the encoding name of the string. As it stands, US-ASCII, ISO-2022-JP, Shift_JIS, CP932, EUC-JP, UTF-8, UTF-16, UTF-16BE, and UTF-16LE are supported. If none of them matches, ISO-8859-1 is selected. This function is available only if QDBM was built with ICONV enabled.
-
- -

The function `cbjetlag' is used in order to get the jet lag of the local time in seconds.

- -
-
int cbjetlag(void);
-
The return value is the jet lag of the local time in seconds.
-
- -

The function `cbcalendar' is used in order to get the Gregorian calendar of a time.

- -
-
void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp);
-
`t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. `yearp' specifies the pointer to a variable to which the year is assigned. If it is `NULL', it is not used. `monp' specifies the pointer to a variable to which the month is assigned. If it is `NULL', it is not used. 1 means January and 12 means December. `dayp' specifies the pointer to a variable to which the day of the month is assigned. If it is `NULL', it is not used. `hourp' specifies the pointer to a variable to which the hours is assigned. If it is `NULL', it is not used. `minp' specifies the pointer to a variable to which the minutes is assigned. If it is `NULL', it is not used. `secp' specifies the pointer to a variable to which the seconds is assigned. If it is `NULL', it is not used.
-
- -

The function `cbdayofweek' is used in order to get the day of week of a date.

- -
-
int cbdayofweek(int year, int mon, int day);
-
`year' specifies the year of a date. `mon' specifies the month of the date. `day' specifies the day of the date. The return value is the day of week of the date. 0 means Sunday and 6 means Saturday.
-
- -

The function `cbdatestrwww' is used in order to get the string for a date in W3CDTF.

- -
-
char *cbdatestrwww(time_t t, int jl);
-
`t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. The return value is the string of the date in W3CDTF (YYYY-MM-DDThh:mm:ddTZD). Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbdatestrhttp' is used in order to get the string for a date in RFC 1123 format.

- -
-
char *cbdatestrhttp(time_t t, int jl);
-
`t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. The return value is the string of the date in RFC 1123 format (Wdy, DD-Mon-YYYY hh:mm:dd TZD). Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `cbstrmktime' is used in order to get the time value of a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123).

- -
-
time_t cbstrmktime(const char *str);
-
`str' specifies a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). The return value is the time value of the date or -1 if the format is invalid. Decimal can be trailed by "s" for in seconds, "m" for in minutes, "h" for in hours, and "d" for in days.
-
- -

The function `cbproctime' is used in order to get user and system processing times.

- -
-
void cbproctime(double *usrp, double *sysp);
-
`usrp' specifies the pointer to a variable to which the user processing time is assigned. If it is `NULL', it is not used. The unit of time is seconds. `sysp' specifies the pointer to a variable to which the system processing time is assigned. If it is `NULL', it is not used. The unit of time is seconds.
-
- -

The function `cbstdiobin' is used in order to ensure that the standard I/O is binary mode.

- -
-
void cbstdiobin(void);
-
This function is useful for applications on dosish file systems.
-
- -

Examples

- -

The following example is typical use.

- -
#include <cabin.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-int main(int argc, char **argv){
-  CBDATUM *datum;
-  CBLIST *list;
-  CBMAP *map;
-  char *buf1, *buf2;
-  int i;
-
-  /* open the datum handle */
-  datum = cbdatumopen("123", -1);
-  /* concatenate the data */
-  cbdatumcat(datum, "abc", -1);
-  /* print the datum */
-  printf("%s\n", cbdatumptr(datum));
-  /* close the datum handle */
-  cbdatumclose(datum);
-
-  /* open the list handle */
-  list = cblistopen();
-  /* add elements into the list */
-  cblistpush(list, "apple", -1);
-  cblistpush(list, "orange", -1);
-  /* print all elements */
-  for(i = 0; i < cblistnum(list); i++){
-    printf("%s\n", cblistval(list, i, NULL));
-  }
-  /* close the list handle */
-  cblistclose(list);
-
-  /* open the map handle */
-  map = cbmapopen();
-  /* add records into the map */
-  cbmapput(map, "dog", -1, "bowwow", -1, 1);
-  cbmapput(map, "cat", -1, "meow", -1, 1);
-  /* search for values and print them */
-  printf("%s\n", cbmapget(map, "dog", -1, NULL));
-  printf("%s\n", cbmapget(map, "cat", -1, NULL));
-  /* close the map */
-  cbmapclose(map);
-
-  /* Base64 encoding */
-  buf1 = cbbaseencode("I miss you.", -1);
-  printf("%s\n", buf1);
-  /* Base64 decoding */
-  buf2 = cbbasedecode(buf1, NULL);
-  printf("%s\n", buf2);
-  /* release the resources */
-  free(buf2);
-  free(buf1);
-
-  /* register a plain pointer to the global garbage collector */
-  buf1 = cbmemdup("Take it easy.", -1);
-  cbglobalgc(buf1, free);
-  /* the pointer is available but you don't have to release it */
-  printf("%s\n", buf1);
-  
-  /* register a list to the global garbage collector */
-  list = cblistopen();
-  cbglobalgc(list, (void (*)(void *))cblistclose);
-  /* the handle is available but you don't have to close it */
-  cblistpush(list, "Don't hesitate.", -1);
-  for(i = 0; i < cblistnum(list); i++){
-    printf("%s\n", cblistval(list, i, NULL));    
-  }
-
-  return 0;
-}
-
- -

Notes

- -

How to build programs using Cabin is the same as the case of Depot.

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

Functions of Cabin except for `cbglobalgc' are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

- -
- -

Commands for Cabin

- -

Cabin has the following command line interfaces.

- -

The command `cbtest' is a utility for facility test and performance test. Measure the execution time of the command. This command is used in the following format. `rnum' specifies the number of records.

- -
-
cbtest sort [-d] rnum
-
Perform test of sorting algorithms.
-
cbtest strstr [-d] rnum
-
Perform test of string locating algorithms.
-
cbtest list [-d] rnum
-
Perform writing test of list.
-
cbtest map [-d] rnum
-
Perform writing test of map.
-
cbtest wicked rnum
-
Perform updating operations of list and map selected at random.
-
cbtest misc
-
Perform test of miscellaneous routines.
-
- -

Options feature the following.

- -
    -
  • -d : read and show data of the result.
  • -
- -

This command returns 0 on success, another on failure.

- -

The command `cbcodec' is a tool to use encoding and decoding features provided by Cabin. This command is used in the following format. `file' specifies a input file. If it is omitted, the standard input is read.

- -
-
cbcodec url [-d] [-br] [-rs base target] [-l] [-e expr] [file]
-
Perform URL encoding and its decoding.
-
cbcodec base [-d] [-l] [-c num] [-e expr] [file]
-
Perform Base64 encoding and its decoding.
-
cbcodec quote [-d] [-l] [-c num] [-e expr] [file]
-
Perform quoted-printable encoding and its decoding.
-
cbcodec mime [-d] [-hd] [-bd] [-part num] [-l] [-ec code] [-qp] [-dc] [-e expr] [file]
-
Perform MIME encoding and its decoding.
-
cbcodec csv [-d] [-t] [-l] [-e expr] [-html] [file]
-
Process CSV. By default, escape meta characters.
-
cbcodec xml [-d] [-p] [-l] [-e expr] [-tsv] [file]
-
Process XML. By default, escape meta characters.
-
cbcodec zlib [-d] [-gz] [-crc] [file]
-
Perform deflation and inflation with ZLIB. It is available only if QDBM was built with ZLIB enabled.
-
cbcodec lzo [-d] [file]
-
Perform compression and decompression with LZO. It is available only if QDBM was built with LZO enabled.
-
cbcodec bzip [-d] [file]
-
Perform compression and decompression with BZIP2. It is available only if QDBM was built with BZIP2 enabled.
-
cbcodec iconv [-ic code] [-oc code] [-ol ltype] [-cn] [-um] [-wc] [file]
-
Convert character encoding with ICONV. It is available only if QDBM was built with ICONV enabled.
-
cbcodec date [-wf] [-rf] [-utc] [str]
-
Convert a date string specified `str'. By default, UNIX time is output. If `str' is omitted, the current date is dealt.
-
- -

Options feature the following.

- -
    -
  • -d : perform decoding (unescaping), not encoding (escaping).
  • -
  • -br : break up URL into elements.
  • -
  • -rs : resolve relative URL.
  • -
  • -l : output the tailing newline.
  • -
  • -e expr : specify input data directly.
  • -
  • -c num : limit the number of columns of the encoded data.
  • -
  • -hd : parse MIME and extract headers in TSV format.
  • -
  • -bd : parse MIME and extract the body.
  • -
  • -part num : parse MIME and extract a part.
  • -
  • -ec code : specify the input encoding, which is UTF-8 by default.
  • -
  • -qp : use quoted-printable encoding, which is Base64 by default.
  • -
  • -dc : output the encoding name instead of the result string when decoding.
  • -
  • -t : parse CSV. Convert the data into TSV. Tab and new-line in a cell are deleted.
  • -
  • -html : parse CSV. Convert the data into HTML.
  • -
  • -p : parse XML. Show tags and text sections with dividing headers.
  • -
  • -tsv : parse XML. Show the result in TSV format. Characters of tabs and new-lines are URL-encoded.
  • -
  • -gz : use GZIP format.
  • -
  • -crc : output the CRC32 checksum as hexadecimal and big endian.
  • -
  • -ic code : specify the input encoding, which is detected automatically by default.
  • -
  • -oc code : specify the output encoding, which is UTF-8 by default.
  • -
  • -ol ltype : convert line feed characters, with `unix'(LF), `dos'(CRLF), and `mac'(CR).
  • -
  • -cn : detect the input encoding and show its name.
  • -
  • -wc : count the number of characters of the input string of UTF-8.
  • -
  • -um : output mappings of UCS-2 characters and C strings of UTF-16BE and UTF-8.
  • -
  • -wf : output in W3CDTF format.
  • -
  • -rf : output in RFC 1123 format.
  • -
  • -utc : output the coordinate universal time.
  • -
- -

This command returns 0 on success, another on failure.

- -
- -

Villa: Advanced API

- -

Overview

- -

Villa is the advanced API of QDBM. It provides routines for managing a database file of B+ tree. Each record is stored being sorted in order defined by a user. As for hash databases, retrieving method is provided only as complete accord. However, with Villa, it is possible to retrieve records specified by range. Cursor is used in order to access each record in order. It is possible to store records duplicating keys in a database. Moreover, according to the transaction mechanism, you can commit or abort operations of a database in a lump.

- -

Villa is implemented, based on Depot and Cabin. A database file of Villa is actual one of Depot. Although processing speed of retrieving and storing is slower than Depot, the size of a database is smaller.

- -

In order to use Villa, you should include `depot.h', `cabin.h', `villa.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

- -
-
#include <depot.h>
-
#include <cabin.h>
-
#include <villa.h>
-
#include <stdlib.h>
-
- -

A pointer to `VILLA' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `vlopen' and closed with `vlclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `vlclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used. Before the cursor is used, it should be initialized by one of `vlcurfirst', `vlcurlast' or `vlcurjump'. Also after storing or deleting a record with functions except for `vlcurput' and `vlcurout', the cursor should be initialized.

- -

Villa also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code.

- -

API

- -

You can define a comparing function to specify the order of records. The function should be the following type.

- -
-
typedef int(*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz);
-
`aptr' specifies the pointer to the region of one key. `asiz' specifies the size of the region of one key. `bptr' specifies the pointer to the region of the other key. `bsiz' specifies the size of the region of the other key. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent.
-
- -

The function `vlopen' is used in order to get a database handle.

- -
-
VILLA *vlopen(const char *name, int omode, VLCFUNC cmp);
-
`name' specifies the name of a database file. `omode' specifies the connection mode: `VL_OWRITER' as a writer, `VL_OREADER' as a reader. If the mode is `VL_OWRITER', the following may be added by bitwise or: `VL_OCREAT', which means it creates a new database if not exist, `VL_OTRUNC', which means it creates a new database regardless if one exists, `VL_OZCOMP', which means leaves in the database are compressed with ZLIB, `VL_OYCOMP', which means leaves in the database are compressed with LZO, `VL_OXCOMP', which means leaves in the database are compressed with BZIP2. Both of `VL_OREADER' and `VL_OWRITER' can be added to by bitwise or: `VL_ONOLCK', which means it opens a database file without file locking, or `VL_OLCKNB', which means locking is performed without blocking. `cmp' specifies the comparing function: `VL_CMPLEX' comparing keys in lexical order, `VL_CMPINT' comparing keys as objects of `int' in native byte order, `VL_CMPNUM' comparing keys as numbers of big en dian, `VL_CMPDEC' comparing keys as decimal strings. Any function based on the declaration of the type `VLCFUNC' can be assigned to the comparing function. The comparing function should be kept same in the life of a database. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. `VL_OZCOMP', `VL_OYCOMP', and `VL_OXCOMP' are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `VL_ONOLCK' is used, the application is responsible for exclusion control.
-
- -

The function `vlclose' is used in order to close a database handle.

- -
-
int vlclose(VILLA *villa);
-
`villa' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. If the transaction is activated and not committed, it is aborted.
-
- -

The function `vlput' is used in order to store a record.

- -
-
int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
-
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `VL_DOVER', which means the specified value overwrites the existing one, `VL_DKEEP', which means the existing value is kept, `VL_DCAT', which means the specified value is concatenated at the end of the existing value, `VL_DDUP', which means duplication of keys is allowed and the specified value is added as the last one, `VL_DDUPR', which means duplication of keys is allowed and the specified value is added as the first one. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database.
-
- -

The function `vlout' is used in order to delete a record.

- -
-
int vlout(VILLA *villa, const char *kbuf, int ksiz);
-
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the first record of the same key is deleted. The cursor becomes unavailable due to updating database.
-
- -

The function `vlget' is used in order to retrieve a record.

- -
-
char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp);
-
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the value of the first record of the same key is selected. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `vlvsiz' is used in order to get the size of the value of a record.

- -
-
int vlvsiz(VILLA *villa, const char *kbuf, int ksiz);
-
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. If multiple records correspond, the size of the first is returned.
-
- -

The function `vlvnum' is used in order to get the number of records corresponding a key.

- -
-
int vlvnum(VILLA *villa, const char *kbuf, int ksiz);
-
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the number of corresponding records. If no record corresponds, 0 is returned.
-
- -

The function `vlputlist' is used in order to store plural records corresponding a key.

- -
-
int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals);
-
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vals' specifies a list handle of values. The list should not be empty. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database.
-
- -

The function `vloutlist' is used in order to delete all records corresponding a key.

- -
-
int vloutlist(VILLA *villa, const char *kbuf, int ksiz);
-
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. The cursor becomes unavailable due to updating database.
-
- -

The function `vlgetlist' is used in order to retrieve values of all records corresponding a key.

- -
-
CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz);
-
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is a list handle of the values of the corresponding records, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
-
- -

The function `vlgetcat' is used in order to retrieve concatenated values of all records corresponding a key.

- -
-
char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp);
-
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the concatenated values of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `vlcurfirst' is used in order to move the cursor to the first record.

- -
-
int vlcurfirst(VILLA *villa);
-
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database.
-
- -

The function `vlcurlast' is used in order to move the cursor to the last record.

- -
-
int vlcurlast(VILLA *villa);
-
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database.
-
- -

The function `vlcurprev' is used in order to move the cursor to the previous record.

- -
-
int vlcurprev(VILLA *villa);
-
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no previous record.
-
- -

The function `vlcurnext' is used in order to move the cursor to the next record.

- -
-
int vlcurnext(VILLA *villa);
-
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no next record.
-
- -

The function `vlcurjump' is used in order to move the cursor to a position around a record.

- -
-
int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode);
-
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `jmode' specifies detail adjustment: `VL_JFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `VL_JBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist. If successful, the return value is true, else, it is false. False is returned if there is no record corresponding the condition.
-
- -

The function `vlcurkey' is used in order to get the key of the record where the cursor is.

- -
-
char *vlcurkey(VILLA *villa, int *sp);
-
`villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the key of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `vlcurval' is used in order to get the value of the record where the cursor is.

- -
-
char *vlcurval(VILLA *villa, int *sp);
-
`villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `vlcurput' is used in order to insert a record around the cursor.

- -
-
int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode);
-
`villa' specifies a database handle connected as a writer. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `cpmode' specifies detail adjustment: `VL_CPCURRENT', which means that the value of the current record is overwritten, `VL_CPBEFORE', which means that a new record is inserted before the current record, `VL_CPAFTER', which means that a new record is inserted after the current record. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After insertion, the cursor is moved to the inserted record.
-
- -

The function `vlcurout' is used in order to delete the record where the cursor is.

- -
-
int vlcurout(VILLA *villa);
-
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After deletion, the cursor is moved to the next record if possible.
-
- -

The function `vlsettuning' is used in order to set the tuning parameters for performance.

- -
-
void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum);
-
`villa' specifies a database handle. `lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is not more than 0, the default value is specified. `nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is not more than 0, the default value is specified. `lcnum' specifies the max number of caching leaf nodes. If it is not more than 0, the default value is specified. `ncnum' specifies the max number of caching non-leaf nodes. If it is not more than 0, the default value is specified. The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning parameters are not saved in a database, you should specify them every opening a database.
-
- -

The function `vlsetfbpsiz' is used in order to set the size of the free block pool of a database handle.

- -
-
int vlsetfbpsiz(VILLA *villa, int size);
-
`villa' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 256. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
-
- -

The function `vlsync' is used in order to synchronize updating contents with the file and the device.

- -
-
int vlsync(VILLA *villa);
-
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database file. This function should not be used while the transaction is activated.
-
- -

The function `vloptimize' is used in order to optimize a database.

- -
-
int vloptimize(VILLA *villa);
-
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them. This function should not be used while the transaction is activated.
-
- -

The function `vlname' is used in order to get the name of a database.

- -
-
char *vlname(VILLA *villa);
-
`villa' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `vlfsiz' is used in order to get the size of a database file.

- -
-
int vlfsiz(VILLA *villa);
-
`villa' specifies a database handle. If successful, the return value is the size of the database file, else, it is -1. Because of the I/O buffer, the return value may be less than the hard size.
-
- -

The function `vllnum' is used in order to get the number of the leaf nodes of B+ tree.

- -
-
int vllnum(VILLA *villa);
-
`villa' specifies a database handle. If successful, the return value is the number of the leaf nodes, else, it is -1.
-
- -

The function `vlnnum' is used in order to get the number of the non-leaf nodes of B+ tree.

- -
-
int vlnnum(VILLA *villa);
-
`villa' specifies a database handle. If successful, the return value is the number of the non-leaf nodes, else, it is -1.
-
- -

The function `vlrnum' is used in order to get the number of the records stored in a database.

- -
-
int vlrnum(VILLA *villa);
-
`villa' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1.
-
- -

The function `vlwritable' is used in order to check whether a database handle is a writer or not.

- -
-
int vlwritable(VILLA *villa);
-
`villa' specifies a database handle. The return value is true if the handle is a writer, false if not.
-
- -

The function `vlfatalerror' is used in order to check whether a database has a fatal error or not.

- -
-
int vlfatalerror(VILLA *villa);
-
`villa' specifies a database handle. The return value is true if the database has a fatal error, false if not.
-
- -

The function `vlinode' is used in order to get the inode number of a database file.

- -
-
int vlinode(VILLA *villa);
-
`villa' specifies a database handle. The return value is the inode number of the database file.
-
- -

The function `vlmtime' is used in order to get the last modified time of a database.

- -
-
time_t vlmtime(VILLA *villa);
-
`villa' specifies a database handle. The return value is the last modified time of the database.
-
- -

The function `vltranbegin' is used in order to begin the transaction.

- -
-
int vltranbegin(VILLA *villa);
-
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Because this function does not perform mutual exclusion control in multi-thread, the application is responsible for it. Only one transaction can be activated with a database handle at the same time.
-
- -

The function `vltrancommit' is used in order to commit the transaction.

- -
-
int vltrancommit(VILLA *villa);
-
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Updating a database in the transaction is fixed when it is committed successfully.
-
- -

The function `vltranabort' is used in order to abort the transaction.

- -
-
int vltranabort(VILLA *villa);
-
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Updating a database in the transaction is discarded when it is aborted. The state of the database is rollbacked to before transaction.
-
- -

The function `vlremove' is used in order to remove a database file.

- -
-
int vlremove(const char *name);
-
`name' specifies the name of a database file. If successful, the return value is true, else, it is false.
-
- -

The function `vlrepair' is used in order to repair a broken database file.

- -
-
int vlrepair(const char *name, VLCFUNC cmp);
-
`name' specifies the name of a database file. `cmp' specifies the comparing function of the database file. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database file correspond to the original or expected state.
-
- -

The function `vlexportdb' is used in order to dump all records as endian independent data.

- -
-
int vlexportdb(VILLA *villa, const char *name);
-
`villa' specifies a database handle. `name' specifies the name of an output file. If successful, the return value is true, else, it is false.
-
- -

The function `vlimportdb' is used in order to load all records from endian independent data.

- -
-
int vlimportdb(VILLA *villa, const char *name);
-
`villa' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input file. If successful, the return value is true, else, it is false.
-
- -

Examples

- -

The following example stores and retrieves a phone number, using the name as the key.

- -
#include <depot.h>
-#include <cabin.h>
-#include <villa.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define NAME     "mikio"
-#define NUMBER   "000-1234-5678"
-#define DBNAME   "book"
-
-int main(int argc, char **argv){
-  VILLA *villa;
-  char *val;
-
-  /* open the database */
-  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
-    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* store the record */
-  if(!vlput(villa, NAME, -1, NUMBER, -1, VL_DOVER)){
-    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
-  }
-
-  /* retrieve the record */
-  if(!(val = vlget(villa, NAME, -1, NULL))){
-    fprintf(stderr, "vlget: %s\n", dperrmsg(dpecode));
-  } else {
-    printf("Name: %s\n", NAME);
-    printf("Number: %s\n", val);
-    free(val);
-  }
-
-  /* close the database */
-  if(!vlclose(villa)){
-    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

The following example performs forward matching search for strings.

- -
#include <depot.h>
-#include <cabin.h>
-#include <villa.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#define DBNAME   "words"
-#define PREFIX   "apple"
-
-int main(int argc, char **argv){
-  VILLA *villa;
-  char *key, *val;
-
-  /* open the database */
-  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
-    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* store records */
-  if(!vlput(villa, "applet", -1, "little application", -1, VL_DDUP) ||
-     !vlput(villa, "aurora", -1, "polar wonderwork", -1, VL_DDUP) ||
-     !vlput(villa, "apple", -1, "delicious fruit", -1, VL_DDUP) ||
-     !vlput(villa, "amigo", -1, "good friend", -1, VL_DDUP) ||
-     !vlput(villa, "apple", -1, "big city", -1, VL_DDUP)){
-    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
-  }
-
-  /* set the cursor at the top of candidates */
-  vlcurjump(villa, PREFIX, -1, VL_JFORWARD);
-
-  /* scan with the cursor */
-  while((key = vlcurkey(villa, NULL)) != NULL){
-    if(strstr(key, PREFIX) != key){
-      free(key);
-      break;
-    }
-    if(!(val = vlcurval(villa, NULL))){
-      fprintf(stderr, "vlcurval: %s\n", dperrmsg(dpecode));
-      free(key);
-      break;
-    }
-    printf("%s: %s\n", key, val);
-    free(val);
-    free(key);
-    vlcurnext(villa);
-  }
-
-  /* close the database */
-  if(!vlclose(villa)){
-    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

Notes

- -

How to build programs using Villa is the same as the case of Depot.

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Villa are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

- -

Vista: Extended Advanced API

- -

Vista is the extended API of Villa. To compensate for the defect that Villa can not handle a file whose size is more than 2GB, Vista does not use Depot but Curia for handling its internal database. While Vista provides data structure and operations of B+ tree as with Villa, its database is realized as a directory.

- -

In order to use Vista, you should include `vista.h' instead of `villa.h'. Because Vista is implemented by overriding symbols of Villa, it can be used as with Villa. That is, Signatures of Villa and Vista is all the same. However, as its adverse effect, modules (compilation unit) using Vista can not use Villa (do not include `villa.h').

- -
- -

Commands for Villa

- -

Villa has the following command line interfaces.

- -

The command `vlmgr' is a utility for debugging Villa and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

- -
-
vlmgr create [-cz|-cy|-cx] name
-
Create a database file.
-
vlmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat|-dup] name key val
-
Store a record with a key and a value.
-
vlmgr out [-l] [-kx|-ki] name key
-
Delete a record with a key.
-
vlmgr get [-nl] [-l] [-kx|-ki] [-ox] [-n] name key
-
Retrieve a record with a key and output it to the standard output.
-
vlmgr list [-nl] [-k|-v] [-kx|-ki] [-ox] [-top key] [-bot key] [-gt] [-lt] [-max num] [-desc] name
-
List all keys and values delimited with tab and line-feed to the standard output.
-
vlmgr optimize name
-
Optimize a database.
-
vlmgr inform [-nl] name
-
Output miscellaneous information to the standard output.
-
vlmgr remove name
-
Remove a database file.
-
vlmgr repair [-ki] name
-
Repair a broken database file.
-
vlmgr exportdb [-ki] name file
-
Dump all records as endian independent data.
-
vlmgr importdb [-ki] name file
-
Load all records from endian independent data.
-
vlmgr version
-
Output version information of QDBM to the standard output.
-
- -

Options feature the following.

- -
    -
  • -cz : compress leaves in the database with ZLIB.
  • -
  • -cy : compress leaves in the database with LZO.
  • -
  • -cx : compress leaves in the database with BZIP2.
  • -
  • -l : all records corresponding the key are dealt.
  • -
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • -
  • -ki : treat `key' as an integer expression of decimal notation.
  • -
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • -
  • -vi : treat `val' as an integer expression of decimal notation.
  • -
  • -vf : read the value from a file specified with `val'.
  • -
  • -keep : specify the storing mode for `VL_DKEEP'.
  • -
  • -cat : specify the storing mode for `VL_DCAT'.
  • -
  • -dup : specify the storing mode for `VL_DDUP'.
  • -
  • -nl : open the database without file locking.
  • -
  • -top key : specify the top key of listing.
  • -
  • -bot key : specify the bottom key of listing.
  • -
  • -gt : do not include the top key of listing.
  • -
  • -lt : do not include the bottom key of listing.
  • -
  • -max num : specify the max number of listing.
  • -
  • -desc : list in descending order.
  • -
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • -
  • -n : do not output the tailing newline.
  • -
  • -k : output keys only.
  • -
  • -v : output values only.
  • -
- -

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

- -

The command `vltest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of the records.

- -
-
vltest write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum
-
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
-
vltest read [-int] [-vc] name
-
Retrieve all records of the database above.
-
vltest rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum pnum
-
Store records with partway duplicated keys using duplicate mode.
-
vltest combo [-cz|-cy|-cx] name
-
Perform combination test of various operations.
-
vltest wicked [-cz|-cy|-cx] name rnum
-
Perform updating operations selected at random.
-
- -

Options feature the following.

- -
    -
  • -int : treat keys and values as objects of `int', and use comparing function `VL_CMPINT'.
  • -
  • -cz : compress leaves in the database with ZLIB.
  • -
  • -cy : compress leaves in the database with LZO.
  • -
  • -cx : compress leaves in the database with BZIP2.
  • -
  • -vc : refer to volatile cache.
  • -
  • -cc : select `VL_DCAT' or `VL_DDUP' at random.
  • -
  • -tune lrecmax nidxmax lcnum ncnum : set tuning parameters.
  • -
  • -fbp num : set the size of the free block pool.
  • -
  • -c : perform comparison test with map of Cabin.
  • -
- -

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

- -

The command `vltsv' features mutual conversion between a database of Villa and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the following format. `name' specifies a database name. The subcommand `export' reads TSV data from the standard input. The subcommand `import' writes TSV data to the standard output.

- -
-
vltsv import [-bin] name
-
Create a database from TSV.
-
vltsv export [-bin] name
-
Write TSV data of a database.
-
- -

Options feature the following.

- -
    -
  • -bin : treat records as Base64 format.
  • -
- -

This command returns 0 on success, another on failure.

- -

Commands of Villa realize a simple database system. For example, to make a database to search `/etc/password' by a user name, perform the following command.

- -
cat /etc/passwd | tr ':' '\t' | vltsv import casket
-
- -

Thus, to retrieve the information of a user `mikio', perform the following command.

- -
vlmgr get casket mikio
-
- -

It is easy to implement functions upsides with these commands, using the API of Villa.

- -

The command `qmttest' checks multi-thread safety of Depot, Curia, and Villa. This command works with multi threads only if QDBM was built with POSIX thread. This command is used in the following format. `name' specifies the prefix of each database. `rnum' specifies the number of records to be stored in each database. `tnum' specifies the number of threads.

- -
-
qmttest name rnum tnum
-
Check multi-thread safety.
-
- -

This command returns 0 on success, another on failure.

- -
- -

Odeum: Inverted API

- -

Overview

- -

Odeum is the API which handles an inverted index. An inverted index is a data structure to retrieve a list of some documents that include one of words which were extracted from a population of documents. It is easy to realize a full-text search system with an inverted index. Odeum provides an abstract data structure which consists of words and attributes of a document. It is used when an application stores a document into a database and when an application retrieves some documents from a database.

- -

Odeum does not provide methods to extract the text from the original data of a document. It should be implemented by applications. Although Odeum provides utilities to extract words from a text, it is oriented to such languages whose words are separated with space characters as English. If an application handles such languages which need morphological analysis or N-gram analysis as Japanese, or if an application perform more such rarefied analysis of natural languages as stemming, its own analyzing method can be adopted. Result of search is expressed as an array contains elements which are structures composed of the ID number of documents and its score. In order to search with two or more words, Odeum provides utilities of set operations.

- -

Odeum is implemented, based on Curia, Cabin, and Villa. Odeum creates a database with a directory name. Some databases of Curia and Villa are placed in the specified directory. For example, `casket/docs', `casket/index', and `casket/rdocs' are created in the case that a database directory named as `casket'. `docs' is a database directory of Curia. The key of each record is the ID number of a document, and the value is such attributes as URI. `index' is a database directory of Curia. The key of each record is the normalized form of a word, and the value is an array whose element is a pair of the ID number of a document including the word and its score. `rdocs' is a database file of Villa. The key of each record is the URI of a document, and the value is its ID number.

- -

In order to use Odeum, you should include `depot.h', `cabin.h', `odeum.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

- -
-
#include <depot.h>
-
#include <cabin.h>
-
#include <odeum.h>
-
#include <stdlib.h>
-
- -

A pointer to `ODEUM' is used as a database handle. A database handle is opened with the function `odopen' and closed with `odclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `odclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used.

- -

A pointer to `ODDOC' is used as a document handle. A document handle is opened with the function `oddocopen' and closed with `oddocclose'. You should not refer directly to any member of the handle. A document consists of attributes and words. Each word is expressed as a pair of a normalized form and a appearance form.

- -

Odeum also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code.

- -

API

- -

Structures of `ODPAIR' type is used in order to handle results of search.

- -
-
typedef struct { int id; int score; } ODPAIR;
-
`id' specifies the ID number of a document. `score' specifies the score calculated from the number of searching words in the document.
-
- -

The function `odopen' is used in order to get a database handle.

- -
-
ODEUM *odopen(const char *name, int omode);
-
`name' specifies the name of a database directory. `omode' specifies the connection mode: `OD_OWRITER' as a writer, `OD_OREADER' as a reader. If the mode is `OD_OWRITER', the following may be added by bitwise or: `OD_OCREAT', which means it creates a new database if not exist, `OD_OTRUNC', which means it creates a new database regardless if one exists. Both of `OD_OREADER' and `OD_OWRITER' can be added to by bitwise or: `OD_ONOLCK', which means it opens a database directory without file locking, or `OD_OLCKNB', which means locking is performed without blocking. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `OD_ONOLCK' is used, the application is responsible for exclusion control.
-
- -

The function `odclose' is used in order to close a database handle.

- -
-
int odclose(ODEUM *odeum);
-
`odeum' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.
-
- -

The function `odput' is used in order to store a document.

- -
-
int odput(ODEUM *odeum, const ODDOC *doc, int wmax, int over);
-
`odeum' specifies a database handle connected as a writer. `doc' specifies a document handle. `wmax' specifies the max number of words to be stored in the document database. If it is negative, the number is unlimited. `over' specifies whether the data of the duplicated document is overwritten or not. If it is false and the URI of the document is duplicated, the function returns as an error. If successful, the return value is true, else, it is false.
-
- -

The function `odout' is used in order to delete a document specified by a URI.

- -
-
int odout(ODEUM *odeum, const char *uri);
-
`odeum' specifies a database handle connected as a writer. `uri' specifies the string of the URI of a document. If successful, the return value is true, else, it is false. False is returned when no document corresponds to the specified URI.
-
- -

The function `odoutbyid' is used in order to delete a document specified by an ID number.

- -
-
int odoutbyid(ODEUM *odeum, int id);
-
`odeum' specifies a database handle connected as a writer. `id' specifies the ID number of a document. If successful, the return value is true, else, it is false. False is returned when no document corresponds to the specified ID number.
-
- -

The function `odget' is used in order to retrieve a document specified by a URI.

- -
-
ODDOC *odget(ODEUM *odeum, const char *uri);
-
`odeum' specifies a database handle. `uri' specifies the string of the URI of a document. If successful, the return value is the handle of the corresponding document, else, it is `NULL'. `NULL' is returned when no document corresponds to the specified URI. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'.
-
- -

The function `odgetbyid' is used in order to retrieve a document by an ID number.

- -
-
ODDOC *odgetbyid(ODEUM *odeum, int id);
-
`odeum' specifies a database handle. `id' specifies the ID number of a document. If successful, the return value is the handle of the corresponding document, else, it is `NULL'. `NULL' is returned when no document corresponds to the specified ID number. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'.
-
- -

The function `odgetidbyuri' is used in order to retrieve the ID of the document specified by a URI.

- -
-
int odgetidbyuri(ODEUM *odeum, const char *uri);
-
`odeum' specifies a database handle. `uri' specifies the string the URI of a document. If successful, the return value is the ID number of the document, else, it is -1. -1 is returned when no document corresponds to the specified URI.
-
- -

The function `odcheck' is used in order to check whether the document specified by an ID number exists.

- -
-
int odcheck(ODEUM *odeum, int id);
-
`odeum' specifies a database handle. `id' specifies the ID number of a document. The return value is true if the document exists, else, it is false.
-
- -

The function `odsearch' is used in order to search the inverted index for documents including a particular word.

- -
-
ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np);
-
`odeum' specifies a database handle. `word' specifies a searching word. `max' specifies the max number of documents to be retrieve. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. If successful, the return value is the pointer to an array, else, it is `NULL'. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified word, it is not error but returns an dummy array. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document.
-
- -

The function `odsearchnum' is used in order to get the number of documents including a word.

- -
-
int odsearchdnum(ODEUM *odeum, const char *word);
-
`odeum' specifies a database handle. `word' specifies a searching word. If successful, the return value is the number of documents including the word, else, it is -1. Because this function does not read the entity of the inverted index, it is faster than `odsearch'.
-
- -

The function `oditerinit' is used in order to initialize the iterator of a database handle.

- -
-
int oditerinit(ODEUM *odeum);
-
`odeum' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access every document stored in a database.
-
- -

The function `oditernext' is used in order to get the next key of the iterator.

- -
-
ODDOC *oditernext(ODEUM *odeum);
-
`odeum' specifies a database handle. If successful, the return value is the handle of the next document, else, it is `NULL'. `NULL' is returned when no document is to be get out of the iterator. It is possible to access every document by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of string matches the one of the traversal access. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'.
-
- -

The function `odsync' is used in order to synchronize updating contents with the files and the devices.

- -
-
int odsync(ODEUM *odeum);
-
`odeum' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database directory.
-
- -

The function `odoptimize' is used in order to optimize a database.

- -
-
int odoptimize(ODEUM *odeum);
-
`odeum' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Elements of the deleted documents in the inverted index are purged.
-
- -

The function `odname' is used in order to get the name of a database.

- -
-
char *odname(ODEUM *odeum);
-
`odeum' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `odfsiz' is used in order to get the total size of database files.

- -
-
double odfsiz(ODEUM *odeum);
-
`odeum' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1.0.
-
- -

The function `odbnum' is used in order to get the total number of the elements of the bucket arrays in the inverted index.

- -
-
int odbnum(ODEUM *odeum);
-
`odeum' specifies a database handle. If successful, the return value is the total number of the elements of the bucket arrays, else, it is -1.
-
- -

The function `odbusenum' is used in order to get the total number of the used elements of the bucket arrays in the inverted index.

- -
-
int odbusenum(ODEUM *odeum);
-
`odeum' specifies a database handle. If successful, the return value is the total number of the used elements of the bucket arrays, else, it is -1.
-
- -

The function `oddnum' is used in order to get the number of the documents stored in a database.

- -
-
int oddnum(ODEUM *odeum);
-
`odeum' specifies a database handle. If successful, the return value is the number of the documents stored in the database, else, it is -1.
-
- -

The function `odwnum' is used in order to get the number of the words stored in a database.

- -
-
int odwnum(ODEUM *odeum);
-
`odeum' specifies a database handle. If successful, the return value is the number of the words stored in the database, else, it is -1. Because of the I/O buffer, the return value may be less than the hard number.
-
- -

The function `odwritable' is used in order to check whether a database handle is a writer or not.

- -
-
int odwritable(ODEUM *odeum);
-
`odeum' specifies a database handle. The return value is true if the handle is a writer, false if not.
-
- -

The function `odfatalerror' is used in order to check whether a database has a fatal error or not.

- -
-
int odfatalerror(ODEUM *odeum);
-
`odeum' specifies a database handle. The return value is true if the database has a fatal error, false if not.
-
- -

The function `odinode' is used in order to get the inode number of a database directory.

- -
-
int odinode(ODEUM *odeum);
-
`odeum' specifies a database handle. The return value is the inode number of the database directory.
-
- -

The function `odmtime' is used in order to get the last modified time of a database.

- -
-
time_t odmtime(ODEUM *odeum);
-
`odeum' specifies a database handle. The return value is the last modified time of the database.
-
- -

The function `odmerge' is used in order to merge plural database directories.

- -
-
int odmerge(const char *name, const CBLIST *elemnames);
-
`name' specifies the name of a database directory to create. `elemnames' specifies a list of names of element databases. If successful, the return value is true, else, it is false. If two or more documents which have the same URL come in, the first one is adopted and the others are ignored.
-
- -

The function `odremove' is used in order to remove a database directory.

- -
-
int odremove(const char *name);
-
`name' specifies the name of a database directory. If successful, the return value is true, else, it is false. A database directory can contain databases of other APIs of QDBM, they are also removed by this function.
-
- -

The function `oddocopen' is used in order to get a document handle.

- -
-
ODDOC *oddocopen(const char *uri);
-
`uri' specifies the URI of a document. The return value is a document handle. The ID number of a new document is not defined. It is defined when the document is stored in a database.
-
- -

The function `oddocclose' is used in order to close a document handle.

- -
-
void oddocclose(ODDOC *doc);
-
`doc' specifies a document handle. Because the region of a closed handle is released, it becomes impossible to use the handle.
-
- -

The function `oddocaddattr' is used in order to add an attribute to a document.

- -
-
void oddocaddattr(ODDOC *doc, const char *name, const char *value);
-
`doc' specifies a document handle. `name' specifies the string of the name of an attribute. `value' specifies the string of the value of the attribute.
-
- -

The function `oddocaddword' is used in order to add a word to a document.

- -
-
void oddocaddword(ODDOC *doc, const char *normal, const char *asis);
-
`doc' specifies a document handle. `normal' specifies the string of the normalized form of a word. Normalized forms are treated as keys of the inverted index. If the normalized form of a word is an empty string, the word is not reflected in the inverted index. `asis' specifies the string of the appearance form of the word. Appearance forms are used after the document is retrieved by an application.
-
- -

The function `oddocid' is used in order to get the ID number of a document.

- -
-
int oddocid(const ODDOC *doc);
-
`doc' specifies a document handle. The return value is the ID number of a document.
-
- -

The function `oddocuri' is used in order to get the URI of a document.

- -
-
const char *oddocuri(const ODDOC *doc);
-
`doc' specifies a document handle. The return value is the string of the URI of a document.
-
- -

The function `oddocgetattr' is used in order to get the value of an attribute of a document.

- -
-
const char *oddocgetattr(const ODDOC *doc, const char *name);
-
`doc' specifies a document handle. `name' specifies the string of the name of an attribute. The return value is the string of the value of the attribute, or `NULL' if no attribute corresponds.
-
- -

The function `oddocnwords' is used in order to get the list handle contains words in normalized form of a document.

- -
-
const CBLIST *oddocnwords(const ODDOC *doc);
-
`doc' specifies a document handle. The return value is the list handle contains words in normalized form.
-
- -

The function `oddocawords' is used in order to get the list handle contains words in appearance form of a document.

- -
-
const CBLIST *oddocawords(const ODDOC *doc);
-
`doc' specifies a document handle. The return value is the list handle contains words in appearance form.
-
- -

The function `oddocscores' is used in order to get the map handle contains keywords in normalized form and their scores.

- -
-
CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum);
-
`doc' specifies a document handle. `max' specifies the max number of keywords to get. `odeum' specifies a database handle with which the IDF for weighting is calculate. If it is `NULL', it is not used. The return value is the map handle contains keywords and their scores. Scores are expressed as decimal strings. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use.
-
- -

The function `odbreaktext' is used in order to break a text into words in appearance form.

- -
-
CBLIST *odbreaktext(const char *text);
-
`text' specifies the string of a text. The return value is the list handle contains words in appearance form. Words are separated with space characters and such delimiters as period, comma and so on. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
-
- -

The function `odnormalizeword' is used in order to make the normalized form of a word.

- -
-
char *odnormalizeword(const char *asis);
-
`asis' specifies the string of the appearance form of a word. The return value is is the string of the normalized form of the word. Alphabets of the ASCII code are unified into lower cases. Words composed of only delimiters are treated as empty strings. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `odpairsand' is used in order to get the common elements of two sets of documents.

- -
-
ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
-
`apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements commonly belong to the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `odpairsor' is used in order to get the sum of elements of two sets of documents.

- -
-
ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
-
`apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements belong to both or either of the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `odpairsnotand' is used in order to get the difference set of documents.

- -
-
ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
-
`apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array of the sum of elements. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements belong to the former set but not to the latter set. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
-
- -

The function `odpairssort' is used in order to sort a set of documents in descending order of scores.

- -
-
void odpairssort(ODPAIR *pairs, int pnum);
-
`pairs' specifies the pointer to a document array. `pnum' specifies the number of the elements of the document array.
-
- -

The function `odlogarithm' is used in order to get the natural logarithm of a number.

- -
-
double odlogarithm(double x);
-
`x' specifies a number. The return value is the natural logarithm of the number. If the number is equal to or less than 1.0, the return value is 0.0. This function is useful when an application calculates the IDF of search results.
-
- -

The function `odvectorcosine' is used in order to get the cosine of the angle of two vectors.

- -
-
double odvectorcosine(const int *avec, const int *bvec, int vnum);
-
`avec' specifies the pointer to one array of numbers. `bvec' specifies the pointer to the other array of numbers. `vnum' specifies the number of elements of each array. The return value is the cosine of the angle of two vectors. This function is useful when an application calculates similarity of documents.
-
- -

The function `odsettuning' is used in order to set the global tuning parameters.

- -
-
void odsettuning(int ibnum, int idnum, int cbnum, int csiz);
-
`ibnum' specifies the number of buckets for inverted indexes. `idnum' specifies the division number of inverted index. `cbnum' specifies the number of buckets for dirty buffers. `csiz' specifies the maximum bytes to use memory for dirty buffers. The default setting is equivalent to `odsettuning(32749, 7, 262139, 8388608)'. This function should be called before opening a handle.
-
- -

The function `odanalyzetext' is used in order to break a text into words and store appearance forms and normalized form into lists.

- -
-
void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords);
-
`odeum' specifies a database handle. `text' specifies the string of a text. `awords' specifies a list handle into which appearance form is store. `nwords' specifies a list handle into which normalized form is store. If it is `NULL', it is ignored. Words are separated with space characters and such delimiters as period, comma and so on.
-
- -

The function `odsetcharclass' is used in order to set the classes of characters used by `odanalyzetext'.

- -
-
void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars);
-
`odeum' specifies a database handle. `spacechars' spacifies a string contains space characters. `delimchars' spacifies a string contains delimiter characters. `gluechars' spacifies a string contains glue characters.
-
- -

The function `odquery' is used in order to query a database using a small boolean query language.

- -
-
ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors);
-
`odeum' specifies a database handle. 'query' specifies the text of the query. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. `errors' specifies a list handle into which error messages are stored. If it is `NULL', it is ignored. If successful, the return value is the pointer to an array, else, it is `NULL'. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified condition, it is not error but returns an dummy array. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document.
-
- -

Examples

- -

The following example stores a document into the database.

- -
#include <depot.h>
-#include <cabin.h>
-#include <odeum.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#define DBNAME   "index"
-
-int main(int argc, char **argv){
-  ODEUM *odeum;
-  ODDOC *doc;
-  CBLIST *awords;
-  const char *asis;
-  char *normal;
-  int i;
-
-  /* open the database */
-  if(!(odeum = odopen(DBNAME, OD_OWRITER | OD_OCREAT))){
-    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* get the document handle */
-  doc = oddocopen("http://www.foo.bar/baz.txt");
-
-  /* set attributes of the document */
-  oddocaddattr(doc, "title", "Balcony Scene");
-  oddocaddattr(doc, "author", "Shakespeare");
-
-  /* break the text and get the word list */
-  awords = odbreaktext("Parting is such sweet sorrow.");
-
-  /* set each word into the document handle */
-  for(i = 0; i < cblistnum(awords); i++){
-    /* get one word of the list */
-    asis = cblistval(awords, i, NULL);
-    /* get the normalized form from the appearance form */
-    normal = odnormalizeword(asis);
-    /* add the word into the document handle */
-    oddocaddword(doc, normal, asis);
-    /* release the region of the normalized form */
-    free(normal);
-  }
-
-  /* store the document into the database */
-  if(!odput(odeum, doc, -1, 1)){
-    fprintf(stderr, "odput: %s\n", dperrmsg(dpecode));
-  }
-
-  /* release the word list */
-  cblistclose(awords);
-
-  /* release the document handle */
-  oddocclose(doc);
-
-  /* close the database */
-  if(!odclose(odeum)){
-    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

The following example retrieves documents.

- -
#include <depot.h>
-#include <cabin.h>
-#include <odeum.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#define DBNAME   "index"
-
-int main(int argc, char **argv){
-  ODEUM *odeum;
-  ODPAIR *pairs;
-  ODDOC *doc;
-  const CBLIST *words;
-  const char *title, *author, *asis;
-  int i, j, pnum;
-
-  /* open the database */
-  if(!(odeum = odopen(DBNAME, OD_OREADER))){
-    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  /* retrieve documents */
-  if((pairs = odsearch(odeum, "sorrow", -1, &pnum)) != NULL){
-
-    /* scan each element of the document array */
-    for(i = 0; i < pnum; i++){
-      /* get the document handle */
-      if(!(doc = odgetbyid(odeum, pairs[i].id))) continue;
-      /* show the attributes */
-      printf("URI: %s\n", oddocuri(doc));
-      title = oddocgetattr(doc, "title");
-      if(title) printf("TITLE: %s\n", title);
-      author = oddocgetattr(doc, "author");
-      if(author) printf("AUTHOR: %s\n", author);
-      /* show words in appearance form */
-      printf("WORDS:");
-      words = oddocawords(doc);
-      for(j = 0; j < cblistnum(words); j++){
-        asis = cblistval(words, j, NULL);
-        printf(" %s", asis);
-      }
-      putchar('\n');
-      /* release the document handle */
-      oddocclose(doc);
-    }
-
-    /* release the document array */
-    free(pairs);
-
-  } else {
-    fprintf(stderr, "odsearch: %s\n", dperrmsg(dpecode));
-  }
-
-  /* close the database */
-  if(!odclose(odeum)){
-    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
-    return 1;
-  }
-
-  return 0;
-}
-
- -

Notes

- -

How to build programs using Odeum is the same as the case of Depot.

- -
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
-
- -

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Odeum are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

- -

If QDBM was built with ZLIB enabled, records in the database for document attributes are compressed. In that case, the size of the database is reduced to 30% or less. Thus, you should enable ZLIB if you use Odeum. A database of Odeum created without ZLIB enabled is not available on environment with ZLIB enabled, and vice versa. If ZLIB was not enabled but LZO, LZO is used instead.

- -

Query Language

- -

The query language of the function `odquery' is a basic language following this grammar:

- -
expr ::= subexpr ( op subexpr )*
-subexpr ::= WORD
-subexpr ::= LPAREN expr RPAREN
-
- -

Operators are "&" (AND), "|" (OR), and "!" (NOTAND). You can use parenthesis to group sub-expressions together in order to change order of operations. The given query is broken up using the function `odanalyzetext', so if you want to specify different text breaking rules, then make sure that you at least set "&", "|", "!", "(", and ")" to be delimiter characters. Consecutive words are treated as having an implicit "&" operator between them, so "zed shaw" is actually "zed & shaw".

- -

The encoding of the query text should be the same with the encoding of target documents. Moreover, each of space characters, delimiter characters, and glue characters should be single byte.

- -
- -

Commands for Odeum

- -

Odeum has the following command line interfaces.

- -

The command `odmgr' is a utility for debugging Odeum and its applications. It features editing and checking of a database. It can be used for full-text search systems with shell scripts. This command is used in the following format. `name' specifies a database name. `file' specifies a file name, `expr' specifies the URI or the ID number of a document, `words' specifies searching words. `elems' specifies element databases.

- -
-
odmgr create name
-
Create a database file.
-
odmgr put [-uri str] [-title str] [-author str] [-date str] [-wmax num] [-keep] name [file]
-
Add a document by reading a file. If `file' is omitted, the standard input is read and URI is needed.
-
odmgr out [-id] name expr
-
Delete a document specified by a URI.
-
odmgr get [-id] [-t|-h] name expr
-
Show a document specified by a URI. The output is the ID number and the URI of a document, in tab separated format.
-
odmgr search [-max num] [-or] [-idf] [-t|-h|-n] name words...
-
Retrieve documents including specified words. The first line of the output is the total number of hits and each word with its number of hits, in tab separated format. The second line and below are the ID numbers and the scores of documents, in tab separated format.
-
odmgr list [-t|-h] name
-
Show all documents in a database. Each line of the output is the ID number and the score of a document, in tab separated format.
-
odmgr optimize name
-
Optimize a database.
-
odmgr inform name
-
Output miscellaneous information.
-
odmgr merge name elems...
-
Merge plural databases.
-
odmgr remove name
-
Remove a database directory.
-
odmgr break [-h|-k|-s] [file]
-
Read a file and output words in the text. Each line of the output is the appearance form and the normalized form of a word, in tab separated format.
-
odmgr version
-
Output version information of QDBM.
-
- -

Options feature the following.

- -
    -
  • -uri str : specify the URI of the document explicitly.
  • -
  • -title str : specify the title of the document.
  • -
  • -author str : specify the author of the document.
  • -
  • -date str : specify the modified date of the document.
  • -
  • -wmax num : specify the max number of words to be stored.
  • -
  • -keep : the storing mode is not to be overwrite.
  • -
  • -id : specify a document not by a URI but by an ID number.
  • -
  • -t : output the details of a document in tab separated format.
  • -
  • -h : output the details of a document in human-readable format.
  • -
  • -k : output keywords of a document.
  • -
  • -s : output summary of a document.
  • -
  • -max num : specify the max number of documents of the output.
  • -
  • -or : perform OR search, nut AND search.
  • -
  • -idf : tune scores with IDF.
  • -
  • -n : show ID numbers and scores only.
  • -
- -

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

- -

The command `odtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `dnum' specifies the number of the documents. `wnum' specifies the number of words per document. `pnum' specifies the number of patterns of words.

- -
-
odtest write [-tune ibnum idnum cbnum csiz] name dnum wnum pnum
-
Store documents with random attributes and random words.
-
odtest read name
-
Retrieve all documents of the database above.
-
odtest combo name
-
Perform combination test of various operations.
-
odtest wicked name dnum
-
Perform updating operations selected at random.
-
- -

Options feature the following.

- -
    -
  • -tune ibnum idnum cbnum csiz : set tuning parameters.
  • -
- -

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

- -

The command `odidx' is a utility for indexing files on the local file system. This command is useful for a full-text search system of a Web site. Supported file format are plain text and HTML. Supported character encoding are US-ASCII and ISO-8859-1. The URI of each document is specified with the path of its file. Attributes named as `title' and `date' are given to each documents. When a document is already existing in the database, it is registered if its last modification time is newer, or it is ignored. Modification times are stored in the sub database `_mtime' in the main database directory. Score information are stored in the sub database `_score' in the main database directory. This command is used in the following format. `name' specifies a database name. `dir' specifies a directory name.

- -
-
odidx register [-l file] [-wmax num] [-tsuf sufs] [-hsuf sufs] name [dir]
-
Register files in the specified directory. If `dir' is omitted, the current directory is specified.
-
odidx relate name
-
Add score information for relational document search to each documents in the database.
-
odidx purge name
-
Purge documents which are not existing on the local files system.
-
- -

Options feature the following.

- -
    -
  • -l file : read a file and get list of paths of files to register. If `-' is specified, the standard input is read.
  • -
  • -wmax num : specify the max number of words to be stored in the document database.
  • -
  • -tsuf sufs : specify suffixes of plain text files in comma separated format. The default is `-tsuf .txt,.text'.
  • -
  • -hsuf sufs : specify suffixes of HTML files in comma separated format. The default is `-hsuf .html,.htm'.
  • -
- -

This command returns 0 on success, another on failure.

- -

Commands of Odeum make it easy to realize a full-text search system. For example, to register files which are under `/home/mikio' and whose suffix are `.txt', `.c', or `.h', perform the following command.

- -
odidx register -tsuf ".txt,.c,.h" -hsuf "" casket /home/mikio
-
- -

Thus, to retrieve documents which include `unix' and `posix' and show the top 8 terms, perform the following command.

- -
odmgr search -max 8 -h casket "unix posix"
-
- -

A database generated by `odidx' is available with the CGI script which is included in QDBM for full-text search.

- -
- -

File Format

- -

File Format of Depot

- -

The contents of a database file managed by Depot is divided roughly into the following three sections: the header section, the bucket section and the record section.

- -

The header section places at the beginning of the file and its length is constant 48 bytes. The following information are stored in the header section.

- -
    -
  1. magic number: from offset 0, contains "[DEPOT]\n\f" for big endian or "[depot]\n\f" for little endian.
  2. -
  3. version number: decimal string of the version number of the library.
  4. -
  5. flags for wrappers: from offset 16, type of `int'.
  6. -
  7. file size: from offset 24, type of `int'.
  8. -
  9. number of the bucket: from offset 32, type of `int'.
  10. -
  11. number of records: from offset 40, type of `int'.
  12. -
- -

The bucket section places after the header section and its length is determined according to the number of the bucket. Each element of the bucket stores an offset of the root node of each separate chain.

- -

The record section places after the bucket section and occupies to the end of the file. The element of the record section contains the following information.

- -
    -
  1. flags: type of `int'.
  2. -
  3. second hash value: type of `int'.
  4. -
  5. size of the key: type of `int'.
  6. -
  7. size of the value: type of `int'.
  8. -
  9. size of the padding: type of `int'.
  10. -
  11. offset of the left child: type of `int'.
  12. -
  13. offset of the right child: type of `int'.
  14. -
  15. entity of the key: serial bytes with variable length.
  16. -
  17. entity of the value: serial bytes with variable length.
  18. -
  19. padding data: void serial bytes with variable length.
  20. -
- -

File Format of Villa

- -

Every data handled by Villa is stored in a database of Depot. Storing data is divided into meta data and logical pages. Logical pages can be classified into leaf nodes and non-leaf nodes. Meta data are such managing information as the number of records. Both of its key and its value are type of `int'. Leaf nodes hold records. Non-leaf nodes hold sparse index referring to pages.

- -

Villa uses variable length numeric format (BER compression) to handle small natural number with frugal storage. A variable length numeric object is parsed from the top of the region and parsing ends at the byte of positive value. Each byte are evaluated as absolute value and calculated as little endian number based on the radix 128.

- -

Record is logical unit of user data. Some records overlapping keys are shaped into one physical record. A Physical record is serialized in the following format.

- -
    -
  1. size of the key: type of variable length number
  2. -
  3. entity of the key: serial bytes with variable length
  4. -
  5. number of values: type of variable length number
  6. -
  7. list of values: serial bytes repeating the following expressions
      -
    1. size: type of variable length number
    2. -
    3. entity of the key: serial bytes with variable length
    4. -
  8. -
- -

Leaf node is physical unit to store a set of records. The key of a leaf node is its ID whose type is `int'. A leaf node is stored in a database of Depot with the following values. Its records are sorted in ascending order of each key.

- -
    -
  1. ID of the previous leaf: type of variable length number
  2. -
  3. ID of the next leaf: type of variable length number
  4. -
  5. list of records: concatenation of serialized records
  6. -
- -

Index is logical unit of a pointer to search for pages. An index is serialized int the following format.

- -
    -
  1. ID of the referring page: type of variable length number
  2. -
  3. size of the key: type of variable length number
  4. -
  5. entity of the key: serial bytes with variable length
  6. -
- -

Non-leaf node is physical unit to store a set of indexes. The key of a non-leaf node is its ID whose type is `int'. A non-leaf node is stored in a database of Depot with the following values. Its indexes are sorted in ascending order of each key.

- -
    -
  1. ID of the first child node: type of variable length number
  2. -
  3. list of indexes: concatenation of serialized indexes
  4. -
- -

Notes

- -

Because the database file is not sparse, move, copy, unlink, ftp, and so on with the file are possible. Because Depot reads and writes data without normalization of byte order, it is impossible to share the same file between the environment with different byte order.

- -

When you distribute a database file of Depot or Villa via network, the MIME type suggested to be `application/x-qdbm'. Suffix of the file name is suggested to be `.qdb'. When you distribute a database directory of Curia, you may convert the directory tree to an archive of such type as TAR.

- -

For the command `file' to recognize database files, append the following expressions into `magic' file.

- -
0       string          [DEPOT]\n\f     QDBM, big endian
->12     string          x               \b, version=%s
->19     byte            ^1              \b, Hash
->19     byte            &1              \b, B+ tree
->19     byte            &2              \b (deflated:ZLIB)
->19     byte            &4              \b (deflated:LZO)
->19     byte            &8              \b (deflated:BZIP2)
->24     belong          x               \b, filesize=%d
->32     belong          x               \b, buckets=%d
->40     belong          x               \b, records=%d
-0       string          [depot]\n\f     QDBM, little endian
->12     string          x               \b, version=%s
->16     byte            ^1              \b, Hash
->16     byte            &1              \b, B+ tree
->16     byte            &2              \b (deflated:ZLIB)
->16     byte            &4              \b (deflated:LZO)
->16     byte            &8              \b (deflated:BZIP2)
->24     lelong          x               \b, filesize=%d
->32     lelong          x               \b, buckets=%d
->40     lelong          x               \b, records=%d
-
- -
- -

Porting

- -

One of the goal of QDBM is to work on all platforms which conform to POSIX. Even if some APIs are not implemented, QDBM should work. Moreover, it should be possible to build QDBM using compilers other than GCC. Porting to various platforms is performed to add a new `Makefile' or modify some parts of source files. As for APIs of C, some of the following files should be modified. Otherwise, you can create new files based on them.

- -
    -
  • Makefile.in : base of `Makefile', used by `./configure'.
  • -
  • myconf.h : configuration of system dependency.
  • -
  • depot.h : header of the basic API.
  • -
  • curia.h : header of the extended API.
  • -
  • relic.h : header of the NDBM-compatible API.
  • -
  • hovel.h : header of the GDBM-compatible API.
  • -
  • cabin.h : header of the utility API.
  • -
  • villa.h : header of the advanced API.
  • -
  • vista.h : header of the extended advanced API.
  • -
  • odeum.h : header of the inverted API.
  • -
  • myconf.c : implementation of system dependency.
  • -
  • depot.c : implementation of the basic API.
  • -
  • curia.c : implementation of the extended API.
  • -
  • relic.c : implementation of the NDBM-compatible API.
  • -
  • hovel.c : implementation of the GDBM-compatible API.
  • -
  • cabin.c : implementation of the utility API.
  • -
  • villa.c : implementation of the advanced API.
  • -
  • vista.c : implementation of the extended advanced API.
  • -
  • odeum.c : implementation of the inverted API.
  • -
- -

On platforms which do not support file locking with `fcntl' call, you should append `-DMYNOLOCK' to the macro `CFLAGS' defined in `Makefile'. In that case, you should consider another exclusion control. As with it, on platforms without `mmap' call, you should append `-DMYNOMMAP' to `CFLAGS'. As for `mmap', its emulation using `malloc' and so on is provided. If other system calls are not implemented, you should define emulation by modification of `myconf.h' and `myconf.c'.

- -

Because POSIX thread is used in C++ API, it is impossible to port C++ API to platforms without the package. Because JNI is used in Java API, you should pay attention to location of the headers and libraries. Moreover, you should consider such type definitions as `long long' or `int64'. Because APIs of Perl and Ruby use building commands provided with each language system, you should be knowledgeable about their specifications.

- -
- -

Bugs

- -

Each document of QDBM should be calibrated by native English speakers.

- -

There is no such bug which are found but not fixed, as crash by segmentation fault, unexpected data vanishing, memory leak and so on.

- -

If you find any bug, report it to the author, with the information of the version of QDBM, the operating system and the compiler.

- -

Databases created with QDBM version 1.7.13 or earlier are not compatible to ones of the later versions.

- -
- -

Frequently Asked Questions

- -
-
Q. : Does QDBM support SQL?
-
A. : No, it does not. QDBM is not a RDBMS (Relational Database Management System). If you want an embedded RDBMS, use SQLite and so on.
-
Q. : After all, how different from GDBM (NDBM, SDBM, Berkeley DB)?
-
A. : Processing speed is higher, a database file is smaller, API is simpler. A highly important thing is that efficiency in time and space is very good when records are frequently overwritten, so, scalability in practical use is high. Moreover, even when constructing such a large database that the number of storing record is more than one million, processing speed does not slowdown deathly, filesize does not grow extremely. However, because other DBM or DBMS may be more suitable in some cases, comparing performance and functionality by yourself is suggested.
-
Q. : Which API should I use?
-
A. : If you search for records as complete accord, try Depot. If the scale is large, try Curia. If you access records in some order, try Villa. If the scale is large, try Vista. If you pursue the greatest number of records, build QDBM with ZLIB or LZO enabled and use Vista.
-
Q. : What is bibliography?
-
A. : Algorithms of QDBM are mainly based on the descriptions in `Data Structures and Algorithms' by Aho et al and `Algorithms in C' by Sedgewick.
-
Q. : Are there good sample codes for applications?
-
A. : Refer to the source code of commands of each API. `dptsv.c', `crtsv.c' and `vltsv.c' are simplest.
-
Q. : My database file has been broken. Why?
-
A. : In most cases, the reason is that your application did not close the database on exit. No matter whether it is a demon process or a CGI script, any application should close handling databases when it exits. Moreover, we should remember that a process of CGI may be killed by SIGPIPE or SIGTERM.
-
Q. : How robust are databases of QDBM?
-
A. : QDBM does not assure absolute robustness. A database may be broken if your operating system crashes. Although transaction of Villa can save a database from crashes of applications, it is inadequate to crashes of operating systems. So, you should consider multiplexing of a database or backup system if you use QDBM for mission critical applications.
-
Q: How should I use alignment of Depot and Curia?
-
A: If your application repeats writing with overwrite or concatenate mode. Alignment saves the rapid growth of the size of the database file. Because the best suited size of alignment of each application is different, you should learn it by experiment. For the meantime, about 32 is suitable.
-
Q. : How should I tune performance parameters of Villa?
-
A. : If you perform mainly ordering access, `lrecmax' and `nidxmax' should be larger. If you perform mainly random access, they should be less. If RAM of your system is abundant, `lcnum' and `ncnum' should be increased in order to improve performance. If ZLIB, LZO, or BZIP2 is enabled, increase `lrecmax' and compression efficiency is improved.
-
Q. : Which is the most preferable of ZLIB, LZO or BZIP2 for Villa?
-
A. : BZIP2 has the best compression retio. LZO has the best compression speed. ZLIB takes a mean position of them. If you don't have any special reason, using ZLIB is suggested. However, if updating of the database is frequent, LZO is more preferable. If updating of the database is very infrequently, BZIP2 is more preferable. Note that the license of LZO is the GNU LGPL.
-
Q. : What is `sparse file'?
-
A. : It is a file where some holes are. `Hole' means a block where any data has never written in. If a file system supports sparse file, holes are not allocated into any physical storage. As for QDBM, if a database is created with such flags as DP_OSPARSE, the bucket array is not initialized and its blocks become holes. According to that mechanism, you can use greatly huge hash tables. However, its performance is strongly depends on the setting of the file system.
-
Q. : Why Depot and Curia do not feature transaction?
-
A. : If an application implements its own transaction, inner transaction of database is superfluous. You can implement transaction for application easily with hash map provided by Cabin.
-
Q. : How should I tune the system for performance?
-
A. : Install more RAM on your machine than the size of a database. Then, enlarge I/O buffer and cut down on flushing dirty buffers. File system is also important. On Linux, although EXT2 is usually fastest, EXT3 is faster in some cases. ReiserFS is okey. The other modes of EXT3 are very slow. About other file systems, you should learn them by experiment.
-
Q. : Can I build QDBM using `cc' instead of `gcc'?
-
A. : Yes. Try to build QDBM with `LTmakefile'.
-
Q. : Can I build QDBM using Visual C++?
-
A. : Yes. Use `VCmakefile' instead of `Makefile'.
-
Q. : Can I use QDBM in other languages?
-
A. : As for PHP, Scheme (Gauche), and OCaml, interfaces of QDBM have been released. If you need it for another language, try to turn it out.
-
Q. : What does `QDBM' mean?
-
A. : `QDBM' stands for `Quick Database Manager'. It means that processing speed is high, and that you can write applications quickly.
-
- -
- -

Copying

- -

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 (See the file `COPYING'); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

- -

QDBM was written by Mikio Hirabayashi. You can contact the author by e-mail to `mikio at users.sourceforge.net'. However, as for topics which can be shared among other users, please send it to the mailing list. To join the mailing list, refer to `http://lists.sourceforge.net/lists/listinfo/qdbm-users'.

- -
- - - - - - Copied: box/trunk/qdbm/spex.html (from rev 2716, box/trunk/qdbm/spex.html) =================================================================== --- box/trunk/qdbm/spex.html (rev 0) +++ box/trunk/qdbm/spex.html 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,4343 @@ + + + + + + + + + + + + + + + +Specifications of QDBM Version 1 + + + + + +

Fundamental Specifications of QDBM Version 1

+ +
Copyright (C) 2000-2007 Mikio Hirabayashi
+
Last Update: Thu, 26 Oct 2006 15:00:20 +0900
+ + +
+ +

Table of Contents

+ +
    +
  1. Overview
  2. +
  3. Features
  4. +
  5. Installation
  6. +
  7. Depot: Basic API
  8. +
  9. Commands for Depot
  10. +
  11. Curia: Extended API
  12. +
  13. Commands for Curia
  14. +
  15. Relic: NDBM-compatible API
  16. +
  17. Commands for Relic
  18. +
  19. Hovel: GDBM-compatible API
  20. +
  21. Commands for Hovel
  22. +
  23. Cabin: Utility API
  24. +
  25. Commands for Cabin
  26. +
  27. Villa: Advanced API
  28. +
  29. Commands for Villa
  30. +
  31. Odeum: Inverted API
  32. +
  33. Commands for Odeum
  34. +
  35. File Format
  36. +
  37. Porting
  38. +
  39. Bugs
  40. +
  41. Frequently Asked Questions
  42. +
  43. Copying
  44. +
+ +
+ +

Overview

+ +

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organized in hash table or B+ tree.

+ +

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers: NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

+ +

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting, and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

+ +

QDBM is written in C, and provided as APIs of C, C++, Java, Perl, and Ruby. QDBM is available on platforms which have API conforming to POSIX. QDBM is a free software licensed under the GNU Lesser General Public License.

+ +
+ +

Features

+ +

Effective Implementation of Hash Database

+ +

QDBM is developed referring to GDBM for the purpose of the following three points: higher processing speed, smaller size of a database file, and simpler API. They have been achieved. Moreover, as with GDBM, the following three restrictions of traditional DBM: a process can handle only one database, the size of a key and a value is bounded, a database file is sparse, are cleared.

+ +

QDBM uses hash algorithm to retrieve records. If a bucket array has sufficient number of elements, the time complexity of retrieval is `O(1)'. That is, time required for retrieving a record is constant, regardless of the scale of a database. It is also the same about storing and deleting. Collision of hash values is managed by separate chaining. Data structure of the chains is binary search tree. Even if a bucket array has unusually scarce elements, the time complexity of retrieval is `O(log n)'.

+ +

QDBM attains improvement in retrieval by loading RAM with the whole of a bucket array. If a bucket array is on RAM, it is possible to access a region of a target record by about one path of file operations. A bucket array saved in a file is not read into RAM with the `read' call but directly mapped to RAM with the `mmap' call. Therefore, preparation time on connecting to a database is very short, and two or more processes can share the same memory map.

+ +

If the number of elements of a bucket array is about half of records stored within a database, although it depends on characteristic of the input, the probability of collision of hash values is about 56.7% (36.8% if the same, 21.3% if twice, 11.5% if four times, 6.0% if eight times). In such case, it is possible to retrieve a record by two or less paths of file operations. If it is made into a performance index, in order to handle a database containing one million of records, a bucket array with half a million of elements is needed. The size of each element is 4 bytes. That is, if 2M bytes of RAM is available, a database containing one million records can be handled.

+ +

QDBM provides two modes to connect to a database: `reader' and `writer'. A reader can perform retrieving but neither storing nor deleting. A writer can perform all access methods. Exclusion control between processes is performed when connecting to a database by file locking. While a writer is connected to a database, neither readers nor writers can be connected. While a reader is connected to a database, other readers can be connect, but writers can not. According to this mechanism, data consistency is guaranteed with simultaneous connections in multitasking environment.

+ +

Traditional DBM provides two modes of the storing operations: `insert' and `replace'. In the case a key overlaps an existing record, the insert mode keeps the existing value, while the replace mode transposes it to the specified value. In addition to the two modes, QDBM provides `concatenate' mode. In the mode, the specified value is concatenated at the end of the existing value and stored. This feature is useful when adding a element to a value as an array. Moreover, although DBM has a method to fetch out a value from a database only by reading the whole of a region of a record, QDBM has a method to fetch out a part of a region of a value. When a value is treated as an array, this feature is also useful.

+ +

Generally speaking, while succession of updating, fragmentation of available regions occurs, and the size of a database grows rapidly. QDBM deal with this problem by coalescence of dispensable regions and reuse of them, and featuring of optimization of a database. When overwriting a record with a value whose size is greater than the existing one, it is necessary to remove the region to another position of the file. Because the time complexity of the operation depends on the size of the region of a record, extending values successively is inefficient. However, QDBM deal with this problem by alignment. If increment can be put in padding, it is not necessary to remove the region.

+ +

As for many file systems, it is impossible to handle a file whose size is more than 2GB. To deal with this problem, QDBM provides a directory database containing multiple database files. Due to this feature, it is possible to handle a database whose total size is up to 1TB in theory. Moreover, because database files can be deployed on multiple disks, the speed of updating operations can be improved as with RAID-0 (striping). It is also possible for the database files to deploy on multiple file servers using NFS and so on.

+ +

Useful Implementation of B+ Tree Database

+ +

Although B+ tree database is slower than hash database, it features ordering access to each record. The order can be assigned by users. Records of B+ tree are sorted and arranged in logical pages. Sparse index organized in B tree that is multiway balanced tree are maintained for each page. Thus, the time complexity of retrieval and so on is `O(log n)'. Cursor is provided to access each record in order. The cursor can jump to a position specified by a key and can step forward or backward from the current position. Because each page is arranged as double linked list, the time complexity of stepping cursor is `O(1)'.

+ +

B+ tree database is implemented, based on above hash database. Because each page of B+ tree is stored as each record of hash database, B+ tree database inherits efficiency of storage management of hash database. Because the header of each record is smaller and alignment of each page is adjusted according to the page size, in most cases, the size of database file is cut by half compared to one of hash database. Although operation of many pages are required to update B+ tree, QDBM expedites the process by caching pages and reducing file operations. In most cases, because whole of the sparse index is cached on memory, it is possible to retrieve a record by one or less path of file operations.

+ +

B+ tree database features transaction mechanism. It is possible to commit a series of operations between the beginning and the end of the transaction in a lump, or to abort the transaction and perform rollback to the state before the transaction. Even if the process of an application is crashed while the transaction, the database file is not broken.

+ +

In case that QDBM was built with ZLIB, LZO, or BZIP2 enabled, a lossless data-compression library, the content of each page of B+ tree is compressed and stored in a file. Because each record in a page has similar patterns, high efficiency of compression is expected due to the Lempel-Ziv algorithm and the like. In case handling text data, the size of a database is reduced to about 25%. If the scale of a database is large and disk I/O is the bottleneck, featuring compression makes the processing speed improved to a large extent.

+ +

Simple but Various Interfaces

+ +

QDBM provides very simple APIs. You can perform database I/O as usual file I/O with `FILE' pointer defined in ANSI C. In the basic API of QDBM, entity of a database is recorded as one file. In the extended API, entity of a database is recorded as several files in one directory. Because the two APIs are very similar with each other, porting an application from one to the other is easy.

+ +

APIs which are compatible with NDBM and GDBM are also provided. As there are a lot of applications using NDBM or GDBM, it is easy to port them onto QDBM. In most cases, it is completed only by replacement of header including (#include) and re-compiling. However, QDBM can not handle database files made by the original NDBM or GDBM.

+ +

In order to handle records on memory easily, the utility API is provided. It implements memory allocating functions, sorting functions, extensible datum, array list, hash map, and so on. Using them, you can handle records in C language cheaply as in such script languages as Perl or Ruby.

+ +

B+ tree database is used with the advanced API. The advanced API is implemented using the basic API and the utility API. Because the advanced API is also similar to the basic API and the extended API, it is easy to learn how to use it.

+ +

In order to handle an inverted index which is used by full-text search systems, the inverted API is provided. If it is easy to handle an inverted index of documents, an application can focus on text processing and natural language processing. Because this API does not depend on character codes nor languages, it is possible to implement a full-text search system which can respond to various requests from users.

+ +

Along with APIs for C, QDBM provides APIs for C++, Java, Perl, and Ruby. APIs for C are composed of seven kinds: the basic API, the extended API, the NDBM-compatible API, the GDBM-compatible API, the utility API, the advanced API, and the inverted API. Command line interfaces corresponding to each API are also provided. They are useful for prototyping, testing, debugging, and so on. The C++ API encapsulates database handling functions of the basic API, the extended API, and the advanced API with class mechanism of C++. The Java API has native methods calling the basic API, the extended API, and the advanced API with Java Native Interface. The Perl API has methods calling the basic API, the extended API, and the advanced API with XS language. The Ruby API has method calling the basic API, the extended API, and the advanced API as modules of Ruby. Moreover, CGI scripts for administration of databases, file uploading, and full-text search are provided.

+ +

Wide Portability

+ +

QDBM is implemented being based on syntax of ANSI C (C89) and using only APIs defined in ANSI C or POSIX. Thus, QDBM works on most UNIX and its compatible OSs. As for C API, checking operations have been done at least on the following platforms.

+ +
    +
  • Linux (2.2, 2.4, 2.6) (IA32, IA64, AMD64, PA-RISC, Alpha, PowerPC, M68000, ARM)
  • +
  • FreeBSD (4.9, 5.0, 5.1, 5.2, 5.3) (IA32, IA64, SPARC, Alpha)
  • +
  • NetBSD (1.6) (IA32)
  • +
  • OpenBSD (3.4) (IA32)
  • +
  • SunOS (5.6, 5.7, 5.8, 5.9, 5.10) (IA32, SPARC)
  • +
  • HP-UX (11.11, 11.23) (IA64, PA-RISC)
  • +
  • AIX (5.2) (POWER)
  • +
  • Windows (2000, XP) (IA32, IA64, AMD64) (Cygwin, MinGW, Visual C++)
  • +
  • Mac OS X (10.2, 10.3, 10.4) (IA32, PowerPC)
  • +
  • Tru64 (5.1) (Alpha)
  • +
  • RISC OS (5.03) (ARM)
  • +
+ +

Although a database file created by QDBM depends on byte order of the processor, to do with it, utilities to dump data in format which is independent to byte orders are provided.

+ +
+ +

Installation

+ +

Preparation

+ +

To install QDBM from a source package, GCC of 2.8 or later version and `make' are required.

+ +

When an archive file of QDBM is extracted, change the current working directory to the generated directory and perform installation.

+ +

Usual Steps

+ +

Follow the procedures below on Linux, BSD, or SunOS.

+ +

Run the configuration script.

+ +
./configure
+
+ +

Build programs.

+ +
make
+
+ +

Perform self-diagnostic test.

+ +
make check
+
+ +

Install programs. This operation must be carried out by the root user.

+ +
make install
+
+ +

Using GNU Libtool

+ +

If above steps do not work, try the following steps. This way needs GNU Libtool of 1.5 or later version.

+ +

Run the configuration script.

+ +
./configure
+
+ +

Build programs.

+ +
make -f LTmakefile
+
+ +

Perform self-diagnostic test.

+ +
make -f LTmakefile check
+
+ +

Install programs. This operation must be carried out by the root user.

+ +
make -f LTmakefile install
+
+ +

Result

+ +

When a series of work finishes, the following files will be installed. As for the rest, manuals will be installed under `/usr/local/man/man1' and '/usr/local/man/man3', other documents will be installed under `/usr/local/share/qdbm'. A configuration file for `pkg-config' will be installed under `/usr/local/lib/pkgconfig'.

+ +
/usr/local/include/depot.h
+/usr/local/include/curia.h
+/usr/local/include/relic.h
+/usr/local/include/hovel.h
+/usr/local/include/cabin.h
+/usr/local/include/villa.h
+/usr/local/include/vista.h
+/usr/local/include/odeum.h
+/usr/local/lib/libqdbm.a
+/usr/local/lib/libqdbm.so.14.13.0
+/usr/local/lib/libqdbm.so.14
+/usr/local/lib/libqdbm.so
+/usr/local/bin/dpmgr
+/usr/local/bin/dptest
+/usr/local/bin/dptsv
+/usr/local/bin/crmgr
+/usr/local/bin/crtest
+/usr/local/bin/crtsv
+/usr/local/bin/rlmgr
+/usr/local/bin/rltest
+/usr/local/bin/hvmgr
+/usr/local/bin/hvtest
+/usr/local/bin/cbtest
+/usr/local/bin/cbcodec
+/usr/local/bin/vlmgr
+/usr/local/bin/vltest
+/usr/local/bin/vltsv
+/usr/local/bin/odmgr
+/usr/local/bin/odtest
+/usr/local/bin/odidx
+/usr/local/bin/qmttest
+
+ +

When you run a program linked dynamically to `libqdbm.so', the library search path should include `/usr/local/lib'. You can set the library search path with the environment variable `LD_LIBRARY_PATH'.

+ +

To uninstall QDBM, execute the following command after `./configure'. This operation must be carried out by the root user.

+ +
make uninstall
+
+ +

If an old version of QDBM is installed on your system, uninstall it before installation of a new one.

+ +

The other APIs except for C nor CGI scripts are not installed by default. Refer to `plus/xspex.html' to know how to install the C++ API. Refer to `java/jspex.html' to know how to install the Java API. Refer to `perl/plspex.html' to know how to install the Perl API. Refer to `ruby/rbspex.html' to know how to install the Ruby API. Refer to `cgi/cgispex.html' to know how to install the CGI script.

+ +

To install QDBM from such a binary package as RPM, refer to the manual of the package manager. For example, if you use RPM, execute like the following command by the root user.

+ +
rpm -ivh qdbm-1.x.x-x.i386.rpm
+
+ +

For Windows

+ +

On Windows (Cygwin), you should follow the procedures below for installation.

+ +

Run the configuration script.

+ +
./configure
+
+ +

Build programs.

+ +
make win
+
+ +

Perform self-diagnostic test.

+ +
make check-win
+
+ +

Install programs. As well, perform `make uninstall-win' to uninstall them.

+ +
make install-win
+
+ +

On Windows, the import library `libqdbm.dll.a' is created as well as the static library `libqdbm.a', and the dynamic linking library `qdbm.dll' is created instead of such shared libraries as `libqdbm.so'. `qdbm.dll' is installed into `/usr/local/bin'.

+ +

In order to build QDBM using MinGW on Cygwin, you should perform `make mingw' instead of `make win'. With the UNIX emulation layer of Cygwin, generated programs depend on `cygwin1.dll' (they come under GNU GPL). This problem is solved by linking them to the Win32 native DLL with MinGW.

+ +

In order to build QDBM using Visual C++, you should edit `VCmakefile' and set the search paths for libraries and headers. And perform `nmake /f VCMakefile'. Applications linking to `qdbm.dll' should link to `msvcrt.dll' by `/MD' or `/MDd' option of the compiler. Refer to `VCmakefile' for detail configurations.

+ +

For Mac OS X

+ +

On Mac OS X (Darwin), you should follow the procedures below for installation.

+ +

Run the configuration script.

+ +
./configure
+
+ +

Build programs.

+ +
make mac
+
+ +

Perform self-diagnostic test.

+ +
make check-mac
+
+ +

Install programs. As well, perform `make uninstall-mac' to uninstall them.

+ +
make install-mac
+
+ +

On Mac OS X, `libqdbm.dylib' and so on are created instead of `libqdbm.so' and so on. You can set the library search path with the environment variable `DYLD_LIBRARY_PATH'.

+ +

For HP-UX

+ +

On HP-UX, you should follow the procedures below for installation.

+ +

Run the configuration script.

+ +
./configure
+
+ +

Build programs.

+ +
make hpux
+
+ +

Perform self-diagnostic test.

+ +
make check-hpux
+
+ +

Install programs. As well, perform `make uninstall-hpux' to uninstall them.

+ +
make install-hpux
+
+ +

On HP-UX, `libqdbm.sl' is created instead of `libqdbm.so' and so on. You can set the library search path with the environment variable `SHLIB_PATH'.

+ +

For RISC OS

+ +

On RISC OS, you should follow the procedures below for installation.

+ +

Build programs. As `cc' is used for compilation by default, if you want to use `gcc', add the argument `CC=gcc'.

+ +
make -f RISCmakefile
+
+ +

When a series of work finishes, the library file `libqdbm' and such commands as `dpmgr' are generated. Because how to install them is not defined, copy them manually for installation. As with it, such header files as `depot.h' should be installed manually.

+ +

Detail Configurations

+ +

You can configure building processes by the following optional arguments of `./configure'.

+ +
    +
  • --enable-debug : build for debugging. Enable debugging symbols, do not perform optimization, and perform static linking.
  • +
  • --enable-devel : build for development. Enable debugging symbols, perform optimization, and perform dynamic linking.
  • +
  • --enable-stable : build for stable release. Perform conservative optimization, and perform dynamic linking.
  • +
  • --enable-pthread : feature POSIX thread and treat global variables as thread specific data.
  • +
  • --disable-lock : build for environments without file locking.
  • +
  • --disable-mmap : build for environments without memory mapping.
  • +
  • --enable-zlib : feature ZLIB compression for B+ tree and inverted index.
  • +
  • --enable-lzo : feature LZO compression for B+ tree and inverted index.
  • +
  • --enable-bzip : feature BZIP2 compression for B+ tree and inverted index.
  • +
  • --enable-iconv : feature ICONV utilities for conversion of character encodings.
  • +
+ +

Usually, QDBM and its applications can be built without any dependency on non-standard libraries except for `libqdbm.*'. However, they depend on `libpthread.*' if POSIX thread is enabled, and they depend on `libz.*' if ZLIB is enabled, and they depend on `liblzo2.*' if LZO is enabled, and they depend on `libbz2.*' if BZIP2 is enabled, and they depend on `libiconv.*' if ICONV is enabled.

+ +

Because the license of LZO is GNU GPL, note that applications linking to `liblzo2.*' should meet commitments of GNU GPL.

+ +
+ +

Depot: Basic API

+ +

Overview

+ +

Depot is the basic API of QDBM. Almost all features for managing a database provided by QDBM are implemented by Depot. Other APIs are no more than wrappers of Depot. Depot is the fastest in all APIs of QDBM.

+ +

In order to use Depot, you should include `depot.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

+ +
+
#include <depot.h>
+
#include <stdlib.h>
+
+ +

A pointer to `DEPOT' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `dpopen' and closed with `dpclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `dpclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used.

+ +

API

+ +

The external variable `dpversion' is the string containing the version information.

+ +
+
extern const char *dpversion;
+
+ +

The external variable `dpecode' is assigned with the last happened error code. Refer to `depot.h' for details of the error codes.

+ +
+
extern int dpecode;
+
The initial value of this variable is `DP_ENOERR'. The other values are `DP_EFATAL', `DP_EMODE', `DP_EBROKEN', `DP_EKEEP', `DP_ENOITEM', `DP_EALLOC', `DP_EMAP', `DP_EOPEN', `DP_ECLOSE', `DP_ETRUNC', `DP_ESYNC', `DP_ESTAT', `DP_ESEEK', `DP_EREAD', `DP_EWRITE', `DP_ELOCK', `DP_EUNLINK', `DP_EMKDIR', `DP_ERMDIR', and `DP_EMISC'.
+
+ +

The function `dperrmsg' is used in order to get a message string corresponding to an error code.

+ +
+
const char *dperrmsg(int ecode);
+
`ecode' specifies an error code. The return value is the message string of the error code. The region of the return value is not writable.
+
+ +

The function `dpopen' is used in order to get a database handle.

+ +
+
DEPOT *dpopen(const char *name, int omode, int bnum);
+
`name' specifies the name of a database file. `omode' specifies the connection mode: `DP_OWRITER' as a writer, `DP_OREADER' as a reader. If the mode is `DP_OWRITER', the following may be added by bitwise or: `DP_OCREAT', which means it creates a new database if not exist, `DP_OTRUNC', which means it creates a new database regardless if one exists. Both of `DP_OREADER' and `DP_OWRITER' can be added to by bitwise or: `DP_ONOLCK', which means it opens a database file without file locking, or `DP_OLCKNB', which means locking is performed without blocking. `DP_OCREAT' can be added to by bitwise or: `DP_OSPARSE', which means it creates a database file as a sparse file. `bnum' specifies the number of elements of the bucket array. If it is not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. If `DP_ONOLCK' is used, the application is responsible for exclusion control.
+
+ +

The function `dpclose' is used in order to close a database handle.

+ +
+
int dpclose(DEPOT *depot);
+
`depot' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.
+
+ +

The function `dpput' is used in order to store a record.

+ +
+
int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+
`depot' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `DP_DOVER', which means the specified value overwrites the existing one, `DP_DKEEP', which means the existing value is kept, `DP_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false.
+
+ +

The function `dpout' is used in order to delete a record.

+ +
+
int dpout(DEPOT *depot, const char *kbuf, int ksiz);
+
`depot' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key.
+
+ +

The function `dpget' is used in order to retrieve a record.

+ +
+
char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp);
+
`depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return valu e is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `dpgetwb' is used in order to retrieve a record and write the value into a buffer.

+ +
+
int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf);
+
`depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be equal to or less than the size of the writing buffer. `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is written. If successful, the return value is the size of the written data, else, it is -1. -1 is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Note that no additional zero code is appended at the end of the region of the writing buffer.
+
+ +

The function `dpvsiz' is used in order to get the size of the value of a record.

+ +
+
int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz);
+
`depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. Because this function does not read the entity of a record, it is faster than `dpget'.
+
+ +

The function `dpiterinit' is used in order to initialize the iterator of a database handle.

+ +
+
int dpiterinit(DEPOT *depot);
+
`depot' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database.
+
+ +

The function `dpiternext' is used in order to get the next key of the iterator.

+ +
+
char *dpiternext(DEPOT *depot, int *sp);
+
`depot' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.
+
+ +

The function `dpsetalign' is used in order to set alignment of a database handle.

+ +
+
int dpsetalign(DEPOT *depot, int align);
+
`depot' specifies a database handle connected as a writer. `align' specifies the size of alignment. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.
+
+ +

The function `dpsetfbpsiz' is used in order to set the size of the free block pool of a database handle.

+ +
+
int dpsetfbpsiz(DEPOT *depot, int size);
+
`depot' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
+
+ +

The function `dpsync' is used in order to synchronize updating contents with the file and the device.

+ +
+
int dpsync(DEPOT *depot);
+
`depot' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database file.
+
+ +

The function `dpoptimize' is used in order to optimize a database.

+ +
+
int dpoptimize(DEPOT *depot, int bnum);
+
`depot' specifies a database handle connected as a writer. `bnum' specifies the number of the elements of the bucket array. If it is not more than 0, the default value is specified. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them.
+
+ +

The function `dpname' is used in order to get the name of a database.

+ +
+
char *dpname(DEPOT *depot);
+
`depot' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `dpfsiz' is used in order to get the size of a database file.

+ +
+
int dpfsiz(DEPOT *depot);
+
`depot' specifies a database handle. If successful, the return value is the size of the database file, else, it is -1.
+
+ +

The function `dpbnum' is used in order to get the number of the elements of the bucket array.

+ +
+
int dpbnum(DEPOT *depot);
+
`depot' specifies a database handle. If successful, the return value is the number of the elements of the bucket array, else, it is -1.
+
+ +

The function `dpbusenum' is used in order to get the number of the used elements of the bucket array.

+ +
+
int dpbusenum(DEPOT *depot);
+
`depot' specifies a database handle. If successful, the return value is the number of the used elements of the bucket array, else, it is -1. This function is inefficient because it accesses all elements of the bucket array.
+
+ +

The function `dprnum' is used in order to get the number of the records stored in a database.

+ +
+
int dprnum(DEPOT *depot);
+
`depot' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1.
+
+ +

The function `dpwritable' is used in order to check whether a database handle is a writer or not.

+ +
+
int dpwritable(DEPOT *depot);
+
`depot' specifies a database handle. The return value is true if the handle is a writer, false if not.
+
+ +

The function `dpfatalerror' is used in order to check whether a database has a fatal error or not.

+ +
+
int dpfatalerror(DEPOT *depot);
+
`depot' specifies a database handle. The return value is true if the database has a fatal error, false if not.
+
+ +

The function `dpinode' is used in order to get the inode number of a database file.

+ +
+
int dpinode(DEPOT *depot);
+
`depot' specifies a database handle. The return value is the inode number of the database file.
+
+ +

The function `dpmtime' is used in order to get the last modified time of a database.

+ +
+
time_t dpmtime(DEPOT *depot);
+
`depot' specifies a database handle. The return value is the last modified time of the database.
+
+ +

The function `dpfdesc' is used in order to get the file descriptor of a database file.

+ +
+
int dpfdesc(DEPOT *depot);
+
`depot' specifies a database handle. The return value is the file descriptor of the database file. Handling the file descriptor of a database file directly is not suggested.
+
+ +

The function `dpremove' is used in order to remove a database file.

+ +
+
int dpremove(const char *name);
+
`name' specifies the name of a database file. If successful, the return value is true, else, it is false.
+
+ +

The function `dprepair' is used in order to repair a broken database file.

+ +
+
int dprepair(const char *name);
+
`name' specifies the name of a database file. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database file correspond to the original or expected state.
+
+ +

The function `dpexportdb' is used in order to dump all records as endian independent data.

+ +
+
int dpexportdb(DEPOT *depot, const char *name);
+
`depot' specifies a database handle. `name' specifies the name of an output file. If successful, the return value is true, else, it is false.
+
+ +

The function `dpimportdb' is used in order to load all records from endian independent data.

+ +
+
int dpimportdb(DEPOT *depot, const char *name);
+
`depot' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input file. If successful, the return value is true, else, it is false.
+
+ +

The function `dpsnaffle' is used in order to retrieve a record directly from a database file.

+ +
+
char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
+
`name' specifies the name of a database file. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Although this function can be used even while the database file is locked by another process, it is not assured that recent updated is reflect ed.
+
+ +

The function `dpinnerhash' is a hash function used inside Depot.

+ +
+
int dpinnerhash(const char *kbuf, int ksiz);
+
`kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the hash value of 31 bits length computed from the key. This function is useful when an application calculates the state of the inside bucket array.
+
+ +

The function `dpouterhash' is a hash function which is independent from the hash functions used inside Depot.

+ +
+
int dpouterhash(const char *kbuf, int ksiz);
+
`kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the hash value of 31 bits length computed from the key. This function is useful when an application uses its own hash algorithm outside Depot.
+
+ +

The function `dpprimenum' is used in order to get a natural prime number not less than a number.

+ +
+
int dpprimenum(int num);
+
`num' specified a natural number. The return value is a natural prime number not less than the specified number. This function is useful when an application determines the size of a bucket array of its own hash algorithm.
+
+ +

Examples

+ +

The following example stores and retrieves a phone number, using the name as the key.

+ +
#include <depot.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NAME     "mikio"
+#define NUMBER   "000-1234-5678"
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  DEPOT *depot;
+  char *val;
+
+  /* open the database */
+  if(!(depot = dpopen(DBNAME, DP_OWRITER | DP_OCREAT, -1))){
+    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* store the record */
+  if(!dpput(depot, NAME, -1, NUMBER, -1, DP_DOVER)){
+    fprintf(stderr, "dpput: %s\n", dperrmsg(dpecode));
+  }
+
+  /* retrieve the record */
+  if(!(val = dpget(depot, NAME, -1, 0, -1, NULL))){
+    fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
+  } else {
+    printf("Name: %s\n", NAME);
+    printf("Number: %s\n", val);
+    free(val);
+  }
+
+  /* close the database */
+  if(!dpclose(depot)){
+    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

The following example shows all records of the database.

+ +
#include <depot.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  DEPOT *depot;
+  char *key, *val;
+
+  /* open the database */
+  if(!(depot = dpopen(DBNAME, DP_OREADER, -1))){
+    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* initialize the iterator */
+  if(!dpiterinit(depot)){
+    fprintf(stderr, "dpiterinit: %s\n", dperrmsg(dpecode));
+  }
+
+  /* scan with the iterator */
+  while((key = dpiternext(depot, NULL)) != NULL){
+    if(!(val = dpget(depot, key, -1, 0, -1, NULL))){
+      fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
+      free(key);
+      break;
+    }
+    printf("%s: %s\n", key, val);
+    free(val);
+    free(key);
+  }
+
+  /* close the database */
+  if(!dpclose(depot)){
+    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

Notes

+ +

For building a program using Depot, the program should be linked with a library file `libqdbm.a' or `libqdbm.so'. For example, the following command is executed to build `sample' from `sample.c'.

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Depot are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

+ +
+ +

Commands for Depot

+ +

Depot has the following command line interfaces.

+ +

The command `dpmgr' is a utility for debugging Depot and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

+ +
+
dpmgr create [-s] [-bnum num] name
+
Create a database file.
+
dpmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-na] name key val
+
Store a record with a key and a value.
+
dpmgr out [-kx|-ki] name key
+
Delete a record with a key.
+
dpmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-n] name key
+
Retrieve a record with a key and output it to the standard output.
+
dpmgr list [-nl] [-k|-v] [-ox] name
+
List all keys and values delimited with tab and line-feed to the standard output.
+
dpmgr optimize [-bnum num] [-na] name
+
Optimize a database.
+
dpmgr inform [-nl] name
+
Output miscellaneous information to the standard output.
+
dpmgr remove name
+
Remove a database file.
+
dpmgr repair name
+
Repair a broken database file.
+
dpmgr exportdb name file
+
Dump all records as endian independent data.
+
dpmgr importdb [-bnum num] name file
+
Load all records from endian independent data.
+
dpmgr snaffle [-kx|-ki] [-ox] [-n] name key
+
Retrieve a record from a locked database with a key and output it to the standard output.
+
dpmgr version
+
Output version information of QDBM to the standard output.
+
+ +

Options feature the following.

+ +
    +
  • -s : make the file sparse.
  • +
  • -bnum num : specify the number of the elements of the bucket array.
  • +
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • +
  • -ki : treat `key' as an integer expression of decimal notation.
  • +
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • +
  • -vi : treat `val' as an integer expression of decimal notation.
  • +
  • -vf : read the value from a file specified with `val'.
  • +
  • -keep : specify the storing mode for `DP_DKEEP'.
  • +
  • -cat : specify the storing mode for `DP_DCAT'.
  • +
  • -na : do not set alignment.
  • +
  • -nl : open the database without file locking.
  • +
  • -start : specify the beginning offset of a value to fetch.
  • +
  • -max : specify the max size of a value to fetch.
  • +
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • +
  • -n : do not output the tailing newline.
  • +
  • -k : output keys only.
  • +
  • -v : output values only.
  • +
+ +

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

+ +

The command `dptest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of the records. `bnum' specifies the number of the elements of the bucket array. `pnum' specifies the number of patterns of the keys. `align' specifies the basic size of alignment. `fbpsiz' specifies the size of the free block pool.

+ +
+
dptest write [-s] name rnum bnum
+
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
+
dptest read [-wb] name
+
Retrieve all records of the database above.
+
dptest rcat [-c] name rnum bnum pnum align fbpsiz
+
Store records with partway duplicated keys using concatenate mode.
+
dptest combo name
+
Perform combination test of various operations.
+
dptest wicked [-c] name rnum
+
Perform updating operations selected at random.
+
+ +

Options feature the following.

+ +
    +
  • -s : make the file sparse.
  • +
  • -wb : use the function `dpgetwb' instead of the function `dpget'.
  • +
  • -c : perform comparison test with map of Cabin.
  • +
+ +

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

+ +

The command `dptsv' features mutual conversion between a database of Depot and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the following format. `name' specifies a database name. The subcommand `export' reads TSV data from the standard input. If a key overlaps, the latter is adopted. `-bnum' specifies the number of the elements of the bucket array. The subcommand `import' writes TSV data to the standard output.

+ +
+
dptsv import [-bnum num] [-bin] name
+
Create a database from TSV.
+
dptsv export [-bin] name
+
Write TSV data of a database.
+
+ +

Options feature the following.

+ +
    +
  • -bnum num : specify the number of the elements of the bucket array.
  • +
  • -bin : treat records as Base64 format.
  • +
+ +

This command returns 0 on success, another on failure.

+ +

Commands of Depot realize a simple database system. For example, to make a database to search `/etc/password' by a user name, perform the following command.

+ +
cat /etc/passwd | tr ':' '\t' | dptsv import casket
+
+ +

Thus, to retrieve the information of a user `mikio', perform the following command.

+ +
dpmgr get casket mikio
+
+ +

It is easy to implement functions upsides with these commands, using the API of Depot.

+ +
+ +

Curia: Extended API

+ +

Overview

+ +

Curia is the extended API of QDBM. It provides routines for managing multiple database files in a directory. Restrictions of some file systems that the size of each file is limited are escaped by dividing a database file into two or more. If the database files deploy on multiple devices, the scalability is improved.

+ +

Although Depot creates a database with a file name, Curia creates a database with a directory name. A database file named as `depot' is placed in the specified directory. Although it keeps the attribute of the database, it does not keep the entities of the records. Besides, sub directories are created by the number of division of the database, named with 4 digits. The database files are placed in the subdirectories. The entities of the records are stored in the database file. For example, in the case that a database directory named as `casket' and the number of division is 3, `casket/depot', `casket/0001/depot', `casket/0002/depot' and `casket/0003/depot' are created. No error occurs even if the namesake directory exists when creating a database. So, if sub directories exists and some devices are mounted on the sub directories, the database files deploy on the multiple devices.

+ +

Curia features managing large objects. Although usual records are stored in some database files, records of large objects are stored in individual files. Because the files of large objects are deployed in different directories named with the hash values, the access speed is part-way robust although it is slower than the speed of usual records. Large and not often accessed data should be secluded as large objects. By doing this, the access speed of usual records is improved. The directory hierarchies of large objects are placed in the directory named as `lob' in the sub directories of the database. Because the key spaces of the usual records and the large objects are different, the operations keep out of each other.

+ +

In order to use Curia, you should include `depot.h', `curia.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

+ +
+
#include <depot.h>
+
#include <curia.h>
+
#include <stdlib.h>
+
+ +

A pointer to `CURIA' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `cropen' and closed with `crclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `crclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database directory should not be used.

+ +

Curia also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code.

+ +

API

+ +

The function `cropen' is used in order to get a database handle.

+ +
+
CURIA *cropen(const char *name, int omode, int bnum, int dnum);
+
`name' specifies the name of a database directory. `omode' specifies the connection mode: `CR_OWRITER' as a writer, `CR_OREADER' as a reader. If the mode is `CR_OWRITER', the following may be added by bitwise or: `CR_OCREAT', which means it creates a new database if not exist, `CR_OTRUNC', which means it creates a new database regardless if one exists. Both of `CR_OREADER' and `CR_OWRITER' can be added to by bitwise or: `CR_ONOLCK', which means it opens a database directory without file locking, or `CR_OLCKNB', which means locking is performed without blocking. `CR_OCREAT' can be added to by bitwise or: `CR_OSPARSE', which means it creates database files as sparse files. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. The size of each bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of each bucket array is about from 0.5 to 4 times of the number of all records to store. `dnum' specifies the number of division of the database. If it is not more than 0, the default value is specified. The number of division can not be changed from the initial value. The max number of division is 512. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `CR_ONOLCK' is used, the application is responsible for exclusion control.
+
+ +

The function `crclose' is used in order to close a database handle.

+ +
+
int crclose(CURIA *curia);
+
`curia' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.
+
+ +

The function `crput' is used in order to store a record.

+ +
+
int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', which means the specified value overwrites the existing one, `CR_DKEEP', which means the existing value is kept, `CR_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false.
+
+ +

The function `crout' is used in order to delete a record.

+ +
+
int crout(CURIA *curia, const char *kbuf, int ksiz);
+
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key.
+
+ +

The function `crget' is used in order to retrieve a record.

+ +
+
char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
+
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return valu e is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `crgetwb' is used in order to retrieve a record and write the value into a buffer.

+ +
+
int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf);
+
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be equal to or less than the size of the writing buffer. `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is written. If successful, the return value is the size of the written data, else, it is -1. -1 is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Note that no additional zero code is appended at the end of the region of the writing buffer.
+
+ +

The function `crvsiz' is used in order to get the size of the value of a record.

+ +
+
int crvsiz(CURIA *curia, const char *kbuf, int ksiz);
+
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. Because this function does not read the entity of a record, it is faster than `crget'.
+
+ +

The function `criterinit' is used in order to initialize the iterator of a database handle.

+ +
+
int criterinit(CURIA *curia);
+
`curia' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database.
+
+ +

The function `criternext' is used in order to get the next key of the iterator.

+ +
+
char *criternext(CURIA *curia, int *sp);
+
`curia' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.
+
+ +

The function `crsetalign' is used in order to set alignment of a database handle.

+ +
+
int crsetalign(CURIA *curia, int align);
+
`curia' specifies a database handle connected as a writer. `align' specifies the size of alignment. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.
+
+ +

The function `crsetfbpsiz' is used in order to set the size of the free block pool of a database handle.

+ +
+
int crsetfbpsiz(CURIA *curia, int size);
+
`curia' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
+
+ +

The function `crsync' is used in order to synchronize updating contents with the files and the devices.

+ +
+
int crsync(CURIA *curia);
+
`curia' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database directory.
+
+ +

The function `croptimize' is used in order to optimize a database.

+ +
+
int croptimize(CURIA *curia, int bnum);
+
`curia' specifies a database handle connected as a writer. `bnum' specifies the number of the elements of each bucket array. If it is not more than 0, the default value is specified. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them.
+
+ +

The function `crname' is used in order to get the name of a database.

+ +
+
char *crname(CURIA *curia);
+
`curia' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `crfsiz' is used in order to get the total size of database files.

+ +
+
int crfsiz(CURIA *curia);
+
`curia' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1. If the total size is more than 2GB, the return value overflows.
+
+ +

The function `crfsizd' is used in order to get the total size of database files as double-precision floating-point number.

+ +
+
double crfsizd(CURIA *curia);
+
`curia' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1.0.
+
+ +

The function `crbnum' is used in order to get the total number of the elements of each bucket array.

+ +
+
int crbnum(CURIA *curia);
+
`curia' specifies a database handle. If successful, the return value is the total number of the elements of each bucket array, else, it is -1.
+
+ +

The function `crbusenum' is used in order to get the total number of the used elements of each bucket array.

+ +
+
int crbusenum(CURIA *curia);
+
`curia' specifies a database handle. If successful, the return value is the total number of the used elements of each bucket array, else, it is -1. This function is inefficient because it accesses all elements of each bucket array.
+
+ +

The function `crrnum' is used in order to get the number of the records stored in a database.

+ +
+
int crrnum(CURIA *curia);
+
`curia' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1.
+
+ +

The function `crwritable' is used in order to check whether a database handle is a writer or not.

+ +
+
int crwritable(CURIA *curia);
+
`curia' specifies a database handle. The return value is true if the handle is a writer, false if not.
+
+ +

The function `crfatalerror' is used in order to check whether a database has a fatal error or not.

+ +
+
int crfatalerror(CURIA *curia);
+
`curia' specifies a database handle. The return value is true if the database has a fatal error, false if not.
+
+ +

The function `crinode' is used in order to get the inode number of a database directory.

+ +
+
int crinode(CURIA *curia);
+
`curia' specifies a database handle. The return value is the inode number of the database directory.
+
+ +

The function `crmtime' is used in order to get the last modified time of a database.

+ +
+
time_t crmtime(CURIA *curia);
+
`curia' specifies a database handle. The return value is the last modified time of the database.
+
+ +

The function `crremove' is used in order to remove a database directory.

+ +
+
int crremove(const char *name);
+
`name' specifies the name of a database directory. If successful, the return value is true, else, it is false.
+
+ +

The function `crrepair' is used in order to repair a broken database directory.

+ +
+
int crrepair(const char *name);
+
`name' specifies the name of a database directory. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database directory correspond to the original or expected state.
+
+ +

The function `crexportdb' is used in order to dump all records as endian independent data.

+ +
+
int crexportdb(CURIA *curia, const char *name);
+
`curia' specifies a database handle. `name' specifies the name of an output directory. If successful, the return value is true, else, it is false. Note that large objects are ignored.
+
+ +

The function `crimportdb' is used in order to load all records from endian independent data.

+ +
+
int crimportdb(CURIA *curia, const char *name);
+
`curia' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input directory. If successful, the return value is true, else, it is false. Note that large objects are ignored.
+
+ +

The function `crsnaffle' is used in order to retrieve a record directly from a database directory.

+ +
+
char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
+
`name' specifies the name of a database directory. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Although this function can be used even while the database directory is locked by another process, it is not assured that recent updated is reflected.
+
+ +

The function `crputlob' is used in order to store a large object.

+ +
+
int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', which means the specified value overwrites the existing one, `CR_DKEEP', which means the existing value is kept, `CR_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false.
+
+ +

The function `croutlob' is used in order to delete a large object.

+ +
+
int croutlob(CURIA *curia, const char *kbuf, int ksiz);
+
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. false is returned when no large object corresponds to the specified key.
+
+ +

The function `crgetlob' is used in order to retrieve a large object.

+ +
+
char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
+
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding large object, else, it is `NULL'. `NULL' is returned when no large object corresponds to the specified key or the size of the value of the corresponding large object is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `crgetlobfd' is used in order to get the file descriptor of a large object.

+ +
+
int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz);
+
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the file descriptor of the corresponding large object, else, it is -1. -1 is returned when no large object corresponds to the specified key. The returned file descriptor is opened with the `open' call. If the database handle was opened as a writer, the descriptor is writable (O_RDWR), else, it is not writable (O_RDONLY). The descriptor should be closed with the `close' call if it is no longer in use.
+
+ +

The function `crvsizlob' is used in order to get the size of the value of a large object.

+ +
+
int crvsizlob(CURIA *curia, const char *kbuf, int ksiz);
+
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding large object, else, it is -1. Because this function does not read the entity of a large object, it is faster than `crgetlob'.
+
+ +

The function `crrnumlob' is used in order to get the number of the large objects stored in a database.

+ +
+
int crrnumlob(CURIA *curia);
+
`curia' specifies a database handle. If successful, the return value is the number of the large objects stored in the database, else, it is -1.
+
+ +

Examples

+ +

The following example stores and retrieves a phone number, using the name as the key.

+ +
#include <depot.h>
+#include <curia.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NAME     "mikio"
+#define NUMBER   "000-1234-5678"
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  CURIA *curia;
+  char *val;
+
+  /* open the database */
+  if(!(curia = cropen(DBNAME, CR_OWRITER | CR_OCREAT, -1, -1))){
+    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* store the record */
+  if(!crput(curia, NAME, -1, NUMBER, -1, CR_DOVER)){
+    fprintf(stderr, "crput: %s\n", dperrmsg(dpecode));
+  }
+
+  /* retrieve the record */
+  if(!(val = crget(curia, NAME, -1, 0, -1, NULL))){
+    fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
+  } else {
+    printf("Name: %s\n", NAME);
+    printf("Number: %s\n", val);
+    free(val);
+  }
+
+  /* close the database */
+  if(!crclose(curia)){
+    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

The following example shows all records of the database.

+ +
#include <depot.h>
+#include <curia.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  CURIA *curia;
+  char *key, *val;
+
+  /* open the database */
+  if(!(curia = cropen(DBNAME, CR_OREADER, -1, -1))){
+    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* initialize the iterator */
+  if(!criterinit(curia)){
+    fprintf(stderr, "criterinit: %s\n", dperrmsg(dpecode));
+  }
+
+  /* scan with the iterator */
+  while((key = criternext(curia, NULL)) != NULL){
+    if(!(val = crget(curia, key, -1, 0, -1, NULL))){
+      fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
+      free(key);
+      break;
+    }
+    printf("%s: %s\n", key, val);
+    free(val);
+    free(key);
+  }
+
+  /* close the iterator */
+  if(!crclose(curia)){
+    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

Notes

+ +

How to build programs using Curia is the same as the case of Depot.

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Curia are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

+ +
+ +

Commands for Curia

+ +

Curia has the following command line interfaces.

+ +

The command `crmgr' is a utility for debugging Curia and its applications. It features editing and checking of a database. It can be used for the database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

+ +
+
crmgr create [-s] [-bnum num] [-dnum num] name
+
Create a database file.
+
crmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] name key val
+
Store a record with a key and a value.
+
crmgr out [-kx|-ki] [-lob] name key
+
Delete a record with a key.
+
crmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-lob] [-n] name key
+
Retrieve a record with a key and output it to the standard output.
+
crmgr list [-nl] [-k|-v] [-ox] name
+
List all keys and values delimited with tab and line-feed to the standard output.
+
crmgr optimize [-bnum num] [-na] name
+
Optimize a database.
+
crmgr inform [-nl] name
+
Output miscellaneous information to the standard output.
+
crmgr remove name
+
Remove a database directory.
+
crmgr repair name
+
Repair a broken database directory.
+
crmgr exportdb name dir
+
Dump all records as endian independent data.
+
crmgr importdb [-bnum num] [-dnum num] name dir
+
Load all records from endian independent data.
+
crmgr snaffle [-kx|-ki] [-ox] [-n] name key
+
Retrieve a record from a locked database with a key and output it to the standard output.
+
crmgr version
+
Output version information of QDBM to the standard output.
+
+ +

Options feature the following.

+ +
    +
  • -s : make the files sparse.
  • +
  • -bnum num : specify the number of elements of each bucket array.
  • +
  • -dnum num : specify the number of division of the database.
  • +
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • +
  • -ki : treat `key' as an integer expression of decimal notation.
  • +
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • +
  • -vi : treat `val' as an integer expression of decimal notation.
  • +
  • -vf : read the value from a file specified with `val'.
  • +
  • -keep : specify the storing mode for `CR_DKEEP'.
  • +
  • -cat : specify the storing mode for `CR_DCAT'.
  • +
  • -na : do not set alignment.
  • +
  • -nl : open the database without file locking.
  • +
  • -start : specify the beginning offset of a value to fetch.
  • +
  • -max : specify the max size of a value to fetch.
  • +
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • +
  • -lob : handle large objects.
  • +
  • -n : do not output the tailing newline.
  • +
  • -k : output keys only.
  • +
  • -v : output values only.
  • +
+ +

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

+ +

The command `crtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records. `bnum' specifies the number of elements of a bucket array. `dnum' specifies the number of division of a database. `pnum' specifies the number of patterns of the keys. `align' specifies the basic size of alignment. `fbpsiz' specifies the size of the free block pool.

+ +
+
crtest write [-s] [-lob] name rnum bnum dnum
+
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
+
crtest read [-wb] [-lob] name
+
Retrieve all records of the database above.
+
crtest rcat [-c] name rnum bnum dnum pnum align fbpsiz
+
Store records with partway duplicated keys using concatenate mode.
+
crtest combo name
+
Perform combination test of various operations.
+
crtest wicked [-c] name rnum
+
Perform updating operations selected at random.
+
+ +

Options feature the following.

+ +
    +
  • -s : make the files sparse.
  • +
  • -lob : handle large objects.
  • +
  • -wb : use the function `crgetwb' instead of the function `crget'.
  • +
  • -c : perform comparison test with map of Cabin.
  • +
+ +

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

+ +

The command `crtsv' features mutual conversion between a database of Curia and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the following format. `name' specifies a database name. The subcommand `export' reads TSV data from the standard input. If a key overlaps, the latter is adopted. `-bnum' specifies the number of the elements of the bucket array. `-dnum' specifies the number of division of the database. The subcommand `import' writes TSV data to the standard output.

+ +
+
crtsv import [-bnum num] [-dnum num] [-bin] name
+
Create a database from TSV.
+
crtsv export [-bin] name
+
Write TSV data of a database.
+
+ +

Options feature the following.

+ +
    +
  • -bnum num : specify the number of the elements of the bucket array.
  • +
  • -dnum num : specify the number of division of the database.
  • +
  • -bin : treat records as Base64 format.
  • +
+ +

This command returns 0 on success, another on failure.

+ +

Commands of Curia realize a simple database system. For example, to make a database to search `/etc/password' by a user name, perform the following command.

+ +
cat /etc/passwd | tr ':' '\t' | crtsv import casket
+
+ +

Thus, to retrieve the information of a user `mikio', perform the following command.

+ +
crmgr get casket mikio
+
+ +

It is easy to implement functions upsides with these commands, using the API of Curia.

+ +
+ +

Relic: NDBM-compatible API

+ +

Overview

+ +

Relic is the API which is compatible with NDBM. So, Relic wraps functions of Depot as API of NDBM. It is easy to port an application from NDBM to QDBM. In most cases, you should only replace the includings of `ndbm.h' with `relic.h' and replace the linking option `-lndbm' with `-lqdbm'.

+ +

The original NDBM treats a database as a pair of files. One, `a directory file', has a name with suffix `.dir' and stores a bit map of keys. The other, `a data file', has a name with suffix `.pag' and stores entities of each records. Relic creates the directory file as a mere dummy file and creates the data file as a database. Relic has no restriction about the size of each record. Relic can not handle database files made by the original NDBM.

+ +

In order to use Relic, you should include `relic.h', `stdlib.h', `sys/types.h', `sys/stat.h' and `fcntl.h' in the source files. Usually, the following description will be near the beginning of a source file.

+ +
+
#include <relic.h>
+
#include <stdlib.h>
+
#include <sys/types.h>
+
#include <sys/stat.h>
+
#include <fcntl.h>
+
+ +

A pointer to `DBM' is used as a database handle. A database handle is opened with the function `dbm_open' and closed with `dbm_close'. You should not refer directly to any member of a handle.

+ +

API

+ +

Structures of `datum' type is used in order to give and receive data of keys and values with functions of Relic.

+ +
+
typedef struct { void *dptr; size_t dsize; } datum;
+
`dptr' specifies the pointer to the region of a key or a value. `dsize' specifies the size of the region.
+
+ +

The function `dbm_open' is used in order to get a database handle.

+ +
+
DBM *dbm_open(char *name, int flags, int mode);
+
`name' specifies the name of a database. The file names are concatenated with suffixes. `flags' is the same as the one of `open' call, although `O_WRONLY' is treated as `O_RDWR' and additional flags except for `O_CREAT' and `O_TRUNC' have no effect. `mode' specifies the mode of the database file as the one of `open' call does. The return value is the database handle or `NULL' if it is not successful.
+
+ +

The function `dbm_close' is used in order to close a database handle.

+ +
+
void dbm_close(DBM *db);
+
`db' specifies a database handle. Because the region of the closed handle is released, it becomes impossible to use the handle.
+
+ +

The function `dbm_store' is used in order to store a record.

+ +
+
int dbm_store(DBM *db, datum key, datum content, int flags);
+
`db' specifies a database handle. `key' specifies a structure of a key. `content' specifies a structure of a value. `flags' specifies behavior when the key overlaps, by the following values: `DBM_REPLACE', which means the specified value overwrites the existing one, `DBM_INSERT', which means the existing value is kept. The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, -1 if other error occurs.
+
+ +

The function `dbm_delete' is used in order to delete a record.

+ +
+
int dbm_delete(DBM *db, datum key);
+
`db' specifies a database handle. `key' specifies a structure of a key. The return value is 0 if it is successful, -1 if some errors occur.
+
+ +

The function `dbm_fetch' is used in order to retrieve a record.

+ +
+
datum dbm_fetch(DBM *db, datum key);
+
`db' specifies a database handle. `key' specifies a structure of a key. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function with the same handle.
+
+ +

The function `dbm_firstkey' is used in order to get the first key of a database.

+ +
+
datum dbm_firstkey(DBM *db);
+
`db' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function or the function `dbm_nextkey' with the same handle.
+
+ +

The function `dbm_nextkey' is used in order to get the next key of a database.

+ +
+
datum dbm_nextkey(DBM *db);
+
`db' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function or the function `dbm_firstkey' with the same handle.
+
+ +

The function `dbm_error' is used in order to check whether a database has a fatal error or not.

+ +
+
int dbm_error(DBM *db);
+
`db' specifies a database handle. The return value is true if the database has a fatal error, false if not.
+
+ +

The function `dbm_clearerr' has no effect.

+ +
+
int dbm_clearerr(DBM *db);
+
`db' specifies a database handle. The return value is 0. The function is only for compatibility.
+
+ +

The function `dbm_rdonly' is used in order to check whether a handle is read-only or not.

+ +
+
int dbm_rdonly(DBM *db);
+
`db' specifies a database handle. The return value is true if the handle is read-only, or false if not read-only.
+
+ +

The function `dbm_dirfno' is used in order to get the file descriptor of a directory file.

+ +
+
int dbm_dirfno(DBM *db);
+
`db' specifies a database handle. The return value is the file descriptor of the directory file.
+
+ +

The function `dbm_pagfno' is used in order to get the file descriptor of a data file.

+ +
+
int dbm_pagfno(DBM *db);
+
`db' specifies a database handle. The return value is the file descriptor of the data file.
+
+ +

Examples

+ +

The following example stores and retrieves a phone number, using the name as the key.

+ +
#include <relic.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+
+#define NAME     "mikio"
+#define NUMBER   "000-1234-5678"
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  DBM *db;
+  datum key, val;
+  int i;
+
+  /* open the database */
+  if(!(db = dbm_open(DBNAME, O_RDWR | O_CREAT, 00644))){
+    perror("dbm_open");
+    return 1;
+  }
+
+  /* prepare the record */
+  key.dptr = NAME;
+  key.dsize = strlen(NAME);
+  val.dptr = NUMBER;
+  val.dsize = strlen(NUMBER);
+
+  /* store the record */
+  if(dbm_store(db, key, val, DBM_REPLACE) != 0){
+    perror("dbm_store");
+  }
+
+  /* retrieve the record */
+  val = dbm_fetch(db, key);
+  if(val.dptr){
+    printf("Name: %s\n", NAME);
+    printf("Number: ");
+    for(i = 0; i < val.dsize; i++){
+      putchar(((char *)val.dptr)[i]);
+    }
+    putchar('\n');
+  } else {
+    perror("dbm_fetch");
+  }
+
+  /* close the database */
+  dbm_close(db);
+
+  return 0;
+}
+
+ +

Notes

+ +

How to build programs using Relic is the same as the case of Depot. Note that an option to be given to a linker is not `-lndbm', but `-lqdbm'.

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

Functions of Relic are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

+ +
+ +

Commands for Relic

+ +

Relic has the following command line interfaces.

+ +

The command `rlmgr' is a utility for debugging Relic and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

+ +
+
rlmgr create name
+
Create a database file.
+
rlmgr store [-kx] [-vx|-vf] [-insert] name key val
+
Store a record with a key and a value.
+
rlmgr delete [-kx] name key
+
Delete a record with a key.
+
rlmgr fetch [-kx] [-ox] [-n] name key
+
Retrieve a record with a key and output to the standard output.
+
rlmgr list [-ox] name
+
List all keys and values delimited with tab and line-feed to the standard output.
+
+ +

Options feature the following.

+ +
    +
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • +
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • +
  • -vf : read the value from a file specified with `val'.
  • +
  • -insert : specify the storing mode for `DBM_INSERT'.
  • +
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • +
  • -n : do not output the tailing newline.
  • +
+ +

This command returns 0 on success, another on failure.

+ +

The command `rltest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records.

+ +
+
rltest write name rnum
+
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
+
rltest read name rnum
+
Retrieve records of the database above.
+
+ +

This command returns 0 on success, another on failure.

+ +
+ +

Hovel: GDBM-compatible API

+ +

Overview

+ +

Hovel is the API which is compatible with GDBM. So, Hovel wraps functions of Depot and Curia as API of GDBM. It is easy to port an application from GDBM to QDBM. In most cases, you should only replace the includings of `gdbm.h' with `hovel.h' and replace the linking option `-lgdbm' with `-lqdbm'. Hovel can not handle database files made by the original GDBM.

+ +

In order to use Hovel, you should include `hovel.h', `stdlib.h', `sys/types.h' and `sys/stat.h' in the source files. Usually, the following description will be near the beginning of a source file.

+ +
+
#include <hovel.h>
+
#include <stdlib.h>
+
#include <sys/types.h>
+
#include <sys/stat.h>
+
+ +

An object of `GDBM_FILE' is used as a database handle. A database handle is opened with the function `gdbm_open' and closed with `gdbm_close'. You should not refer directly to any member of a handle. Although Hovel works as a wrapper of Depot and handles a database file usually, if you use the function `gdbm_open2' to open the handle, it is possible to make behavior of a handle as a wrapper of Curia and treat a database directory.

+ +

API

+ +

Structures of `datum' type is used in order to give and receive data of keys and values with functions of Hovel.

+ +
+
typedef struct { char *dptr; size_t dsize; } datum;
+
`dptr' specifies the pointer to the region of a key or a value. `dsize' specifies the size of the region.
+
+ +

The external variable `gdbm_version' is the string containing the version information.

+ +
+
extern char *gdbm_version;
+
+ +

The external variable `gdbm_errno' is assigned with the last happened error code. Refer to `hovel.h' for details of the error codes.

+ +
+
extern gdbm_error gdbm_errno;
+
The initial value of this variable is `GDBM_NO_ERROR'. The other values are `GDBM_MALLOC_ERROR', `GDBM_BLOCK_SIZE_ERROR', `GDBM_FILE_OPEN_ERROR', `GDBM_FILE_WRITE_ERROR', `GDBM_FILE_SEEK_ERROR', `GDBM_FILE_READ_ERROR', `GDBM_BAD_MAGIC_NUMBER', `GDBM_EMPTY_DATABASE', `GDBM_CANT_BE_READER', `GDBM_CANT_BE_WRITER', `GDBM_READER_CANT_DELETE', `GDBM_READER_CANT_STORE', `GDBM_READER_CANT_REORGANIZE', `GDBM_UNKNOWN_UPDATE', `GDBM_ITEM_NOT_FOUND', `GDBM_REORGANIZE_FAILED', `GDBM_CANNOT_REPLACE', `GDBM_ILLEGAL_DATA', `GDBM_OPT_ALREADY_SET', and `GDBM_OPT_ILLEGAL'.
+
+ +

The function `gdbm_strerror' is used in order to get a message string corresponding to an error code.

+ +
+
char *gdbm_strerror(gdbm_error gdbmerrno);
+
`gdbmerrno' specifies an error code. The return value is the message string of the error code. The region of the return value is not writable.
+
+ +

The function `gdbm_open' is used in order to get a database handle after the fashion of GDBM.

+ +
+
GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, void (*fatal_func)(void));
+
`name' specifies the name of a database. `block_size' is ignored. `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', `GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. `GDBM_SPARSE' is an original mode of QDBM and makes database a sparse file. `mode' specifies mode of a database file as the one of `open' call does. `fatal_func' is ignored. The return value is the database handle or `NULL' if it is not successful.
+
+ +

The function `gdbm_open2' is used in order to get a database handle after the fashion of QDBM.

+ +
+
GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align);
+
`name' specifies the name of a database. `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', 'GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. `GDBM_SPARSE' is an original mode of QDBM and makes database sparse files. `mode' specifies a mode of a database file or a database directory as the one of `open' or `mkdir' call does. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. `dnum' specif ies the number of division of the database. If it is not more than 0, the returning handle is created as a wrapper of Depot, else, it is as a wrapper of Curia. `align' specifies the basic size of alignment. The return value is the database handle or `NULL' if it is not successful. If the database already exists, whether it is one of Depot or Curia is measured automatically.
+
+ +

The function `gdbm_close' is used in order to close a database handle.

+ +
+
void gdbm_close(GDBM_FILE dbf);
+
`dbf' specifies a database handle. Because the region of the closed handle is released, it becomes impossible to use the handle.
+
+ +

The function `gdbm_store' is used in order to store a record.

+ +
+
int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag);
+
`dbf' specifies a database handle connected as a writer. `key' specifies a structure of a key. `content' specifies a structure of a value. `flag' specifies behavior when the key overlaps, by the following values: `GDBM_REPLACE', which means the specified value overwrites the existing one, `GDBM_INSERT', which means the existing value is kept. The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, -1 if other error occurs.
+
+ +

The function `gdbm_delete' is used in order to delete a record.

+ +
+
int gdbm_delete(GDBM_FILE dbf, datum key);
+
`dbf' specifies a database handle connected as a writer. `key' specifies a structure of a key. The return value is 0 if it is successful, -1 if some errors occur.
+
+ +

The function `gdbm_fetch' is used in order to retrieve a record.

+ +
+
datum gdbm_fetch(GDBM_FILE dbf, datum key);
+
`dbf' specifies a database handle. `key' specifies a structure of a key. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `gdbm_exists' is used in order to check whether a record exists or not.

+ +
+
int gdbm_exists(GDBM_FILE dbf, datum key);
+
`dbf' specifies a database handle. `key' specifies a structure of a key. The return value is true if a record corresponds and no error occurs, or false, else, it is false.
+
+ +

The function `gdbm_firstkey' is used in order to get the first key of a database.

+ +
+
datum gdbm_firstkey(GDBM_FILE dbf);
+
`dbf' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `gdbm_nextkey' is used in order to get the next key of a database.

+ +
+
datum gdbm_nextkey(GDBM_FILE dbf, datum key);
+
`dbf' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `gdbm_sync' is used in order to synchronize updating contents with the file and the device.

+ +
+
void gdbm_sync(GDBM_FILE dbf);
+
`dbf' specifies a database handle connected as a writer.
+
+ +

The function `gdbm_reorganize' is used in order to reorganize a database.

+ +
+
int gdbm_reorganize(GDBM_FILE dbf);
+
`dbf' specifies a database handle connected as a writer. If successful, the return value is 0, else -1.
+
+ +

The function `gdbm_fdesc' is used in order to get the file descriptor of a database file.

+ +
+
int gdbm_fdesc(GDBM_FILE dbf);
+
`dbf' specifies a database handle connected as a writer. The return value is the file descriptor of the database file. If the database is a directory the return value is -1.
+
+ +

The function `gdbm_setopt' has no effect.

+ +
+
int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size);
+
`dbf' specifies a database handle. `option' is ignored. `size' is ignored. The return value is 0. The function is only for compatibility.
+
+ +

Examples

+ +

The following example stores and retrieves a phone number, using the name as the key.

+ +
#include <hovel.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+
+#define NAME     "mikio"
+#define NUMBER   "000-1234-5678"
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  GDBM_FILE dbf;
+  datum key, val;
+  int i;
+
+  /* open the database */
+  if(!(dbf = gdbm_open(DBNAME, 0, GDBM_WRCREAT, 00644, NULL))){
+    fprintf(stderr, "gdbm_open: %s\n", gdbm_strerror(gdbm_errno));
+    return 1;
+  }
+
+  /* prepare the record */
+  key.dptr = NAME;
+  key.dsize = strlen(NAME);
+  val.dptr = NUMBER;
+  val.dsize = strlen(NUMBER);
+
+  /* store the record */
+  if(gdbm_store(dbf, key, val, GDBM_REPLACE) != 0){
+    fprintf(stderr, "gdbm_store: %s\n", gdbm_strerror(gdbm_errno));
+  }
+
+  /* retrieve the record */
+  val = gdbm_fetch(dbf, key);
+  if(val.dptr){
+    printf("Name: %s\n", NAME);
+    printf("Number: ");
+    for(i = 0; i < val.dsize; i++){
+      putchar(val.dptr[i]);
+    }
+    putchar('\n');
+    free(val.dptr);
+  } else {
+    fprintf(stderr, "gdbm_fetch: %s\n", gdbm_strerror(gdbm_errno));
+  }
+
+  /* close the database */
+  gdbm_close(dbf);
+
+  return 0;
+}
+
+ +

Notes

+ +

How to build programs using Hovel is the same as the case of Depot. Note that an option to be given to a linker is not `-lgdbm', but `-lqdbm'.

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

If QDBM was built with POSIX thread enabled, the global variable `gdbm_errno' is treated as thread specific data, and functions of Hovel are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

+ +
+ +

Commands for Hovel

+ +

Hovel has the following command line interfaces.

+ +

The command `hvmgr' is a utility for debugging Hovel and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

+ +
+
hvmgr create [-qdbm bnum dnum] [-s] name
+
Create a database file.
+
hvmgr store [-qdbm] [-kx] [-vx|-vf] [-insert] name key val
+
Store a record with a key and a value.
+
hvmgr delete [-qdbm] [-kx] name key
+
Delete a record with a key.
+
hvmgr fetch [-qdbm] [-kx] [-ox] [-n] name key
+
Retrieve a record with a key and output to the standard output.
+
hvmgr list [-qdbm] [-ox] name
+
List all keys and values delimited with tab and line-feed to the standard output.
+
hvmgr optimize [-qdbm] name
+
Optimize a database.
+
+ +

Options feature the following.

+ +
    +
  • -qdbm [bnum dnum] : use `gdbm_open2' to open the database. `bnum' specifies the number of the elements of the bucket array. `dnum' specifies the number of division of the database.
  • +
  • -s : make the file sparse.
  • +
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • +
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • +
  • -vf : read the value from a file specified with `val'.
  • +
  • -insert : specify the storing mode for `GDBM_INSERT'.
  • +
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • +
  • -n : do not output the trailing newline.
  • +
+ +

This command returns 0 on success, another on failure.

+ +

The command `hvtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records.

+ +
+
hvtest write [-qdbm] [-s] name rnum
+
Store records with keys of 8 bytes. They changes as `00000001', `00000002'...
+
hvtest read [-qdbm] name rnum
+
Retrieve records of the database above.
+
+ +

Options feature the following.

+ +
    +
  • -qdbm : use `gdbm_open2' and open the handle as Curia.
  • +
  • -s : make the file sparse.
  • +
+ +

This command returns 0 on success, another on failure.

+ +
+ +

Cabin: Utility API

+ +

Overview

+ +

Cabin is the utility API which provides memory allocating functions, sorting functions, extensible datum, array list, hash map, heap array, and so on for handling records easily on memory. This API features also parsing MIME, CSV, and XML, and features various types of encoding and decoding.

+ +

In order to use Cabin, you should include `cabin.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

+ +
+
#include <cabin.h>
+
#include <stdlib.h>
+
+ +

A pointer to `CBDATUM' is used as a handle of an extensible datum. A datum handle is opened with the function `cbdatumopen' and closed with `cbdatumclose'. A pointer to `CBLIST' is used as a handle of an array list. A list handle is opened with the function `cblistopen' and closed with `cblistclose'. A pointer to `CBMAP' is used as a handle of a hash map. A map handle is opened with the function `cbmapopen' and closed with `cbmapclose'. A pointer to `CBHEAP' is used as a handle of a heap array. A heap handle is opened with the function `cbheapopen' and closed with `cbheapclose'. You should not refer directly to any member of each handles.

+ +

API

+ +

The external variable `cbfatalfunc' is the pointer to call back function for handling a fatal error.

+ +
+
extern void (*cbfatalfunc)(const char *);
+
The argument specifies the error message. The initial value of this variable is `NULL'. If the value is `NULL', the default function is called when a fatal error occurs. A fatal error occurs when memory allocation is failed.
+
+ +

The function `cbmalloc' is used in order to allocate a region on memory.

+ +
+
void *cbmalloc(size_t size);
+
`size' specifies the size of the region. The return value is the pointer to the allocated region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbrealloc' is used in order to re-allocate a region on memory.

+ +
+
void *cbrealloc(void *ptr, size_t size);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. The return value is the pointer to the re-allocated region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbmemdup' is used in order to duplicate a region on memory.

+ +
+
char *cbmemdup(const char *ptr, int size);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the allocated region of the duplicate. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbfree' is used in order to free a region on memory.

+ +
+
void cbfree(void *ptr);
+
`ptr' specifies the pointer to a region. If it is `NULL', this function has no effect. Although this function is just a wrapper of `free' call, this is useful in applications using another package of the `malloc' series.
+
+ +

The function `cbglobalgc' is used in order to register the pointer or handle of an object to the global garbage collector.

+ +
+
void cbglobalgc(void *ptr, void (*func)(void *));
+
`ptr' specifies the pointer or handle of an object. `func' specifies the pointer to a function to release resources of the object. Its argument is the pointer or handle of the object to release. This function assures that resources of an object are released when the process exits normally by returning from the `main' function or calling the `exit' function.
+
+ +

The function `cbggcsweep' is used in order to exercise the global garbage collector explicitly.

+ +
+
void cbggcsweep(void);
+
Note that you should not use objects registered to the global garbage collector any longer after calling this function. Because the global garbage collector is initialized and you can register new objects into it.
+
+ +

The function `cbvmemavail' is used in order to check availability of allocation of the virtual memory.

+ +
+
int cbvmemavail(size_t size);
+
`size' specifies the size of region to be allocated newly. The return value is true if allocation should be success, or false if not.
+
+ +

The function `cbisort' is used in order to sort an array using insert sort.

+ +
+
void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Insert sort is useful only if most elements have been sorted already.
+
+ +

The function `cbssort' is used in order to sort an array using shell sort.

+ +
+
void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. If most elements have been sorted, shell sort may be faster than heap sort or quick sort.
+
+ +

The function `cbhsort' is used in order to sort an array using heap sort.

+ +
+
void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Although heap sort is robust against bias of input, quick sort is faster in most cases.
+
+ +

The function `cbqsort' is used in order to sort an array using quick sort.

+ +
+
void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
+
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Being sensitive to bias of input, quick sort is the fastest sorting algorithm.
+
+ +

The function `cbstricmp' is used in order to compare two strings with case insensitive evaluation.

+ +
+
int cbstricmp(const char *astr, const char *bstr);
+
`astr' specifies the pointer of one string. `astr' specifies the pointer of the other string. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. Upper cases and lower cases of alphabets in ASCII code are not distinguished.
+
+ +

The function `cbstrfwmatch' is used in order to check whether a string begins with a key.

+ +
+
int cbstrfwmatch(const char *str, const char *key);
+
`str' specifies the pointer of a target string. `key' specifies the pointer of a forward matching key string. The return value is true if the target string begins with the key, else, it is false.
+
+ +

The function `cbstrfwimatch' is used in order to check whether a string begins with a key, with case insensitive evaluation.

+ +
+
int cbstrfwimatch(const char *str, const char *key);
+
`str' specifies the pointer of a target string. `key' specifies the pointer of a forward matching key string. The return value is true if the target string begins with the key, else, it is false. Upper cases and lower cases of alphabets in ASCII code are not distinguished.
+
+ +

The function `cbstrbwmatch' is used in order to check whether a string ends with a key.

+ +
+
int cbstrbwmatch(const char *str, const char *key);
+
`str' specifies the pointer of a target string. `key' specifies the pointer of a backward matching key string. The return value is true if the target string ends with the key, else, it is false.
+
+ +

The function `cbstrbwimatch' is used in order to check whether a string ends with a key, with case insensitive evaluation.

+ +
+
int cbstrbwimatch(const char *str, const char *key);
+
`str' specifies the pointer of a target string. `key' specifies the pointer of a backward matching key string. The return value is true if the target string ends with the key, else, it is false. Upper cases and lower cases of alphabets in ASCII code are not distinguished.
+
+ +

The function `cbstrstrkmp' is used in order to locate a substring in a string using KMP method.

+ +
+
char *cbstrstrkmp(const char *haystack, const char *needle);
+
`haystack' specifies the pointer of a target string. `needle' specifies the pointer of a substring to be found. The return value is the pointer to the beginning of the substring or `NULL' if the substring is not found. In most cases, `strstr' as a built-in function of the compiler is faster than this function.
+
+ +

The function `cbstrstrkmp' is used in order to locate a substring in a string using BM method.

+ +
+
char *cbstrstrbm(const char *haystack, const char *needle);
+
`haystack' specifies the pointer of a target string. `needle' specifies the pointer of a substring to be found. The return value is the pointer to the beginning of the substring or `NULL' if the substring is not found. In most cases, `strstr' as a built-in function of the compiler is faster than this function.
+
+ +

The function `cbstrtoupper' is used in order to convert the letters of a string to upper case.

+ +
+
char *cbstrtoupper(char *str);
+
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.
+
+ +

The function `cbstrtolower' is used in order to convert the letters of a string to lower case.

+ +
+
char *cbstrtolower(char *str);
+
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.
+
+ +

The function `cbstrtrim' is used in order to cut space characters at head or tail of a string.

+ +
+
char *cbstrtrim(char *str);
+
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.
+
+ +

The function `cbstrsqzspc' is used in order to squeeze space characters in a string and trim it.

+ +
+
char *cbstrsqzspc(char *str);
+
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.
+
+ +

The function `cbstrcountutf' is used in order to count the number of characters in a string of UTF-8.

+ +
+
int cbstrcountutf(const char *str);
+
`str' specifies the pointer of a string of UTF-8. The return value is the number of characters in the string.
+
+ +

The function `cbstrcututf' is used in order to cut a string of UTF-8 at the specified number of characters.

+ +
+
char *cbstrcututf(char *str, int num);
+
`str' specifies the pointer of a string of UTF-8. `num' specifies the number of characters to be kept. The return value is the pointer to the string.
+
+ +

The function `cbdatumopen' is used in order to get a datum handle.

+ +
+
CBDATUM *cbdatumopen(const char *ptr, int size);
+
`ptr' specifies the pointer to the region of the initial content. If it is `NULL', an empty datum is created. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is a datum handle.
+
+ +

The function `cbdatumdup' is used in order to copy a datum.

+ +
+
CBDATUM *cbdatumdup(const CBDATUM *datum);
+
`datum' specifies a datum handle. The return value is a new datum handle.
+
+ +

The function `cbdatumclose' is used in order to free a datum handle.

+ +
+
void cbdatumclose(CBDATUM *datum);
+
`datum' specifies a datum handle. Because the region of a closed handle is released, it becomes impossible to use the handle.
+
+ +

The function `cbdatumcat' is used in order to concatenate a datum and a region.

+ +
+
void cbdatumcat(CBDATUM *datum, const char *ptr, int size);
+
`datum' specifies a datum handle. `ptr' specifies the pointer to the region to be appended. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.
+
+ +

The function `cbdatumptr' is used in order to get the pointer of the region of a datum.

+ +
+
const char *cbdatumptr(const CBDATUM *datum);
+
`datum' specifies a datum handle. The return value is the pointer of the region of a datum. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.
+
+ +

The function `cbdatumsize' is used in order to get the size of the region of a datum.

+ +
+
int cbdatumsize(const CBDATUM *datum);
+
`datum' specifies a datum handle. The return value is the size of the region of a datum.
+
+ +

The function `cbdatumsetsize' is used in order to change the size of the region of a datum.

+ +
+
void cbdatumsetsize(CBDATUM *datum, int size);
+
`datum' specifies a datum handle. `size' specifies the new size of the region. If the new size is bigger than the one of old, the surplus region is filled with zero codes.
+
+ +

The function `cbdatumprintf' is used in order to perform formatted output into a datum.

+ +
+
void cbdatumprintf(CBDATUM *datum, const char *format, ...);
+
`format' specifies a printf-like format string. The conversion character `%' can be used with such flag characters as `s', `d', `o', `u', `x', `X', `c', `e', `E', `f', `g', `G', `@', `?', `:', `%'. `@' works as with `s' but escapes meta characters of XML. `?' works as with `s' but escapes meta characters of URL. `:' works as with `s' but performs MIME encoding as UTF-8. The other conversion character work as with each original.
+
+ +

The function `cbdatumtomalloc' is used in order to convert a datum to an allocated region.

+ +
+
char *cbdatumtomalloc(CBDATUM *datum, int *sp);
+
`datum' specifies a datum handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the datum. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Because the region of the original datum is released, it should not be released again.
+
+ +

The function `cblistopen' is used in order to get a list handle.

+ +
+
CBLIST *cblistopen(void);
+
The return value is a list handle.
+
+ +

The function `cblistdup' is used in order to copy a list.

+ +
+
CBLIST *cblistdup(const CBLIST *list);
+
`list' specifies a list handle. The return value is a new list handle.
+
+ +

The function `cblistclose' is used in order to close a list handle.

+ +
+
void cblistclose(CBLIST *list);
+
`list' specifies a list handle. Because the region of a closed handle is released, it becomes impossible to use the handle.
+
+ +

The function `cblistnum' is used in order to get the number of elements of a list.

+ +
+
int cblistnum(const CBLIST *list);
+
`list' specifies a list handle. The return value is the number of elements of the list.
+
+ +

The function `cblistval' is used in order to get the pointer to the region of an element of a list.

+ +
+
const char *cblistval(const CBLIST *list, int index, int *sp);
+
`list' specifies a list handle. `index' specifies the index of an element. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the element. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. If `index' is equal to or more than the number of elements, the return value is `NULL'.
+
+ +

The function `cblistpush' is used in order to add an element at the end of a list.

+ +
+
void cblistpush(CBLIST *list, const char *ptr, int size);
+
`list' specifies a list handle. `ptr' specifies the pointer to the region of an element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.
+
+ +

The function `cblistpop' is used in order to remove an element of the end of a list.

+ +
+
char *cblistpop(CBLIST *list, int *sp);
+
`list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If the list is empty, the return value is `NULL'.
+
+ +

The function `cblistunshift' is used in order to add an element at the top of a list.

+ +
+
void cblistunshift(CBLIST *list, const char *ptr, int size);
+
`list' specifies a list handle. `ptr' specifies the pointer to the region of an element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.
+
+ +

The function `cblistshift' is used in order to remove an element of the top of a list.

+ +
+
char *cblistshift(CBLIST *list, int *sp);
+
`list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If the list is empty, the return value is `NULL'.
+
+ +

The function `cblistinsert' is used in order to add an element at the specified location of a list.

+ +
+
void cblistinsert(CBLIST *list, int index, const char *ptr, int size);
+
`list' specifies a list handle. `index' specifies the index of an element. `ptr' specifies the pointer to the region of the element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.
+
+ +

The function `cblistremove' is used in order to remove an element at the specified location of a list.

+ +
+
char *cblistremove(CBLIST *list, int index, int *sp);
+
`list' specifies a list handle. `index' specifies the index of an element. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If `index' is equal to or more than the number of elements, no element is removed and the return value is `NULL'.
+
+ +

The function `cblistover' is used in order to overwrite an element at the specified location of a list.

+ +
+
void cblistover(CBLIST *list, int index, const char *ptr, int size);
+
`list' specifies a list handle. `index' specifies the index of an element. `ptr' specifies the pointer to the region of the new content. `size' specifies the size of the new content. If it is negative, the size is assigned with `strlen(ptr)'. If `index' is equal to or more than the number of elements, this function has no effect.
+
+ +

The function `cblistsort' is used in order to sort elements of a list in lexical order.

+ +
+
void cblistsort(CBLIST *list);
+
`list' specifies a list handle. Quick sort is used for sorting.
+
+ +

The function `cblistlsearch' is used in order to search a list for an element using liner search.

+ +
+
int cblistlsearch(const CBLIST *list, const char *ptr, int size);
+
`list' specifies a list handle. `ptr' specifies the pointer to the region of a key. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the index of a corresponding element or -1 if there is no corresponding element. If two or more elements corresponds, the former returns.
+
+ +

The function `cblistbsearch' is used in order to search a list for an element using binary search.

+ +
+
int cblistbsearch(const CBLIST *list, const char *ptr, int size);
+
`list' specifies a list handle. It should be sorted in lexical order. `ptr' specifies the pointer to the region of a key. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the index of a corresponding element or -1 if there is no corresponding element. If two or more elements corresponds, which returns is not defined.
+
+ +

The function `cblistdump' is used in order to serialize a list into a byte array.

+ +
+
char *cblistdump(const CBLIST *list, int *sp);
+
`list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. The return value is the pointer to the region of the result serial region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cblistload' is used in order to redintegrate a serialized list.

+ +
+
CBLIST *cblistload(const char *ptr, int size);
+
`ptr' specifies the pointer to a byte array. `size' specifies the size of the region. The return value is a new list handle.
+
+ +

The function `cbmapopen' is used in order to get a map handle.

+ +
+
CBMAP *cbmapopen(void);
+
The return value is a map handle.
+
+ +

The function `cbmapdup' is used in order to copy a map.

+ +
+
CBMAP *cbmapdup(CBMAP *map);
+
`map' specifies a map handle. The return value is a new map handle. The iterator of the source map is initialized.
+
+ +

The function `cbmapclose' is used in order to close a map handle.

+ +
+
void cbmapclose(CBMAP *map);
+
`map' specifies a map handle. Because the region of a closed handle is released, it becomes impossible to use the handle.
+
+ +

The function `cbmapput' is used in order to store a record into a map.

+ +
+
int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over);
+
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `over' specifies whether the value of the duplicated record is overwritten or not. If `over' is false and the key duplicated, the return value is false, else, it is true.
+
+ +

The function `cbmapputcat' is used in order to concatenate a value at the end of the value of the existing record.

+ +
+
void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz);
+
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. If there is no corresponding record, a new record is created.
+
+ +

The function `cbmapout' is used in order to delete a record of a map.

+ +
+
int cbmapout(CBMAP *map, const char *kbuf, int ksiz);
+
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true. False is returned when no record corresponds to the specified key.
+
+ +

The function `cbmapget' is used in order to retrieve a record of a map.

+ +
+
const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp);
+
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record. `NULL' is returned when no record corresponds. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.
+
+ +

The function `cbmapmove' is used in order to move a record to the edge of a map.

+ +
+
int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head);
+
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `head' specifies the destination which is head if it is true or tail if else. If successful, the return value is true. False is returned when no record corresponds to the specified key.
+
+ +

The function `cbmapiterinit' is used in order to initialize the iterator of a map.

+ +
+
void cbmapiterinit(CBMAP *map);
+
`map' specifies a map handle. The iterator is used in order to access the key of every record stored in a map.
+
+ +

The function `cbmapiternext' is used in order to get the next key of the iterator of a map.

+ +
+
const char *cbmapiternext(CBMAP *map, int *sp);
+
`map' specifies a map handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. The order of iteration is assured to be the same of the one of storing.
+
+ +

The function `cbmapiterval' is used in order to get the value binded to the key fetched from the iterator of a map.

+ +
+
const char *cbmapiterval(const char *kbuf, int *sp);
+
`kbuf' specifies the pointer to the region of a iteration key. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value of the corresponding record. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.
+
+ +

The function `cbmaprnum' is used in order to get the number of the records stored in a map.

+ +
+
int cbmaprnum(const CBMAP *map);
+
`map' specifies a map handle. The return value is the number of the records stored in the map.
+
+ +

The function `cbmapkeys' is used in order to get the list handle contains all keys in a map.

+ +
+
CBLIST *cbmapkeys(CBMAP *map);
+
`map' specifies a map handle. The return value is the list handle contains all keys in the map. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
+
+ +

The function `cbmapvals' is used in order to get the list handle contains all values in a map.

+ +
+
CBLIST *cbmapvals(CBMAP *map);
+
`map' specifies a map handle. The return value is the list handle contains all values in the map. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
+
+ +

The function `cbmapdump' is used in order to serialize a map into a byte array.

+ +
+
char *cbmapdump(const CBMAP *map, int *sp);
+
`map' specifies a map handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. The return value is the pointer to the region of the result serial region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbmapload' is used in order to redintegrate a serialized map.

+ +
+
CBMAP *cbmapload(const char *ptr, int size);
+
`ptr' specifies the pointer to a byte array. `size' specifies the size of the region. The return value is a new map handle.
+
+ +

The function `cbmaploadone' is used in order to extract a record from a serialized map.

+ +
+
char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp);
+
`ptr' specifies the pointer to a byte array. `size' specifies the size of the region. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record. `NULL' is returned when no record corresponds. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.
+
+ + +

The function `cbheapopen' is used in order to get a heap handle.

+ +
+
CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *));
+
`size' specifies the size of each record. `max' specifies the maximum number of records in the heap. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of records. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. The return value is a heap handle.
+
+ +

The function `cbheapdup' is used in order to copy a heap.

+ +
+
CBHEAP *cbheapdup(CBHEAP *heap);
+
`heap' specifies a heap handle. The return value is a new heap handle.
+
+ +

The function `cbheapclose' is used in order to close a heap handle.

+ +
+
void cbheapclose(CBHEAP *heap);
+
`heap' specifies a heap handle. Because the region of a closed handle is released, it becomes impossible to use the handle.
+
+ +

The function `cbheapnum' is used in order to get the number of the records stored in a heap.

+ +
+
int cbheapnum(CBHEAP *heap);
+
`heap' specifies a heap handle. The return value is the number of the records stored in the heap.
+
+ +

The function `cbheapinsert' is used in order to insert a record into a heap.

+ +
+
int cbheapinsert(CBHEAP *heap, const void *ptr);
+
`heap' specifies a heap handle. `ptr' specifies the pointer to the region of a record. The return value is true if the record is added, else false. If the new record is bigger than the biggest existing regord, the new record is not added. If the new record is added and the number of records exceeds the maximum number, the biggest existing record is removed.
+
+ +

The function `cbheapval' is used in order to get the pointer to the region of a record in a heap.

+ +
+
void *cbheapval(CBHEAP *heap, int index);
+
`heap' specifies a heap handle. `index' specifies the index of a record. The return value is the pointer to the region of the record. If `index' is equal to or more than the number of records, the return value is `NULL'. Note that records are organized by the nagative order the comparing function.
+
+ +

The function `cbheaptomalloc' is used in order to convert a heap to an allocated region.

+ +
+
void *cbheaptomalloc(CBHEAP *heap, int *np);
+
`heap' specifies a heap handle. `np' specifies the pointer to a variable to which the number of records of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the heap. Records are sorted. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Because the region of the original heap is released, it should not be released again.
+
+ +

The function `cbsprintf' is used in order to allocate a formatted string on memory.

+ +
+
char *cbsprintf(const char *format, ...);
+
`format' specifies a printf-like format string. The conversion character `%' can be used with such flag characters as `d', `o', `u', `x', `X', `e', `E', `f', `g', `G', `c', `s', and `%'. Specifiers of the field length and the precision can be put between the conversion characters and the flag characters. The specifiers consist of decimal characters, `.', `+', `-', and the space character. The other arguments are used according to the format string. The return value is the pointer to the allocated region of the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbreplace' is used in order to replace some patterns in a string.

+ +
+
char *cbreplace(const char *str, CBMAP *pairs);
+
`str' specifies the pointer to a source string. `pairs' specifies the handle of a map composed of pairs of replacement. The key of each pair specifies a pattern before replacement and its value specifies the pattern after replacement. The return value is the pointer to the allocated region of the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbsplit' is used in order to make a list by splitting a serial datum.

+ +
+
CBLIST *cbsplit(const char *ptr, int size, const char *delim);
+
`ptr' specifies the pointer to the region of the source content. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `delim' specifies a string containing delimiting characters. If it is `NULL', zero code is used as a delimiter. The return value is a list handle. If two delimiters are successive, it is assumed that an empty element is between the two. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose'.
+
+ +

The function `cbreadfile' is used in order to read whole data of a file.

+ +
+
char *cbreadfile(const char *name, int *sp);
+
`name' specifies the name of a file. If it is `NULL', the standard input is specified. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the allocated region of the read data. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbwritefile' is used in order to write a serial datum into a file.

+ +
+
int cbwritefile(const char *name, const char *ptr, int size);
+
`name specifies the name of a file. If it is `NULL', the standard output is specified. `ptr' specifies the pointer to the region of the source content. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. If successful, the return value is true, else, it is false. If the file exists, it is overwritten. Else, a new file is created.
+
+ +

The function `cbreadlines' is used in order to read every line of a file.

+ +
+
CBLIST *cbreadlines(const char *name);
+
`name' specifies the name of a file. If it is `NULL', the standard input is specified. The return value is a list handle of the lines if successful, else it is NULL. Line separators are cut out. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
+
+ +

The function `cbdirlist' is used in order to read names of files in a directory.

+ +
+
CBLIST *cbdirlist(const char *name);
+
`name' specifies the name of a directory. The return value is a list handle of names if successful, else it is NULL. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
+
+ +

The function `cbfilestat' is used in order to get the status of a file or a directory.

+ +
+
int cbfilestat(const char *name, int *isdirp, int *sizep, int *mtimep);
+
`name' specifies the name of a file or a directory. `dirp' specifies the pointer to a variable to which whether the file is a directory is assigned. If it is `NULL', it is not used. `sizep' specifies the pointer to a variable to which the size of the file is assigned. If it is `NULL', it is not used. `mtimep' specifies the pointer to a variable to which the last modified time of the file is assigned. If it is `NULL', it is not used. If successful, the return value is true, else, false. False is returned when the file does not exist or the permission is denied.
+
+ +

The function `cbremove' is used in order to remove a file or a directory and its sub ones recursively.

+ +
+
int cbremove(const char *name);
+
`name' specifies the name of a file or a directory. If successful, the return value is true, else, false. False is returned when the file does not exist or the permission is denied.
+
+ +

The function `cburlbreak' is used in order to break up a URL into elements.

+ +
+
CBMAP *cburlbreak(const char *str);
+
`str' specifies the pointer to a string of URL. The return value is a map handle. Each key of the map is the name of an element. The key "self" specifies the URL itself. The key "scheme" specifies the scheme. The key "host" specifies the host of the server. The key "port" specifies the port number of the server. The key "authority" specifies the authority information. The key "path" specifies the path of the resource. The key "file" specifies the file name without the directory section. The key "query" specifies the query string. The key "fragment" specifies the fragment string. Supported schema are HTTP, HTTPS, FTP, and FILE. Absolute URL and relative URL are supported. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use.
+
+ +

The runction `cburlresolve' is used in order to resolve a relative URL with another absolute URL.

+ +
+
char *cburlresolve(const char *base, const char *target);
+
`base' specifies an absolute URL of a base location. `target' specifies a URL to be resolved. The return value is a resolved URL. If the target URL is relative, a new URL of relative location from the base location is returned. Else, a copy of the target URL is returned. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cburlencode' is used in order to encode a serial object with URL encoding.

+ +
+
char *cburlencode(const char *ptr, int size);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cburldecode' is used in order to decode a string encoded with URL encoding.

+ +
+
char *cburldecode(const char *str, int *sp);
+
`str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbbaseencode' is used in order to encode a serial object with Base64 encoding.

+ +
+
char *cbbaseencode(const char *ptr, int size);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbbasedecode' is used in order to decode a string encoded with Base64 encoding.

+ +
+
char *cbbasedecode(const char *str, int *sp);
+
`str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbquoteencode' is used in order to encode a serial object with quoted-printable encoding.

+ +
+
char *cbquoteencode(const char *ptr, int size);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbquotedecode' is used in order to decode a string encoded with quoted-printable encoding.

+ +
+
char *cbquotedecode(const char *str, int *sp);
+
`str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ + +

The function `cbmimebreak' is used in order to split a string of MIME into headers and the body.

+ +
+
char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp);
+
`ptr' specifies the pointer to the region of MIME data. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `attrs' specifies a map handle to store attributes. If it is `NULL', it is not used. Each key of the map is an attribute name uncapitalized. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer of the body data. If the content type is defined, the attribute map has the key "TYPE" specifying the type. If the character encoding is defined, the key "CHARSET" specifies the encoding name. If the boundary string of multipart is defined, the key "BOUNDARY" specifies the string. If the content disposition is defined, the key "DISPOSITION" specifies the direction. If the file name is defined, the key "FILENAME" specifies the name. If the attribute name is defined, the key "NAME" specifies the nam e. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbmimeparts' is used in order to split multipart data of MIME into its parts.

+ +
+
CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary);
+
`ptr' specifies the pointer to the region of multipart data of MIME. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `boundary' specifies the pointer to the region of the boundary string. The return value is a list handle. Each element of the list is the string of a part. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
+
+ +

The function `cbmimeencode' is used in order to encode a string with MIME encoding.

+ +
+
char *cbmimeencode(const char *str, const char *encname, int base);
+
`str' specifies the pointer to a string. `encname' specifies a string of the name of the character encoding. The return value is the pointer to the result string. `base' specifies whether to use Base64 encoding. If it is false, quoted-printable is used. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbmimedecode' is used in order to decode a string encoded with MIME encoding.

+ +
+
char *cbmimedecode(const char *str, char *enp);
+
`str' specifies the pointer to an encoded string. `enp' specifies the pointer to a region into which the name of encoding is written. If it is `NULL', it is not used. The size of the buffer should be equal to or more than 32 bytes. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbcsvrows' is used in order to split a string of CSV into rows.

+ +
+
CBLIST *cbcsvrows(const char *str);
+
`str' specifies the pointer to the region of an CSV string. The return value is a list handle. Each element of the list is a string of a row. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. The character encoding of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Being compatible with MS-Excel, these functions for CSV can handle cells including such meta characters as comma, between double quotation marks.
+
+ +

The function `cbcsvcells' is used in order to split the string of a row of CSV into cells.

+ +
+
CBLIST *cbcsvcells(const char *str);
+
`str' specifies the pointer to the region of a row of CSV. The return value is a list handle. Each element of the list is the unescaped string of a cell of the row. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
+
+ +

The function `cbcsvescape' is used in order to escape a string with the meta characters of CSV.

+ +
+
char *cbcsvescape(const char *str);
+
`str' specifies the pointer to the region of a string. The return value is the pointer to the escaped string sanitized of meta characters. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbcsvunescape' is used in order to unescape a string with the escaped meta characters of CSV.

+ +
+
char *cbcsvunescape(const char *str);
+
`str' specifies the pointer to the region of a string with meta characters. The return value is the pointer to the unescaped string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbxmlbreak' is used in order to split a string of XML into tags and text sections.

+ +
+
CBLIST *cbxmlbreak(const char *str, int cr);
+
`str' specifies the pointer to the region of an XML string. `cr' specifies whether to remove comments. The return value is a list handle. Each element of the list is the string of a tag or a text section. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. The character encoding of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Because these functions for XML are not XML parser with validation check, it can handle also HTML and SGML.
+
+ +

The function `cbxmlattrs' is used in order to get the map of attributes of an XML tag.

+ +
+
CBMAP *cbxmlattrs(const char *str);
+
`str' specifies the pointer to the region of a tag string. The return value is a map handle. Each key of the map is the name of an attribute. Each value is unescaped. You can get the name of the tag with the key of an empty string. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use.
+
+ +

The function `cbxmlescape' is used in order to escape a string with the meta characters of XML.

+ +
+
char *cbxmlescape(const char *str);
+
`str' specifies the pointer to the region of a string. The return value is the pointer to the escaped string sanitized of meta characters. This function converts only `&', `<', `>', and `"'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbxmlunescape' is used in order to unescape a string with the entity references of XML.

+ +
+
char *cbxmlunescape(const char *str);
+
`str' specifies the pointer to the region of a string. The return value is the pointer to the unescaped string. This function restores only `&amp;', `&lt;', `&gt;', and `&quot;'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbdeflate' is used in order to compress a serial object with ZLIB.

+ +
+
char *cbdeflate(const char *ptr, int size, int *sp);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.
+
+ +

The function `cbinflate' is used in order to decompress a serial object compressed with ZLIB.

+ +
+
char *cbinflate(const char *ptr, int size, int *sp);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.
+
+ +

The function `cbgzencode' is used in order to compress a serial object with GZIP.

+ +
+
char *cbgzencode(const char *ptr, int size, int *sp);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.
+
+ +

The function `cbgzdecode' is used in order to decompress a serial object compressed with GZIP.

+ +
+
char *cbgzdecode(const char *ptr, int size, int *sp);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.
+
+ +

The function `cbgetcrc' is used in order to get the CRC32 checksum of a serial object.

+ +
+
unsigned int cbgetcrc(const char *ptr, int size);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the CRC32 checksum of the object. This function is available only if QDBM was built with ZLIB enabled.
+
+ +

The function `cblzoencode' is used in order to compress a serial object with LZO.

+ +
+
char *cblzoencode(const char *ptr, int size, int *sp);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled.
+
+ +

The function `cblzodecode' is used in order to decompress a serial object compressed with LZO.

+ +
+
char *cblzodecode(const char *ptr, int size, int *sp);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled.
+
+ +

The function `cbbzencode' is used in order to compress a serial object with BZIP2.

+ +
+
char *cbbzencode(const char *ptr, int size, int *sp);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with BZIP2 enabled.
+
+ +

The function `cbbzdecode' is used in order to decompress a serial object compressed with BZIP2.

+ +
+
char *cbbzdecode(const char *ptr, int size, int *sp);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with BZIP2 enabled.
+
+ +

The function `cbiconv' is used in order to convert the character encoding of a string.

+ +
+
char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `icode' specifies the name of encoding of the input string. `ocode' specifies the name of encoding of the output string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. `mp' specifies the pointer to a variable to which the number of missing characters by failure of conversion is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QD BM was built with ICONV enabled.
+
+ +

The function `cbencname' is used in order to detect the encoding of a string automatically.

+ +
+
const char *cbencname(const char *ptr, int size);
+
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the string of the encoding name of the string. As it stands, US-ASCII, ISO-2022-JP, Shift_JIS, CP932, EUC-JP, UTF-8, UTF-16, UTF-16BE, and UTF-16LE are supported. If none of them matches, ISO-8859-1 is selected. This function is available only if QDBM was built with ICONV enabled.
+
+ +

The function `cbjetlag' is used in order to get the jet lag of the local time in seconds.

+ +
+
int cbjetlag(void);
+
The return value is the jet lag of the local time in seconds.
+
+ +

The function `cbcalendar' is used in order to get the Gregorian calendar of a time.

+ +
+
void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp);
+
`t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. `yearp' specifies the pointer to a variable to which the year is assigned. If it is `NULL', it is not used. `monp' specifies the pointer to a variable to which the month is assigned. If it is `NULL', it is not used. 1 means January and 12 means December. `dayp' specifies the pointer to a variable to which the day of the month is assigned. If it is `NULL', it is not used. `hourp' specifies the pointer to a variable to which the hours is assigned. If it is `NULL', it is not used. `minp' specifies the pointer to a variable to which the minutes is assigned. If it is `NULL', it is not used. `secp' specifies the pointer to a variable to which the seconds is assigned. If it is `NULL', it is not used.
+
+ +

The function `cbdayofweek' is used in order to get the day of week of a date.

+ +
+
int cbdayofweek(int year, int mon, int day);
+
`year' specifies the year of a date. `mon' specifies the month of the date. `day' specifies the day of the date. The return value is the day of week of the date. 0 means Sunday and 6 means Saturday.
+
+ +

The function `cbdatestrwww' is used in order to get the string for a date in W3CDTF.

+ +
+
char *cbdatestrwww(time_t t, int jl);
+
`t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. The return value is the string of the date in W3CDTF (YYYY-MM-DDThh:mm:ddTZD). Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbdatestrhttp' is used in order to get the string for a date in RFC 1123 format.

+ +
+
char *cbdatestrhttp(time_t t, int jl);
+
`t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. The return value is the string of the date in RFC 1123 format (Wdy, DD-Mon-YYYY hh:mm:dd TZD). Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `cbstrmktime' is used in order to get the time value of a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123).

+ +
+
time_t cbstrmktime(const char *str);
+
`str' specifies a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). The return value is the time value of the date or -1 if the format is invalid. Decimal can be trailed by "s" for in seconds, "m" for in minutes, "h" for in hours, and "d" for in days.
+
+ +

The function `cbproctime' is used in order to get user and system processing times.

+ +
+
void cbproctime(double *usrp, double *sysp);
+
`usrp' specifies the pointer to a variable to which the user processing time is assigned. If it is `NULL', it is not used. The unit of time is seconds. `sysp' specifies the pointer to a variable to which the system processing time is assigned. If it is `NULL', it is not used. The unit of time is seconds.
+
+ +

The function `cbstdiobin' is used in order to ensure that the standard I/O is binary mode.

+ +
+
void cbstdiobin(void);
+
This function is useful for applications on dosish file systems.
+
+ +

Examples

+ +

The following example is typical use.

+ +
#include <cabin.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int main(int argc, char **argv){
+  CBDATUM *datum;
+  CBLIST *list;
+  CBMAP *map;
+  char *buf1, *buf2;
+  int i;
+
+  /* open the datum handle */
+  datum = cbdatumopen("123", -1);
+  /* concatenate the data */
+  cbdatumcat(datum, "abc", -1);
+  /* print the datum */
+  printf("%s\n", cbdatumptr(datum));
+  /* close the datum handle */
+  cbdatumclose(datum);
+
+  /* open the list handle */
+  list = cblistopen();
+  /* add elements into the list */
+  cblistpush(list, "apple", -1);
+  cblistpush(list, "orange", -1);
+  /* print all elements */
+  for(i = 0; i < cblistnum(list); i++){
+    printf("%s\n", cblistval(list, i, NULL));
+  }
+  /* close the list handle */
+  cblistclose(list);
+
+  /* open the map handle */
+  map = cbmapopen();
+  /* add records into the map */
+  cbmapput(map, "dog", -1, "bowwow", -1, 1);
+  cbmapput(map, "cat", -1, "meow", -1, 1);
+  /* search for values and print them */
+  printf("%s\n", cbmapget(map, "dog", -1, NULL));
+  printf("%s\n", cbmapget(map, "cat", -1, NULL));
+  /* close the map */
+  cbmapclose(map);
+
+  /* Base64 encoding */
+  buf1 = cbbaseencode("I miss you.", -1);
+  printf("%s\n", buf1);
+  /* Base64 decoding */
+  buf2 = cbbasedecode(buf1, NULL);
+  printf("%s\n", buf2);
+  /* release the resources */
+  free(buf2);
+  free(buf1);
+
+  /* register a plain pointer to the global garbage collector */
+  buf1 = cbmemdup("Take it easy.", -1);
+  cbglobalgc(buf1, free);
+  /* the pointer is available but you don't have to release it */
+  printf("%s\n", buf1);
+  
+  /* register a list to the global garbage collector */
+  list = cblistopen();
+  cbglobalgc(list, (void (*)(void *))cblistclose);
+  /* the handle is available but you don't have to close it */
+  cblistpush(list, "Don't hesitate.", -1);
+  for(i = 0; i < cblistnum(list); i++){
+    printf("%s\n", cblistval(list, i, NULL));    
+  }
+
+  return 0;
+}
+
+ +

Notes

+ +

How to build programs using Cabin is the same as the case of Depot.

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

Functions of Cabin except for `cbglobalgc' are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

+ +
+ +

Commands for Cabin

+ +

Cabin has the following command line interfaces.

+ +

The command `cbtest' is a utility for facility test and performance test. Measure the execution time of the command. This command is used in the following format. `rnum' specifies the number of records.

+ +
+
cbtest sort [-d] rnum
+
Perform test of sorting algorithms.
+
cbtest strstr [-d] rnum
+
Perform test of string locating algorithms.
+
cbtest list [-d] rnum
+
Perform writing test of list.
+
cbtest map [-d] rnum
+
Perform writing test of map.
+
cbtest wicked rnum
+
Perform updating operations of list and map selected at random.
+
cbtest misc
+
Perform test of miscellaneous routines.
+
+ +

Options feature the following.

+ +
    +
  • -d : read and show data of the result.
  • +
+ +

This command returns 0 on success, another on failure.

+ +

The command `cbcodec' is a tool to use encoding and decoding features provided by Cabin. This command is used in the following format. `file' specifies a input file. If it is omitted, the standard input is read.

+ +
+
cbcodec url [-d] [-br] [-rs base target] [-l] [-e expr] [file]
+
Perform URL encoding and its decoding.
+
cbcodec base [-d] [-l] [-c num] [-e expr] [file]
+
Perform Base64 encoding and its decoding.
+
cbcodec quote [-d] [-l] [-c num] [-e expr] [file]
+
Perform quoted-printable encoding and its decoding.
+
cbcodec mime [-d] [-hd] [-bd] [-part num] [-l] [-ec code] [-qp] [-dc] [-e expr] [file]
+
Perform MIME encoding and its decoding.
+
cbcodec csv [-d] [-t] [-l] [-e expr] [-html] [file]
+
Process CSV. By default, escape meta characters.
+
cbcodec xml [-d] [-p] [-l] [-e expr] [-tsv] [file]
+
Process XML. By default, escape meta characters.
+
cbcodec zlib [-d] [-gz] [-crc] [file]
+
Perform deflation and inflation with ZLIB. It is available only if QDBM was built with ZLIB enabled.
+
cbcodec lzo [-d] [file]
+
Perform compression and decompression with LZO. It is available only if QDBM was built with LZO enabled.
+
cbcodec bzip [-d] [file]
+
Perform compression and decompression with BZIP2. It is available only if QDBM was built with BZIP2 enabled.
+
cbcodec iconv [-ic code] [-oc code] [-ol ltype] [-cn] [-um] [-wc] [file]
+
Convert character encoding with ICONV. It is available only if QDBM was built with ICONV enabled.
+
cbcodec date [-wf] [-rf] [-utc] [str]
+
Convert a date string specified `str'. By default, UNIX time is output. If `str' is omitted, the current date is dealt.
+
+ +

Options feature the following.

+ +
    +
  • -d : perform decoding (unescaping), not encoding (escaping).
  • +
  • -br : break up URL into elements.
  • +
  • -rs : resolve relative URL.
  • +
  • -l : output the tailing newline.
  • +
  • -e expr : specify input data directly.
  • +
  • -c num : limit the number of columns of the encoded data.
  • +
  • -hd : parse MIME and extract headers in TSV format.
  • +
  • -bd : parse MIME and extract the body.
  • +
  • -part num : parse MIME and extract a part.
  • +
  • -ec code : specify the input encoding, which is UTF-8 by default.
  • +
  • -qp : use quoted-printable encoding, which is Base64 by default.
  • +
  • -dc : output the encoding name instead of the result string when decoding.
  • +
  • -t : parse CSV. Convert the data into TSV. Tab and new-line in a cell are deleted.
  • +
  • -html : parse CSV. Convert the data into HTML.
  • +
  • -p : parse XML. Show tags and text sections with dividing headers.
  • +
  • -tsv : parse XML. Show the result in TSV format. Characters of tabs and new-lines are URL-encoded.
  • +
  • -gz : use GZIP format.
  • +
  • -crc : output the CRC32 checksum as hexadecimal and big endian.
  • +
  • -ic code : specify the input encoding, which is detected automatically by default.
  • +
  • -oc code : specify the output encoding, which is UTF-8 by default.
  • +
  • -ol ltype : convert line feed characters, with `unix'(LF), `dos'(CRLF), and `mac'(CR).
  • +
  • -cn : detect the input encoding and show its name.
  • +
  • -wc : count the number of characters of the input string of UTF-8.
  • +
  • -um : output mappings of UCS-2 characters and C strings of UTF-16BE and UTF-8.
  • +
  • -wf : output in W3CDTF format.
  • +
  • -rf : output in RFC 1123 format.
  • +
  • -utc : output the coordinate universal time.
  • +
+ +

This command returns 0 on success, another on failure.

+ +
+ +

Villa: Advanced API

+ +

Overview

+ +

Villa is the advanced API of QDBM. It provides routines for managing a database file of B+ tree. Each record is stored being sorted in order defined by a user. As for hash databases, retrieving method is provided only as complete accord. However, with Villa, it is possible to retrieve records specified by range. Cursor is used in order to access each record in order. It is possible to store records duplicating keys in a database. Moreover, according to the transaction mechanism, you can commit or abort operations of a database in a lump.

+ +

Villa is implemented, based on Depot and Cabin. A database file of Villa is actual one of Depot. Although processing speed of retrieving and storing is slower than Depot, the size of a database is smaller.

+ +

In order to use Villa, you should include `depot.h', `cabin.h', `villa.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

+ +
+
#include <depot.h>
+
#include <cabin.h>
+
#include <villa.h>
+
#include <stdlib.h>
+
+ +

A pointer to `VILLA' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `vlopen' and closed with `vlclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `vlclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used. Before the cursor is used, it should be initialized by one of `vlcurfirst', `vlcurlast' or `vlcurjump'. Also after storing or deleting a record with functions except for `vlcurput' and `vlcurout', the cursor should be initialized.

+ +

Villa also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code.

+ +

API

+ +

You can define a comparing function to specify the order of records. The function should be the following type.

+ +
+
typedef int(*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz);
+
`aptr' specifies the pointer to the region of one key. `asiz' specifies the size of the region of one key. `bptr' specifies the pointer to the region of the other key. `bsiz' specifies the size of the region of the other key. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent.
+
+ +

The function `vlopen' is used in order to get a database handle.

+ +
+
VILLA *vlopen(const char *name, int omode, VLCFUNC cmp);
+
`name' specifies the name of a database file. `omode' specifies the connection mode: `VL_OWRITER' as a writer, `VL_OREADER' as a reader. If the mode is `VL_OWRITER', the following may be added by bitwise or: `VL_OCREAT', which means it creates a new database if not exist, `VL_OTRUNC', which means it creates a new database regardless if one exists, `VL_OZCOMP', which means leaves in the database are compressed with ZLIB, `VL_OYCOMP', which means leaves in the database are compressed with LZO, `VL_OXCOMP', which means leaves in the database are compressed with BZIP2. Both of `VL_OREADER' and `VL_OWRITER' can be added to by bitwise or: `VL_ONOLCK', which means it opens a database file without file locking, or `VL_OLCKNB', which means locking is performed without blocking. `cmp' specifies the comparing function: `VL_CMPLEX' comparing keys in lexical order, `VL_CMPINT' comparing keys as objects of `int' in native byte order, `VL_CMPNUM' comparing keys as numbers of big en dian, `VL_CMPDEC' comparing keys as decimal strings. Any function based on the declaration of the type `VLCFUNC' can be assigned to the comparing function. The comparing function should be kept same in the life of a database. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. `VL_OZCOMP', `VL_OYCOMP', and `VL_OXCOMP' are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `VL_ONOLCK' is used, the application is responsible for exclusion control.
+
+ +

The function `vlclose' is used in order to close a database handle.

+ +
+
int vlclose(VILLA *villa);
+
`villa' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. If the transaction is activated and not committed, it is aborted.
+
+ +

The function `vlput' is used in order to store a record.

+ +
+
int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
+
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `VL_DOVER', which means the specified value overwrites the existing one, `VL_DKEEP', which means the existing value is kept, `VL_DCAT', which means the specified value is concatenated at the end of the existing value, `VL_DDUP', which means duplication of keys is allowed and the specified value is added as the last one, `VL_DDUPR', which means duplication of keys is allowed and the specified value is added as the first one. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database.
+
+ +

The function `vlout' is used in order to delete a record.

+ +
+
int vlout(VILLA *villa, const char *kbuf, int ksiz);
+
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the first record of the same key is deleted. The cursor becomes unavailable due to updating database.
+
+ +

The function `vlget' is used in order to retrieve a record.

+ +
+
char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp);
+
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the value of the first record of the same key is selected. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `vlvsiz' is used in order to get the size of the value of a record.

+ +
+
int vlvsiz(VILLA *villa, const char *kbuf, int ksiz);
+
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. If multiple records correspond, the size of the first is returned.
+
+ +

The function `vlvnum' is used in order to get the number of records corresponding a key.

+ +
+
int vlvnum(VILLA *villa, const char *kbuf, int ksiz);
+
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the number of corresponding records. If no record corresponds, 0 is returned.
+
+ +

The function `vlputlist' is used in order to store plural records corresponding a key.

+ +
+
int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals);
+
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vals' specifies a list handle of values. The list should not be empty. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database.
+
+ +

The function `vloutlist' is used in order to delete all records corresponding a key.

+ +
+
int vloutlist(VILLA *villa, const char *kbuf, int ksiz);
+
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. The cursor becomes unavailable due to updating database.
+
+ +

The function `vlgetlist' is used in order to retrieve values of all records corresponding a key.

+ +
+
CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz);
+
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is a list handle of the values of the corresponding records, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
+
+ +

The function `vlgetcat' is used in order to retrieve concatenated values of all records corresponding a key.

+ +
+
char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp);
+
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the concatenated values of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `vlcurfirst' is used in order to move the cursor to the first record.

+ +
+
int vlcurfirst(VILLA *villa);
+
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database.
+
+ +

The function `vlcurlast' is used in order to move the cursor to the last record.

+ +
+
int vlcurlast(VILLA *villa);
+
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database.
+
+ +

The function `vlcurprev' is used in order to move the cursor to the previous record.

+ +
+
int vlcurprev(VILLA *villa);
+
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no previous record.
+
+ +

The function `vlcurnext' is used in order to move the cursor to the next record.

+ +
+
int vlcurnext(VILLA *villa);
+
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no next record.
+
+ +

The function `vlcurjump' is used in order to move the cursor to a position around a record.

+ +
+
int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode);
+
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `jmode' specifies detail adjustment: `VL_JFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `VL_JBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist. If successful, the return value is true, else, it is false. False is returned if there is no record corresponding the condition.
+
+ +

The function `vlcurkey' is used in order to get the key of the record where the cursor is.

+ +
+
char *vlcurkey(VILLA *villa, int *sp);
+
`villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the key of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `vlcurval' is used in order to get the value of the record where the cursor is.

+ +
+
char *vlcurval(VILLA *villa, int *sp);
+
`villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `vlcurput' is used in order to insert a record around the cursor.

+ +
+
int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode);
+
`villa' specifies a database handle connected as a writer. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `cpmode' specifies detail adjustment: `VL_CPCURRENT', which means that the value of the current record is overwritten, `VL_CPBEFORE', which means that a new record is inserted before the current record, `VL_CPAFTER', which means that a new record is inserted after the current record. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After insertion, the cursor is moved to the inserted record.
+
+ +

The function `vlcurout' is used in order to delete the record where the cursor is.

+ +
+
int vlcurout(VILLA *villa);
+
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After deletion, the cursor is moved to the next record if possible.
+
+ +

The function `vlsettuning' is used in order to set the tuning parameters for performance.

+ +
+
void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum);
+
`villa' specifies a database handle. `lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is not more than 0, the default value is specified. `nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is not more than 0, the default value is specified. `lcnum' specifies the max number of caching leaf nodes. If it is not more than 0, the default value is specified. `ncnum' specifies the max number of caching non-leaf nodes. If it is not more than 0, the default value is specified. The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning parameters are not saved in a database, you should specify them every opening a database.
+
+ +

The function `vlsetfbpsiz' is used in order to set the size of the free block pool of a database handle.

+ +
+
int vlsetfbpsiz(VILLA *villa, int size);
+
`villa' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 256. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
+
+ +

The function `vlsync' is used in order to synchronize updating contents with the file and the device.

+ +
+
int vlsync(VILLA *villa);
+
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database file. This function should not be used while the transaction is activated.
+
+ +

The function `vloptimize' is used in order to optimize a database.

+ +
+
int vloptimize(VILLA *villa);
+
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them. This function should not be used while the transaction is activated.
+
+ +

The function `vlname' is used in order to get the name of a database.

+ +
+
char *vlname(VILLA *villa);
+
`villa' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `vlfsiz' is used in order to get the size of a database file.

+ +
+
int vlfsiz(VILLA *villa);
+
`villa' specifies a database handle. If successful, the return value is the size of the database file, else, it is -1. Because of the I/O buffer, the return value may be less than the hard size.
+
+ +

The function `vllnum' is used in order to get the number of the leaf nodes of B+ tree.

+ +
+
int vllnum(VILLA *villa);
+
`villa' specifies a database handle. If successful, the return value is the number of the leaf nodes, else, it is -1.
+
+ +

The function `vlnnum' is used in order to get the number of the non-leaf nodes of B+ tree.

+ +
+
int vlnnum(VILLA *villa);
+
`villa' specifies a database handle. If successful, the return value is the number of the non-leaf nodes, else, it is -1.
+
+ +

The function `vlrnum' is used in order to get the number of the records stored in a database.

+ +
+
int vlrnum(VILLA *villa);
+
`villa' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1.
+
+ +

The function `vlwritable' is used in order to check whether a database handle is a writer or not.

+ +
+
int vlwritable(VILLA *villa);
+
`villa' specifies a database handle. The return value is true if the handle is a writer, false if not.
+
+ +

The function `vlfatalerror' is used in order to check whether a database has a fatal error or not.

+ +
+
int vlfatalerror(VILLA *villa);
+
`villa' specifies a database handle. The return value is true if the database has a fatal error, false if not.
+
+ +

The function `vlinode' is used in order to get the inode number of a database file.

+ +
+
int vlinode(VILLA *villa);
+
`villa' specifies a database handle. The return value is the inode number of the database file.
+
+ +

The function `vlmtime' is used in order to get the last modified time of a database.

+ +
+
time_t vlmtime(VILLA *villa);
+
`villa' specifies a database handle. The return value is the last modified time of the database.
+
+ +

The function `vltranbegin' is used in order to begin the transaction.

+ +
+
int vltranbegin(VILLA *villa);
+
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Because this function does not perform mutual exclusion control in multi-thread, the application is responsible for it. Only one transaction can be activated with a database handle at the same time.
+
+ +

The function `vltrancommit' is used in order to commit the transaction.

+ +
+
int vltrancommit(VILLA *villa);
+
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Updating a database in the transaction is fixed when it is committed successfully.
+
+ +

The function `vltranabort' is used in order to abort the transaction.

+ +
+
int vltranabort(VILLA *villa);
+
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Updating a database in the transaction is discarded when it is aborted. The state of the database is rollbacked to before transaction.
+
+ +

The function `vlremove' is used in order to remove a database file.

+ +
+
int vlremove(const char *name);
+
`name' specifies the name of a database file. If successful, the return value is true, else, it is false.
+
+ +

The function `vlrepair' is used in order to repair a broken database file.

+ +
+
int vlrepair(const char *name, VLCFUNC cmp);
+
`name' specifies the name of a database file. `cmp' specifies the comparing function of the database file. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database file correspond to the original or expected state.
+
+ +

The function `vlexportdb' is used in order to dump all records as endian independent data.

+ +
+
int vlexportdb(VILLA *villa, const char *name);
+
`villa' specifies a database handle. `name' specifies the name of an output file. If successful, the return value is true, else, it is false.
+
+ +

The function `vlimportdb' is used in order to load all records from endian independent data.

+ +
+
int vlimportdb(VILLA *villa, const char *name);
+
`villa' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input file. If successful, the return value is true, else, it is false.
+
+ +

Examples

+ +

The following example stores and retrieves a phone number, using the name as the key.

+ +
#include <depot.h>
+#include <cabin.h>
+#include <villa.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NAME     "mikio"
+#define NUMBER   "000-1234-5678"
+#define DBNAME   "book"
+
+int main(int argc, char **argv){
+  VILLA *villa;
+  char *val;
+
+  /* open the database */
+  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
+    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* store the record */
+  if(!vlput(villa, NAME, -1, NUMBER, -1, VL_DOVER)){
+    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
+  }
+
+  /* retrieve the record */
+  if(!(val = vlget(villa, NAME, -1, NULL))){
+    fprintf(stderr, "vlget: %s\n", dperrmsg(dpecode));
+  } else {
+    printf("Name: %s\n", NAME);
+    printf("Number: %s\n", val);
+    free(val);
+  }
+
+  /* close the database */
+  if(!vlclose(villa)){
+    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

The following example performs forward matching search for strings.

+ +
#include <depot.h>
+#include <cabin.h>
+#include <villa.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define DBNAME   "words"
+#define PREFIX   "apple"
+
+int main(int argc, char **argv){
+  VILLA *villa;
+  char *key, *val;
+
+  /* open the database */
+  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
+    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* store records */
+  if(!vlput(villa, "applet", -1, "little application", -1, VL_DDUP) ||
+     !vlput(villa, "aurora", -1, "polar wonderwork", -1, VL_DDUP) ||
+     !vlput(villa, "apple", -1, "delicious fruit", -1, VL_DDUP) ||
+     !vlput(villa, "amigo", -1, "good friend", -1, VL_DDUP) ||
+     !vlput(villa, "apple", -1, "big city", -1, VL_DDUP)){
+    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
+  }
+
+  /* set the cursor at the top of candidates */
+  vlcurjump(villa, PREFIX, -1, VL_JFORWARD);
+
+  /* scan with the cursor */
+  while((key = vlcurkey(villa, NULL)) != NULL){
+    if(strstr(key, PREFIX) != key){
+      free(key);
+      break;
+    }
+    if(!(val = vlcurval(villa, NULL))){
+      fprintf(stderr, "vlcurval: %s\n", dperrmsg(dpecode));
+      free(key);
+      break;
+    }
+    printf("%s: %s\n", key, val);
+    free(val);
+    free(key);
+    vlcurnext(villa);
+  }
+
+  /* close the database */
+  if(!vlclose(villa)){
+    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

Notes

+ +

How to build programs using Villa is the same as the case of Depot.

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Villa are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

+ +

Vista: Extended Advanced API

+ +

Vista is the extended API of Villa. To compensate for the defect that Villa can not handle a file whose size is more than 2GB, Vista does not use Depot but Curia for handling its internal database. While Vista provides data structure and operations of B+ tree as with Villa, its database is realized as a directory.

+ +

In order to use Vista, you should include `vista.h' instead of `villa.h'. Because Vista is implemented by overriding symbols of Villa, it can be used as with Villa. That is, Signatures of Villa and Vista is all the same. However, as its adverse effect, modules (compilation unit) using Vista can not use Villa (do not include `villa.h').

+ +
+ +

Commands for Villa

+ +

Villa has the following command line interfaces.

+ +

The command `vlmgr' is a utility for debugging Villa and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

+ +
+
vlmgr create [-cz|-cy|-cx] name
+
Create a database file.
+
vlmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat|-dup] name key val
+
Store a record with a key and a value.
+
vlmgr out [-l] [-kx|-ki] name key
+
Delete a record with a key.
+
vlmgr get [-nl] [-l] [-kx|-ki] [-ox] [-n] name key
+
Retrieve a record with a key and output it to the standard output.
+
vlmgr list [-nl] [-k|-v] [-kx|-ki] [-ox] [-top key] [-bot key] [-gt] [-lt] [-max num] [-desc] name
+
List all keys and values delimited with tab and line-feed to the standard output.
+
vlmgr optimize name
+
Optimize a database.
+
vlmgr inform [-nl] name
+
Output miscellaneous information to the standard output.
+
vlmgr remove name
+
Remove a database file.
+
vlmgr repair [-ki] name
+
Repair a broken database file.
+
vlmgr exportdb [-ki] name file
+
Dump all records as endian independent data.
+
vlmgr importdb [-ki] name file
+
Load all records from endian independent data.
+
vlmgr version
+
Output version information of QDBM to the standard output.
+
+ +

Options feature the following.

+ +
    +
  • -cz : compress leaves in the database with ZLIB.
  • +
  • -cy : compress leaves in the database with LZO.
  • +
  • -cx : compress leaves in the database with BZIP2.
  • +
  • -l : all records corresponding the key are dealt.
  • +
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • +
  • -ki : treat `key' as an integer expression of decimal notation.
  • +
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • +
  • -vi : treat `val' as an integer expression of decimal notation.
  • +
  • -vf : read the value from a file specified with `val'.
  • +
  • -keep : specify the storing mode for `VL_DKEEP'.
  • +
  • -cat : specify the storing mode for `VL_DCAT'.
  • +
  • -dup : specify the storing mode for `VL_DDUP'.
  • +
  • -nl : open the database without file locking.
  • +
  • -top key : specify the top key of listing.
  • +
  • -bot key : specify the bottom key of listing.
  • +
  • -gt : do not include the top key of listing.
  • +
  • -lt : do not include the bottom key of listing.
  • +
  • -max num : specify the max number of listing.
  • +
  • -desc : list in descending order.
  • +
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • +
  • -n : do not output the tailing newline.
  • +
  • -k : output keys only.
  • +
  • -v : output values only.
  • +
+ +

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

+ +

The command `vltest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of the records.

+ +
+
vltest write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum
+
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
+
vltest read [-int] [-vc] name
+
Retrieve all records of the database above.
+
vltest rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum pnum
+
Store records with partway duplicated keys using duplicate mode.
+
vltest combo [-cz|-cy|-cx] name
+
Perform combination test of various operations.
+
vltest wicked [-cz|-cy|-cx] name rnum
+
Perform updating operations selected at random.
+
+ +

Options feature the following.

+ +
    +
  • -int : treat keys and values as objects of `int', and use comparing function `VL_CMPINT'.
  • +
  • -cz : compress leaves in the database with ZLIB.
  • +
  • -cy : compress leaves in the database with LZO.
  • +
  • -cx : compress leaves in the database with BZIP2.
  • +
  • -vc : refer to volatile cache.
  • +
  • -cc : select `VL_DCAT' or `VL_DDUP' at random.
  • +
  • -tune lrecmax nidxmax lcnum ncnum : set tuning parameters.
  • +
  • -fbp num : set the size of the free block pool.
  • +
  • -c : perform comparison test with map of Cabin.
  • +
+ +

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

+ +

The command `vltsv' features mutual conversion between a database of Villa and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the following format. `name' specifies a database name. The subcommand `export' reads TSV data from the standard input. The subcommand `import' writes TSV data to the standard output.

+ +
+
vltsv import [-bin] name
+
Create a database from TSV.
+
vltsv export [-bin] name
+
Write TSV data of a database.
+
+ +

Options feature the following.

+ +
    +
  • -bin : treat records as Base64 format.
  • +
+ +

This command returns 0 on success, another on failure.

+ +

Commands of Villa realize a simple database system. For example, to make a database to search `/etc/password' by a user name, perform the following command.

+ +
cat /etc/passwd | tr ':' '\t' | vltsv import casket
+
+ +

Thus, to retrieve the information of a user `mikio', perform the following command.

+ +
vlmgr get casket mikio
+
+ +

It is easy to implement functions upsides with these commands, using the API of Villa.

+ +

The command `qmttest' checks multi-thread safety of Depot, Curia, and Villa. This command works with multi threads only if QDBM was built with POSIX thread. This command is used in the following format. `name' specifies the prefix of each database. `rnum' specifies the number of records to be stored in each database. `tnum' specifies the number of threads.

+ +
+
qmttest name rnum tnum
+
Check multi-thread safety.
+
+ +

This command returns 0 on success, another on failure.

+ +
+ +

Odeum: Inverted API

+ +

Overview

+ +

Odeum is the API which handles an inverted index. An inverted index is a data structure to retrieve a list of some documents that include one of words which were extracted from a population of documents. It is easy to realize a full-text search system with an inverted index. Odeum provides an abstract data structure which consists of words and attributes of a document. It is used when an application stores a document into a database and when an application retrieves some documents from a database.

+ +

Odeum does not provide methods to extract the text from the original data of a document. It should be implemented by applications. Although Odeum provides utilities to extract words from a text, it is oriented to such languages whose words are separated with space characters as English. If an application handles such languages which need morphological analysis or N-gram analysis as Japanese, or if an application perform more such rarefied analysis of natural languages as stemming, its own analyzing method can be adopted. Result of search is expressed as an array contains elements which are structures composed of the ID number of documents and its score. In order to search with two or more words, Odeum provides utilities of set operations.

+ +

Odeum is implemented, based on Curia, Cabin, and Villa. Odeum creates a database with a directory name. Some databases of Curia and Villa are placed in the specified directory. For example, `casket/docs', `casket/index', and `casket/rdocs' are created in the case that a database directory named as `casket'. `docs' is a database directory of Curia. The key of each record is the ID number of a document, and the value is such attributes as URI. `index' is a database directory of Curia. The key of each record is the normalized form of a word, and the value is an array whose element is a pair of the ID number of a document including the word and its score. `rdocs' is a database file of Villa. The key of each record is the URI of a document, and the value is its ID number.

+ +

In order to use Odeum, you should include `depot.h', `cabin.h', `odeum.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

+ +
+
#include <depot.h>
+
#include <cabin.h>
+
#include <odeum.h>
+
#include <stdlib.h>
+
+ +

A pointer to `ODEUM' is used as a database handle. A database handle is opened with the function `odopen' and closed with `odclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `odclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used.

+ +

A pointer to `ODDOC' is used as a document handle. A document handle is opened with the function `oddocopen' and closed with `oddocclose'. You should not refer directly to any member of the handle. A document consists of attributes and words. Each word is expressed as a pair of a normalized form and a appearance form.

+ +

Odeum also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code.

+ +

API

+ +

Structures of `ODPAIR' type is used in order to handle results of search.

+ +
+
typedef struct { int id; int score; } ODPAIR;
+
`id' specifies the ID number of a document. `score' specifies the score calculated from the number of searching words in the document.
+
+ +

The function `odopen' is used in order to get a database handle.

+ +
+
ODEUM *odopen(const char *name, int omode);
+
`name' specifies the name of a database directory. `omode' specifies the connection mode: `OD_OWRITER' as a writer, `OD_OREADER' as a reader. If the mode is `OD_OWRITER', the following may be added by bitwise or: `OD_OCREAT', which means it creates a new database if not exist, `OD_OTRUNC', which means it creates a new database regardless if one exists. Both of `OD_OREADER' and `OD_OWRITER' can be added to by bitwise or: `OD_ONOLCK', which means it opens a database directory without file locking, or `OD_OLCKNB', which means locking is performed without blocking. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `OD_ONOLCK' is used, the application is responsible for exclusion control.
+
+ +

The function `odclose' is used in order to close a database handle.

+ +
+
int odclose(ODEUM *odeum);
+
`odeum' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.
+
+ +

The function `odput' is used in order to store a document.

+ +
+
int odput(ODEUM *odeum, const ODDOC *doc, int wmax, int over);
+
`odeum' specifies a database handle connected as a writer. `doc' specifies a document handle. `wmax' specifies the max number of words to be stored in the document database. If it is negative, the number is unlimited. `over' specifies whether the data of the duplicated document is overwritten or not. If it is false and the URI of the document is duplicated, the function returns as an error. If successful, the return value is true, else, it is false.
+
+ +

The function `odout' is used in order to delete a document specified by a URI.

+ +
+
int odout(ODEUM *odeum, const char *uri);
+
`odeum' specifies a database handle connected as a writer. `uri' specifies the string of the URI of a document. If successful, the return value is true, else, it is false. False is returned when no document corresponds to the specified URI.
+
+ +

The function `odoutbyid' is used in order to delete a document specified by an ID number.

+ +
+
int odoutbyid(ODEUM *odeum, int id);
+
`odeum' specifies a database handle connected as a writer. `id' specifies the ID number of a document. If successful, the return value is true, else, it is false. False is returned when no document corresponds to the specified ID number.
+
+ +

The function `odget' is used in order to retrieve a document specified by a URI.

+ +
+
ODDOC *odget(ODEUM *odeum, const char *uri);
+
`odeum' specifies a database handle. `uri' specifies the string of the URI of a document. If successful, the return value is the handle of the corresponding document, else, it is `NULL'. `NULL' is returned when no document corresponds to the specified URI. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'.
+
+ +

The function `odgetbyid' is used in order to retrieve a document by an ID number.

+ +
+
ODDOC *odgetbyid(ODEUM *odeum, int id);
+
`odeum' specifies a database handle. `id' specifies the ID number of a document. If successful, the return value is the handle of the corresponding document, else, it is `NULL'. `NULL' is returned when no document corresponds to the specified ID number. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'.
+
+ +

The function `odgetidbyuri' is used in order to retrieve the ID of the document specified by a URI.

+ +
+
int odgetidbyuri(ODEUM *odeum, const char *uri);
+
`odeum' specifies a database handle. `uri' specifies the string the URI of a document. If successful, the return value is the ID number of the document, else, it is -1. -1 is returned when no document corresponds to the specified URI.
+
+ +

The function `odcheck' is used in order to check whether the document specified by an ID number exists.

+ +
+
int odcheck(ODEUM *odeum, int id);
+
`odeum' specifies a database handle. `id' specifies the ID number of a document. The return value is true if the document exists, else, it is false.
+
+ +

The function `odsearch' is used in order to search the inverted index for documents including a particular word.

+ +
+
ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np);
+
`odeum' specifies a database handle. `word' specifies a searching word. `max' specifies the max number of documents to be retrieve. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. If successful, the return value is the pointer to an array, else, it is `NULL'. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified word, it is not error but returns an dummy array. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document.
+
+ +

The function `odsearchnum' is used in order to get the number of documents including a word.

+ +
+
int odsearchdnum(ODEUM *odeum, const char *word);
+
`odeum' specifies a database handle. `word' specifies a searching word. If successful, the return value is the number of documents including the word, else, it is -1. Because this function does not read the entity of the inverted index, it is faster than `odsearch'.
+
+ +

The function `oditerinit' is used in order to initialize the iterator of a database handle.

+ +
+
int oditerinit(ODEUM *odeum);
+
`odeum' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access every document stored in a database.
+
+ +

The function `oditernext' is used in order to get the next key of the iterator.

+ +
+
ODDOC *oditernext(ODEUM *odeum);
+
`odeum' specifies a database handle. If successful, the return value is the handle of the next document, else, it is `NULL'. `NULL' is returned when no document is to be get out of the iterator. It is possible to access every document by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of string matches the one of the traversal access. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'.
+
+ +

The function `odsync' is used in order to synchronize updating contents with the files and the devices.

+ +
+
int odsync(ODEUM *odeum);
+
`odeum' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database directory.
+
+ +

The function `odoptimize' is used in order to optimize a database.

+ +
+
int odoptimize(ODEUM *odeum);
+
`odeum' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Elements of the deleted documents in the inverted index are purged.
+
+ +

The function `odname' is used in order to get the name of a database.

+ +
+
char *odname(ODEUM *odeum);
+
`odeum' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `odfsiz' is used in order to get the total size of database files.

+ +
+
double odfsiz(ODEUM *odeum);
+
`odeum' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1.0.
+
+ +

The function `odbnum' is used in order to get the total number of the elements of the bucket arrays in the inverted index.

+ +
+
int odbnum(ODEUM *odeum);
+
`odeum' specifies a database handle. If successful, the return value is the total number of the elements of the bucket arrays, else, it is -1.
+
+ +

The function `odbusenum' is used in order to get the total number of the used elements of the bucket arrays in the inverted index.

+ +
+
int odbusenum(ODEUM *odeum);
+
`odeum' specifies a database handle. If successful, the return value is the total number of the used elements of the bucket arrays, else, it is -1.
+
+ +

The function `oddnum' is used in order to get the number of the documents stored in a database.

+ +
+
int oddnum(ODEUM *odeum);
+
`odeum' specifies a database handle. If successful, the return value is the number of the documents stored in the database, else, it is -1.
+
+ +

The function `odwnum' is used in order to get the number of the words stored in a database.

+ +
+
int odwnum(ODEUM *odeum);
+
`odeum' specifies a database handle. If successful, the return value is the number of the words stored in the database, else, it is -1. Because of the I/O buffer, the return value may be less than the hard number.
+
+ +

The function `odwritable' is used in order to check whether a database handle is a writer or not.

+ +
+
int odwritable(ODEUM *odeum);
+
`odeum' specifies a database handle. The return value is true if the handle is a writer, false if not.
+
+ +

The function `odfatalerror' is used in order to check whether a database has a fatal error or not.

+ +
+
int odfatalerror(ODEUM *odeum);
+
`odeum' specifies a database handle. The return value is true if the database has a fatal error, false if not.
+
+ +

The function `odinode' is used in order to get the inode number of a database directory.

+ +
+
int odinode(ODEUM *odeum);
+
`odeum' specifies a database handle. The return value is the inode number of the database directory.
+
+ +

The function `odmtime' is used in order to get the last modified time of a database.

+ +
+
time_t odmtime(ODEUM *odeum);
+
`odeum' specifies a database handle. The return value is the last modified time of the database.
+
+ +

The function `odmerge' is used in order to merge plural database directories.

+ +
+
int odmerge(const char *name, const CBLIST *elemnames);
+
`name' specifies the name of a database directory to create. `elemnames' specifies a list of names of element databases. If successful, the return value is true, else, it is false. If two or more documents which have the same URL come in, the first one is adopted and the others are ignored.
+
+ +

The function `odremove' is used in order to remove a database directory.

+ +
+
int odremove(const char *name);
+
`name' specifies the name of a database directory. If successful, the return value is true, else, it is false. A database directory can contain databases of other APIs of QDBM, they are also removed by this function.
+
+ +

The function `oddocopen' is used in order to get a document handle.

+ +
+
ODDOC *oddocopen(const char *uri);
+
`uri' specifies the URI of a document. The return value is a document handle. The ID number of a new document is not defined. It is defined when the document is stored in a database.
+
+ +

The function `oddocclose' is used in order to close a document handle.

+ +
+
void oddocclose(ODDOC *doc);
+
`doc' specifies a document handle. Because the region of a closed handle is released, it becomes impossible to use the handle.
+
+ +

The function `oddocaddattr' is used in order to add an attribute to a document.

+ +
+
void oddocaddattr(ODDOC *doc, const char *name, const char *value);
+
`doc' specifies a document handle. `name' specifies the string of the name of an attribute. `value' specifies the string of the value of the attribute.
+
+ +

The function `oddocaddword' is used in order to add a word to a document.

+ +
+
void oddocaddword(ODDOC *doc, const char *normal, const char *asis);
+
`doc' specifies a document handle. `normal' specifies the string of the normalized form of a word. Normalized forms are treated as keys of the inverted index. If the normalized form of a word is an empty string, the word is not reflected in the inverted index. `asis' specifies the string of the appearance form of the word. Appearance forms are used after the document is retrieved by an application.
+
+ +

The function `oddocid' is used in order to get the ID number of a document.

+ +
+
int oddocid(const ODDOC *doc);
+
`doc' specifies a document handle. The return value is the ID number of a document.
+
+ +

The function `oddocuri' is used in order to get the URI of a document.

+ +
+
const char *oddocuri(const ODDOC *doc);
+
`doc' specifies a document handle. The return value is the string of the URI of a document.
+
+ +

The function `oddocgetattr' is used in order to get the value of an attribute of a document.

+ +
+
const char *oddocgetattr(const ODDOC *doc, const char *name);
+
`doc' specifies a document handle. `name' specifies the string of the name of an attribute. The return value is the string of the value of the attribute, or `NULL' if no attribute corresponds.
+
+ +

The function `oddocnwords' is used in order to get the list handle contains words in normalized form of a document.

+ +
+
const CBLIST *oddocnwords(const ODDOC *doc);
+
`doc' specifies a document handle. The return value is the list handle contains words in normalized form.
+
+ +

The function `oddocawords' is used in order to get the list handle contains words in appearance form of a document.

+ +
+
const CBLIST *oddocawords(const ODDOC *doc);
+
`doc' specifies a document handle. The return value is the list handle contains words in appearance form.
+
+ +

The function `oddocscores' is used in order to get the map handle contains keywords in normalized form and their scores.

+ +
+
CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum);
+
`doc' specifies a document handle. `max' specifies the max number of keywords to get. `odeum' specifies a database handle with which the IDF for weighting is calculate. If it is `NULL', it is not used. The return value is the map handle contains keywords and their scores. Scores are expressed as decimal strings. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use.
+
+ +

The function `odbreaktext' is used in order to break a text into words in appearance form.

+ +
+
CBLIST *odbreaktext(const char *text);
+
`text' specifies the string of a text. The return value is the list handle contains words in appearance form. Words are separated with space characters and such delimiters as period, comma and so on. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.
+
+ +

The function `odnormalizeword' is used in order to make the normalized form of a word.

+ +
+
char *odnormalizeword(const char *asis);
+
`asis' specifies the string of the appearance form of a word. The return value is is the string of the normalized form of the word. Alphabets of the ASCII code are unified into lower cases. Words composed of only delimiters are treated as empty strings. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `odpairsand' is used in order to get the common elements of two sets of documents.

+ +
+
ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
+
`apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements commonly belong to the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `odpairsor' is used in order to get the sum of elements of two sets of documents.

+ +
+
ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
+
`apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements belong to both or either of the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `odpairsnotand' is used in order to get the difference set of documents.

+ +
+
ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
+
`apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array of the sum of elements. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements belong to the former set but not to the latter set. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.
+
+ +

The function `odpairssort' is used in order to sort a set of documents in descending order of scores.

+ +
+
void odpairssort(ODPAIR *pairs, int pnum);
+
`pairs' specifies the pointer to a document array. `pnum' specifies the number of the elements of the document array.
+
+ +

The function `odlogarithm' is used in order to get the natural logarithm of a number.

+ +
+
double odlogarithm(double x);
+
`x' specifies a number. The return value is the natural logarithm of the number. If the number is equal to or less than 1.0, the return value is 0.0. This function is useful when an application calculates the IDF of search results.
+
+ +

The function `odvectorcosine' is used in order to get the cosine of the angle of two vectors.

+ +
+
double odvectorcosine(const int *avec, const int *bvec, int vnum);
+
`avec' specifies the pointer to one array of numbers. `bvec' specifies the pointer to the other array of numbers. `vnum' specifies the number of elements of each array. The return value is the cosine of the angle of two vectors. This function is useful when an application calculates similarity of documents.
+
+ +

The function `odsettuning' is used in order to set the global tuning parameters.

+ +
+
void odsettuning(int ibnum, int idnum, int cbnum, int csiz);
+
`ibnum' specifies the number of buckets for inverted indexes. `idnum' specifies the division number of inverted index. `cbnum' specifies the number of buckets for dirty buffers. `csiz' specifies the maximum bytes to use memory for dirty buffers. The default setting is equivalent to `odsettuning(32749, 7, 262139, 8388608)'. This function should be called before opening a handle.
+
+ +

The function `odanalyzetext' is used in order to break a text into words and store appearance forms and normalized form into lists.

+ +
+
void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords);
+
`odeum' specifies a database handle. `text' specifies the string of a text. `awords' specifies a list handle into which appearance form is store. `nwords' specifies a list handle into which normalized form is store. If it is `NULL', it is ignored. Words are separated with space characters and such delimiters as period, comma and so on.
+
+ +

The function `odsetcharclass' is used in order to set the classes of characters used by `odanalyzetext'.

+ +
+
void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars);
+
`odeum' specifies a database handle. `spacechars' spacifies a string contains space characters. `delimchars' spacifies a string contains delimiter characters. `gluechars' spacifies a string contains glue characters.
+
+ +

The function `odquery' is used in order to query a database using a small boolean query language.

+ +
+
ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors);
+
`odeum' specifies a database handle. 'query' specifies the text of the query. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. `errors' specifies a list handle into which error messages are stored. If it is `NULL', it is ignored. If successful, the return value is the pointer to an array, else, it is `NULL'. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified condition, it is not error but returns an dummy array. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document.
+
+ +

Examples

+ +

The following example stores a document into the database.

+ +
#include <depot.h>
+#include <cabin.h>
+#include <odeum.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define DBNAME   "index"
+
+int main(int argc, char **argv){
+  ODEUM *odeum;
+  ODDOC *doc;
+  CBLIST *awords;
+  const char *asis;
+  char *normal;
+  int i;
+
+  /* open the database */
+  if(!(odeum = odopen(DBNAME, OD_OWRITER | OD_OCREAT))){
+    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* get the document handle */
+  doc = oddocopen("http://www.foo.bar/baz.txt");
+
+  /* set attributes of the document */
+  oddocaddattr(doc, "title", "Balcony Scene");
+  oddocaddattr(doc, "author", "Shakespeare");
+
+  /* break the text and get the word list */
+  awords = odbreaktext("Parting is such sweet sorrow.");
+
+  /* set each word into the document handle */
+  for(i = 0; i < cblistnum(awords); i++){
+    /* get one word of the list */
+    asis = cblistval(awords, i, NULL);
+    /* get the normalized form from the appearance form */
+    normal = odnormalizeword(asis);
+    /* add the word into the document handle */
+    oddocaddword(doc, normal, asis);
+    /* release the region of the normalized form */
+    free(normal);
+  }
+
+  /* store the document into the database */
+  if(!odput(odeum, doc, -1, 1)){
+    fprintf(stderr, "odput: %s\n", dperrmsg(dpecode));
+  }
+
+  /* release the word list */
+  cblistclose(awords);
+
+  /* release the document handle */
+  oddocclose(doc);
+
+  /* close the database */
+  if(!odclose(odeum)){
+    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

The following example retrieves documents.

+ +
#include <depot.h>
+#include <cabin.h>
+#include <odeum.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define DBNAME   "index"
+
+int main(int argc, char **argv){
+  ODEUM *odeum;
+  ODPAIR *pairs;
+  ODDOC *doc;
+  const CBLIST *words;
+  const char *title, *author, *asis;
+  int i, j, pnum;
+
+  /* open the database */
+  if(!(odeum = odopen(DBNAME, OD_OREADER))){
+    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  /* retrieve documents */
+  if((pairs = odsearch(odeum, "sorrow", -1, &pnum)) != NULL){
+
+    /* scan each element of the document array */
+    for(i = 0; i < pnum; i++){
+      /* get the document handle */
+      if(!(doc = odgetbyid(odeum, pairs[i].id))) continue;
+      /* show the attributes */
+      printf("URI: %s\n", oddocuri(doc));
+      title = oddocgetattr(doc, "title");
+      if(title) printf("TITLE: %s\n", title);
+      author = oddocgetattr(doc, "author");
+      if(author) printf("AUTHOR: %s\n", author);
+      /* show words in appearance form */
+      printf("WORDS:");
+      words = oddocawords(doc);
+      for(j = 0; j < cblistnum(words); j++){
+        asis = cblistval(words, j, NULL);
+        printf(" %s", asis);
+      }
+      putchar('\n');
+      /* release the document handle */
+      oddocclose(doc);
+    }
+
+    /* release the document array */
+    free(pairs);
+
+  } else {
+    fprintf(stderr, "odsearch: %s\n", dperrmsg(dpecode));
+  }
+
+  /* close the database */
+  if(!odclose(odeum)){
+    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
+    return 1;
+  }
+
+  return 0;
+}
+
+ +

Notes

+ +

How to build programs using Odeum is the same as the case of Depot.

+ +
gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm
+
+ +

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Odeum are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

+ +

If QDBM was built with ZLIB enabled, records in the database for document attributes are compressed. In that case, the size of the database is reduced to 30% or less. Thus, you should enable ZLIB if you use Odeum. A database of Odeum created without ZLIB enabled is not available on environment with ZLIB enabled, and vice versa. If ZLIB was not enabled but LZO, LZO is used instead.

+ +

Query Language

+ +

The query language of the function `odquery' is a basic language following this grammar:

+ +
expr ::= subexpr ( op subexpr )*
+subexpr ::= WORD
+subexpr ::= LPAREN expr RPAREN
+
+ +

Operators are "&" (AND), "|" (OR), and "!" (NOTAND). You can use parenthesis to group sub-expressions together in order to change order of operations. The given query is broken up using the function `odanalyzetext', so if you want to specify different text breaking rules, then make sure that you at least set "&", "|", "!", "(", and ")" to be delimiter characters. Consecutive words are treated as having an implicit "&" operator between them, so "zed shaw" is actually "zed & shaw".

+ +

The encoding of the query text should be the same with the encoding of target documents. Moreover, each of space characters, delimiter characters, and glue characters should be single byte.

+ +
+ +

Commands for Odeum

+ +

Odeum has the following command line interfaces.

+ +

The command `odmgr' is a utility for debugging Odeum and its applications. It features editing and checking of a database. It can be used for full-text search systems with shell scripts. This command is used in the following format. `name' specifies a database name. `file' specifies a file name, `expr' specifies the URI or the ID number of a document, `words' specifies searching words. `elems' specifies element databases.

+ +
+
odmgr create name
+
Create a database file.
+
odmgr put [-uri str] [-title str] [-author str] [-date str] [-wmax num] [-keep] name [file]
+
Add a document by reading a file. If `file' is omitted, the standard input is read and URI is needed.
+
odmgr out [-id] name expr
+
Delete a document specified by a URI.
+
odmgr get [-id] [-t|-h] name expr
+
Show a document specified by a URI. The output is the ID number and the URI of a document, in tab separated format.
+
odmgr search [-max num] [-or] [-idf] [-t|-h|-n] name words...
+
Retrieve documents including specified words. The first line of the output is the total number of hits and each word with its number of hits, in tab separated format. The second line and below are the ID numbers and the scores of documents, in tab separated format.
+
odmgr list [-t|-h] name
+
Show all documents in a database. Each line of the output is the ID number and the score of a document, in tab separated format.
+
odmgr optimize name
+
Optimize a database.
+
odmgr inform name
+
Output miscellaneous information.
+
odmgr merge name elems...
+
Merge plural databases.
+
odmgr remove name
+
Remove a database directory.
+
odmgr break [-h|-k|-s] [file]
+
Read a file and output words in the text. Each line of the output is the appearance form and the normalized form of a word, in tab separated format.
+
odmgr version
+
Output version information of QDBM.
+
+ +

Options feature the following.

+ +
    +
  • -uri str : specify the URI of the document explicitly.
  • +
  • -title str : specify the title of the document.
  • +
  • -author str : specify the author of the document.
  • +
  • -date str : specify the modified date of the document.
  • +
  • -wmax num : specify the max number of words to be stored.
  • +
  • -keep : the storing mode is not to be overwrite.
  • +
  • -id : specify a document not by a URI but by an ID number.
  • +
  • -t : output the details of a document in tab separated format.
  • +
  • -h : output the details of a document in human-readable format.
  • +
  • -k : output keywords of a document.
  • +
  • -s : output summary of a document.
  • +
  • -max num : specify the max number of documents of the output.
  • +
  • -or : perform OR search, nut AND search.
  • +
  • -idf : tune scores with IDF.
  • +
  • -n : show ID numbers and scores only.
  • +
+ +

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

+ +

The command `odtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `dnum' specifies the number of the documents. `wnum' specifies the number of words per document. `pnum' specifies the number of patterns of words.

+ +
+
odtest write [-tune ibnum idnum cbnum csiz] name dnum wnum pnum
+
Store documents with random attributes and random words.
+
odtest read name
+
Retrieve all documents of the database above.
+
odtest combo name
+
Perform combination test of various operations.
+
odtest wicked name dnum
+
Perform updating operations selected at random.
+
+ +

Options feature the following.

+ +
    +
  • -tune ibnum idnum cbnum csiz : set tuning parameters.
  • +
+ +

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

+ +

The command `odidx' is a utility for indexing files on the local file system. This command is useful for a full-text search system of a Web site. Supported file format are plain text and HTML. Supported character encoding are US-ASCII and ISO-8859-1. The URI of each document is specified with the path of its file. Attributes named as `title' and `date' are given to each documents. When a document is already existing in the database, it is registered if its last modification time is newer, or it is ignored. Modification times are stored in the sub database `_mtime' in the main database directory. Score information are stored in the sub database `_score' in the main database directory. This command is used in the following format. `name' specifies a database name. `dir' specifies a directory name.

+ +
+
odidx register [-l file] [-wmax num] [-tsuf sufs] [-hsuf sufs] name [dir]
+
Register files in the specified directory. If `dir' is omitted, the current directory is specified.
+
odidx relate name
+
Add score information for relational document search to each documents in the database.
+
odidx purge name
+
Purge documents which are not existing on the local files system.
+
+ +

Options feature the following.

+ +
    +
  • -l file : read a file and get list of paths of files to register. If `-' is specified, the standard input is read.
  • +
  • -wmax num : specify the max number of words to be stored in the document database.
  • +
  • -tsuf sufs : specify suffixes of plain text files in comma separated format. The default is `-tsuf .txt,.text'.
  • +
  • -hsuf sufs : specify suffixes of HTML files in comma separated format. The default is `-hsuf .html,.htm'.
  • +
+ +

This command returns 0 on success, another on failure.

+ +

Commands of Odeum make it easy to realize a full-text search system. For example, to register files which are under `/home/mikio' and whose suffix are `.txt', `.c', or `.h', perform the following command.

+ +
odidx register -tsuf ".txt,.c,.h" -hsuf "" casket /home/mikio
+
+ +

Thus, to retrieve documents which include `unix' and `posix' and show the top 8 terms, perform the following command.

+ +
odmgr search -max 8 -h casket "unix posix"
+
+ +

A database generated by `odidx' is available with the CGI script which is included in QDBM for full-text search.

+ +
+ +

File Format

+ +

File Format of Depot

+ +

The contents of a database file managed by Depot is divided roughly into the following three sections: the header section, the bucket section and the record section.

+ +

The header section places at the beginning of the file and its length is constant 48 bytes. The following information are stored in the header section.

+ +
    +
  1. magic number: from offset 0, contains "[DEPOT]\n\f" for big endian or "[depot]\n\f" for little endian.
  2. +
  3. version number: decimal string of the version number of the library.
  4. +
  5. flags for wrappers: from offset 16, type of `int'.
  6. +
  7. file size: from offset 24, type of `int'.
  8. +
  9. number of the bucket: from offset 32, type of `int'.
  10. +
  11. number of records: from offset 40, type of `int'.
  12. +
+ +

The bucket section places after the header section and its length is determined according to the number of the bucket. Each element of the bucket stores an offset of the root node of each separate chain.

+ +

The record section places after the bucket section and occupies to the end of the file. The element of the record section contains the following information.

+ +
    +
  1. flags: type of `int'.
  2. +
  3. second hash value: type of `int'.
  4. +
  5. size of the key: type of `int'.
  6. +
  7. size of the value: type of `int'.
  8. +
  9. size of the padding: type of `int'.
  10. +
  11. offset of the left child: type of `int'.
  12. +
  13. offset of the right child: type of `int'.
  14. +
  15. entity of the key: serial bytes with variable length.
  16. +
  17. entity of the value: serial bytes with variable length.
  18. +
  19. padding data: void serial bytes with variable length.
  20. +
+ +

File Format of Villa

+ +

Every data handled by Villa is stored in a database of Depot. Storing data is divided into meta data and logical pages. Logical pages can be classified into leaf nodes and non-leaf nodes. Meta data are such managing information as the number of records. Both of its key and its value are type of `int'. Leaf nodes hold records. Non-leaf nodes hold sparse index referring to pages.

+ +

Villa uses variable length numeric format (BER compression) to handle small natural number with frugal storage. A variable length numeric object is parsed from the top of the region and parsing ends at the byte of positive value. Each byte are evaluated as absolute value and calculated as little endian number based on the radix 128.

+ +

Record is logical unit of user data. Some records overlapping keys are shaped into one physical record. A Physical record is serialized in the following format.

+ +
    +
  1. size of the key: type of variable length number
  2. +
  3. entity of the key: serial bytes with variable length
  4. +
  5. number of values: type of variable length number
  6. +
  7. list of values: serial bytes repeating the following expressions
      +
    1. size: type of variable length number
    2. +
    3. entity of the key: serial bytes with variable length
    4. +
  8. +
+ +

Leaf node is physical unit to store a set of records. The key of a leaf node is its ID whose type is `int'. A leaf node is stored in a database of Depot with the following values. Its records are sorted in ascending order of each key.

+ +
    +
  1. ID of the previous leaf: type of variable length number
  2. +
  3. ID of the next leaf: type of variable length number
  4. +
  5. list of records: concatenation of serialized records
  6. +
+ +

Index is logical unit of a pointer to search for pages. An index is serialized int the following format.

+ +
    +
  1. ID of the referring page: type of variable length number
  2. +
  3. size of the key: type of variable length number
  4. +
  5. entity of the key: serial bytes with variable length
  6. +
+ +

Non-leaf node is physical unit to store a set of indexes. The key of a non-leaf node is its ID whose type is `int'. A non-leaf node is stored in a database of Depot with the following values. Its indexes are sorted in ascending order of each key.

+ +
    +
  1. ID of the first child node: type of variable length number
  2. +
  3. list of indexes: concatenation of serialized indexes
  4. +
+ +

Notes

+ +

Because the database file is not sparse, move, copy, unlink, ftp, and so on with the file are possible. Because Depot reads and writes data without normalization of byte order, it is impossible to share the same file between the environment with different byte order.

+ +

When you distribute a database file of Depot or Villa via network, the MIME type suggested to be `application/x-qdbm'. Suffix of the file name is suggested to be `.qdb'. When you distribute a database directory of Curia, you may convert the directory tree to an archive of such type as TAR.

+ +

For the command `file' to recognize database files, append the following expressions into `magic' file.

+ +
0       string          [DEPOT]\n\f     QDBM, big endian
+>12     string          x               \b, version=%s
+>19     byte            ^1              \b, Hash
+>19     byte            &1              \b, B+ tree
+>19     byte            &2              \b (deflated:ZLIB)
+>19     byte            &4              \b (deflated:LZO)
+>19     byte            &8              \b (deflated:BZIP2)
+>24     belong          x               \b, filesize=%d
+>32     belong          x               \b, buckets=%d
+>40     belong          x               \b, records=%d
+0       string          [depot]\n\f     QDBM, little endian
+>12     string          x               \b, version=%s
+>16     byte            ^1              \b, Hash
+>16     byte            &1              \b, B+ tree
+>16     byte            &2              \b (deflated:ZLIB)
+>16     byte            &4              \b (deflated:LZO)
+>16     byte            &8              \b (deflated:BZIP2)
+>24     lelong          x               \b, filesize=%d
+>32     lelong          x               \b, buckets=%d
+>40     lelong          x               \b, records=%d
+
+ +
+ +

Porting

+ +

One of the goal of QDBM is to work on all platforms which conform to POSIX. Even if some APIs are not implemented, QDBM should work. Moreover, it should be possible to build QDBM using compilers other than GCC. Porting to various platforms is performed to add a new `Makefile' or modify some parts of source files. As for APIs of C, some of the following files should be modified. Otherwise, you can create new files based on them.

+ +
    +
  • Makefile.in : base of `Makefile', used by `./configure'.
  • +
  • myconf.h : configuration of system dependency.
  • +
  • depot.h : header of the basic API.
  • +
  • curia.h : header of the extended API.
  • +
  • relic.h : header of the NDBM-compatible API.
  • +
  • hovel.h : header of the GDBM-compatible API.
  • +
  • cabin.h : header of the utility API.
  • +
  • villa.h : header of the advanced API.
  • +
  • vista.h : header of the extended advanced API.
  • +
  • odeum.h : header of the inverted API.
  • +
  • myconf.c : implementation of system dependency.
  • +
  • depot.c : implementation of the basic API.
  • +
  • curia.c : implementation of the extended API.
  • +
  • relic.c : implementation of the NDBM-compatible API.
  • +
  • hovel.c : implementation of the GDBM-compatible API.
  • +
  • cabin.c : implementation of the utility API.
  • +
  • villa.c : implementation of the advanced API.
  • +
  • vista.c : implementation of the extended advanced API.
  • +
  • odeum.c : implementation of the inverted API.
  • +
+ +

On platforms which do not support file locking with `fcntl' call, you should append `-DMYNOLOCK' to the macro `CFLAGS' defined in `Makefile'. In that case, you should consider another exclusion control. As with it, on platforms without `mmap' call, you should append `-DMYNOMMAP' to `CFLAGS'. As for `mmap', its emulation using `malloc' and so on is provided. If other system calls are not implemented, you should define emulation by modification of `myconf.h' and `myconf.c'.

+ +

Because POSIX thread is used in C++ API, it is impossible to port C++ API to platforms without the package. Because JNI is used in Java API, you should pay attention to location of the headers and libraries. Moreover, you should consider such type definitions as `long long' or `int64'. Because APIs of Perl and Ruby use building commands provided with each language system, you should be knowledgeable about their specifications.

+ +
+ +

Bugs

+ +

Each document of QDBM should be calibrated by native English speakers.

+ +

There is no such bug which are found but not fixed, as crash by segmentation fault, unexpected data vanishing, memory leak and so on.

+ +

If you find any bug, report it to the author, with the information of the version of QDBM, the operating system and the compiler.

+ +

Databases created with QDBM version 1.7.13 or earlier are not compatible to ones of the later versions.

+ +
+ +

Frequently Asked Questions

+ +
+
Q. : Does QDBM support SQL?
+
A. : No, it does not. QDBM is not a RDBMS (Relational Database Management System). If you want an embedded RDBMS, use SQLite and so on.
+
Q. : After all, how different from GDBM (NDBM, SDBM, Berkeley DB)?
+
A. : Processing speed is higher, a database file is smaller, API is simpler. A highly important thing is that efficiency in time and space is very good when records are frequently overwritten, so, scalability in practical use is high. Moreover, even when constructing such a large database that the number of storing record is more than one million, processing speed does not slowdown deathly, filesize does not grow extremely. However, because other DBM or DBMS may be more suitable in some cases, comparing performance and functionality by yourself is suggested.
+
Q. : Which API should I use?
+
A. : If you search for records as complete accord, try Depot. If the scale is large, try Curia. If you access records in some order, try Villa. If the scale is large, try Vista. If you pursue the greatest number of records, build QDBM with ZLIB or LZO enabled and use Vista.
+
Q. : What is bibliography?
+
A. : Algorithms of QDBM are mainly based on the descriptions in `Data Structures and Algorithms' by Aho et al and `Algorithms in C' by Sedgewick.
+
Q. : Are there good sample codes for applications?
+
A. : Refer to the source code of commands of each API. `dptsv.c', `crtsv.c' and `vltsv.c' are simplest.
+
Q. : My database file has been broken. Why?
+
A. : In most cases, the reason is that your application did not close the database on exit. No matter whether it is a demon process or a CGI script, any application should close handling databases when it exits. Moreover, we should remember that a process of CGI may be killed by SIGPIPE or SIGTERM.
+
Q. : How robust are databases of QDBM?
+
A. : QDBM does not assure absolute robustness. A database may be broken if your operating system crashes. Although transaction of Villa can save a database from crashes of applications, it is inadequate to crashes of operating systems. So, you should consider multiplexing of a database or backup system if you use QDBM for mission critical applications.
+
Q: How should I use alignment of Depot and Curia?
+
A: If your application repeats writing with overwrite or concatenate mode. Alignment saves the rapid growth of the size of the database file. Because the best suited size of alignment of each application is different, you should learn it by experiment. For the meantime, about 32 is suitable.
+
Q. : How should I tune performance parameters of Villa?
+
A. : If you perform mainly ordering access, `lrecmax' and `nidxmax' should be larger. If you perform mainly random access, they should be less. If RAM of your system is abundant, `lcnum' and `ncnum' should be increased in order to improve performance. If ZLIB, LZO, or BZIP2 is enabled, increase `lrecmax' and compression efficiency is improved.
+
Q. : Which is the most preferable of ZLIB, LZO or BZIP2 for Villa?
+
A. : BZIP2 has the best compression retio. LZO has the best compression speed. ZLIB takes a mean position of them. If you don't have any special reason, using ZLIB is suggested. However, if updating of the database is frequent, LZO is more preferable. If updating of the database is very infrequently, BZIP2 is more preferable. Note that the license of LZO is the GNU LGPL.
+
Q. : What is `sparse file'?
+
A. : It is a file where some holes are. `Hole' means a block where any data has never written in. If a file system supports sparse file, holes are not allocated into any physical storage. As for QDBM, if a database is created with such flags as DP_OSPARSE, the bucket array is not initialized and its blocks become holes. According to that mechanism, you can use greatly huge hash tables. However, its performance is strongly depends on the setting of the file system.
+
Q. : Why Depot and Curia do not feature transaction?
+
A. : If an application implements its own transaction, inner transaction of database is superfluous. You can implement transaction for application easily with hash map provided by Cabin.
+
Q. : How should I tune the system for performance?
+
A. : Install more RAM on your machine than the size of a database. Then, enlarge I/O buffer and cut down on flushing dirty buffers. File system is also important. On Linux, although EXT2 is usually fastest, EXT3 is faster in some cases. ReiserFS is okey. The other modes of EXT3 are very slow. About other file systems, you should learn them by experiment.
+
Q. : Can I build QDBM using `cc' instead of `gcc'?
+
A. : Yes. Try to build QDBM with `LTmakefile'.
+
Q. : Can I build QDBM using Visual C++?
+
A. : Yes. Use `VCmakefile' instead of `Makefile'.
+
Q. : Can I use QDBM in other languages?
+
A. : As for PHP, Scheme (Gauche), and OCaml, interfaces of QDBM have been released. If you need it for another language, try to turn it out.
+
Q. : What does `QDBM' mean?
+
A. : `QDBM' stands for `Quick Database Manager'. It means that processing speed is high, and that you can write applications quickly.
+
+ +
+ +

Copying

+ +

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 (See the file `COPYING'); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

+ +

QDBM was written by Mikio Hirabayashi. You can contact the author by e-mail to `mikio at users.sourceforge.net'. However, as for topics which can be shared among other users, please send it to the mailing list. To join the mailing list, refer to `http://lists.sourceforge.net/lists/listinfo/qdbm-users'.

+ +
+ + + + + + Deleted: box/trunk/qdbm/villa.c =================================================================== --- box/trunk/qdbm/villa.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/villa.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,2666 +0,0 @@ -/************************************************************************************************* - * Implementation of Villa - * 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. - *************************************************************************************************/ - - -#define QDBM_INTERNAL 1 - -#include "villa.h" -#include "myconf.h" - -#define VL_LEAFIDMIN 1 /* minimum number of leaf ID */ -#define VL_NODEIDMIN 100000000 /* minimum number of node ID */ -#define VL_VNUMBUFSIZ 8 /* size of a buffer for variable length number */ -#define VL_NUMBUFSIZ 32 /* size of a buffer for a number */ -#define VL_PAGEBUFSIZ 32768 /* size of a buffer to read each page */ -#define VL_MAXLEAFSIZ 49152 /* maximum size of each leaf */ -#define VL_DEFLRECMAX 49 /* default number of records in each leaf */ -#define VL_DEFNIDXMAX 192 /* default number of indexes in each node */ -#define VL_DEFLCNUM 1024 /* default number of leaf cache */ -#define VL_DEFNCNUM 512 /* default number of node cache */ -#define VL_CACHEOUT 8 /* number of pages in a process of cacheout */ -#define VL_INITBNUM 32749 /* initial bucket number */ -#define VL_PAGEALIGN -3 /* alignment for pages */ -#define VL_FBPOOLSIZ 128 /* size of free block pool */ -#define VL_PATHBUFSIZ 1024 /* size of a path buffer */ -#define VL_TMPFSUF MYEXTSTR "vltmp" /* suffix of a temporary file */ -#define VL_ROOTKEY -1 /* key of the root key */ -#define VL_LASTKEY -2 /* key of the last key */ -#define VL_LNUMKEY -3 /* key of the number of leaves */ -#define VL_NNUMKEY -4 /* key of the number of nodes */ -#define VL_RNUMKEY -5 /* key of the number of records */ -#define VL_CRDNUM 7 /* default division number for Vista */ - -/* set a buffer for a variable length number */ -#define VL_SETVNUMBUF(VL_len, VL_buf, VL_num) \ - do { \ - int _VL_num; \ - _VL_num = VL_num; \ - if(_VL_num == 0){ \ - ((signed char *)(VL_buf))[0] = 0; \ - (VL_len) = 1; \ - } else { \ - (VL_len) = 0; \ - while(_VL_num > 0){ \ - int _VL_rem = _VL_num & 0x7f; \ - _VL_num >>= 7; \ - if(_VL_num > 0){ \ - ((signed char *)(VL_buf))[(VL_len)] = -_VL_rem - 1; \ - } else { \ - ((signed char *)(VL_buf))[(VL_len)] = _VL_rem; \ - } \ - (VL_len)++; \ - } \ - } \ - } while(FALSE) - -/* read a variable length buffer */ -#define VL_READVNUMBUF(VL_buf, VL_size, VL_num, VL_step) \ - do { \ - int _VL_i, _VL_base; \ - (VL_num) = 0; \ - _VL_base = 1; \ - if((VL_size) < 2){ \ - (VL_num) = ((signed char *)(VL_buf))[0]; \ - (VL_step) = 1; \ - } else { \ - for(_VL_i = 0; _VL_i < (VL_size); _VL_i++){ \ - if(((signed char *)(VL_buf))[_VL_i] >= 0){ \ - (VL_num) += ((signed char *)(VL_buf))[_VL_i] * _VL_base; \ - break; \ - } \ - (VL_num) += _VL_base * (((signed char *)(VL_buf))[_VL_i] + 1) * -1; \ - _VL_base *= 128; \ - } \ - (VL_step) = _VL_i + 1; \ - } \ - } while(FALSE) - -enum { /* enumeration for flags */ - VL_FLISVILLA = 1 << 0, /* whether for Villa */ - VL_FLISZLIB = 1 << 1, /* whether with ZLIB */ - VL_FLISLZO = 1 << 2, /* whether with LZO */ - VL_FLISBZIP = 1 << 3 /* whether with BZIP2 */ -}; - - -/* private function prototypes */ -static int vllexcompare(const char *aptr, int asiz, const char *bptr, int bsiz); -static int vlintcompare(const char *aptr, int asiz, const char *bptr, int bsiz); -static int vlnumcompare(const char *aptr, int asiz, const char *bptr, int bsiz); -static int vldeccompare(const char *aptr, int asiz, const char *bptr, int bsiz); -static int vldpputnum(DEPOT *depot, int knum, int vnum); -static int vldpgetnum(DEPOT *depot, int knum, int *vnp); -static VLLEAF *vlleafnew(VILLA *villa, int prev, int next); -static int vlleafcacheout(VILLA *villa, int id); -static int vlleafsave(VILLA *villa, VLLEAF *leaf); -static VLLEAF *vlleafload(VILLA *villa, int id); -static VLLEAF *vlgethistleaf(VILLA *villa, const char *kbuf, int ksiz); -static int vlleafaddrec(VILLA *villa, VLLEAF *leaf, int dmode, - const char *kbuf, int ksiz, const char *vbuf, int vsiz); -static int vlleafdatasize(VLLEAF *leaf); -static VLLEAF *vlleafdivide(VILLA *villa, VLLEAF *leaf); -static VLNODE *vlnodenew(VILLA *villa, int heir); -static int vlnodecacheout(VILLA *villa, int id); -static int vlnodesave(VILLA *villa, VLNODE *node); -static VLNODE *vlnodeload(VILLA *villa, int id); -static void vlnodeaddidx(VILLA *villa, VLNODE *node, int order, - int pid, const char *kbuf, int ksiz); -static int vlsearchleaf(VILLA *villa, const char *kbuf, int ksiz); -static int vlcacheadjust(VILLA *villa); -static VLREC *vlrecsearch(VILLA *villa, VLLEAF *leaf, const char *kbuf, int ksiz, int *ip); - - - -/************************************************************************************************* - * public objects - *************************************************************************************************/ - - -/* Comparing functions. */ -VLCFUNC VL_CMPLEX = vllexcompare; -VLCFUNC VL_CMPINT = vlintcompare; -VLCFUNC VL_CMPNUM = vlnumcompare; -VLCFUNC VL_CMPDEC = vldeccompare; - - -/* Get a database handle. */ -VILLA *vlopen(const char *name, int omode, VLCFUNC cmp){ - DEPOT *depot; - int dpomode, flags, cmode, root, last, lnum, nnum, rnum; - VILLA *villa; - VLLEAF *leaf; - assert(name && cmp); - dpomode = DP_OREADER; - if(omode & VL_OWRITER){ - dpomode = DP_OWRITER; - if(omode & VL_OCREAT) dpomode |= DP_OCREAT; - if(omode & VL_OTRUNC) dpomode |= DP_OTRUNC; - } - if(omode & VL_ONOLCK) dpomode |= DP_ONOLCK; - if(omode & VL_OLCKNB) dpomode |= DP_OLCKNB; - if(!(depot = dpopen(name, dpomode, VL_INITBNUM))) return NULL; - flags = dpgetflags(depot); - cmode = 0; - root = -1; - last = -1; - lnum = 0; - nnum = 0; - rnum = 0; - if(dprnum(depot) > 0){ - if(!(flags & VL_FLISVILLA) || - !vldpgetnum(depot, VL_ROOTKEY, &root) || !vldpgetnum(depot, VL_LASTKEY, &last) || - !vldpgetnum(depot, VL_LNUMKEY, &lnum) || !vldpgetnum(depot, VL_NNUMKEY, &nnum) || - !vldpgetnum(depot, VL_RNUMKEY, &rnum) || root < VL_LEAFIDMIN || last < VL_LEAFIDMIN || - lnum < 0 || nnum < 0 || rnum < 0){ - dpclose(depot); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - if(flags & VL_FLISZLIB){ - cmode = VL_OZCOMP; - } else if(flags & VL_FLISLZO){ - cmode = VL_OYCOMP; - } else if(flags & VL_FLISBZIP){ - cmode = VL_OXCOMP; - } - } else if(omode & VL_OWRITER){ - if(omode & VL_OZCOMP){ - cmode = VL_OZCOMP; - } else if(omode & VL_OYCOMP){ - cmode = VL_OYCOMP; - } else if(omode & VL_OXCOMP){ - cmode = VL_OXCOMP; - } - } - if(omode & VL_OWRITER){ - flags |= VL_FLISVILLA; - if(_qdbm_deflate && cmode == VL_OZCOMP){ - flags |= VL_FLISZLIB; - } else if(_qdbm_lzoencode && cmode == VL_OYCOMP){ - flags |= VL_FLISLZO; - } else if(_qdbm_bzencode && cmode == VL_OXCOMP){ - flags |= VL_FLISBZIP; - } - if(!dpsetflags(depot, flags) || !dpsetalign(depot, VL_PAGEALIGN) || - !dpsetfbpsiz(depot, VL_FBPOOLSIZ)){ - dpclose(depot); - return NULL; - } - } - CB_MALLOC(villa, sizeof(VILLA)); - villa->depot = depot; - villa->cmp = cmp; - villa->wmode = (omode & VL_OWRITER); - villa->cmode = cmode; - villa->root = root; - villa->last = last; - villa->lnum = lnum; - villa->nnum = nnum; - villa->rnum = rnum; - villa->leafc = cbmapopen(); - villa->nodec = cbmapopen(); - villa->hnum = 0; - villa->hleaf = -1; - villa->lleaf = -1; - villa->curleaf = -1; - villa->curknum = -1; - villa->curvnum = -1; - villa->leafrecmax = VL_DEFLRECMAX; - villa->nodeidxmax = VL_DEFNIDXMAX; - villa->leafcnum = VL_DEFLCNUM; - villa->nodecnum = VL_DEFNCNUM; - villa->tran = FALSE; - villa->rbroot = -1; - villa->rblast = -1; - villa->rblnum = -1; - villa->rbnnum = -1; - villa->rbrnum = -1; - if(root == -1){ - leaf = vlleafnew(villa, -1, -1); - villa->root = leaf->id; - villa->last = leaf->id; - if(!vltranbegin(villa) || !vltranabort(villa)){ - vlclose(villa); - return NULL; - } - } - return villa; -} - - -/* Close a database handle. */ -int vlclose(VILLA *villa){ - int err, pid; - const char *tmp; - assert(villa); - err = FALSE; - if(villa->tran){ - if(!vltranabort(villa)) err = TRUE; - } - cbmapiterinit(villa->leafc); - while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ - pid = *(int *)tmp; - if(!vlleafcacheout(villa, pid)) err = TRUE; - } - cbmapiterinit(villa->nodec); - while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ - pid = *(int *)tmp; - if(!vlnodecacheout(villa, pid)) err = TRUE; - } - if(villa->wmode){ - if(!dpsetalign(villa->depot, 0)) err = TRUE; - if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; - if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; - if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; - if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; - if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; - } - cbmapclose(villa->leafc); - cbmapclose(villa->nodec); - if(!dpclose(villa->depot)) err = TRUE; - free(villa); - return err ? FALSE : TRUE; -} - - -/* Store a record. */ -int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ - VLLEAF *leaf, *newleaf; - VLNODE *node, *newnode; - VLIDX *idxp; - CBDATUM *key; - int i, pid, todiv, heir, parent, mid; - assert(villa && kbuf && vbuf); - villa->curleaf = -1; - villa->curknum = -1; - villa->curvnum = -1; - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(ksiz < 0) ksiz = strlen(kbuf); - if(vsiz < 0) vsiz = strlen(vbuf); - if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ - if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return FALSE; - if(!(leaf = vlleafload(villa, pid))) return FALSE; - } - if(!vlleafaddrec(villa, leaf, dmode, kbuf, ksiz, vbuf, vsiz)){ - dpecodeset(DP_EKEEP, __FILE__, __LINE__); - return FALSE; - } - todiv = FALSE; - switch(CB_LISTNUM(leaf->recs) % 4){ - case 0: - if(CB_LISTNUM(leaf->recs) >= 4 && - vlleafdatasize(leaf) > VL_MAXLEAFSIZ * (villa->cmode > 0 ? 2 : 1)){ - todiv = TRUE; - break; - } - case 2: - if(CB_LISTNUM(leaf->recs) > villa->leafrecmax) todiv = TRUE; - break; - } - if(todiv){ - if(!(newleaf = vlleafdivide(villa, leaf))) return FALSE; - if(leaf->id == villa->last) villa->last = newleaf->id; - heir = leaf->id; - pid = newleaf->id; - key = ((VLREC *)CB_LISTVAL(newleaf->recs, 0))->key; - key = cbdatumdup(key); - while(TRUE){ - if(villa->hnum < 1){ - node = vlnodenew(villa, heir); - vlnodeaddidx(villa, node, TRUE, pid, CB_DATUMPTR(key), CB_DATUMSIZE(key)); - villa->root = node->id; - CB_DATUMCLOSE(key); - break; - } - parent = villa->hist[--villa->hnum]; - if(!(node = vlnodeload(villa, parent))){ - CB_DATUMCLOSE(key); - return FALSE; - } - vlnodeaddidx(villa, node, FALSE, pid, CB_DATUMPTR(key), CB_DATUMSIZE(key)); - CB_DATUMCLOSE(key); - if(CB_LISTNUM(node->idxs) <= villa->nodeidxmax) break; - mid = CB_LISTNUM(node->idxs) / 2; - idxp = (VLIDX *)CB_LISTVAL(node->idxs, mid); - newnode = vlnodenew(villa, idxp->pid); - heir = node->id; - pid = newnode->id; - CB_DATUMOPEN2(key, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); - for(i = mid + 1; i < CB_LISTNUM(node->idxs); i++){ - idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); - vlnodeaddidx(villa, newnode, TRUE, idxp->pid, - CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); - } - for(i = 0; i < CB_LISTNUM(newnode->idxs); i++){ - idxp = (VLIDX *)cblistpop(node->idxs, NULL); - CB_DATUMCLOSE(idxp->key); - free(idxp); - } - node->dirty = TRUE; - } - } - if(!villa->tran && !vlcacheadjust(villa)) return FALSE; - return TRUE; -} - - -/* Delete a record. */ -int vlout(VILLA *villa, const char *kbuf, int ksiz){ - VLLEAF *leaf; - VLREC *recp; - int pid, ri, vsiz; - char *vbuf; - assert(villa && kbuf); - villa->curleaf = -1; - villa->curknum = -1; - villa->curvnum = -1; - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(ksiz < 0) ksiz = strlen(kbuf); - if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ - if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return FALSE; - if(!(leaf = vlleafload(villa, pid))) return FALSE; - } - if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, &ri))){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(recp->rest){ - CB_DATUMCLOSE(recp->first); - vbuf = cblistshift(recp->rest, &vsiz); - CB_DATUMOPEN2(recp->first, vbuf, vsiz); - free(vbuf); - if(CB_LISTNUM(recp->rest) < 1){ - CB_LISTCLOSE(recp->rest); - recp->rest = NULL; - } - } else { - CB_DATUMCLOSE(recp->key); - CB_DATUMCLOSE(recp->first); - free(cblistremove(leaf->recs, ri, NULL)); - } - leaf->dirty = TRUE; - villa->rnum--; - if(!villa->tran && !vlcacheadjust(villa)) return FALSE; - return TRUE; -} - - -/* Retrieve a record. */ -char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp){ - VLLEAF *leaf; - VLREC *recp; - char *rv; - int pid; - assert(villa && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ - if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; - if(!(leaf = vlleafload(villa, pid))) return NULL; - } - if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return NULL; - } - if(!villa->tran && !vlcacheadjust(villa)) return NULL; - if(sp) *sp = CB_DATUMSIZE(recp->first); - CB_MEMDUP(rv, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); - return rv; -} - - -/* Get the size of the value of a record. */ -int vlvsiz(VILLA *villa, const char *kbuf, int ksiz){ - VLLEAF *leaf; - VLREC *recp; - int pid; - assert(villa && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ - if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return -1; - if(!(leaf = vlleafload(villa, pid))) return -1; - } - if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return -1; - } - if(!villa->tran && !vlcacheadjust(villa)) return -1; - return CB_DATUMSIZE(recp->first); -} - - -/* Get the number of records corresponding a key. */ -int vlvnum(VILLA *villa, const char *kbuf, int ksiz){ - VLLEAF *leaf; - VLREC *recp; - int pid; - assert(villa && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ - if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return 0; - if(!(leaf = vlleafload(villa, pid))) return 0; - } - if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return 0; - } - if(!villa->tran && !vlcacheadjust(villa)) return 0; - return 1 + (recp->rest ? CB_LISTNUM(recp->rest) : 0); -} - - -/* Store plural records corresponding a key. */ -int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals){ - int i, vsiz; - const char *vbuf; - assert(villa && kbuf && vals); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(CB_LISTNUM(vals) < 1){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - if(ksiz < 0) ksiz = strlen(kbuf); - for(i = 0; i < CB_LISTNUM(vals); i++){ - vbuf = CB_LISTVAL2(vals, i, vsiz); - if(!vlput(villa, kbuf, ksiz, vbuf, vsiz, VL_DDUP)) return FALSE; - } - return TRUE; -} - - -/* Delete all records corresponding a key. */ -int vloutlist(VILLA *villa, const char *kbuf, int ksiz){ - int i, vnum; - assert(villa && kbuf); - if(!villa->wmode){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - if(ksiz < 0) ksiz = strlen(kbuf); - if((vnum = vlvnum(villa, kbuf, ksiz)) < 1) return FALSE; - for(i = 0; i < vnum; i++){ - if(!vlout(villa, kbuf, ksiz)) return FALSE; - } - return TRUE; -} - - -/* Retrieve values of all records corresponding a key. */ -CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz){ - VLLEAF *leaf; - VLREC *recp; - int pid, i, vsiz; - CBLIST *vals; - const char *vbuf; - assert(villa && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ - if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; - if(!(leaf = vlleafload(villa, pid))) return NULL; - } - if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return NULL; - } - CB_LISTOPEN(vals); - CB_LISTPUSH(vals, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); - if(recp->rest){ - for(i = 0; i < CB_LISTNUM(recp->rest); i++){ - vbuf = CB_LISTVAL2(recp->rest, i, vsiz); - CB_LISTPUSH(vals, vbuf, vsiz); - } - } - if(!villa->tran && !vlcacheadjust(villa)){ - CB_LISTCLOSE(vals); - return NULL; - } - return vals; -} - - -/* Retrieve concatenated values of all records corresponding a key. */ -char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp){ - VLLEAF *leaf; - VLREC *recp; - int pid, i, vsiz, rsiz; - char *rbuf; - const char *vbuf; - assert(villa && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ - if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; - if(!(leaf = vlleafload(villa, pid))) return NULL; - } - if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return NULL; - } - rsiz = CB_DATUMSIZE(recp->first); - CB_MALLOC(rbuf, rsiz + 1); - memcpy(rbuf, CB_DATUMPTR(recp->first), rsiz); - if(recp->rest){ - for(i = 0; i < CB_LISTNUM(recp->rest); i++){ - vbuf = CB_LISTVAL2(recp->rest, i, vsiz); - CB_REALLOC(rbuf, rsiz + vsiz + 1); - memcpy(rbuf + rsiz, vbuf, vsiz); - rsiz += vsiz; - } - } - rbuf[rsiz] = '\0'; - if(!villa->tran && !vlcacheadjust(villa)){ - free(rbuf); - return NULL; - } - if(sp) *sp = rsiz; - return rbuf; -} - - -/* Move the cursor to the first record. */ -int vlcurfirst(VILLA *villa){ - VLLEAF *leaf; - assert(villa); - villa->curleaf = VL_LEAFIDMIN; - villa->curknum = 0; - villa->curvnum = 0; - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - while(CB_LISTNUM(leaf->recs) < 1){ - villa->curleaf = leaf->next; - villa->curknum = 0; - villa->curvnum = 0; - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - } - return TRUE; -} - - -/* Move the cursor to the last record. */ -int vlcurlast(VILLA *villa){ - VLLEAF *leaf; - VLREC *recp; - assert(villa); - villa->curleaf = villa->last; - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - while(CB_LISTNUM(leaf->recs) < 1){ - villa->curleaf = leaf->prev; - if(villa->curleaf == -1){ - villa->curleaf = -1; - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - } - villa->curknum = CB_LISTNUM(leaf->recs) - 1; - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0; - return TRUE; -} - - -/* Move the cursor to the previous record. */ -int vlcurprev(VILLA *villa){ - VLLEAF *leaf; - VLREC *recp; - assert(villa); - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf)) || CB_LISTNUM(leaf->recs) < 1){ - villa->curleaf = -1; - return FALSE; - } - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - villa->curvnum--; - if(villa->curvnum < 0){ - villa->curknum--; - if(villa->curknum < 0){ - villa->curleaf = leaf->prev; - if(villa->curleaf == -1){ - villa->curleaf = -1; - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - while(CB_LISTNUM(leaf->recs) < 1){ - villa->curleaf = leaf->prev; - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - } - villa->curknum = CB_LISTNUM(leaf->recs) - 1; - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0; - } - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0; - } - if(!villa->tran && !vlcacheadjust(villa)) return FALSE; - return TRUE; -} - - -/* Move the cursor to the next record. */ -int vlcurnext(VILLA *villa){ - VLLEAF *leaf; - VLREC *recp; - assert(villa); - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf)) || CB_LISTNUM(leaf->recs) < 1){ - villa->curleaf = -1; - return FALSE; - } - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - villa->curvnum++; - if(villa->curvnum > (recp->rest ? CB_LISTNUM(recp->rest) : 0)){ - villa->curknum++; - villa->curvnum = 0; - } - if(villa->curknum >= CB_LISTNUM(leaf->recs)){ - villa->curleaf = leaf->next; - villa->curknum = 0; - villa->curvnum = 0; - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - while(CB_LISTNUM(leaf->recs) < 1){ - villa->curleaf = leaf->next; - villa->curknum = 0; - villa->curvnum = 0; - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - } - } - if(!villa->tran && !vlcacheadjust(villa)) return FALSE; - return TRUE; -} - - -/* Move the cursor to a position around a record. */ -int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode){ - VLLEAF *leaf; - VLREC *recp; - int pid, index; - assert(villa && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1){ - villa->curleaf = -1; - return FALSE; - } - if(!(leaf = vlleafload(villa, pid))){ - villa->curleaf = -1; - return FALSE; - } - while(CB_LISTNUM(leaf->recs) < 1){ - villa->curleaf = (jmode == VL_JFORWARD) ? leaf->next : leaf->prev; - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - } - if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, &index))){ - if(jmode == VL_JFORWARD){ - villa->curleaf = leaf->id; - if(index >= CB_LISTNUM(leaf->recs)) index--; - villa->curknum = index; - villa->curvnum = 0; - recp = (VLREC *)CB_LISTVAL(leaf->recs, index); - if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)) < 0) return TRUE; - villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0); - return vlcurnext(villa); - } else { - villa->curleaf = leaf->id; - if(index >= CB_LISTNUM(leaf->recs)) index--; - villa->curknum = index; - recp = (VLREC *)CB_LISTVAL(leaf->recs, index); - villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0); - if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)) > 0) return TRUE; - villa->curvnum = 0; - return vlcurprev(villa); - } - } - if(jmode == VL_JFORWARD){ - villa->curleaf = pid; - villa->curknum = index; - villa->curvnum = 0; - } else { - villa->curleaf = pid; - villa->curknum = index; - villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0); - } - return TRUE; -} - - -/* Get the key of the record where the cursor is. */ -char *vlcurkey(VILLA *villa, int *sp){ - VLLEAF *leaf; - VLREC *recp; - const char *kbuf; - char *rv; - int ksiz; - assert(villa); - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - kbuf = CB_DATUMPTR(recp->key); - ksiz = CB_DATUMSIZE(recp->key); - if(sp) *sp = ksiz; - CB_MEMDUP(rv, kbuf, ksiz); - return rv; -} - - -/* Get the value of the record where the cursor is. */ -char *vlcurval(VILLA *villa, int *sp){ - VLLEAF *leaf; - VLREC *recp; - const char *vbuf; - char *rv; - int vsiz; - assert(villa); - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - if(villa->curvnum < 1){ - vbuf = CB_DATUMPTR(recp->first); - vsiz = CB_DATUMSIZE(recp->first); - } else { - vbuf = CB_LISTVAL2(recp->rest, villa->curvnum - 1, vsiz); - } - if(sp) *sp = vsiz; - CB_MEMDUP(rv, vbuf, vsiz); - return rv; -} - - -/* Insert a record around the cursor. */ -int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode){ - VLLEAF *leaf; - VLREC *recp; - char *tbuf; - int tsiz; - assert(villa && vbuf); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(vsiz < 0) vsiz = strlen(vbuf); - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - switch(cpmode){ - case VL_CPBEFORE: - if(villa->curvnum < 1){ - if(!recp->rest){ - CB_DATUMTOMALLOC(recp->first, tbuf, tsiz); - CB_DATUMOPEN2(recp->first, vbuf, vsiz); - CB_LISTOPEN(recp->rest); - CB_LISTPUSHBUF(recp->rest, tbuf, tsiz); - } else { - cblistunshift(recp->rest, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); - CB_DATUMSETSIZE(recp->first, 0); - CB_DATUMCAT(recp->first, vbuf, vsiz); - } - } else { - CB_LISTINSERT(recp->rest, villa->curvnum - 1, vbuf, vsiz); - } - villa->rnum++; - break; - case VL_CPAFTER: - if(!recp->rest) CB_LISTOPEN(recp->rest); - CB_LISTINSERT(recp->rest, villa->curvnum, vbuf, vsiz); - villa->curvnum++; - villa->rnum++; - break; - default: - if(villa->curvnum < 1){ - CB_DATUMSETSIZE(recp->first, 0); - CB_DATUMCAT(recp->first, vbuf, vsiz); - } else { - cblistover(recp->rest, villa->curvnum - 1, vbuf, vsiz); - } - break; - } - leaf->dirty = TRUE; - return TRUE; -} - - -/* Delete the record where the cursor is. */ -int vlcurout(VILLA *villa){ - VLLEAF *leaf; - VLREC *recp; - char *vbuf; - int vsiz; - assert(villa); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - if(villa->curvnum < 1){ - if(recp->rest){ - vbuf = cblistshift(recp->rest, &vsiz); - CB_DATUMSETSIZE(recp->first, 0); - CB_DATUMCAT(recp->first, vbuf, vsiz); - free(vbuf); - if(CB_LISTNUM(recp->rest) < 1){ - CB_LISTCLOSE(recp->rest); - recp->rest = NULL; - } - } else { - CB_DATUMCLOSE(recp->first); - CB_DATUMCLOSE(recp->key); - free(cblistremove(leaf->recs, villa->curknum, NULL)); - } - } else { - free(cblistremove(recp->rest, villa->curvnum - 1, NULL)); - if(villa->curvnum - 1 >= CB_LISTNUM(recp->rest)){ - villa->curknum++; - villa->curvnum = 0; - } - if(CB_LISTNUM(recp->rest) < 1){ - CB_LISTCLOSE(recp->rest); - recp->rest = NULL; - } - } - villa->rnum--; - leaf->dirty = TRUE; - if(villa->curknum >= CB_LISTNUM(leaf->recs)){ - villa->curleaf = leaf->next; - villa->curknum = 0; - villa->curvnum = 0; - while(villa->curleaf != -1 && (leaf = vlleafload(villa, villa->curleaf)) != NULL && - CB_LISTNUM(leaf->recs) < 1){ - villa->curleaf = leaf->next; - } - } - return TRUE; -} - - -/* Set the tuning parameters for performance. */ -void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum){ - assert(villa); - if(lrecmax < 1) lrecmax = VL_DEFLRECMAX; - if(lrecmax < 3) lrecmax = 3; - if(nidxmax < 1) nidxmax = VL_DEFNIDXMAX; - if(nidxmax < 4) nidxmax = 4; - if(lcnum < 1) lcnum = VL_DEFLCNUM; - if(lcnum < VL_CACHEOUT * 2) lcnum = VL_CACHEOUT * 2; - if(ncnum < 1) ncnum = VL_DEFNCNUM; - if(ncnum < VL_CACHEOUT * 2) ncnum = VL_CACHEOUT * 2; - villa->leafrecmax = lrecmax; - villa->nodeidxmax = nidxmax; - villa->leafcnum = lcnum; - villa->nodecnum = ncnum; -} - - -/* Set the size of the free block pool of a database handle. */ -int vlsetfbpsiz(VILLA *villa, int size){ - assert(villa && size >= 0); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - return dpsetfbpsiz(villa->depot, size); -} - - -/* Synchronize updating contents with the file and the device. */ -int vlsync(VILLA *villa){ - int err; - err = FALSE; - if(!vlmemsync(villa)) err = TRUE; - if(!dpsync(villa->depot)) err = TRUE; - return err ? FALSE : TRUE; -} - - -/* Optimize a database. */ -int vloptimize(VILLA *villa){ - int err; - assert(villa); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(villa->tran){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - if(!vlsync(villa)) return FALSE; - if(!dpoptimize(villa->depot, -1)) err = TRUE; - return err ? FALSE : TRUE; -} - - -/* Get the name of a database. */ -char *vlname(VILLA *villa){ - assert(villa); - return dpname(villa->depot); -} - - -/* Get the size of a database file. */ -int vlfsiz(VILLA *villa){ - return dpfsiz(villa->depot); -} - - -/* Get the number of the leaf nodes of B+ tree. */ -int vllnum(VILLA *villa){ - assert(villa); - return villa->lnum; -} - - -/* Get the number of the non-leaf nodes of B+ tree. */ -int vlnnum(VILLA *villa){ - assert(villa); - return villa->nnum; -} - - -/* Get the number of the records stored in a database. */ -int vlrnum(VILLA *villa){ - assert(villa); - return villa->rnum; -} - - -/* Check whether a database handle is a writer or not. */ -int vlwritable(VILLA *villa){ - assert(villa); - return villa->wmode; -} - - -/* Check whether a database has a fatal error or not. */ -int vlfatalerror(VILLA *villa){ - assert(villa); - return dpfatalerror(villa->depot); -} - - -/* Get the inode number of a database file. */ -int vlinode(VILLA *villa){ - assert(villa); - return dpinode(villa->depot); -} - - -/* Get the last modified time of a database. */ -time_t vlmtime(VILLA *villa){ - assert(villa); - return dpmtime(villa->depot); -} - - -/* Begin the transaction. */ -int vltranbegin(VILLA *villa){ - int err, pid; - const char *tmp; - VLLEAF *leaf; - VLNODE *node; - assert(villa); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(villa->tran){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - cbmapiterinit(villa->leafc); - while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ - pid = *(int *)tmp; - leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL); - if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE; - } - cbmapiterinit(villa->nodec); - while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ - pid = *(int *)tmp; - node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL); - if(node->dirty && !vlnodesave(villa, node)) err = TRUE; - } - if(!dpsetalign(villa->depot, 0)) err = TRUE; - if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; - if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; - if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; - if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; - if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; - if(!dpmemsync(villa->depot)) err = TRUE; - if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; - villa->tran = TRUE; - villa->rbroot = villa->root; - villa->rblast = villa->last; - villa->rblnum = villa->lnum; - villa->rbnnum = villa->nnum; - villa->rbrnum = villa->rnum; - return err ? FALSE : TRUE; -} - - -/* Commit the transaction. */ -int vltrancommit(VILLA *villa){ - int err, pid; - const char *tmp; - VLLEAF *leaf; - VLNODE *node; - assert(villa); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(!villa->tran){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - cbmapiterinit(villa->leafc); - while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ - pid = *(int *)tmp; - leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL); - if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE; - } - cbmapiterinit(villa->nodec); - while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ - pid = *(int *)tmp; - node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL); - if(node->dirty && !vlnodesave(villa, node)) err = TRUE; - } - if(!dpsetalign(villa->depot, 0)) err = TRUE; - if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; - if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; - if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; - if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; - if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; - if(!dpmemsync(villa->depot)) err = TRUE; - if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; - villa->tran = FALSE; - villa->rbroot = -1; - villa->rblast = -1; - villa->rblnum = -1; - villa->rbnnum = -1; - villa->rbrnum = -1; - while(cbmaprnum(villa->leafc) > villa->leafcnum || cbmaprnum(villa->nodec) > villa->nodecnum){ - if(!vlcacheadjust(villa)){ - err = TRUE; - break; - } - } - return err ? FALSE : TRUE; -} - - -/* Abort the transaction. */ -int vltranabort(VILLA *villa){ - int err, pid; - const char *tmp; - VLLEAF *leaf; - VLNODE *node; - assert(villa); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(!villa->tran){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - cbmapiterinit(villa->leafc); - while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ - pid = *(int *)tmp; - if(!(leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL))){ - err = TRUE; - continue; - } - if(leaf->dirty){ - leaf->dirty = FALSE; - if(!vlleafcacheout(villa, pid)) err = TRUE; - } - } - cbmapiterinit(villa->nodec); - while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ - pid = *(int *)tmp; - if(!(node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL))){ - err = TRUE; - continue; - } - if(node->dirty){ - node->dirty = FALSE; - if(!vlnodecacheout(villa, pid)) err = TRUE; - } - } - villa->tran = FALSE; - villa->root = villa->rbroot; - villa->last = villa->rblast; - villa->lnum = villa->rblnum; - villa->nnum = villa->rbnnum; - villa->rnum = villa->rbrnum; - while(cbmaprnum(villa->leafc) > villa->leafcnum || cbmaprnum(villa->nodec) > villa->nodecnum){ - if(!vlcacheadjust(villa)){ - err = TRUE; - break; - } - } - return err ? FALSE : TRUE; -} - - -/* Remove a database file. */ -int vlremove(const char *name){ - assert(name); - return dpremove(name); -} - - -/* Repair a broken database file. */ -int vlrepair(const char *name, VLCFUNC cmp){ - DEPOT *depot; - VILLA *tvilla; - char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *zbuf, *rp, *tkbuf, *tvbuf; - int i, err, flags, omode, ksiz, vsiz, zsiz, size, step, tksiz, tvsiz, vnum; - assert(name && cmp); - err = FALSE; - if(!dprepair(name)) err = TRUE; - if(!(depot = dpopen(name, DP_OREADER, -1))) return FALSE; - flags = dpgetflags(depot); - if(!(flags & VL_FLISVILLA)){ - dpclose(depot); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return FALSE; - } - sprintf(path, "%s%s", name, VL_TMPFSUF); - omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC; - if(flags & VL_FLISZLIB){ - omode |= VL_OZCOMP; - } else if(flags & VL_FLISLZO){ - omode |= VL_OXCOMP; - } else if(flags & VL_FLISBZIP){ - omode |= VL_OYCOMP; - } - if(!(tvilla = vlopen(path, omode, cmp))){ - dpclose(depot); - return FALSE; - } - if(!dpiterinit(depot)) err = TRUE; - while((kbuf = dpiternext(depot, &ksiz)) != NULL){ - if(ksiz == sizeof(int) && *(int *)kbuf < VL_NODEIDMIN && *(int *)kbuf > 0){ - if((vbuf = dpget(depot, (char *)kbuf, sizeof(int), 0, -1, &vsiz)) != NULL){ - if(_qdbm_inflate && (flags & VL_FLISZLIB) && - (zbuf = _qdbm_inflate(vbuf, vsiz, &zsiz, _QDBM_ZMRAW)) != NULL){ - free(vbuf); - vbuf = zbuf; - vsiz = zsiz; - } else if(_qdbm_lzodecode && (flags & VL_FLISLZO) && - (zbuf = _qdbm_lzodecode(vbuf, vsiz, &zsiz)) != NULL){ - free(vbuf); - vbuf = zbuf; - vsiz = zsiz; - } else if(_qdbm_bzdecode && (flags & VL_FLISBZIP) && - (zbuf = _qdbm_bzdecode(vbuf, vsiz, &zsiz)) != NULL){ - free(vbuf); - vbuf = zbuf; - vsiz = zsiz; - } - rp = vbuf; - size = vsiz; - if(size >= 1){ - VL_READVNUMBUF(rp, size, vnum, step); - rp += step; - size -= step; - } - if(size >= 1){ - VL_READVNUMBUF(rp, size, vnum, step); - rp += step; - size -= step; - } - while(size >= 1){ - VL_READVNUMBUF(rp, size, tksiz, step); - rp += step; - size -= step; - if(size < tksiz) break; - tkbuf = rp; - rp += tksiz; - size -= tksiz; - if(size < 1) break; - VL_READVNUMBUF(rp, size, vnum, step); - rp += step; - size -= step; - if(vnum < 1 || size < 1) break; - for(i = 0; i < vnum && size >= 1; i++){ - VL_READVNUMBUF(rp, size, tvsiz, step); - rp += step; - size -= step; - if(size < tvsiz) break; - tvbuf = rp; - rp += tvsiz; - size -= tvsiz; - if(!vlput(tvilla, tkbuf, tksiz, tvbuf, tvsiz, VL_DDUP)) err = TRUE; - } - } - free(vbuf); - } - } - free(kbuf); - } - if(!vlclose(tvilla)) err = TRUE; - if(!dpclose(depot)) err = TRUE; - if(!dpremove(name)) err = TRUE; - if(rename(path, name) == -1){ - if(!err) dpecodeset(DP_EMISC, __FILE__, __LINE__); - err = TRUE; - } - return err ? FALSE : TRUE; -} - - -/* Dump all records as endian independent data. */ -int vlexportdb(VILLA *villa, const char *name){ - DEPOT *depot; - char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *nkey; - int i, err, ksiz, vsiz, ki; - assert(villa && name); - sprintf(path, "%s%s", name, VL_TMPFSUF); - if(!(depot = dpopen(path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))) return FALSE; - err = FALSE; - vlcurfirst(villa); - for(i = 0; !err && (kbuf = vlcurkey(villa, &ksiz)) != NULL; i++){ - if((vbuf = vlcurval(villa, &vsiz)) != NULL){ - CB_MALLOC(nkey, ksiz + VL_NUMBUFSIZ); - ki = sprintf(nkey, "%X\t", i); - memcpy(nkey + ki, kbuf, ksiz); - if(!dpput(depot, nkey, ki + ksiz, vbuf, vsiz, DP_DKEEP)) err = TRUE; - free(nkey); - free(vbuf); - } else { - err = TRUE; - } - free(kbuf); - vlcurnext(villa); - } - if(!dpexportdb(depot, name)) err = TRUE; - if(!dpclose(depot)) err = TRUE; - if(!dpremove(path)) err = TRUE; - return !err && !vlfatalerror(villa); -} - - -/* Load all records from endian independent data. */ -int vlimportdb(VILLA *villa, const char *name){ - DEPOT *depot; - char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *rp; - int err, ksiz, vsiz; - assert(villa && name); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(vlrnum(villa) > 0){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - kbuf = dpname(villa->depot); - sprintf(path, "%s%s", kbuf, VL_TMPFSUF); - free(kbuf); - if(!(depot = dpopen(path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))) return FALSE; - err = FALSE; - if(!dpimportdb(depot, name)) err = TRUE; - dpiterinit(depot); - while(!err && (kbuf = dpiternext(depot, &ksiz)) != NULL){ - if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ - if((rp = strchr(kbuf, '\t')) != NULL){ - rp++; - if(!vlput(villa, rp, ksiz - (rp - kbuf), vbuf, vsiz, VL_DDUP)) err = TRUE; - } else { - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - err = TRUE; - } - free(vbuf); - } else { - err = TRUE; - } - free(kbuf); - } - if(!dpclose(depot)) err = TRUE; - if(!dpremove(path)) err = TRUE; - return !err && !vlfatalerror(villa); -} - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Number of division of the database for Vista. */ -int *vlcrdnumptr(void){ - static int defvlcrdnum = VL_CRDNUM; - void *ptr; - if(_qdbm_ptsafe){ - if(!(ptr = _qdbm_settsd(&defvlcrdnum, sizeof(int), &defvlcrdnum))){ - defvlcrdnum = DP_EMISC; - return &defvlcrdnum; - } - return (int *)ptr; - } - return &defvlcrdnum; -} - - -/* Synchronize updating contents on memory. */ -int vlmemsync(VILLA *villa){ - int err, pid; - const char *tmp; - assert(villa); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(villa->tran){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - cbmapiterinit(villa->leafc); - while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ - pid = *(int *)tmp; - if(!vlleafcacheout(villa, pid)) err = TRUE; - } - cbmapiterinit(villa->nodec); - while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ - pid = *(int *)tmp; - if(!vlnodecacheout(villa, pid)) err = TRUE; - } - if(!dpsetalign(villa->depot, 0)) err = TRUE; - if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; - if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; - if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; - if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; - if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; - if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; - if(!dpmemsync(villa->depot)) err = TRUE; - return err ? FALSE : TRUE; -} - - -/* Synchronize updating contents on memory, not physically. */ -int vlmemflush(VILLA *villa){ - int err, pid; - const char *tmp; - assert(villa); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - if(villa->tran){ - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - err = FALSE; - cbmapiterinit(villa->leafc); - while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ - pid = *(int *)tmp; - if(!vlleafcacheout(villa, pid)) err = TRUE; - } - cbmapiterinit(villa->nodec); - while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ - pid = *(int *)tmp; - if(!vlnodecacheout(villa, pid)) err = TRUE; - } - if(!dpsetalign(villa->depot, 0)) err = TRUE; - if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; - if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; - if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; - if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; - if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; - if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; - if(!dpmemflush(villa->depot)) err = TRUE; - return err ? FALSE : TRUE; -} - - -/* Refer to a volatile cache of a value of a record. */ -const char *vlgetcache(VILLA *villa, const char *kbuf, int ksiz, int *sp){ - VLLEAF *leaf; - VLREC *recp; - int pid; - assert(villa && kbuf); - if(ksiz < 0) ksiz = strlen(kbuf); - if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ - if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; - if(!(leaf = vlleafload(villa, pid))) return NULL; - } - if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return NULL; - } - if(!villa->tran && !vlcacheadjust(villa)) return NULL; - if(sp) *sp = CB_DATUMSIZE(recp->first); - return CB_DATUMPTR(recp->first); -} - - -/* Refer to volatile cache of the key of the record where the cursor is. */ -const char *vlcurkeycache(VILLA *villa, int *sp){ - VLLEAF *leaf; - VLREC *recp; - const char *kbuf; - int ksiz; - assert(villa); - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - kbuf = CB_DATUMPTR(recp->key); - ksiz = CB_DATUMSIZE(recp->key); - if(sp) *sp = ksiz; - return kbuf; -} - - -/* Refer to volatile cache of the value of the record where the cursor is. */ -const char *vlcurvalcache(VILLA *villa, int *sp){ - VLLEAF *leaf; - VLREC *recp; - const char *vbuf; - int vsiz; - assert(villa); - if(villa->curleaf == -1){ - dpecodeset(DP_ENOITEM, __FILE__, __LINE__); - return FALSE; - } - if(!(leaf = vlleafload(villa, villa->curleaf))){ - villa->curleaf = -1; - return FALSE; - } - recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); - if(villa->curvnum < 1){ - vbuf = CB_DATUMPTR(recp->first); - vsiz = CB_DATUMSIZE(recp->first); - } else { - vbuf = CB_LISTVAL2(recp->rest, villa->curvnum - 1, vsiz); - } - if(sp) *sp = vsiz; - return vbuf; -} - - -/* Get a multiple cursor handle. */ -VLMULCUR *vlmulcuropen(VILLA *villa){ - VLMULCUR *mulcur; - assert(villa); - if(villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return NULL; - } - CB_MALLOC(mulcur, sizeof(VLMULCUR)); - mulcur->villa = villa; - mulcur->curleaf = -1; - mulcur->curknum = -1; - mulcur->curvnum = -1; - return mulcur; -} - - -/* Close a multiple cursor handle. */ -void vlmulcurclose(VLMULCUR *mulcur){ - assert(mulcur); - free(mulcur); -} - - -/* Move a multiple cursor to the first record. */ -int vlmulcurfirst(VLMULCUR *mulcur){ - VLMULCUR swap; - int rv; - assert(mulcur); - swap.curleaf = mulcur->villa->curleaf; - swap.curknum = mulcur->villa->curknum; - swap.curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = mulcur->curleaf; - mulcur->villa->curknum = mulcur->curknum; - mulcur->villa->curvnum = mulcur->curvnum; - rv = vlcurfirst(mulcur->villa); - mulcur->curleaf = mulcur->villa->curleaf; - mulcur->curknum = mulcur->villa->curknum; - mulcur->curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = swap.curleaf; - mulcur->villa->curknum = swap.curknum; - mulcur->villa->curvnum = swap.curvnum; - return rv; -} - - -/* Move a multiple cursor to the last record. */ -int vlmulcurlast(VLMULCUR *mulcur){ - VLMULCUR swap; - int rv; - assert(mulcur); - swap.curleaf = mulcur->villa->curleaf; - swap.curknum = mulcur->villa->curknum; - swap.curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = mulcur->curleaf; - mulcur->villa->curknum = mulcur->curknum; - mulcur->villa->curvnum = mulcur->curvnum; - rv = vlcurlast(mulcur->villa); - mulcur->curleaf = mulcur->villa->curleaf; - mulcur->curknum = mulcur->villa->curknum; - mulcur->curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = swap.curleaf; - mulcur->villa->curknum = swap.curknum; - mulcur->villa->curvnum = swap.curvnum; - return rv; -} - - -/* Move a multiple cursor to the previous record. */ -int vlmulcurprev(VLMULCUR *mulcur){ - VLMULCUR swap; - int rv; - assert(mulcur); - swap.curleaf = mulcur->villa->curleaf; - swap.curknum = mulcur->villa->curknum; - swap.curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = mulcur->curleaf; - mulcur->villa->curknum = mulcur->curknum; - mulcur->villa->curvnum = mulcur->curvnum; - rv = vlcurprev(mulcur->villa); - mulcur->curleaf = mulcur->villa->curleaf; - mulcur->curknum = mulcur->villa->curknum; - mulcur->curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = swap.curleaf; - mulcur->villa->curknum = swap.curknum; - mulcur->villa->curvnum = swap.curvnum; - return rv; -} - - -/* Move a multiple cursor to the next record. */ -int vlmulcurnext(VLMULCUR *mulcur){ - VLMULCUR swap; - int rv; - assert(mulcur); - swap.curleaf = mulcur->villa->curleaf; - swap.curknum = mulcur->villa->curknum; - swap.curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = mulcur->curleaf; - mulcur->villa->curknum = mulcur->curknum; - mulcur->villa->curvnum = mulcur->curvnum; - rv = vlcurnext(mulcur->villa); - mulcur->curleaf = mulcur->villa->curleaf; - mulcur->curknum = mulcur->villa->curknum; - mulcur->curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = swap.curleaf; - mulcur->villa->curknum = swap.curknum; - mulcur->villa->curvnum = swap.curvnum; - return rv; -} - - -/* Move a multiple cursor to a position around a record. */ -int vlmulcurjump(VLMULCUR *mulcur, const char *kbuf, int ksiz, int jmode){ - VLMULCUR swap; - int rv; - assert(mulcur); - swap.curleaf = mulcur->villa->curleaf; - swap.curknum = mulcur->villa->curknum; - swap.curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = mulcur->curleaf; - mulcur->villa->curknum = mulcur->curknum; - mulcur->villa->curvnum = mulcur->curvnum; - rv = vlcurjump(mulcur->villa, kbuf, ksiz, jmode); - mulcur->curleaf = mulcur->villa->curleaf; - mulcur->curknum = mulcur->villa->curknum; - mulcur->curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = swap.curleaf; - mulcur->villa->curknum = swap.curknum; - mulcur->villa->curvnum = swap.curvnum; - return rv; -} - - -/* Get the key of the record where a multiple cursor is. */ -char *vlmulcurkey(VLMULCUR *mulcur, int *sp){ - VLMULCUR swap; - char *rv; - assert(mulcur); - swap.curleaf = mulcur->villa->curleaf; - swap.curknum = mulcur->villa->curknum; - swap.curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = mulcur->curleaf; - mulcur->villa->curknum = mulcur->curknum; - mulcur->villa->curvnum = mulcur->curvnum; - rv = vlcurkey(mulcur->villa, sp); - mulcur->curleaf = mulcur->villa->curleaf; - mulcur->curknum = mulcur->villa->curknum; - mulcur->curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = swap.curleaf; - mulcur->villa->curknum = swap.curknum; - mulcur->villa->curvnum = swap.curvnum; - return rv; -} - - -/* Get the value of the record where a multiple cursor is. */ -char *vlmulcurval(VLMULCUR *mulcur, int *sp){ - VLMULCUR swap; - char *rv; - assert(mulcur); - swap.curleaf = mulcur->villa->curleaf; - swap.curknum = mulcur->villa->curknum; - swap.curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = mulcur->curleaf; - mulcur->villa->curknum = mulcur->curknum; - mulcur->villa->curvnum = mulcur->curvnum; - rv = vlcurval(mulcur->villa, sp); - mulcur->curleaf = mulcur->villa->curleaf; - mulcur->curknum = mulcur->villa->curknum; - mulcur->curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = swap.curleaf; - mulcur->villa->curknum = swap.curknum; - mulcur->villa->curvnum = swap.curvnum; - return rv; -} - - -/* Refer to volatile cache of the key of the record where a multiple cursor is. */ -const char *vlmulcurkeycache(VLMULCUR *mulcur, int *sp){ - VLMULCUR swap; - const char *rv; - assert(mulcur); - swap.curleaf = mulcur->villa->curleaf; - swap.curknum = mulcur->villa->curknum; - swap.curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = mulcur->curleaf; - mulcur->villa->curknum = mulcur->curknum; - mulcur->villa->curvnum = mulcur->curvnum; - rv = vlcurkeycache(mulcur->villa, sp); - mulcur->curleaf = mulcur->villa->curleaf; - mulcur->curknum = mulcur->villa->curknum; - mulcur->curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = swap.curleaf; - mulcur->villa->curknum = swap.curknum; - mulcur->villa->curvnum = swap.curvnum; - return rv; -} - - -/* Refer to volatile cache of the value of the record where a multiple cursor is. */ -const char *vlmulcurvalcache(VLMULCUR *mulcur, int *sp){ - VLMULCUR swap; - const char *rv; - assert(mulcur); - swap.curleaf = mulcur->villa->curleaf; - swap.curknum = mulcur->villa->curknum; - swap.curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = mulcur->curleaf; - mulcur->villa->curknum = mulcur->curknum; - mulcur->villa->curvnum = mulcur->curvnum; - rv = vlcurvalcache(mulcur->villa, sp); - mulcur->curleaf = mulcur->villa->curleaf; - mulcur->curknum = mulcur->villa->curknum; - mulcur->curvnum = mulcur->villa->curvnum; - mulcur->villa->curleaf = swap.curleaf; - mulcur->villa->curknum = swap.curknum; - mulcur->villa->curvnum = swap.curvnum; - return rv; -} - - - -/************************************************************************************************* - * private objects - *************************************************************************************************/ - - -/* Compare keys of two records by lexical order. - `aptr' specifies the pointer to the region of one key. - `asiz' specifies the size of the region of one key. - `bptr' specifies the pointer to the region of the other key. - `bsiz' specifies the size of the region of the other key. - The return value is positive if the former is big, negative if the latter is big, 0 if both - are equivalent. */ -static int vllexcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ - int i, min; - assert(aptr && asiz >= 0 && bptr && bsiz >= 0); - min = asiz < bsiz ? asiz : bsiz; - for(i = 0; i < min; i++){ - if(((unsigned char *)aptr)[i] != ((unsigned char *)bptr)[i]) - return ((unsigned char *)aptr)[i] - ((unsigned char *)bptr)[i]; - } - if(asiz == bsiz) return 0; - return asiz - bsiz; -} - - -/* Compare keys of two records as native integers. - `aptr' specifies the pointer to the region of one key. - `asiz' specifies the size of the region of one key. - `bptr' specifies the pointer to the region of the other key. - `bsiz' specifies the size of the region of the other key. - The return value is positive if the former is big, negative if the latter is big, 0 if both - are equivalent. */ -static int vlintcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ - int anum, bnum; - assert(aptr && asiz >= 0 && bptr && bsiz >= 0); - if(asiz != bsiz) return asiz - bsiz; - anum = (asiz == sizeof(int) ? *(int *)aptr : INT_MIN); - bnum = (bsiz == sizeof(int) ? *(int *)bptr : INT_MIN); - return anum - bnum; -} - - -/* Compare keys of two records as numbers of big endian. - `aptr' specifies the pointer to the region of one key. - `asiz' specifies the size of the region of one key. - `bptr' specifies the pointer to the region of the other key. - `bsiz' specifies the size of the region of the other key. - The return value is positive if the former is big, negative if the latter is big, 0 if both - are equivalent. */ -static int vlnumcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ - int i; - assert(aptr && asiz >= 0 && bptr && bsiz >= 0); - if(asiz != bsiz) return asiz - bsiz; - for(i = 0; i < asiz; i++){ - if(aptr[i] != bptr[i]) return aptr[i] - bptr[i]; - } - return 0; -} - - -/* Compare keys of two records as numeric strings of octal, decimal or hexadecimal. - `aptr' specifies the pointer to the region of one key. - `asiz' specifies the size of the region of one key. - `bptr' specifies the pointer to the region of the other key. - `bsiz' specifies the size of the region of the other key. - The return value is positive if the former is big, negative if the latter is big, 0 if both - are equivalent. */ -static int vldeccompare(const char *aptr, int asiz, const char *bptr, int bsiz){ - assert(aptr && asiz >= 0 && bptr && bsiz >= 0); - return (int)(strtod(aptr, NULL) - strtod(bptr, NULL)); -} - - -/* Store a record composed of a pair of integers. - `depot' specifies an internal database handle. - `knum' specifies an integer of the key. - `vnum' specifies an integer of the value. - The return value is true if successful, else, it is false. */ -static int vldpputnum(DEPOT *depot, int knum, int vnum){ - assert(depot); - return dpput(depot, (char *)&knum, sizeof(int), (char *)&vnum, sizeof(int), DP_DOVER); -} - - -/* Retrieve a record composed of a pair of integers. - `depot' specifies an internal database handle. - `knum' specifies an integer of the key. - `vip' specifies the pointer to a variable to assign the result to. - The return value is true if successful, else, it is false. */ -static int vldpgetnum(DEPOT *depot, int knum, int *vnp){ - char *vbuf; - int vsiz; - assert(depot && vnp); - vbuf = dpget(depot, (char *)&knum, sizeof(int), 0, -1, &vsiz); - if(!vbuf || vsiz != sizeof(int)){ - free(vbuf); - return FALSE; - } - *vnp = *(int *)vbuf; - free(vbuf); - return TRUE; -} - - -/* Create a new leaf. - `villa' specifies a database handle. - `prev' specifies the ID number of the previous leaf. - `next' specifies the ID number of the previous leaf. - The return value is a handle of the leaf. */ -static VLLEAF *vlleafnew(VILLA *villa, int prev, int next){ - VLLEAF lent; - assert(villa); - lent.id = villa->lnum + VL_LEAFIDMIN; - lent.dirty = TRUE; - CB_LISTOPEN(lent.recs); - lent.prev = prev; - lent.next = next; - villa->lnum++; - cbmapput(villa->leafc, (char *)&(lent.id), sizeof(int), (char *)&lent, sizeof(VLLEAF), TRUE); - return (VLLEAF *)cbmapget(villa->leafc, (char *)&(lent.id), sizeof(int), NULL); -} - - -/* Remove a leaf from the cache. - `villa' specifies a database handle. - `id' specifies the ID number of the leaf. - The return value is true if successful, else, it is false. */ -static int vlleafcacheout(VILLA *villa, int id){ - VLLEAF *leaf; - VLREC *recp; - CBLIST *recs; - int i, err, ln; - assert(villa && id >= VL_LEAFIDMIN); - if(!(leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&id, sizeof(int), NULL))) return FALSE; - err = FALSE; - if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE; - recs = leaf->recs; - ln = CB_LISTNUM(recs); - for(i = 0; i < ln; i++){ - recp = (VLREC *)CB_LISTVAL(recs, i); - CB_DATUMCLOSE(recp->key); - CB_DATUMCLOSE(recp->first); - if(recp->rest) CB_LISTCLOSE(recp->rest); - } - CB_LISTCLOSE(recs); - cbmapout(villa->leafc, (char *)&id, sizeof(int)); - return err ? FALSE : TRUE; -} - - -/* Save a leaf into the database. - `villa' specifies a database handle. - `leaf' specifies a leaf handle. - The return value is true if successful, else, it is false. */ -static int vlleafsave(VILLA *villa, VLLEAF *leaf){ - VLREC *recp; - CBLIST *recs; - CBDATUM *buf; - char vnumbuf[VL_VNUMBUFSIZ], *zbuf; - const char *vbuf; - int i, j, ksiz, vnum, vsiz, prev, next, vnumsiz, ln, zsiz; - assert(villa && leaf); - CB_DATUMOPEN(buf); - prev = leaf->prev; - if(prev == -1) prev = VL_NODEIDMIN - 1; - VL_SETVNUMBUF(vnumsiz, vnumbuf, prev); - CB_DATUMCAT(buf, vnumbuf, vnumsiz); - next = leaf->next; - if(next == -1) next = VL_NODEIDMIN - 1; - VL_SETVNUMBUF(vnumsiz, vnumbuf, next); - CB_DATUMCAT(buf, vnumbuf, vnumsiz); - recs = leaf->recs; - ln = CB_LISTNUM(recs); - for(i = 0; i < ln; i++){ - recp = (VLREC *)CB_LISTVAL(recs, i); - ksiz = CB_DATUMSIZE(recp->key); - VL_SETVNUMBUF(vnumsiz, vnumbuf, ksiz); - CB_DATUMCAT(buf, vnumbuf, vnumsiz); - CB_DATUMCAT(buf, CB_DATUMPTR(recp->key), ksiz); - vnum = 1 + (recp->rest ? CB_LISTNUM(recp->rest) : 0); - VL_SETVNUMBUF(vnumsiz, vnumbuf, vnum); - CB_DATUMCAT(buf, vnumbuf, vnumsiz); - vsiz = CB_DATUMSIZE(recp->first); - VL_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); - CB_DATUMCAT(buf, vnumbuf, vnumsiz); - CB_DATUMCAT(buf, CB_DATUMPTR(recp->first), vsiz); - if(recp->rest){ - for(j = 0; j < CB_LISTNUM(recp->rest); j++){ - vbuf = CB_LISTVAL2(recp->rest, j, vsiz); - VL_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); - CB_DATUMCAT(buf, vnumbuf, vnumsiz); - CB_DATUMCAT(buf, vbuf, vsiz); - } - } - } - if(_qdbm_deflate && villa->cmode == VL_OZCOMP){ - if(!(zbuf = _qdbm_deflate(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz, _QDBM_ZMRAW))){ - CB_DATUMCLOSE(buf); - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){ - CB_DATUMCLOSE(buf); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return FALSE; - } - free(zbuf); - } else if(_qdbm_lzoencode && villa->cmode == VL_OYCOMP){ - if(!(zbuf = _qdbm_lzoencode(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz))){ - CB_DATUMCLOSE(buf); - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){ - CB_DATUMCLOSE(buf); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return FALSE; - } - free(zbuf); - } else if(_qdbm_bzencode && villa->cmode == VL_OXCOMP){ - if(!(zbuf = _qdbm_bzencode(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz))){ - CB_DATUMCLOSE(buf); - dpecodeset(DP_EMISC, __FILE__, __LINE__); - return FALSE; - } - if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){ - CB_DATUMCLOSE(buf); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return FALSE; - } - free(zbuf); - } else { - if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), - CB_DATUMPTR(buf), CB_DATUMSIZE(buf), DP_DOVER)){ - CB_DATUMCLOSE(buf); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return FALSE; - } - } - CB_DATUMCLOSE(buf); - leaf->dirty = FALSE; - return TRUE; -} - - -/* Load a leaf from the database. - `villa' specifies a database handle. - `id' specifies the ID number of the leaf. - If successful, the return value is the pointer to the leaf, else, it is `NULL'. */ -static VLLEAF *vlleafload(VILLA *villa, int id){ - char wbuf[VL_PAGEBUFSIZ], *buf, *rp, *kbuf, *vbuf, *zbuf; - int i, size, step, ksiz, vnum, vsiz, prev, next, zsiz; - VLLEAF *leaf, lent; - VLREC rec; - assert(villa && id >= VL_LEAFIDMIN); - if((leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&id, sizeof(int), NULL)) != NULL){ - cbmapmove(villa->leafc, (char *)&id, sizeof(int), FALSE); - return leaf; - } - ksiz = -1; - prev = -1; - next = -1; - if((size = dpgetwb(villa->depot, (char *)&id, sizeof(int), 0, VL_PAGEBUFSIZ, wbuf)) > 0 && - size < VL_PAGEBUFSIZ){ - buf = NULL; - } else if(!(buf = dpget(villa->depot, (char *)&id, sizeof(int), 0, -1, &size))){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - if(_qdbm_inflate && villa->cmode == VL_OZCOMP){ - if(!(zbuf = _qdbm_inflate(buf ? buf : wbuf, size, &zsiz, _QDBM_ZMRAW))){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - free(buf); - return NULL; - } - free(buf); - buf = zbuf; - size = zsiz; - } else if(_qdbm_lzodecode && villa->cmode == VL_OYCOMP){ - if(!(zbuf = _qdbm_lzodecode(buf ? buf : wbuf, size, &zsiz))){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - free(buf); - return NULL; - } - free(buf); - buf = zbuf; - size = zsiz; - } else if(_qdbm_bzdecode && villa->cmode == VL_OXCOMP){ - if(!(zbuf = _qdbm_bzdecode(buf ? buf : wbuf, size, &zsiz))){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - free(buf); - return NULL; - } - free(buf); - buf = zbuf; - size = zsiz; - } - rp = buf ? buf : wbuf; - if(size >= 1){ - VL_READVNUMBUF(rp, size, prev, step); - rp += step; - size -= step; - if(prev >= VL_NODEIDMIN - 1) prev = -1; - } - if(size >= 1){ - VL_READVNUMBUF(rp, size, next, step); - rp += step; - size -= step; - if(next >= VL_NODEIDMIN - 1) next = -1; - } - lent.id = id; - lent.dirty = FALSE; - CB_LISTOPEN(lent.recs); - lent.prev = prev; - lent.next = next; - while(size >= 1){ - VL_READVNUMBUF(rp, size, ksiz, step); - rp += step; - size -= step; - if(size < ksiz) break; - kbuf = rp; - rp += ksiz; - size -= ksiz; - VL_READVNUMBUF(rp, size, vnum, step); - rp += step; - size -= step; - if(vnum < 1 || size < 1) break; - for(i = 0; i < vnum && size >= 1; i++){ - VL_READVNUMBUF(rp, size, vsiz, step); - rp += step; - size -= step; - if(size < vsiz) break; - vbuf = rp; - rp += vsiz; - size -= vsiz; - if(i < 1){ - CB_DATUMOPEN2(rec.key, kbuf, ksiz); - CB_DATUMOPEN2(rec.first, vbuf, vsiz); - rec.rest = NULL; - } else { - if(!rec.rest) CB_LISTOPEN(rec.rest); - CB_LISTPUSH(rec.rest, vbuf, vsiz); - } - } - if(i > 0) CB_LISTPUSH(lent.recs, (char *)&rec, sizeof(VLREC)); - } - free(buf); - cbmapput(villa->leafc, (char *)&(lent.id), sizeof(int), (char *)&lent, sizeof(VLLEAF), TRUE); - return (VLLEAF *)cbmapget(villa->leafc, (char *)&(lent.id), sizeof(int), NULL); -} - - -/* Load the historical leaf from the database. - `villa' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. - If successful, the return value is the pointer to the leaf, else, it is `NULL'. */ -static VLLEAF *vlgethistleaf(VILLA *villa, const char *kbuf, int ksiz){ - VLLEAF *leaf; - VLREC *recp; - int ln, rv; - assert(villa && kbuf && ksiz >= 0); - if(!(leaf = vlleafload(villa, villa->hleaf))) return NULL; - if((ln = CB_LISTNUM(leaf->recs)) < 2) return NULL; - recp = (VLREC *)CB_LISTVAL(leaf->recs, 0); - rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); - if(rv == 0) return leaf; - if(rv < 0) return NULL; - recp = (VLREC *)CB_LISTVAL(leaf->recs, ln - 1); - rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); - if(rv <= 0 || leaf->next < VL_LEAFIDMIN) return leaf; - return NULL; -} - - -/* Add a record to a leaf. - `villa' specifies a database handle. - `leaf' specifies a leaf handle. - `dmode' specifies behavior when the key overlaps. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region of the value. - The return value is true if successful, else, it is false. */ -static int vlleafaddrec(VILLA *villa, VLLEAF *leaf, int dmode, - const char *kbuf, int ksiz, const char *vbuf, int vsiz){ - VLREC *recp, rec; - CBLIST *recs; - int i, rv, left, right, ln, tsiz; - char *tbuf; - assert(villa && leaf && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); - left = 0; - recs = leaf->recs; - ln = CB_LISTNUM(recs); - right = ln; - i = (left + right) / 2; - while(right >= left && i < ln){ - recp = (VLREC *)CB_LISTVAL(recs, i); - rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); - if(rv == 0){ - break; - } else if(rv <= 0){ - right = i - 1; - } else { - left = i + 1; - } - i = (left + right) / 2; - } - while(i < ln){ - recp = (VLREC *)CB_LISTVAL(recs, i); - rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); - if(rv == 0){ - switch(dmode){ - case VL_DKEEP: - return FALSE; - case VL_DCAT: - CB_DATUMCAT(recp->first, vbuf, vsiz); - break; - case VL_DDUP: - if(!recp->rest) CB_LISTOPEN(recp->rest); - CB_LISTPUSH(recp->rest, vbuf, vsiz); - villa->rnum++; - break; - case VL_DDUPR: - if(!recp->rest){ - CB_DATUMTOMALLOC(recp->first, tbuf, tsiz); - CB_DATUMOPEN2(recp->first, vbuf, vsiz); - CB_LISTOPEN(recp->rest); - CB_LISTPUSHBUF(recp->rest, tbuf, tsiz); - } else { - cblistunshift(recp->rest, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); - CB_DATUMSETSIZE(recp->first, 0); - CB_DATUMCAT(recp->first, vbuf, vsiz); - } - villa->rnum++; - break; - default: - CB_DATUMSETSIZE(recp->first, 0); - CB_DATUMCAT(recp->first, vbuf, vsiz); - break; - } - break; - } else if(rv < 0){ - CB_DATUMOPEN2(rec.key, kbuf, ksiz); - CB_DATUMOPEN2(rec.first, vbuf, vsiz); - rec.rest = NULL; - CB_LISTINSERT(recs, i, (char *)&rec, sizeof(VLREC)); - villa->rnum++; - break; - } - i++; - } - if(i >= ln){ - CB_DATUMOPEN2(rec.key, kbuf, ksiz); - CB_DATUMOPEN2(rec.first, vbuf, vsiz); - rec.rest = NULL; - CB_LISTPUSH(recs, (char *)&rec, sizeof(VLREC)); - villa->rnum++; - } - leaf->dirty = TRUE; - return TRUE; -} - - -/* Calculate the size of data of a leaf. - `leaf' specifies a leaf handle. - The return value is size of data of the leaf. */ -static int vlleafdatasize(VLLEAF *leaf){ - VLREC *recp; - CBLIST *recs, *rest; - const char *vbuf; - int i, j, sum, rnum, restnum, vsiz; - assert(leaf); - sum = 0; - recs = leaf->recs; - rnum = CB_LISTNUM(recs); - for(i = 0; i < rnum; i++){ - recp = (VLREC *)CB_LISTVAL(recs, i); - sum += CB_DATUMSIZE(recp->key); - sum += CB_DATUMSIZE(recp->first); - if(recp->rest){ - rest = recp->rest; - restnum = CB_LISTNUM(rest); - for(j = 0; j < restnum; j++){ - vbuf = CB_LISTVAL2(rest, j, vsiz); - sum += vsiz; - } - } - } - return sum; -} - - -/* Divide a leaf into two. - `villa' specifies a database handle. - `leaf' specifies a leaf handle. - The return value is the handle of a new leaf, or `NULL' on failure. */ -static VLLEAF *vlleafdivide(VILLA *villa, VLLEAF *leaf){ - VLLEAF *newleaf, *nextleaf; - VLREC *recp; - CBLIST *recs, *newrecs; - int i, mid, ln; - assert(villa && leaf); - villa->hleaf = -1; - recs = leaf->recs; - mid = CB_LISTNUM(recs) / 2; - recp = (VLREC *)CB_LISTVAL(recs, mid); - newleaf = vlleafnew(villa, leaf->id, leaf->next); - if(newleaf->next != -1){ - if(!(nextleaf = vlleafload(villa, newleaf->next))) return NULL; - nextleaf->prev = newleaf->id; - nextleaf->dirty = TRUE; - } - leaf->next = newleaf->id; - leaf->dirty = TRUE; - ln = CB_LISTNUM(recs); - newrecs = newleaf->recs; - for(i = mid; i < ln; i++){ - recp = (VLREC *)CB_LISTVAL(recs, i); - CB_LISTPUSH(newrecs, (char *)recp, sizeof(VLREC)); - } - ln = CB_LISTNUM(newrecs); - for(i = 0; i < ln; i++){ - CB_LISTDROP(recs); - } - return newleaf; -} - - -/* Create a new node. - `villa' specifies a database handle. - `heir' specifies the ID of the child before the first index. - The return value is a handle of the node. */ -static VLNODE *vlnodenew(VILLA *villa, int heir){ - VLNODE nent; - assert(villa && heir >= VL_LEAFIDMIN); - nent.id = villa->nnum + VL_NODEIDMIN; - nent.dirty = TRUE; - nent.heir = heir; - CB_LISTOPEN(nent.idxs); - villa->nnum++; - cbmapput(villa->nodec, (char *)&(nent.id), sizeof(int), (char *)&nent, sizeof(VLNODE), TRUE); - return (VLNODE *)cbmapget(villa->nodec, (char *)&(nent.id), sizeof(int), NULL); -} - - -/* Remove a node from the cache. - `villa' specifies a database handle. - `id' specifies the ID number of the node. - The return value is true if successful, else, it is false. */ -static int vlnodecacheout(VILLA *villa, int id){ - VLNODE *node; - VLIDX *idxp; - int i, err, ln; - assert(villa && id >= VL_NODEIDMIN); - if(!(node = (VLNODE *)cbmapget(villa->nodec, (char *)&id, sizeof(int), NULL))) return FALSE; - err = FALSE; - if(node->dirty && !vlnodesave(villa, node)) err = TRUE; - ln = CB_LISTNUM(node->idxs); - for(i = 0; i < ln; i++){ - idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); - CB_DATUMCLOSE(idxp->key); - } - CB_LISTCLOSE(node->idxs); - cbmapout(villa->nodec, (char *)&id, sizeof(int)); - return err ? FALSE : TRUE; -} - - -/* Save a node into the database. - `villa' specifies a database handle. - `node' specifies a node handle. - The return value is true if successful, else, it is false. */ -static int vlnodesave(VILLA *villa, VLNODE *node){ - CBDATUM *buf; - char vnumbuf[VL_VNUMBUFSIZ]; - VLIDX *idxp; - int i, heir, pid, ksiz, vnumsiz, ln; - assert(villa && node); - CB_DATUMOPEN(buf); - heir = node->heir; - VL_SETVNUMBUF(vnumsiz, vnumbuf, heir); - CB_DATUMCAT(buf, vnumbuf, vnumsiz); - ln = CB_LISTNUM(node->idxs); - for(i = 0; i < ln; i++){ - idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); - pid = idxp->pid; - VL_SETVNUMBUF(vnumsiz, vnumbuf, pid); - CB_DATUMCAT(buf, vnumbuf, vnumsiz); - ksiz = CB_DATUMSIZE(idxp->key); - VL_SETVNUMBUF(vnumsiz, vnumbuf, ksiz); - CB_DATUMCAT(buf, vnumbuf, vnumsiz); - CB_DATUMCAT(buf, CB_DATUMPTR(idxp->key), ksiz); - } - if(!dpput(villa->depot, (char *)&(node->id), sizeof(int), - CB_DATUMPTR(buf), CB_DATUMSIZE(buf), DP_DOVER)){ - CB_DATUMCLOSE(buf); - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return FALSE; - } - CB_DATUMCLOSE(buf); - node->dirty = FALSE; - return TRUE; -} - - -/* Load a node from the database. - `villa' specifies a database handle. - `id' specifies the ID number of the node. - If successful, the return value is the pointer to the node, else, it is `NULL'. */ -static VLNODE *vlnodeload(VILLA *villa, int id){ - char wbuf[VL_PAGEBUFSIZ], *buf, *rp, *kbuf; - int size, step, heir, pid, ksiz; - VLNODE *node, nent; - VLIDX idx; - assert(villa && id >= VL_NODEIDMIN); - if((node = (VLNODE *)cbmapget(villa->nodec, (char *)&id, sizeof(int), NULL)) != NULL){ - cbmapmove(villa->nodec, (char *)&id, sizeof(int), FALSE); - return node; - } - heir = -1; - if((size = dpgetwb(villa->depot, (char *)&id, sizeof(int), 0, VL_PAGEBUFSIZ, wbuf)) > 0 && - size < VL_PAGEBUFSIZ){ - buf = NULL; - } else if(!(buf = dpget(villa->depot, (char *)&id, sizeof(int), 0, -1, &size))){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return NULL; - } - rp = buf ? buf : wbuf; - if(size >= 1){ - VL_READVNUMBUF(rp, size, heir, step); - rp += step; - size -= step; - } - if(heir < 0){ - free(buf); - return NULL; - } - nent.id = id; - nent.dirty = FALSE; - nent.heir = heir; - CB_LISTOPEN(nent.idxs); - while(size >= 1){ - VL_READVNUMBUF(rp, size, pid, step); - rp += step; - size -= step; - if(size < 1) break; - VL_READVNUMBUF(rp, size, ksiz, step); - rp += step; - size -= step; - if(size < ksiz) break; - kbuf = rp; - rp += ksiz; - size -= ksiz; - idx.pid = pid; - CB_DATUMOPEN2(idx.key, kbuf, ksiz); - CB_LISTPUSH(nent.idxs, (char *)&idx, sizeof(VLIDX)); - } - free(buf); - cbmapput(villa->nodec, (char *)&(nent.id), sizeof(int), (char *)&nent, sizeof(VLNODE), TRUE); - return (VLNODE *)cbmapget(villa->nodec, (char *)&(nent.id), sizeof(int), NULL); -} - - -/* Add an index to a node. - `villa' specifies a database handle. - `node' specifies a node handle. - `order' specifies whether the calling sequence is orderd or not. - `pid' specifies the ID number of referred page. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. */ -static void vlnodeaddidx(VILLA *villa, VLNODE *node, int order, - int pid, const char *kbuf, int ksiz){ - VLIDX idx, *idxp; - int i, rv, left, right, ln; - assert(villa && node && pid >= VL_LEAFIDMIN && kbuf && ksiz >= 0); - idx.pid = pid; - CB_DATUMOPEN2(idx.key, kbuf, ksiz); - if(order){ - CB_LISTPUSH(node->idxs, (char *)&idx, sizeof(VLIDX)); - } else { - left = 0; - right = CB_LISTNUM(node->idxs); - i = (left + right) / 2; - ln = CB_LISTNUM(node->idxs); - while(right >= left && i < ln){ - idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); - rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); - if(rv == 0){ - break; - } else if(rv <= 0){ - right = i - 1; - } else { - left = i + 1; - } - i = (left + right) / 2; - } - ln = CB_LISTNUM(node->idxs); - while(i < ln){ - idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); - if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)) < 0){ - CB_LISTINSERT(node->idxs, i, (char *)&idx, sizeof(VLIDX)); - break; - } - i++; - } - if(i >= CB_LISTNUM(node->idxs)) CB_LISTPUSH(node->idxs, (char *)&idx, sizeof(VLIDX)); - } - node->dirty = TRUE; -} - - -/* Search the leaf corresponding to a key. - `villa' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. - The return value is the ID number of the leaf, or -1 on failure. */ -static int vlsearchleaf(VILLA *villa, const char *kbuf, int ksiz){ - VLNODE *node; - VLIDX *idxp; - int i, pid, rv, left, right, ln; - assert(villa && kbuf && ksiz >= 0); - pid = villa->root; - idxp = NULL; - villa->hnum = 0; - villa->hleaf = -1; - while(pid >= VL_NODEIDMIN){ - if(!(node = vlnodeload(villa, pid)) || (ln = CB_LISTNUM(node->idxs)) < 1){ - dpecodeset(DP_EBROKEN, __FILE__, __LINE__); - return -1; - } - villa->hist[villa->hnum++] = node->id; - left = 1; - right = ln; - i = (left + right) / 2; - while(right >= left && i < ln){ - idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); - rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); - if(rv == 0){ - break; - } else if(rv <= 0){ - right = i - 1; - } else { - left = i + 1; - } - i = (left + right) / 2; - } - if(i > 0) i--; - while(i < ln){ - idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); - if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)) < 0){ - if(i == 0){ - pid = node->heir; - break; - } - idxp = (VLIDX *)CB_LISTVAL(node->idxs, i - 1); - pid = idxp->pid; - break; - } - i++; - } - if(i >= ln) pid = idxp->pid; - } - if(villa->lleaf == pid) villa->hleaf = pid; - villa->lleaf = pid; - return pid; -} - - -/* Adjust the caches for leaves and nodes. - `villa' specifies a database handle. - The return value is true if successful, else, it is false. */ -static int vlcacheadjust(VILLA *villa){ - const char *tmp; - int i, pid, err; - err = FALSE; - if(cbmaprnum(villa->leafc) > villa->leafcnum){ - cbmapiterinit(villa->leafc); - for(i = 0; i < VL_CACHEOUT; i++){ - tmp = cbmapiternext(villa->leafc, NULL); - pid = *(int *)tmp; - if(!vlleafcacheout(villa, pid)) err = TRUE; - } - } - if(cbmaprnum(villa->nodec) > villa->nodecnum){ - cbmapiterinit(villa->nodec); - for(i = 0; i < VL_CACHEOUT; i++){ - tmp = cbmapiternext(villa->nodec, NULL); - pid = *(int *)tmp; - if(!vlnodecacheout(villa, pid)) err = TRUE; - } - } - return err ? FALSE : TRUE; -} - - -/* Search a record of a leaf. - `villa' specifies a database handle. - `leaf' specifies a leaf handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. - `ip' specifies the pointer to a variable to fetch the index of the correspnding record. - The return value is the pointer to a corresponding record, or `NULL' on failure. */ -static VLREC *vlrecsearch(VILLA *villa, VLLEAF *leaf, const char *kbuf, int ksiz, int *ip){ - VLREC *recp; - CBLIST *recs; - int i, rv, left, right, ln; - assert(villa && leaf && kbuf && ksiz >= 0); - recs = leaf->recs; - ln = CB_LISTNUM(recs); - left = 0; - right = ln; - i = (left + right) / 2; - while(right >= left && i < ln){ - recp = (VLREC *)CB_LISTVAL(recs, i); - rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); - if(rv == 0){ - if(ip) *ip = i; - return recp; - } else if(rv <= 0){ - right = i - 1; - } else { - left = i + 1; - } - i = (left + right) / 2; - } - if(ip) *ip = i; - return NULL; -} - - -/* Get flags of a database. */ -int vlgetflags(VILLA *villa){ - assert(villa); - return dpgetflags(villa->depot); -} - - -/* Set flags of a database. - `villa' specifies a database handle connected as a writer. - `flags' specifies flags to set. Lesser ten bits are reserved for internal use. - If successful, the return value is true, else, it is false. */ -int vlsetflags(VILLA *villa, int flags){ - assert(villa); - if(!villa->wmode){ - dpecodeset(DP_EMODE, __FILE__, __LINE__); - return FALSE; - } - return dpsetflags(villa->depot, flags); -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/villa.c (from rev 2716, box/trunk/qdbm/villa.c) =================================================================== --- box/trunk/qdbm/villa.c (rev 0) +++ box/trunk/qdbm/villa.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,2666 @@ +/************************************************************************************************* + * Implementation of Villa + * 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. + *************************************************************************************************/ + + +#define QDBM_INTERNAL 1 + +#include "villa.h" +#include "myconf.h" + +#define VL_LEAFIDMIN 1 /* minimum number of leaf ID */ +#define VL_NODEIDMIN 100000000 /* minimum number of node ID */ +#define VL_VNUMBUFSIZ 8 /* size of a buffer for variable length number */ +#define VL_NUMBUFSIZ 32 /* size of a buffer for a number */ +#define VL_PAGEBUFSIZ 32768 /* size of a buffer to read each page */ +#define VL_MAXLEAFSIZ 49152 /* maximum size of each leaf */ +#define VL_DEFLRECMAX 49 /* default number of records in each leaf */ +#define VL_DEFNIDXMAX 192 /* default number of indexes in each node */ +#define VL_DEFLCNUM 1024 /* default number of leaf cache */ +#define VL_DEFNCNUM 512 /* default number of node cache */ +#define VL_CACHEOUT 8 /* number of pages in a process of cacheout */ +#define VL_INITBNUM 32749 /* initial bucket number */ +#define VL_PAGEALIGN -3 /* alignment for pages */ +#define VL_FBPOOLSIZ 128 /* size of free block pool */ +#define VL_PATHBUFSIZ 1024 /* size of a path buffer */ +#define VL_TMPFSUF MYEXTSTR "vltmp" /* suffix of a temporary file */ +#define VL_ROOTKEY -1 /* key of the root key */ +#define VL_LASTKEY -2 /* key of the last key */ +#define VL_LNUMKEY -3 /* key of the number of leaves */ +#define VL_NNUMKEY -4 /* key of the number of nodes */ +#define VL_RNUMKEY -5 /* key of the number of records */ +#define VL_CRDNUM 7 /* default division number for Vista */ + +/* set a buffer for a variable length number */ +#define VL_SETVNUMBUF(VL_len, VL_buf, VL_num) \ + do { \ + int _VL_num; \ + _VL_num = VL_num; \ + if(_VL_num == 0){ \ + ((signed char *)(VL_buf))[0] = 0; \ + (VL_len) = 1; \ + } else { \ + (VL_len) = 0; \ + while(_VL_num > 0){ \ + int _VL_rem = _VL_num & 0x7f; \ + _VL_num >>= 7; \ + if(_VL_num > 0){ \ + ((signed char *)(VL_buf))[(VL_len)] = -_VL_rem - 1; \ + } else { \ + ((signed char *)(VL_buf))[(VL_len)] = _VL_rem; \ + } \ + (VL_len)++; \ + } \ + } \ + } while(FALSE) + +/* read a variable length buffer */ +#define VL_READVNUMBUF(VL_buf, VL_size, VL_num, VL_step) \ + do { \ + int _VL_i, _VL_base; \ + (VL_num) = 0; \ + _VL_base = 1; \ + if((VL_size) < 2){ \ + (VL_num) = ((signed char *)(VL_buf))[0]; \ + (VL_step) = 1; \ + } else { \ + for(_VL_i = 0; _VL_i < (VL_size); _VL_i++){ \ + if(((signed char *)(VL_buf))[_VL_i] >= 0){ \ + (VL_num) += ((signed char *)(VL_buf))[_VL_i] * _VL_base; \ + break; \ + } \ + (VL_num) += _VL_base * (((signed char *)(VL_buf))[_VL_i] + 1) * -1; \ + _VL_base *= 128; \ + } \ + (VL_step) = _VL_i + 1; \ + } \ + } while(FALSE) + +enum { /* enumeration for flags */ + VL_FLISVILLA = 1 << 0, /* whether for Villa */ + VL_FLISZLIB = 1 << 1, /* whether with ZLIB */ + VL_FLISLZO = 1 << 2, /* whether with LZO */ + VL_FLISBZIP = 1 << 3 /* whether with BZIP2 */ +}; + + +/* private function prototypes */ +static int vllexcompare(const char *aptr, int asiz, const char *bptr, int bsiz); +static int vlintcompare(const char *aptr, int asiz, const char *bptr, int bsiz); +static int vlnumcompare(const char *aptr, int asiz, const char *bptr, int bsiz); +static int vldeccompare(const char *aptr, int asiz, const char *bptr, int bsiz); +static int vldpputnum(DEPOT *depot, int knum, int vnum); +static int vldpgetnum(DEPOT *depot, int knum, int *vnp); +static VLLEAF *vlleafnew(VILLA *villa, int prev, int next); +static int vlleafcacheout(VILLA *villa, int id); +static int vlleafsave(VILLA *villa, VLLEAF *leaf); +static VLLEAF *vlleafload(VILLA *villa, int id); +static VLLEAF *vlgethistleaf(VILLA *villa, const char *kbuf, int ksiz); +static int vlleafaddrec(VILLA *villa, VLLEAF *leaf, int dmode, + const char *kbuf, int ksiz, const char *vbuf, int vsiz); +static int vlleafdatasize(VLLEAF *leaf); +static VLLEAF *vlleafdivide(VILLA *villa, VLLEAF *leaf); +static VLNODE *vlnodenew(VILLA *villa, int heir); +static int vlnodecacheout(VILLA *villa, int id); +static int vlnodesave(VILLA *villa, VLNODE *node); +static VLNODE *vlnodeload(VILLA *villa, int id); +static void vlnodeaddidx(VILLA *villa, VLNODE *node, int order, + int pid, const char *kbuf, int ksiz); +static int vlsearchleaf(VILLA *villa, const char *kbuf, int ksiz); +static int vlcacheadjust(VILLA *villa); +static VLREC *vlrecsearch(VILLA *villa, VLLEAF *leaf, const char *kbuf, int ksiz, int *ip); + + + +/************************************************************************************************* + * public objects + *************************************************************************************************/ + + +/* Comparing functions. */ +VLCFUNC VL_CMPLEX = vllexcompare; +VLCFUNC VL_CMPINT = vlintcompare; +VLCFUNC VL_CMPNUM = vlnumcompare; +VLCFUNC VL_CMPDEC = vldeccompare; + + +/* Get a database handle. */ +VILLA *vlopen(const char *name, int omode, VLCFUNC cmp){ + DEPOT *depot; + int dpomode, flags, cmode, root, last, lnum, nnum, rnum; + VILLA *villa; + VLLEAF *leaf; + assert(name && cmp); + dpomode = DP_OREADER; + if(omode & VL_OWRITER){ + dpomode = DP_OWRITER; + if(omode & VL_OCREAT) dpomode |= DP_OCREAT; + if(omode & VL_OTRUNC) dpomode |= DP_OTRUNC; + } + if(omode & VL_ONOLCK) dpomode |= DP_ONOLCK; + if(omode & VL_OLCKNB) dpomode |= DP_OLCKNB; + if(!(depot = dpopen(name, dpomode, VL_INITBNUM))) return NULL; + flags = dpgetflags(depot); + cmode = 0; + root = -1; + last = -1; + lnum = 0; + nnum = 0; + rnum = 0; + if(dprnum(depot) > 0){ + if(!(flags & VL_FLISVILLA) || + !vldpgetnum(depot, VL_ROOTKEY, &root) || !vldpgetnum(depot, VL_LASTKEY, &last) || + !vldpgetnum(depot, VL_LNUMKEY, &lnum) || !vldpgetnum(depot, VL_NNUMKEY, &nnum) || + !vldpgetnum(depot, VL_RNUMKEY, &rnum) || root < VL_LEAFIDMIN || last < VL_LEAFIDMIN || + lnum < 0 || nnum < 0 || rnum < 0){ + dpclose(depot); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + if(flags & VL_FLISZLIB){ + cmode = VL_OZCOMP; + } else if(flags & VL_FLISLZO){ + cmode = VL_OYCOMP; + } else if(flags & VL_FLISBZIP){ + cmode = VL_OXCOMP; + } + } else if(omode & VL_OWRITER){ + if(omode & VL_OZCOMP){ + cmode = VL_OZCOMP; + } else if(omode & VL_OYCOMP){ + cmode = VL_OYCOMP; + } else if(omode & VL_OXCOMP){ + cmode = VL_OXCOMP; + } + } + if(omode & VL_OWRITER){ + flags |= VL_FLISVILLA; + if(_qdbm_deflate && cmode == VL_OZCOMP){ + flags |= VL_FLISZLIB; + } else if(_qdbm_lzoencode && cmode == VL_OYCOMP){ + flags |= VL_FLISLZO; + } else if(_qdbm_bzencode && cmode == VL_OXCOMP){ + flags |= VL_FLISBZIP; + } + if(!dpsetflags(depot, flags) || !dpsetalign(depot, VL_PAGEALIGN) || + !dpsetfbpsiz(depot, VL_FBPOOLSIZ)){ + dpclose(depot); + return NULL; + } + } + CB_MALLOC(villa, sizeof(VILLA)); + villa->depot = depot; + villa->cmp = cmp; + villa->wmode = (omode & VL_OWRITER); + villa->cmode = cmode; + villa->root = root; + villa->last = last; + villa->lnum = lnum; + villa->nnum = nnum; + villa->rnum = rnum; + villa->leafc = cbmapopen(); + villa->nodec = cbmapopen(); + villa->hnum = 0; + villa->hleaf = -1; + villa->lleaf = -1; + villa->curleaf = -1; + villa->curknum = -1; + villa->curvnum = -1; + villa->leafrecmax = VL_DEFLRECMAX; + villa->nodeidxmax = VL_DEFNIDXMAX; + villa->leafcnum = VL_DEFLCNUM; + villa->nodecnum = VL_DEFNCNUM; + villa->tran = FALSE; + villa->rbroot = -1; + villa->rblast = -1; + villa->rblnum = -1; + villa->rbnnum = -1; + villa->rbrnum = -1; + if(root == -1){ + leaf = vlleafnew(villa, -1, -1); + villa->root = leaf->id; + villa->last = leaf->id; + if(!vltranbegin(villa) || !vltranabort(villa)){ + vlclose(villa); + return NULL; + } + } + return villa; +} + + +/* Close a database handle. */ +int vlclose(VILLA *villa){ + int err, pid; + const char *tmp; + assert(villa); + err = FALSE; + if(villa->tran){ + if(!vltranabort(villa)) err = TRUE; + } + cbmapiterinit(villa->leafc); + while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ + pid = *(int *)tmp; + if(!vlleafcacheout(villa, pid)) err = TRUE; + } + cbmapiterinit(villa->nodec); + while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ + pid = *(int *)tmp; + if(!vlnodecacheout(villa, pid)) err = TRUE; + } + if(villa->wmode){ + if(!dpsetalign(villa->depot, 0)) err = TRUE; + if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; + if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; + if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; + if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; + if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; + } + cbmapclose(villa->leafc); + cbmapclose(villa->nodec); + if(!dpclose(villa->depot)) err = TRUE; + free(villa); + return err ? FALSE : TRUE; +} + + +/* Store a record. */ +int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ + VLLEAF *leaf, *newleaf; + VLNODE *node, *newnode; + VLIDX *idxp; + CBDATUM *key; + int i, pid, todiv, heir, parent, mid; + assert(villa && kbuf && vbuf); + villa->curleaf = -1; + villa->curknum = -1; + villa->curvnum = -1; + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(ksiz < 0) ksiz = strlen(kbuf); + if(vsiz < 0) vsiz = strlen(vbuf); + if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ + if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return FALSE; + if(!(leaf = vlleafload(villa, pid))) return FALSE; + } + if(!vlleafaddrec(villa, leaf, dmode, kbuf, ksiz, vbuf, vsiz)){ + dpecodeset(DP_EKEEP, __FILE__, __LINE__); + return FALSE; + } + todiv = FALSE; + switch(CB_LISTNUM(leaf->recs) % 4){ + case 0: + if(CB_LISTNUM(leaf->recs) >= 4 && + vlleafdatasize(leaf) > VL_MAXLEAFSIZ * (villa->cmode > 0 ? 2 : 1)){ + todiv = TRUE; + break; + } + case 2: + if(CB_LISTNUM(leaf->recs) > villa->leafrecmax) todiv = TRUE; + break; + } + if(todiv){ + if(!(newleaf = vlleafdivide(villa, leaf))) return FALSE; + if(leaf->id == villa->last) villa->last = newleaf->id; + heir = leaf->id; + pid = newleaf->id; + key = ((VLREC *)CB_LISTVAL(newleaf->recs, 0))->key; + key = cbdatumdup(key); + while(TRUE){ + if(villa->hnum < 1){ + node = vlnodenew(villa, heir); + vlnodeaddidx(villa, node, TRUE, pid, CB_DATUMPTR(key), CB_DATUMSIZE(key)); + villa->root = node->id; + CB_DATUMCLOSE(key); + break; + } + parent = villa->hist[--villa->hnum]; + if(!(node = vlnodeload(villa, parent))){ + CB_DATUMCLOSE(key); + return FALSE; + } + vlnodeaddidx(villa, node, FALSE, pid, CB_DATUMPTR(key), CB_DATUMSIZE(key)); + CB_DATUMCLOSE(key); + if(CB_LISTNUM(node->idxs) <= villa->nodeidxmax) break; + mid = CB_LISTNUM(node->idxs) / 2; + idxp = (VLIDX *)CB_LISTVAL(node->idxs, mid); + newnode = vlnodenew(villa, idxp->pid); + heir = node->id; + pid = newnode->id; + CB_DATUMOPEN2(key, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); + for(i = mid + 1; i < CB_LISTNUM(node->idxs); i++){ + idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); + vlnodeaddidx(villa, newnode, TRUE, idxp->pid, + CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); + } + for(i = 0; i < CB_LISTNUM(newnode->idxs); i++){ + idxp = (VLIDX *)cblistpop(node->idxs, NULL); + CB_DATUMCLOSE(idxp->key); + free(idxp); + } + node->dirty = TRUE; + } + } + if(!villa->tran && !vlcacheadjust(villa)) return FALSE; + return TRUE; +} + + +/* Delete a record. */ +int vlout(VILLA *villa, const char *kbuf, int ksiz){ + VLLEAF *leaf; + VLREC *recp; + int pid, ri, vsiz; + char *vbuf; + assert(villa && kbuf); + villa->curleaf = -1; + villa->curknum = -1; + villa->curvnum = -1; + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(ksiz < 0) ksiz = strlen(kbuf); + if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ + if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return FALSE; + if(!(leaf = vlleafload(villa, pid))) return FALSE; + } + if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, &ri))){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(recp->rest){ + CB_DATUMCLOSE(recp->first); + vbuf = cblistshift(recp->rest, &vsiz); + CB_DATUMOPEN2(recp->first, vbuf, vsiz); + free(vbuf); + if(CB_LISTNUM(recp->rest) < 1){ + CB_LISTCLOSE(recp->rest); + recp->rest = NULL; + } + } else { + CB_DATUMCLOSE(recp->key); + CB_DATUMCLOSE(recp->first); + free(cblistremove(leaf->recs, ri, NULL)); + } + leaf->dirty = TRUE; + villa->rnum--; + if(!villa->tran && !vlcacheadjust(villa)) return FALSE; + return TRUE; +} + + +/* Retrieve a record. */ +char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp){ + VLLEAF *leaf; + VLREC *recp; + char *rv; + int pid; + assert(villa && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ + if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; + if(!(leaf = vlleafload(villa, pid))) return NULL; + } + if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return NULL; + } + if(!villa->tran && !vlcacheadjust(villa)) return NULL; + if(sp) *sp = CB_DATUMSIZE(recp->first); + CB_MEMDUP(rv, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); + return rv; +} + + +/* Get the size of the value of a record. */ +int vlvsiz(VILLA *villa, const char *kbuf, int ksiz){ + VLLEAF *leaf; + VLREC *recp; + int pid; + assert(villa && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ + if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return -1; + if(!(leaf = vlleafload(villa, pid))) return -1; + } + if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return -1; + } + if(!villa->tran && !vlcacheadjust(villa)) return -1; + return CB_DATUMSIZE(recp->first); +} + + +/* Get the number of records corresponding a key. */ +int vlvnum(VILLA *villa, const char *kbuf, int ksiz){ + VLLEAF *leaf; + VLREC *recp; + int pid; + assert(villa && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ + if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return 0; + if(!(leaf = vlleafload(villa, pid))) return 0; + } + if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return 0; + } + if(!villa->tran && !vlcacheadjust(villa)) return 0; + return 1 + (recp->rest ? CB_LISTNUM(recp->rest) : 0); +} + + +/* Store plural records corresponding a key. */ +int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals){ + int i, vsiz; + const char *vbuf; + assert(villa && kbuf && vals); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(CB_LISTNUM(vals) < 1){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + if(ksiz < 0) ksiz = strlen(kbuf); + for(i = 0; i < CB_LISTNUM(vals); i++){ + vbuf = CB_LISTVAL2(vals, i, vsiz); + if(!vlput(villa, kbuf, ksiz, vbuf, vsiz, VL_DDUP)) return FALSE; + } + return TRUE; +} + + +/* Delete all records corresponding a key. */ +int vloutlist(VILLA *villa, const char *kbuf, int ksiz){ + int i, vnum; + assert(villa && kbuf); + if(!villa->wmode){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + if(ksiz < 0) ksiz = strlen(kbuf); + if((vnum = vlvnum(villa, kbuf, ksiz)) < 1) return FALSE; + for(i = 0; i < vnum; i++){ + if(!vlout(villa, kbuf, ksiz)) return FALSE; + } + return TRUE; +} + + +/* Retrieve values of all records corresponding a key. */ +CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz){ + VLLEAF *leaf; + VLREC *recp; + int pid, i, vsiz; + CBLIST *vals; + const char *vbuf; + assert(villa && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ + if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; + if(!(leaf = vlleafload(villa, pid))) return NULL; + } + if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return NULL; + } + CB_LISTOPEN(vals); + CB_LISTPUSH(vals, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); + if(recp->rest){ + for(i = 0; i < CB_LISTNUM(recp->rest); i++){ + vbuf = CB_LISTVAL2(recp->rest, i, vsiz); + CB_LISTPUSH(vals, vbuf, vsiz); + } + } + if(!villa->tran && !vlcacheadjust(villa)){ + CB_LISTCLOSE(vals); + return NULL; + } + return vals; +} + + +/* Retrieve concatenated values of all records corresponding a key. */ +char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp){ + VLLEAF *leaf; + VLREC *recp; + int pid, i, vsiz, rsiz; + char *rbuf; + const char *vbuf; + assert(villa && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ + if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; + if(!(leaf = vlleafload(villa, pid))) return NULL; + } + if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return NULL; + } + rsiz = CB_DATUMSIZE(recp->first); + CB_MALLOC(rbuf, rsiz + 1); + memcpy(rbuf, CB_DATUMPTR(recp->first), rsiz); + if(recp->rest){ + for(i = 0; i < CB_LISTNUM(recp->rest); i++){ + vbuf = CB_LISTVAL2(recp->rest, i, vsiz); + CB_REALLOC(rbuf, rsiz + vsiz + 1); + memcpy(rbuf + rsiz, vbuf, vsiz); + rsiz += vsiz; + } + } + rbuf[rsiz] = '\0'; + if(!villa->tran && !vlcacheadjust(villa)){ + free(rbuf); + return NULL; + } + if(sp) *sp = rsiz; + return rbuf; +} + + +/* Move the cursor to the first record. */ +int vlcurfirst(VILLA *villa){ + VLLEAF *leaf; + assert(villa); + villa->curleaf = VL_LEAFIDMIN; + villa->curknum = 0; + villa->curvnum = 0; + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + while(CB_LISTNUM(leaf->recs) < 1){ + villa->curleaf = leaf->next; + villa->curknum = 0; + villa->curvnum = 0; + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + } + return TRUE; +} + + +/* Move the cursor to the last record. */ +int vlcurlast(VILLA *villa){ + VLLEAF *leaf; + VLREC *recp; + assert(villa); + villa->curleaf = villa->last; + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + while(CB_LISTNUM(leaf->recs) < 1){ + villa->curleaf = leaf->prev; + if(villa->curleaf == -1){ + villa->curleaf = -1; + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + } + villa->curknum = CB_LISTNUM(leaf->recs) - 1; + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0; + return TRUE; +} + + +/* Move the cursor to the previous record. */ +int vlcurprev(VILLA *villa){ + VLLEAF *leaf; + VLREC *recp; + assert(villa); + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf)) || CB_LISTNUM(leaf->recs) < 1){ + villa->curleaf = -1; + return FALSE; + } + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + villa->curvnum--; + if(villa->curvnum < 0){ + villa->curknum--; + if(villa->curknum < 0){ + villa->curleaf = leaf->prev; + if(villa->curleaf == -1){ + villa->curleaf = -1; + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + while(CB_LISTNUM(leaf->recs) < 1){ + villa->curleaf = leaf->prev; + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + } + villa->curknum = CB_LISTNUM(leaf->recs) - 1; + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0; + } + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0; + } + if(!villa->tran && !vlcacheadjust(villa)) return FALSE; + return TRUE; +} + + +/* Move the cursor to the next record. */ +int vlcurnext(VILLA *villa){ + VLLEAF *leaf; + VLREC *recp; + assert(villa); + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf)) || CB_LISTNUM(leaf->recs) < 1){ + villa->curleaf = -1; + return FALSE; + } + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + villa->curvnum++; + if(villa->curvnum > (recp->rest ? CB_LISTNUM(recp->rest) : 0)){ + villa->curknum++; + villa->curvnum = 0; + } + if(villa->curknum >= CB_LISTNUM(leaf->recs)){ + villa->curleaf = leaf->next; + villa->curknum = 0; + villa->curvnum = 0; + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + while(CB_LISTNUM(leaf->recs) < 1){ + villa->curleaf = leaf->next; + villa->curknum = 0; + villa->curvnum = 0; + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + } + } + if(!villa->tran && !vlcacheadjust(villa)) return FALSE; + return TRUE; +} + + +/* Move the cursor to a position around a record. */ +int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode){ + VLLEAF *leaf; + VLREC *recp; + int pid, index; + assert(villa && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1){ + villa->curleaf = -1; + return FALSE; + } + if(!(leaf = vlleafload(villa, pid))){ + villa->curleaf = -1; + return FALSE; + } + while(CB_LISTNUM(leaf->recs) < 1){ + villa->curleaf = (jmode == VL_JFORWARD) ? leaf->next : leaf->prev; + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + } + if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, &index))){ + if(jmode == VL_JFORWARD){ + villa->curleaf = leaf->id; + if(index >= CB_LISTNUM(leaf->recs)) index--; + villa->curknum = index; + villa->curvnum = 0; + recp = (VLREC *)CB_LISTVAL(leaf->recs, index); + if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)) < 0) return TRUE; + villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0); + return vlcurnext(villa); + } else { + villa->curleaf = leaf->id; + if(index >= CB_LISTNUM(leaf->recs)) index--; + villa->curknum = index; + recp = (VLREC *)CB_LISTVAL(leaf->recs, index); + villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0); + if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)) > 0) return TRUE; + villa->curvnum = 0; + return vlcurprev(villa); + } + } + if(jmode == VL_JFORWARD){ + villa->curleaf = pid; + villa->curknum = index; + villa->curvnum = 0; + } else { + villa->curleaf = pid; + villa->curknum = index; + villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0); + } + return TRUE; +} + + +/* Get the key of the record where the cursor is. */ +char *vlcurkey(VILLA *villa, int *sp){ + VLLEAF *leaf; + VLREC *recp; + const char *kbuf; + char *rv; + int ksiz; + assert(villa); + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + kbuf = CB_DATUMPTR(recp->key); + ksiz = CB_DATUMSIZE(recp->key); + if(sp) *sp = ksiz; + CB_MEMDUP(rv, kbuf, ksiz); + return rv; +} + + +/* Get the value of the record where the cursor is. */ +char *vlcurval(VILLA *villa, int *sp){ + VLLEAF *leaf; + VLREC *recp; + const char *vbuf; + char *rv; + int vsiz; + assert(villa); + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + if(villa->curvnum < 1){ + vbuf = CB_DATUMPTR(recp->first); + vsiz = CB_DATUMSIZE(recp->first); + } else { + vbuf = CB_LISTVAL2(recp->rest, villa->curvnum - 1, vsiz); + } + if(sp) *sp = vsiz; + CB_MEMDUP(rv, vbuf, vsiz); + return rv; +} + + +/* Insert a record around the cursor. */ +int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode){ + VLLEAF *leaf; + VLREC *recp; + char *tbuf; + int tsiz; + assert(villa && vbuf); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(vsiz < 0) vsiz = strlen(vbuf); + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + switch(cpmode){ + case VL_CPBEFORE: + if(villa->curvnum < 1){ + if(!recp->rest){ + CB_DATUMTOMALLOC(recp->first, tbuf, tsiz); + CB_DATUMOPEN2(recp->first, vbuf, vsiz); + CB_LISTOPEN(recp->rest); + CB_LISTPUSHBUF(recp->rest, tbuf, tsiz); + } else { + cblistunshift(recp->rest, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); + CB_DATUMSETSIZE(recp->first, 0); + CB_DATUMCAT(recp->first, vbuf, vsiz); + } + } else { + CB_LISTINSERT(recp->rest, villa->curvnum - 1, vbuf, vsiz); + } + villa->rnum++; + break; + case VL_CPAFTER: + if(!recp->rest) CB_LISTOPEN(recp->rest); + CB_LISTINSERT(recp->rest, villa->curvnum, vbuf, vsiz); + villa->curvnum++; + villa->rnum++; + break; + default: + if(villa->curvnum < 1){ + CB_DATUMSETSIZE(recp->first, 0); + CB_DATUMCAT(recp->first, vbuf, vsiz); + } else { + cblistover(recp->rest, villa->curvnum - 1, vbuf, vsiz); + } + break; + } + leaf->dirty = TRUE; + return TRUE; +} + + +/* Delete the record where the cursor is. */ +int vlcurout(VILLA *villa){ + VLLEAF *leaf; + VLREC *recp; + char *vbuf; + int vsiz; + assert(villa); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + if(villa->curvnum < 1){ + if(recp->rest){ + vbuf = cblistshift(recp->rest, &vsiz); + CB_DATUMSETSIZE(recp->first, 0); + CB_DATUMCAT(recp->first, vbuf, vsiz); + free(vbuf); + if(CB_LISTNUM(recp->rest) < 1){ + CB_LISTCLOSE(recp->rest); + recp->rest = NULL; + } + } else { + CB_DATUMCLOSE(recp->first); + CB_DATUMCLOSE(recp->key); + free(cblistremove(leaf->recs, villa->curknum, NULL)); + } + } else { + free(cblistremove(recp->rest, villa->curvnum - 1, NULL)); + if(villa->curvnum - 1 >= CB_LISTNUM(recp->rest)){ + villa->curknum++; + villa->curvnum = 0; + } + if(CB_LISTNUM(recp->rest) < 1){ + CB_LISTCLOSE(recp->rest); + recp->rest = NULL; + } + } + villa->rnum--; + leaf->dirty = TRUE; + if(villa->curknum >= CB_LISTNUM(leaf->recs)){ + villa->curleaf = leaf->next; + villa->curknum = 0; + villa->curvnum = 0; + while(villa->curleaf != -1 && (leaf = vlleafload(villa, villa->curleaf)) != NULL && + CB_LISTNUM(leaf->recs) < 1){ + villa->curleaf = leaf->next; + } + } + return TRUE; +} + + +/* Set the tuning parameters for performance. */ +void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum){ + assert(villa); + if(lrecmax < 1) lrecmax = VL_DEFLRECMAX; + if(lrecmax < 3) lrecmax = 3; + if(nidxmax < 1) nidxmax = VL_DEFNIDXMAX; + if(nidxmax < 4) nidxmax = 4; + if(lcnum < 1) lcnum = VL_DEFLCNUM; + if(lcnum < VL_CACHEOUT * 2) lcnum = VL_CACHEOUT * 2; + if(ncnum < 1) ncnum = VL_DEFNCNUM; + if(ncnum < VL_CACHEOUT * 2) ncnum = VL_CACHEOUT * 2; + villa->leafrecmax = lrecmax; + villa->nodeidxmax = nidxmax; + villa->leafcnum = lcnum; + villa->nodecnum = ncnum; +} + + +/* Set the size of the free block pool of a database handle. */ +int vlsetfbpsiz(VILLA *villa, int size){ + assert(villa && size >= 0); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + return dpsetfbpsiz(villa->depot, size); +} + + +/* Synchronize updating contents with the file and the device. */ +int vlsync(VILLA *villa){ + int err; + err = FALSE; + if(!vlmemsync(villa)) err = TRUE; + if(!dpsync(villa->depot)) err = TRUE; + return err ? FALSE : TRUE; +} + + +/* Optimize a database. */ +int vloptimize(VILLA *villa){ + int err; + assert(villa); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(villa->tran){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + if(!vlsync(villa)) return FALSE; + if(!dpoptimize(villa->depot, -1)) err = TRUE; + return err ? FALSE : TRUE; +} + + +/* Get the name of a database. */ +char *vlname(VILLA *villa){ + assert(villa); + return dpname(villa->depot); +} + + +/* Get the size of a database file. */ +int vlfsiz(VILLA *villa){ + return dpfsiz(villa->depot); +} + + +/* Get the number of the leaf nodes of B+ tree. */ +int vllnum(VILLA *villa){ + assert(villa); + return villa->lnum; +} + + +/* Get the number of the non-leaf nodes of B+ tree. */ +int vlnnum(VILLA *villa){ + assert(villa); + return villa->nnum; +} + + +/* Get the number of the records stored in a database. */ +int vlrnum(VILLA *villa){ + assert(villa); + return villa->rnum; +} + + +/* Check whether a database handle is a writer or not. */ +int vlwritable(VILLA *villa){ + assert(villa); + return villa->wmode; +} + + +/* Check whether a database has a fatal error or not. */ +int vlfatalerror(VILLA *villa){ + assert(villa); + return dpfatalerror(villa->depot); +} + + +/* Get the inode number of a database file. */ +int vlinode(VILLA *villa){ + assert(villa); + return dpinode(villa->depot); +} + + +/* Get the last modified time of a database. */ +time_t vlmtime(VILLA *villa){ + assert(villa); + return dpmtime(villa->depot); +} + + +/* Begin the transaction. */ +int vltranbegin(VILLA *villa){ + int err, pid; + const char *tmp; + VLLEAF *leaf; + VLNODE *node; + assert(villa); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(villa->tran){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + cbmapiterinit(villa->leafc); + while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ + pid = *(int *)tmp; + leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL); + if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE; + } + cbmapiterinit(villa->nodec); + while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ + pid = *(int *)tmp; + node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL); + if(node->dirty && !vlnodesave(villa, node)) err = TRUE; + } + if(!dpsetalign(villa->depot, 0)) err = TRUE; + if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; + if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; + if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; + if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; + if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; + if(!dpmemsync(villa->depot)) err = TRUE; + if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; + villa->tran = TRUE; + villa->rbroot = villa->root; + villa->rblast = villa->last; + villa->rblnum = villa->lnum; + villa->rbnnum = villa->nnum; + villa->rbrnum = villa->rnum; + return err ? FALSE : TRUE; +} + + +/* Commit the transaction. */ +int vltrancommit(VILLA *villa){ + int err, pid; + const char *tmp; + VLLEAF *leaf; + VLNODE *node; + assert(villa); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(!villa->tran){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + cbmapiterinit(villa->leafc); + while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ + pid = *(int *)tmp; + leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL); + if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE; + } + cbmapiterinit(villa->nodec); + while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ + pid = *(int *)tmp; + node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL); + if(node->dirty && !vlnodesave(villa, node)) err = TRUE; + } + if(!dpsetalign(villa->depot, 0)) err = TRUE; + if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; + if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; + if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; + if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; + if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; + if(!dpmemsync(villa->depot)) err = TRUE; + if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; + villa->tran = FALSE; + villa->rbroot = -1; + villa->rblast = -1; + villa->rblnum = -1; + villa->rbnnum = -1; + villa->rbrnum = -1; + while(cbmaprnum(villa->leafc) > villa->leafcnum || cbmaprnum(villa->nodec) > villa->nodecnum){ + if(!vlcacheadjust(villa)){ + err = TRUE; + break; + } + } + return err ? FALSE : TRUE; +} + + +/* Abort the transaction. */ +int vltranabort(VILLA *villa){ + int err, pid; + const char *tmp; + VLLEAF *leaf; + VLNODE *node; + assert(villa); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(!villa->tran){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + cbmapiterinit(villa->leafc); + while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ + pid = *(int *)tmp; + if(!(leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL))){ + err = TRUE; + continue; + } + if(leaf->dirty){ + leaf->dirty = FALSE; + if(!vlleafcacheout(villa, pid)) err = TRUE; + } + } + cbmapiterinit(villa->nodec); + while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ + pid = *(int *)tmp; + if(!(node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL))){ + err = TRUE; + continue; + } + if(node->dirty){ + node->dirty = FALSE; + if(!vlnodecacheout(villa, pid)) err = TRUE; + } + } + villa->tran = FALSE; + villa->root = villa->rbroot; + villa->last = villa->rblast; + villa->lnum = villa->rblnum; + villa->nnum = villa->rbnnum; + villa->rnum = villa->rbrnum; + while(cbmaprnum(villa->leafc) > villa->leafcnum || cbmaprnum(villa->nodec) > villa->nodecnum){ + if(!vlcacheadjust(villa)){ + err = TRUE; + break; + } + } + return err ? FALSE : TRUE; +} + + +/* Remove a database file. */ +int vlremove(const char *name){ + assert(name); + return dpremove(name); +} + + +/* Repair a broken database file. */ +int vlrepair(const char *name, VLCFUNC cmp){ + DEPOT *depot; + VILLA *tvilla; + char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *zbuf, *rp, *tkbuf, *tvbuf; + int i, err, flags, omode, ksiz, vsiz, zsiz, size, step, tksiz, tvsiz, vnum; + assert(name && cmp); + err = FALSE; + if(!dprepair(name)) err = TRUE; + if(!(depot = dpopen(name, DP_OREADER, -1))) return FALSE; + flags = dpgetflags(depot); + if(!(flags & VL_FLISVILLA)){ + dpclose(depot); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return FALSE; + } + sprintf(path, "%s%s", name, VL_TMPFSUF); + omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC; + if(flags & VL_FLISZLIB){ + omode |= VL_OZCOMP; + } else if(flags & VL_FLISLZO){ + omode |= VL_OXCOMP; + } else if(flags & VL_FLISBZIP){ + omode |= VL_OYCOMP; + } + if(!(tvilla = vlopen(path, omode, cmp))){ + dpclose(depot); + return FALSE; + } + if(!dpiterinit(depot)) err = TRUE; + while((kbuf = dpiternext(depot, &ksiz)) != NULL){ + if(ksiz == sizeof(int) && *(int *)kbuf < VL_NODEIDMIN && *(int *)kbuf > 0){ + if((vbuf = dpget(depot, (char *)kbuf, sizeof(int), 0, -1, &vsiz)) != NULL){ + if(_qdbm_inflate && (flags & VL_FLISZLIB) && + (zbuf = _qdbm_inflate(vbuf, vsiz, &zsiz, _QDBM_ZMRAW)) != NULL){ + free(vbuf); + vbuf = zbuf; + vsiz = zsiz; + } else if(_qdbm_lzodecode && (flags & VL_FLISLZO) && + (zbuf = _qdbm_lzodecode(vbuf, vsiz, &zsiz)) != NULL){ + free(vbuf); + vbuf = zbuf; + vsiz = zsiz; + } else if(_qdbm_bzdecode && (flags & VL_FLISBZIP) && + (zbuf = _qdbm_bzdecode(vbuf, vsiz, &zsiz)) != NULL){ + free(vbuf); + vbuf = zbuf; + vsiz = zsiz; + } + rp = vbuf; + size = vsiz; + if(size >= 1){ + VL_READVNUMBUF(rp, size, vnum, step); + rp += step; + size -= step; + } + if(size >= 1){ + VL_READVNUMBUF(rp, size, vnum, step); + rp += step; + size -= step; + } + while(size >= 1){ + VL_READVNUMBUF(rp, size, tksiz, step); + rp += step; + size -= step; + if(size < tksiz) break; + tkbuf = rp; + rp += tksiz; + size -= tksiz; + if(size < 1) break; + VL_READVNUMBUF(rp, size, vnum, step); + rp += step; + size -= step; + if(vnum < 1 || size < 1) break; + for(i = 0; i < vnum && size >= 1; i++){ + VL_READVNUMBUF(rp, size, tvsiz, step); + rp += step; + size -= step; + if(size < tvsiz) break; + tvbuf = rp; + rp += tvsiz; + size -= tvsiz; + if(!vlput(tvilla, tkbuf, tksiz, tvbuf, tvsiz, VL_DDUP)) err = TRUE; + } + } + free(vbuf); + } + } + free(kbuf); + } + if(!vlclose(tvilla)) err = TRUE; + if(!dpclose(depot)) err = TRUE; + if(!dpremove(name)) err = TRUE; + if(rename(path, name) == -1){ + if(!err) dpecodeset(DP_EMISC, __FILE__, __LINE__); + err = TRUE; + } + return err ? FALSE : TRUE; +} + + +/* Dump all records as endian independent data. */ +int vlexportdb(VILLA *villa, const char *name){ + DEPOT *depot; + char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *nkey; + int i, err, ksiz, vsiz, ki; + assert(villa && name); + sprintf(path, "%s%s", name, VL_TMPFSUF); + if(!(depot = dpopen(path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))) return FALSE; + err = FALSE; + vlcurfirst(villa); + for(i = 0; !err && (kbuf = vlcurkey(villa, &ksiz)) != NULL; i++){ + if((vbuf = vlcurval(villa, &vsiz)) != NULL){ + CB_MALLOC(nkey, ksiz + VL_NUMBUFSIZ); + ki = sprintf(nkey, "%X\t", i); + memcpy(nkey + ki, kbuf, ksiz); + if(!dpput(depot, nkey, ki + ksiz, vbuf, vsiz, DP_DKEEP)) err = TRUE; + free(nkey); + free(vbuf); + } else { + err = TRUE; + } + free(kbuf); + vlcurnext(villa); + } + if(!dpexportdb(depot, name)) err = TRUE; + if(!dpclose(depot)) err = TRUE; + if(!dpremove(path)) err = TRUE; + return !err && !vlfatalerror(villa); +} + + +/* Load all records from endian independent data. */ +int vlimportdb(VILLA *villa, const char *name){ + DEPOT *depot; + char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *rp; + int err, ksiz, vsiz; + assert(villa && name); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(vlrnum(villa) > 0){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + kbuf = dpname(villa->depot); + sprintf(path, "%s%s", kbuf, VL_TMPFSUF); + free(kbuf); + if(!(depot = dpopen(path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))) return FALSE; + err = FALSE; + if(!dpimportdb(depot, name)) err = TRUE; + dpiterinit(depot); + while(!err && (kbuf = dpiternext(depot, &ksiz)) != NULL){ + if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ + if((rp = strchr(kbuf, '\t')) != NULL){ + rp++; + if(!vlput(villa, rp, ksiz - (rp - kbuf), vbuf, vsiz, VL_DDUP)) err = TRUE; + } else { + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + err = TRUE; + } + free(vbuf); + } else { + err = TRUE; + } + free(kbuf); + } + if(!dpclose(depot)) err = TRUE; + if(!dpremove(path)) err = TRUE; + return !err && !vlfatalerror(villa); +} + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Number of division of the database for Vista. */ +int *vlcrdnumptr(void){ + static int defvlcrdnum = VL_CRDNUM; + void *ptr; + if(_qdbm_ptsafe){ + if(!(ptr = _qdbm_settsd(&defvlcrdnum, sizeof(int), &defvlcrdnum))){ + defvlcrdnum = DP_EMISC; + return &defvlcrdnum; + } + return (int *)ptr; + } + return &defvlcrdnum; +} + + +/* Synchronize updating contents on memory. */ +int vlmemsync(VILLA *villa){ + int err, pid; + const char *tmp; + assert(villa); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(villa->tran){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + cbmapiterinit(villa->leafc); + while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ + pid = *(int *)tmp; + if(!vlleafcacheout(villa, pid)) err = TRUE; + } + cbmapiterinit(villa->nodec); + while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ + pid = *(int *)tmp; + if(!vlnodecacheout(villa, pid)) err = TRUE; + } + if(!dpsetalign(villa->depot, 0)) err = TRUE; + if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; + if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; + if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; + if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; + if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; + if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; + if(!dpmemsync(villa->depot)) err = TRUE; + return err ? FALSE : TRUE; +} + + +/* Synchronize updating contents on memory, not physically. */ +int vlmemflush(VILLA *villa){ + int err, pid; + const char *tmp; + assert(villa); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + if(villa->tran){ + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + err = FALSE; + cbmapiterinit(villa->leafc); + while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ + pid = *(int *)tmp; + if(!vlleafcacheout(villa, pid)) err = TRUE; + } + cbmapiterinit(villa->nodec); + while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ + pid = *(int *)tmp; + if(!vlnodecacheout(villa, pid)) err = TRUE; + } + if(!dpsetalign(villa->depot, 0)) err = TRUE; + if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; + if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; + if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; + if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; + if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; + if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; + if(!dpmemflush(villa->depot)) err = TRUE; + return err ? FALSE : TRUE; +} + + +/* Refer to a volatile cache of a value of a record. */ +const char *vlgetcache(VILLA *villa, const char *kbuf, int ksiz, int *sp){ + VLLEAF *leaf; + VLREC *recp; + int pid; + assert(villa && kbuf); + if(ksiz < 0) ksiz = strlen(kbuf); + if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ + if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; + if(!(leaf = vlleafload(villa, pid))) return NULL; + } + if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return NULL; + } + if(!villa->tran && !vlcacheadjust(villa)) return NULL; + if(sp) *sp = CB_DATUMSIZE(recp->first); + return CB_DATUMPTR(recp->first); +} + + +/* Refer to volatile cache of the key of the record where the cursor is. */ +const char *vlcurkeycache(VILLA *villa, int *sp){ + VLLEAF *leaf; + VLREC *recp; + const char *kbuf; + int ksiz; + assert(villa); + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + kbuf = CB_DATUMPTR(recp->key); + ksiz = CB_DATUMSIZE(recp->key); + if(sp) *sp = ksiz; + return kbuf; +} + + +/* Refer to volatile cache of the value of the record where the cursor is. */ +const char *vlcurvalcache(VILLA *villa, int *sp){ + VLLEAF *leaf; + VLREC *recp; + const char *vbuf; + int vsiz; + assert(villa); + if(villa->curleaf == -1){ + dpecodeset(DP_ENOITEM, __FILE__, __LINE__); + return FALSE; + } + if(!(leaf = vlleafload(villa, villa->curleaf))){ + villa->curleaf = -1; + return FALSE; + } + recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); + if(villa->curvnum < 1){ + vbuf = CB_DATUMPTR(recp->first); + vsiz = CB_DATUMSIZE(recp->first); + } else { + vbuf = CB_LISTVAL2(recp->rest, villa->curvnum - 1, vsiz); + } + if(sp) *sp = vsiz; + return vbuf; +} + + +/* Get a multiple cursor handle. */ +VLMULCUR *vlmulcuropen(VILLA *villa){ + VLMULCUR *mulcur; + assert(villa); + if(villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return NULL; + } + CB_MALLOC(mulcur, sizeof(VLMULCUR)); + mulcur->villa = villa; + mulcur->curleaf = -1; + mulcur->curknum = -1; + mulcur->curvnum = -1; + return mulcur; +} + + +/* Close a multiple cursor handle. */ +void vlmulcurclose(VLMULCUR *mulcur){ + assert(mulcur); + free(mulcur); +} + + +/* Move a multiple cursor to the first record. */ +int vlmulcurfirst(VLMULCUR *mulcur){ + VLMULCUR swap; + int rv; + assert(mulcur); + swap.curleaf = mulcur->villa->curleaf; + swap.curknum = mulcur->villa->curknum; + swap.curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = mulcur->curleaf; + mulcur->villa->curknum = mulcur->curknum; + mulcur->villa->curvnum = mulcur->curvnum; + rv = vlcurfirst(mulcur->villa); + mulcur->curleaf = mulcur->villa->curleaf; + mulcur->curknum = mulcur->villa->curknum; + mulcur->curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = swap.curleaf; + mulcur->villa->curknum = swap.curknum; + mulcur->villa->curvnum = swap.curvnum; + return rv; +} + + +/* Move a multiple cursor to the last record. */ +int vlmulcurlast(VLMULCUR *mulcur){ + VLMULCUR swap; + int rv; + assert(mulcur); + swap.curleaf = mulcur->villa->curleaf; + swap.curknum = mulcur->villa->curknum; + swap.curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = mulcur->curleaf; + mulcur->villa->curknum = mulcur->curknum; + mulcur->villa->curvnum = mulcur->curvnum; + rv = vlcurlast(mulcur->villa); + mulcur->curleaf = mulcur->villa->curleaf; + mulcur->curknum = mulcur->villa->curknum; + mulcur->curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = swap.curleaf; + mulcur->villa->curknum = swap.curknum; + mulcur->villa->curvnum = swap.curvnum; + return rv; +} + + +/* Move a multiple cursor to the previous record. */ +int vlmulcurprev(VLMULCUR *mulcur){ + VLMULCUR swap; + int rv; + assert(mulcur); + swap.curleaf = mulcur->villa->curleaf; + swap.curknum = mulcur->villa->curknum; + swap.curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = mulcur->curleaf; + mulcur->villa->curknum = mulcur->curknum; + mulcur->villa->curvnum = mulcur->curvnum; + rv = vlcurprev(mulcur->villa); + mulcur->curleaf = mulcur->villa->curleaf; + mulcur->curknum = mulcur->villa->curknum; + mulcur->curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = swap.curleaf; + mulcur->villa->curknum = swap.curknum; + mulcur->villa->curvnum = swap.curvnum; + return rv; +} + + +/* Move a multiple cursor to the next record. */ +int vlmulcurnext(VLMULCUR *mulcur){ + VLMULCUR swap; + int rv; + assert(mulcur); + swap.curleaf = mulcur->villa->curleaf; + swap.curknum = mulcur->villa->curknum; + swap.curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = mulcur->curleaf; + mulcur->villa->curknum = mulcur->curknum; + mulcur->villa->curvnum = mulcur->curvnum; + rv = vlcurnext(mulcur->villa); + mulcur->curleaf = mulcur->villa->curleaf; + mulcur->curknum = mulcur->villa->curknum; + mulcur->curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = swap.curleaf; + mulcur->villa->curknum = swap.curknum; + mulcur->villa->curvnum = swap.curvnum; + return rv; +} + + +/* Move a multiple cursor to a position around a record. */ +int vlmulcurjump(VLMULCUR *mulcur, const char *kbuf, int ksiz, int jmode){ + VLMULCUR swap; + int rv; + assert(mulcur); + swap.curleaf = mulcur->villa->curleaf; + swap.curknum = mulcur->villa->curknum; + swap.curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = mulcur->curleaf; + mulcur->villa->curknum = mulcur->curknum; + mulcur->villa->curvnum = mulcur->curvnum; + rv = vlcurjump(mulcur->villa, kbuf, ksiz, jmode); + mulcur->curleaf = mulcur->villa->curleaf; + mulcur->curknum = mulcur->villa->curknum; + mulcur->curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = swap.curleaf; + mulcur->villa->curknum = swap.curknum; + mulcur->villa->curvnum = swap.curvnum; + return rv; +} + + +/* Get the key of the record where a multiple cursor is. */ +char *vlmulcurkey(VLMULCUR *mulcur, int *sp){ + VLMULCUR swap; + char *rv; + assert(mulcur); + swap.curleaf = mulcur->villa->curleaf; + swap.curknum = mulcur->villa->curknum; + swap.curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = mulcur->curleaf; + mulcur->villa->curknum = mulcur->curknum; + mulcur->villa->curvnum = mulcur->curvnum; + rv = vlcurkey(mulcur->villa, sp); + mulcur->curleaf = mulcur->villa->curleaf; + mulcur->curknum = mulcur->villa->curknum; + mulcur->curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = swap.curleaf; + mulcur->villa->curknum = swap.curknum; + mulcur->villa->curvnum = swap.curvnum; + return rv; +} + + +/* Get the value of the record where a multiple cursor is. */ +char *vlmulcurval(VLMULCUR *mulcur, int *sp){ + VLMULCUR swap; + char *rv; + assert(mulcur); + swap.curleaf = mulcur->villa->curleaf; + swap.curknum = mulcur->villa->curknum; + swap.curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = mulcur->curleaf; + mulcur->villa->curknum = mulcur->curknum; + mulcur->villa->curvnum = mulcur->curvnum; + rv = vlcurval(mulcur->villa, sp); + mulcur->curleaf = mulcur->villa->curleaf; + mulcur->curknum = mulcur->villa->curknum; + mulcur->curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = swap.curleaf; + mulcur->villa->curknum = swap.curknum; + mulcur->villa->curvnum = swap.curvnum; + return rv; +} + + +/* Refer to volatile cache of the key of the record where a multiple cursor is. */ +const char *vlmulcurkeycache(VLMULCUR *mulcur, int *sp){ + VLMULCUR swap; + const char *rv; + assert(mulcur); + swap.curleaf = mulcur->villa->curleaf; + swap.curknum = mulcur->villa->curknum; + swap.curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = mulcur->curleaf; + mulcur->villa->curknum = mulcur->curknum; + mulcur->villa->curvnum = mulcur->curvnum; + rv = vlcurkeycache(mulcur->villa, sp); + mulcur->curleaf = mulcur->villa->curleaf; + mulcur->curknum = mulcur->villa->curknum; + mulcur->curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = swap.curleaf; + mulcur->villa->curknum = swap.curknum; + mulcur->villa->curvnum = swap.curvnum; + return rv; +} + + +/* Refer to volatile cache of the value of the record where a multiple cursor is. */ +const char *vlmulcurvalcache(VLMULCUR *mulcur, int *sp){ + VLMULCUR swap; + const char *rv; + assert(mulcur); + swap.curleaf = mulcur->villa->curleaf; + swap.curknum = mulcur->villa->curknum; + swap.curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = mulcur->curleaf; + mulcur->villa->curknum = mulcur->curknum; + mulcur->villa->curvnum = mulcur->curvnum; + rv = vlcurvalcache(mulcur->villa, sp); + mulcur->curleaf = mulcur->villa->curleaf; + mulcur->curknum = mulcur->villa->curknum; + mulcur->curvnum = mulcur->villa->curvnum; + mulcur->villa->curleaf = swap.curleaf; + mulcur->villa->curknum = swap.curknum; + mulcur->villa->curvnum = swap.curvnum; + return rv; +} + + + +/************************************************************************************************* + * private objects + *************************************************************************************************/ + + +/* Compare keys of two records by lexical order. + `aptr' specifies the pointer to the region of one key. + `asiz' specifies the size of the region of one key. + `bptr' specifies the pointer to the region of the other key. + `bsiz' specifies the size of the region of the other key. + The return value is positive if the former is big, negative if the latter is big, 0 if both + are equivalent. */ +static int vllexcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ + int i, min; + assert(aptr && asiz >= 0 && bptr && bsiz >= 0); + min = asiz < bsiz ? asiz : bsiz; + for(i = 0; i < min; i++){ + if(((unsigned char *)aptr)[i] != ((unsigned char *)bptr)[i]) + return ((unsigned char *)aptr)[i] - ((unsigned char *)bptr)[i]; + } + if(asiz == bsiz) return 0; + return asiz - bsiz; +} + + +/* Compare keys of two records as native integers. + `aptr' specifies the pointer to the region of one key. + `asiz' specifies the size of the region of one key. + `bptr' specifies the pointer to the region of the other key. + `bsiz' specifies the size of the region of the other key. + The return value is positive if the former is big, negative if the latter is big, 0 if both + are equivalent. */ +static int vlintcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ + int anum, bnum; + assert(aptr && asiz >= 0 && bptr && bsiz >= 0); + if(asiz != bsiz) return asiz - bsiz; + anum = (asiz == sizeof(int) ? *(int *)aptr : INT_MIN); + bnum = (bsiz == sizeof(int) ? *(int *)bptr : INT_MIN); + return anum - bnum; +} + + +/* Compare keys of two records as numbers of big endian. + `aptr' specifies the pointer to the region of one key. + `asiz' specifies the size of the region of one key. + `bptr' specifies the pointer to the region of the other key. + `bsiz' specifies the size of the region of the other key. + The return value is positive if the former is big, negative if the latter is big, 0 if both + are equivalent. */ +static int vlnumcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ + int i; + assert(aptr && asiz >= 0 && bptr && bsiz >= 0); + if(asiz != bsiz) return asiz - bsiz; + for(i = 0; i < asiz; i++){ + if(aptr[i] != bptr[i]) return aptr[i] - bptr[i]; + } + return 0; +} + + +/* Compare keys of two records as numeric strings of octal, decimal or hexadecimal. + `aptr' specifies the pointer to the region of one key. + `asiz' specifies the size of the region of one key. + `bptr' specifies the pointer to the region of the other key. + `bsiz' specifies the size of the region of the other key. + The return value is positive if the former is big, negative if the latter is big, 0 if both + are equivalent. */ +static int vldeccompare(const char *aptr, int asiz, const char *bptr, int bsiz){ + assert(aptr && asiz >= 0 && bptr && bsiz >= 0); + return (int)(strtod(aptr, NULL) - strtod(bptr, NULL)); +} + + +/* Store a record composed of a pair of integers. + `depot' specifies an internal database handle. + `knum' specifies an integer of the key. + `vnum' specifies an integer of the value. + The return value is true if successful, else, it is false. */ +static int vldpputnum(DEPOT *depot, int knum, int vnum){ + assert(depot); + return dpput(depot, (char *)&knum, sizeof(int), (char *)&vnum, sizeof(int), DP_DOVER); +} + + +/* Retrieve a record composed of a pair of integers. + `depot' specifies an internal database handle. + `knum' specifies an integer of the key. + `vip' specifies the pointer to a variable to assign the result to. + The return value is true if successful, else, it is false. */ +static int vldpgetnum(DEPOT *depot, int knum, int *vnp){ + char *vbuf; + int vsiz; + assert(depot && vnp); + vbuf = dpget(depot, (char *)&knum, sizeof(int), 0, -1, &vsiz); + if(!vbuf || vsiz != sizeof(int)){ + free(vbuf); + return FALSE; + } + *vnp = *(int *)vbuf; + free(vbuf); + return TRUE; +} + + +/* Create a new leaf. + `villa' specifies a database handle. + `prev' specifies the ID number of the previous leaf. + `next' specifies the ID number of the previous leaf. + The return value is a handle of the leaf. */ +static VLLEAF *vlleafnew(VILLA *villa, int prev, int next){ + VLLEAF lent; + assert(villa); + lent.id = villa->lnum + VL_LEAFIDMIN; + lent.dirty = TRUE; + CB_LISTOPEN(lent.recs); + lent.prev = prev; + lent.next = next; + villa->lnum++; + cbmapput(villa->leafc, (char *)&(lent.id), sizeof(int), (char *)&lent, sizeof(VLLEAF), TRUE); + return (VLLEAF *)cbmapget(villa->leafc, (char *)&(lent.id), sizeof(int), NULL); +} + + +/* Remove a leaf from the cache. + `villa' specifies a database handle. + `id' specifies the ID number of the leaf. + The return value is true if successful, else, it is false. */ +static int vlleafcacheout(VILLA *villa, int id){ + VLLEAF *leaf; + VLREC *recp; + CBLIST *recs; + int i, err, ln; + assert(villa && id >= VL_LEAFIDMIN); + if(!(leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&id, sizeof(int), NULL))) return FALSE; + err = FALSE; + if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE; + recs = leaf->recs; + ln = CB_LISTNUM(recs); + for(i = 0; i < ln; i++){ + recp = (VLREC *)CB_LISTVAL(recs, i); + CB_DATUMCLOSE(recp->key); + CB_DATUMCLOSE(recp->first); + if(recp->rest) CB_LISTCLOSE(recp->rest); + } + CB_LISTCLOSE(recs); + cbmapout(villa->leafc, (char *)&id, sizeof(int)); + return err ? FALSE : TRUE; +} + + +/* Save a leaf into the database. + `villa' specifies a database handle. + `leaf' specifies a leaf handle. + The return value is true if successful, else, it is false. */ +static int vlleafsave(VILLA *villa, VLLEAF *leaf){ + VLREC *recp; + CBLIST *recs; + CBDATUM *buf; + char vnumbuf[VL_VNUMBUFSIZ], *zbuf; + const char *vbuf; + int i, j, ksiz, vnum, vsiz, prev, next, vnumsiz, ln, zsiz; + assert(villa && leaf); + CB_DATUMOPEN(buf); + prev = leaf->prev; + if(prev == -1) prev = VL_NODEIDMIN - 1; + VL_SETVNUMBUF(vnumsiz, vnumbuf, prev); + CB_DATUMCAT(buf, vnumbuf, vnumsiz); + next = leaf->next; + if(next == -1) next = VL_NODEIDMIN - 1; + VL_SETVNUMBUF(vnumsiz, vnumbuf, next); + CB_DATUMCAT(buf, vnumbuf, vnumsiz); + recs = leaf->recs; + ln = CB_LISTNUM(recs); + for(i = 0; i < ln; i++){ + recp = (VLREC *)CB_LISTVAL(recs, i); + ksiz = CB_DATUMSIZE(recp->key); + VL_SETVNUMBUF(vnumsiz, vnumbuf, ksiz); + CB_DATUMCAT(buf, vnumbuf, vnumsiz); + CB_DATUMCAT(buf, CB_DATUMPTR(recp->key), ksiz); + vnum = 1 + (recp->rest ? CB_LISTNUM(recp->rest) : 0); + VL_SETVNUMBUF(vnumsiz, vnumbuf, vnum); + CB_DATUMCAT(buf, vnumbuf, vnumsiz); + vsiz = CB_DATUMSIZE(recp->first); + VL_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); + CB_DATUMCAT(buf, vnumbuf, vnumsiz); + CB_DATUMCAT(buf, CB_DATUMPTR(recp->first), vsiz); + if(recp->rest){ + for(j = 0; j < CB_LISTNUM(recp->rest); j++){ + vbuf = CB_LISTVAL2(recp->rest, j, vsiz); + VL_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); + CB_DATUMCAT(buf, vnumbuf, vnumsiz); + CB_DATUMCAT(buf, vbuf, vsiz); + } + } + } + if(_qdbm_deflate && villa->cmode == VL_OZCOMP){ + if(!(zbuf = _qdbm_deflate(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz, _QDBM_ZMRAW))){ + CB_DATUMCLOSE(buf); + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){ + CB_DATUMCLOSE(buf); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return FALSE; + } + free(zbuf); + } else if(_qdbm_lzoencode && villa->cmode == VL_OYCOMP){ + if(!(zbuf = _qdbm_lzoencode(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz))){ + CB_DATUMCLOSE(buf); + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){ + CB_DATUMCLOSE(buf); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return FALSE; + } + free(zbuf); + } else if(_qdbm_bzencode && villa->cmode == VL_OXCOMP){ + if(!(zbuf = _qdbm_bzencode(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz))){ + CB_DATUMCLOSE(buf); + dpecodeset(DP_EMISC, __FILE__, __LINE__); + return FALSE; + } + if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){ + CB_DATUMCLOSE(buf); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return FALSE; + } + free(zbuf); + } else { + if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), + CB_DATUMPTR(buf), CB_DATUMSIZE(buf), DP_DOVER)){ + CB_DATUMCLOSE(buf); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return FALSE; + } + } + CB_DATUMCLOSE(buf); + leaf->dirty = FALSE; + return TRUE; +} + + +/* Load a leaf from the database. + `villa' specifies a database handle. + `id' specifies the ID number of the leaf. + If successful, the return value is the pointer to the leaf, else, it is `NULL'. */ +static VLLEAF *vlleafload(VILLA *villa, int id){ + char wbuf[VL_PAGEBUFSIZ], *buf, *rp, *kbuf, *vbuf, *zbuf; + int i, size, step, ksiz, vnum, vsiz, prev, next, zsiz; + VLLEAF *leaf, lent; + VLREC rec; + assert(villa && id >= VL_LEAFIDMIN); + if((leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&id, sizeof(int), NULL)) != NULL){ + cbmapmove(villa->leafc, (char *)&id, sizeof(int), FALSE); + return leaf; + } + ksiz = -1; + prev = -1; + next = -1; + if((size = dpgetwb(villa->depot, (char *)&id, sizeof(int), 0, VL_PAGEBUFSIZ, wbuf)) > 0 && + size < VL_PAGEBUFSIZ){ + buf = NULL; + } else if(!(buf = dpget(villa->depot, (char *)&id, sizeof(int), 0, -1, &size))){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + if(_qdbm_inflate && villa->cmode == VL_OZCOMP){ + if(!(zbuf = _qdbm_inflate(buf ? buf : wbuf, size, &zsiz, _QDBM_ZMRAW))){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + free(buf); + return NULL; + } + free(buf); + buf = zbuf; + size = zsiz; + } else if(_qdbm_lzodecode && villa->cmode == VL_OYCOMP){ + if(!(zbuf = _qdbm_lzodecode(buf ? buf : wbuf, size, &zsiz))){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + free(buf); + return NULL; + } + free(buf); + buf = zbuf; + size = zsiz; + } else if(_qdbm_bzdecode && villa->cmode == VL_OXCOMP){ + if(!(zbuf = _qdbm_bzdecode(buf ? buf : wbuf, size, &zsiz))){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + free(buf); + return NULL; + } + free(buf); + buf = zbuf; + size = zsiz; + } + rp = buf ? buf : wbuf; + if(size >= 1){ + VL_READVNUMBUF(rp, size, prev, step); + rp += step; + size -= step; + if(prev >= VL_NODEIDMIN - 1) prev = -1; + } + if(size >= 1){ + VL_READVNUMBUF(rp, size, next, step); + rp += step; + size -= step; + if(next >= VL_NODEIDMIN - 1) next = -1; + } + lent.id = id; + lent.dirty = FALSE; + CB_LISTOPEN(lent.recs); + lent.prev = prev; + lent.next = next; + while(size >= 1){ + VL_READVNUMBUF(rp, size, ksiz, step); + rp += step; + size -= step; + if(size < ksiz) break; + kbuf = rp; + rp += ksiz; + size -= ksiz; + VL_READVNUMBUF(rp, size, vnum, step); + rp += step; + size -= step; + if(vnum < 1 || size < 1) break; + for(i = 0; i < vnum && size >= 1; i++){ + VL_READVNUMBUF(rp, size, vsiz, step); + rp += step; + size -= step; + if(size < vsiz) break; + vbuf = rp; + rp += vsiz; + size -= vsiz; + if(i < 1){ + CB_DATUMOPEN2(rec.key, kbuf, ksiz); + CB_DATUMOPEN2(rec.first, vbuf, vsiz); + rec.rest = NULL; + } else { + if(!rec.rest) CB_LISTOPEN(rec.rest); + CB_LISTPUSH(rec.rest, vbuf, vsiz); + } + } + if(i > 0) CB_LISTPUSH(lent.recs, (char *)&rec, sizeof(VLREC)); + } + free(buf); + cbmapput(villa->leafc, (char *)&(lent.id), sizeof(int), (char *)&lent, sizeof(VLLEAF), TRUE); + return (VLLEAF *)cbmapget(villa->leafc, (char *)&(lent.id), sizeof(int), NULL); +} + + +/* Load the historical leaf from the database. + `villa' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. + If successful, the return value is the pointer to the leaf, else, it is `NULL'. */ +static VLLEAF *vlgethistleaf(VILLA *villa, const char *kbuf, int ksiz){ + VLLEAF *leaf; + VLREC *recp; + int ln, rv; + assert(villa && kbuf && ksiz >= 0); + if(!(leaf = vlleafload(villa, villa->hleaf))) return NULL; + if((ln = CB_LISTNUM(leaf->recs)) < 2) return NULL; + recp = (VLREC *)CB_LISTVAL(leaf->recs, 0); + rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); + if(rv == 0) return leaf; + if(rv < 0) return NULL; + recp = (VLREC *)CB_LISTVAL(leaf->recs, ln - 1); + rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); + if(rv <= 0 || leaf->next < VL_LEAFIDMIN) return leaf; + return NULL; +} + + +/* Add a record to a leaf. + `villa' specifies a database handle. + `leaf' specifies a leaf handle. + `dmode' specifies behavior when the key overlaps. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region of the value. + The return value is true if successful, else, it is false. */ +static int vlleafaddrec(VILLA *villa, VLLEAF *leaf, int dmode, + const char *kbuf, int ksiz, const char *vbuf, int vsiz){ + VLREC *recp, rec; + CBLIST *recs; + int i, rv, left, right, ln, tsiz; + char *tbuf; + assert(villa && leaf && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); + left = 0; + recs = leaf->recs; + ln = CB_LISTNUM(recs); + right = ln; + i = (left + right) / 2; + while(right >= left && i < ln){ + recp = (VLREC *)CB_LISTVAL(recs, i); + rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); + if(rv == 0){ + break; + } else if(rv <= 0){ + right = i - 1; + } else { + left = i + 1; + } + i = (left + right) / 2; + } + while(i < ln){ + recp = (VLREC *)CB_LISTVAL(recs, i); + rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); + if(rv == 0){ + switch(dmode){ + case VL_DKEEP: + return FALSE; + case VL_DCAT: + CB_DATUMCAT(recp->first, vbuf, vsiz); + break; + case VL_DDUP: + if(!recp->rest) CB_LISTOPEN(recp->rest); + CB_LISTPUSH(recp->rest, vbuf, vsiz); + villa->rnum++; + break; + case VL_DDUPR: + if(!recp->rest){ + CB_DATUMTOMALLOC(recp->first, tbuf, tsiz); + CB_DATUMOPEN2(recp->first, vbuf, vsiz); + CB_LISTOPEN(recp->rest); + CB_LISTPUSHBUF(recp->rest, tbuf, tsiz); + } else { + cblistunshift(recp->rest, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); + CB_DATUMSETSIZE(recp->first, 0); + CB_DATUMCAT(recp->first, vbuf, vsiz); + } + villa->rnum++; + break; + default: + CB_DATUMSETSIZE(recp->first, 0); + CB_DATUMCAT(recp->first, vbuf, vsiz); + break; + } + break; + } else if(rv < 0){ + CB_DATUMOPEN2(rec.key, kbuf, ksiz); + CB_DATUMOPEN2(rec.first, vbuf, vsiz); + rec.rest = NULL; + CB_LISTINSERT(recs, i, (char *)&rec, sizeof(VLREC)); + villa->rnum++; + break; + } + i++; + } + if(i >= ln){ + CB_DATUMOPEN2(rec.key, kbuf, ksiz); + CB_DATUMOPEN2(rec.first, vbuf, vsiz); + rec.rest = NULL; + CB_LISTPUSH(recs, (char *)&rec, sizeof(VLREC)); + villa->rnum++; + } + leaf->dirty = TRUE; + return TRUE; +} + + +/* Calculate the size of data of a leaf. + `leaf' specifies a leaf handle. + The return value is size of data of the leaf. */ +static int vlleafdatasize(VLLEAF *leaf){ + VLREC *recp; + CBLIST *recs, *rest; + const char *vbuf; + int i, j, sum, rnum, restnum, vsiz; + assert(leaf); + sum = 0; + recs = leaf->recs; + rnum = CB_LISTNUM(recs); + for(i = 0; i < rnum; i++){ + recp = (VLREC *)CB_LISTVAL(recs, i); + sum += CB_DATUMSIZE(recp->key); + sum += CB_DATUMSIZE(recp->first); + if(recp->rest){ + rest = recp->rest; + restnum = CB_LISTNUM(rest); + for(j = 0; j < restnum; j++){ + vbuf = CB_LISTVAL2(rest, j, vsiz); + sum += vsiz; + } + } + } + return sum; +} + + +/* Divide a leaf into two. + `villa' specifies a database handle. + `leaf' specifies a leaf handle. + The return value is the handle of a new leaf, or `NULL' on failure. */ +static VLLEAF *vlleafdivide(VILLA *villa, VLLEAF *leaf){ + VLLEAF *newleaf, *nextleaf; + VLREC *recp; + CBLIST *recs, *newrecs; + int i, mid, ln; + assert(villa && leaf); + villa->hleaf = -1; + recs = leaf->recs; + mid = CB_LISTNUM(recs) / 2; + recp = (VLREC *)CB_LISTVAL(recs, mid); + newleaf = vlleafnew(villa, leaf->id, leaf->next); + if(newleaf->next != -1){ + if(!(nextleaf = vlleafload(villa, newleaf->next))) return NULL; + nextleaf->prev = newleaf->id; + nextleaf->dirty = TRUE; + } + leaf->next = newleaf->id; + leaf->dirty = TRUE; + ln = CB_LISTNUM(recs); + newrecs = newleaf->recs; + for(i = mid; i < ln; i++){ + recp = (VLREC *)CB_LISTVAL(recs, i); + CB_LISTPUSH(newrecs, (char *)recp, sizeof(VLREC)); + } + ln = CB_LISTNUM(newrecs); + for(i = 0; i < ln; i++){ + CB_LISTDROP(recs); + } + return newleaf; +} + + +/* Create a new node. + `villa' specifies a database handle. + `heir' specifies the ID of the child before the first index. + The return value is a handle of the node. */ +static VLNODE *vlnodenew(VILLA *villa, int heir){ + VLNODE nent; + assert(villa && heir >= VL_LEAFIDMIN); + nent.id = villa->nnum + VL_NODEIDMIN; + nent.dirty = TRUE; + nent.heir = heir; + CB_LISTOPEN(nent.idxs); + villa->nnum++; + cbmapput(villa->nodec, (char *)&(nent.id), sizeof(int), (char *)&nent, sizeof(VLNODE), TRUE); + return (VLNODE *)cbmapget(villa->nodec, (char *)&(nent.id), sizeof(int), NULL); +} + + +/* Remove a node from the cache. + `villa' specifies a database handle. + `id' specifies the ID number of the node. + The return value is true if successful, else, it is false. */ +static int vlnodecacheout(VILLA *villa, int id){ + VLNODE *node; + VLIDX *idxp; + int i, err, ln; + assert(villa && id >= VL_NODEIDMIN); + if(!(node = (VLNODE *)cbmapget(villa->nodec, (char *)&id, sizeof(int), NULL))) return FALSE; + err = FALSE; + if(node->dirty && !vlnodesave(villa, node)) err = TRUE; + ln = CB_LISTNUM(node->idxs); + for(i = 0; i < ln; i++){ + idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); + CB_DATUMCLOSE(idxp->key); + } + CB_LISTCLOSE(node->idxs); + cbmapout(villa->nodec, (char *)&id, sizeof(int)); + return err ? FALSE : TRUE; +} + + +/* Save a node into the database. + `villa' specifies a database handle. + `node' specifies a node handle. + The return value is true if successful, else, it is false. */ +static int vlnodesave(VILLA *villa, VLNODE *node){ + CBDATUM *buf; + char vnumbuf[VL_VNUMBUFSIZ]; + VLIDX *idxp; + int i, heir, pid, ksiz, vnumsiz, ln; + assert(villa && node); + CB_DATUMOPEN(buf); + heir = node->heir; + VL_SETVNUMBUF(vnumsiz, vnumbuf, heir); + CB_DATUMCAT(buf, vnumbuf, vnumsiz); + ln = CB_LISTNUM(node->idxs); + for(i = 0; i < ln; i++){ + idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); + pid = idxp->pid; + VL_SETVNUMBUF(vnumsiz, vnumbuf, pid); + CB_DATUMCAT(buf, vnumbuf, vnumsiz); + ksiz = CB_DATUMSIZE(idxp->key); + VL_SETVNUMBUF(vnumsiz, vnumbuf, ksiz); + CB_DATUMCAT(buf, vnumbuf, vnumsiz); + CB_DATUMCAT(buf, CB_DATUMPTR(idxp->key), ksiz); + } + if(!dpput(villa->depot, (char *)&(node->id), sizeof(int), + CB_DATUMPTR(buf), CB_DATUMSIZE(buf), DP_DOVER)){ + CB_DATUMCLOSE(buf); + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return FALSE; + } + CB_DATUMCLOSE(buf); + node->dirty = FALSE; + return TRUE; +} + + +/* Load a node from the database. + `villa' specifies a database handle. + `id' specifies the ID number of the node. + If successful, the return value is the pointer to the node, else, it is `NULL'. */ +static VLNODE *vlnodeload(VILLA *villa, int id){ + char wbuf[VL_PAGEBUFSIZ], *buf, *rp, *kbuf; + int size, step, heir, pid, ksiz; + VLNODE *node, nent; + VLIDX idx; + assert(villa && id >= VL_NODEIDMIN); + if((node = (VLNODE *)cbmapget(villa->nodec, (char *)&id, sizeof(int), NULL)) != NULL){ + cbmapmove(villa->nodec, (char *)&id, sizeof(int), FALSE); + return node; + } + heir = -1; + if((size = dpgetwb(villa->depot, (char *)&id, sizeof(int), 0, VL_PAGEBUFSIZ, wbuf)) > 0 && + size < VL_PAGEBUFSIZ){ + buf = NULL; + } else if(!(buf = dpget(villa->depot, (char *)&id, sizeof(int), 0, -1, &size))){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return NULL; + } + rp = buf ? buf : wbuf; + if(size >= 1){ + VL_READVNUMBUF(rp, size, heir, step); + rp += step; + size -= step; + } + if(heir < 0){ + free(buf); + return NULL; + } + nent.id = id; + nent.dirty = FALSE; + nent.heir = heir; + CB_LISTOPEN(nent.idxs); + while(size >= 1){ + VL_READVNUMBUF(rp, size, pid, step); + rp += step; + size -= step; + if(size < 1) break; + VL_READVNUMBUF(rp, size, ksiz, step); + rp += step; + size -= step; + if(size < ksiz) break; + kbuf = rp; + rp += ksiz; + size -= ksiz; + idx.pid = pid; + CB_DATUMOPEN2(idx.key, kbuf, ksiz); + CB_LISTPUSH(nent.idxs, (char *)&idx, sizeof(VLIDX)); + } + free(buf); + cbmapput(villa->nodec, (char *)&(nent.id), sizeof(int), (char *)&nent, sizeof(VLNODE), TRUE); + return (VLNODE *)cbmapget(villa->nodec, (char *)&(nent.id), sizeof(int), NULL); +} + + +/* Add an index to a node. + `villa' specifies a database handle. + `node' specifies a node handle. + `order' specifies whether the calling sequence is orderd or not. + `pid' specifies the ID number of referred page. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. */ +static void vlnodeaddidx(VILLA *villa, VLNODE *node, int order, + int pid, const char *kbuf, int ksiz){ + VLIDX idx, *idxp; + int i, rv, left, right, ln; + assert(villa && node && pid >= VL_LEAFIDMIN && kbuf && ksiz >= 0); + idx.pid = pid; + CB_DATUMOPEN2(idx.key, kbuf, ksiz); + if(order){ + CB_LISTPUSH(node->idxs, (char *)&idx, sizeof(VLIDX)); + } else { + left = 0; + right = CB_LISTNUM(node->idxs); + i = (left + right) / 2; + ln = CB_LISTNUM(node->idxs); + while(right >= left && i < ln){ + idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); + rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); + if(rv == 0){ + break; + } else if(rv <= 0){ + right = i - 1; + } else { + left = i + 1; + } + i = (left + right) / 2; + } + ln = CB_LISTNUM(node->idxs); + while(i < ln){ + idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); + if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)) < 0){ + CB_LISTINSERT(node->idxs, i, (char *)&idx, sizeof(VLIDX)); + break; + } + i++; + } + if(i >= CB_LISTNUM(node->idxs)) CB_LISTPUSH(node->idxs, (char *)&idx, sizeof(VLIDX)); + } + node->dirty = TRUE; +} + + +/* Search the leaf corresponding to a key. + `villa' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. + The return value is the ID number of the leaf, or -1 on failure. */ +static int vlsearchleaf(VILLA *villa, const char *kbuf, int ksiz){ + VLNODE *node; + VLIDX *idxp; + int i, pid, rv, left, right, ln; + assert(villa && kbuf && ksiz >= 0); + pid = villa->root; + idxp = NULL; + villa->hnum = 0; + villa->hleaf = -1; + while(pid >= VL_NODEIDMIN){ + if(!(node = vlnodeload(villa, pid)) || (ln = CB_LISTNUM(node->idxs)) < 1){ + dpecodeset(DP_EBROKEN, __FILE__, __LINE__); + return -1; + } + villa->hist[villa->hnum++] = node->id; + left = 1; + right = ln; + i = (left + right) / 2; + while(right >= left && i < ln){ + idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); + rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); + if(rv == 0){ + break; + } else if(rv <= 0){ + right = i - 1; + } else { + left = i + 1; + } + i = (left + right) / 2; + } + if(i > 0) i--; + while(i < ln){ + idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); + if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)) < 0){ + if(i == 0){ + pid = node->heir; + break; + } + idxp = (VLIDX *)CB_LISTVAL(node->idxs, i - 1); + pid = idxp->pid; + break; + } + i++; + } + if(i >= ln) pid = idxp->pid; + } + if(villa->lleaf == pid) villa->hleaf = pid; + villa->lleaf = pid; + return pid; +} + + +/* Adjust the caches for leaves and nodes. + `villa' specifies a database handle. + The return value is true if successful, else, it is false. */ +static int vlcacheadjust(VILLA *villa){ + const char *tmp; + int i, pid, err; + err = FALSE; + if(cbmaprnum(villa->leafc) > villa->leafcnum){ + cbmapiterinit(villa->leafc); + for(i = 0; i < VL_CACHEOUT; i++){ + tmp = cbmapiternext(villa->leafc, NULL); + pid = *(int *)tmp; + if(!vlleafcacheout(villa, pid)) err = TRUE; + } + } + if(cbmaprnum(villa->nodec) > villa->nodecnum){ + cbmapiterinit(villa->nodec); + for(i = 0; i < VL_CACHEOUT; i++){ + tmp = cbmapiternext(villa->nodec, NULL); + pid = *(int *)tmp; + if(!vlnodecacheout(villa, pid)) err = TRUE; + } + } + return err ? FALSE : TRUE; +} + + +/* Search a record of a leaf. + `villa' specifies a database handle. + `leaf' specifies a leaf handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. + `ip' specifies the pointer to a variable to fetch the index of the correspnding record. + The return value is the pointer to a corresponding record, or `NULL' on failure. */ +static VLREC *vlrecsearch(VILLA *villa, VLLEAF *leaf, const char *kbuf, int ksiz, int *ip){ + VLREC *recp; + CBLIST *recs; + int i, rv, left, right, ln; + assert(villa && leaf && kbuf && ksiz >= 0); + recs = leaf->recs; + ln = CB_LISTNUM(recs); + left = 0; + right = ln; + i = (left + right) / 2; + while(right >= left && i < ln){ + recp = (VLREC *)CB_LISTVAL(recs, i); + rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); + if(rv == 0){ + if(ip) *ip = i; + return recp; + } else if(rv <= 0){ + right = i - 1; + } else { + left = i + 1; + } + i = (left + right) / 2; + } + if(ip) *ip = i; + return NULL; +} + + +/* Get flags of a database. */ +int vlgetflags(VILLA *villa){ + assert(villa); + return dpgetflags(villa->depot); +} + + +/* Set flags of a database. + `villa' specifies a database handle connected as a writer. + `flags' specifies flags to set. Lesser ten bits are reserved for internal use. + If successful, the return value is true, else, it is false. */ +int vlsetflags(VILLA *villa, int flags){ + assert(villa); + if(!villa->wmode){ + dpecodeset(DP_EMODE, __FILE__, __LINE__); + return FALSE; + } + return dpsetflags(villa->depot, flags); +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/villa.h =================================================================== --- box/trunk/qdbm/villa.h 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/villa.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,758 +0,0 @@ -/************************************************************************************************* - * The advanced API of QDBM - * 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. - *************************************************************************************************/ - - -#ifndef _VILLA_H /* duplication check */ -#define _VILLA_H - -#if defined(__cplusplus) /* export for C++ */ -extern "C" { -#endif - - -#include -#include -#include -#include - - -#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) -#define MYEXTERN extern __declspec(dllimport) -#else -#define MYEXTERN extern -#endif - - - -/************************************************************************************************* - * API - *************************************************************************************************/ - - -#define VL_LEVELMAX 64 /* max level of B+ tree */ - -typedef struct { /* type of structure for a record */ - CBDATUM *key; /* datum of the key */ - CBDATUM *first; /* datum of the first value */ - CBLIST *rest; /* list of the rest values */ -} VLREC; - -typedef struct { /* type of structure for index of a page */ - int pid; /* ID number of the referring page */ - CBDATUM *key; /* threshold key of the page */ -} VLIDX; - -typedef struct { /* type of structure for a leaf page */ - int id; /* ID number of the leaf */ - int dirty; /* whether to be written back */ - CBLIST *recs; /* list of records */ - int prev; /* ID number of the previous leaf */ - int next; /* ID number of the next leaf */ -} VLLEAF; - -typedef struct { /* type of structure for a node page */ - int id; /* ID number of the node */ - int dirty; /* whether to be written back */ - int heir; /* ID of the child before the first index */ - CBLIST *idxs; /* list of indexes */ -} VLNODE; - -/* type of the pointer to a comparing function. - `aptr' specifies the pointer to the region of one key. - `asiz' specifies the size of the region of one key. - `bptr' specifies the pointer to the region of the other key. - `bsiz' specifies the size of the region of the other key. - The return value is positive if the former is big, negative if the latter is big, 0 if both - are equivalent. */ -typedef int (*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz); -MYEXTERN VLCFUNC VL_CMPLEX; /* lexical comparing function */ -MYEXTERN VLCFUNC VL_CMPINT; /* native integer comparing function */ -MYEXTERN VLCFUNC VL_CMPNUM; /* big endian number comparing function */ -MYEXTERN VLCFUNC VL_CMPDEC; /* decimal string comparing function */ - -typedef struct { /* type of structure for a database handle */ - DEPOT *depot; /* internal database handle */ - VLCFUNC cmp; /* pointer to the comparing function */ - int wmode; /* whether to be writable */ - int cmode; /* compression mode for leaves */ - int root; /* ID number of the root page */ - int last; /* ID number of the last leaf */ - int lnum; /* number of leaves */ - int nnum; /* number of nodes */ - int rnum; /* number of records */ - CBMAP *leafc; /* cache for leaves */ - CBMAP *nodec; /* cache for nodes */ - int hist[VL_LEVELMAX]; /* array history of visited nodes */ - int hnum; /* number of elements of the history */ - int hleaf; /* ID number of the leaf referred by the history */ - int lleaf; /* ID number of the last visited leaf */ - int curleaf; /* ID number of the leaf where the cursor is */ - int curknum; /* index of the key where the cursor is */ - int curvnum; /* index of the value where the cursor is */ - int leafrecmax; /* max number of records in a leaf */ - int nodeidxmax; /* max number of indexes in a node */ - int leafcnum; /* max number of caching leaves */ - int nodecnum; /* max number of caching nodes */ - int avglsiz; /* average size of each leave */ - int avgnsiz; /* average size of each node */ - int tran; /* whether in the transaction */ - int rbroot; /* root for rollback */ - int rblast; /* last for rollback */ - int rblnum; /* lnum for rollback */ - int rbnnum; /* nnum for rollback */ - int rbrnum; /* rnum for rollback */ -} VILLA; - -typedef struct { /* type of structure for a multiple cursor handle */ - VILLA *villa; /* database handle */ - int curleaf; /* ID number of the leaf where the cursor is */ - int curknum; /* index of the key where the cursor is */ - int curvnum; /* index of the value where the cursor is */ -} VLMULCUR; - -enum { /* enumeration for open modes */ - VL_OREADER = 1 << 0, /* open as a reader */ - VL_OWRITER = 1 << 1, /* open as a writer */ - VL_OCREAT = 1 << 2, /* a writer creating */ - VL_OTRUNC = 1 << 3, /* a writer truncating */ - VL_ONOLCK = 1 << 4, /* open without locking */ - VL_OLCKNB = 1 << 5, /* lock without blocking */ - VL_OZCOMP = 1 << 6, /* compress leaves with ZLIB */ - VL_OYCOMP = 1 << 7, /* compress leaves with LZO */ - VL_OXCOMP = 1 << 8 /* compress leaves with BZIP2 */ -}; - -enum { /* enumeration for write modes */ - VL_DOVER, /* overwrite the existing value */ - VL_DKEEP, /* keep the existing value */ - VL_DCAT, /* concatenate values */ - VL_DDUP, /* allow duplication of keys */ - VL_DDUPR /* allow duplication with reverse order */ -}; - -enum { /* enumeration for jump modes */ - VL_JFORWARD, /* step forward */ - VL_JBACKWARD /* step backward */ -}; - -enum { /* enumeration for insertion modes */ - VL_CPCURRENT, /* overwrite the current record */ - VL_CPBEFORE, /* insert before the current record */ - VL_CPAFTER /* insert after the current record */ -}; - - -/* Get a database handle. - `name' specifies the name of a database file. - `omode' specifies the connection mode: `VL_OWRITER' as a writer, `VL_OREADER' as a reader. - If the mode is `VL_OWRITER', the following may be added by bitwise or: `VL_OCREAT', which - means it creates a new database if not exist, `VL_OTRUNC', which means it creates a new - database regardless if one exists, `VL_OZCOMP', which means leaves in the database are - compressed with ZLIB, `VL_OYCOMP', which means leaves in the database are compressed with LZO, - `VL_OXCOMP', which means leaves in the database are compressed with BZIP2. Both of - `VL_OREADER' and `VL_OWRITER' can be added to by bitwise or: `VL_ONOLCK', which means it opens - a database file without file locking, or `VL_OLCKNB', which means locking is performed without - blocking. - `cmp' specifies a comparing function: `VL_CMPLEX' comparing keys in lexical order, - `VL_CMPINT' comparing keys as objects of `int' in native byte order, `VL_CMPNUM' comparing - keys as numbers of big endian, `VL_CMPDEC' comparing keys as decimal strings. Any function - based on the declaration of the type `VLCFUNC' can be assigned to the comparing function. - The comparing function should be kept same in the life of a database. - The return value is the database handle or `NULL' if it is not successful. - While connecting as a writer, an exclusive lock is invoked to the database file. - While connecting as a reader, a shared lock is invoked to the database file. The thread - blocks until the lock is achieved. `VL_OZCOMP', `VL_OYCOMP', and `VL_OXCOMP' are available - only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `VL_ONOLCK' is used, the - application is responsible for exclusion control. */ -VILLA *vlopen(const char *name, int omode, VLCFUNC cmp); - - -/* Close a database handle. - `villa' specifies a database handle. - If successful, the return value is true, else, it is false. - Because the region of a closed handle is released, it becomes impossible to use the handle. - Updating a database is assured to be written when the handle is closed. If a writer opens - a database but does not close it appropriately, the database will be broken. If the - transaction is activated and not committed, it is aborted. */ -int vlclose(VILLA *villa); - - -/* Store a record. - `villa' specifies a database handle connected as a writer. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region of the value. If it is negative, the size is - assigned with `strlen(vbuf)'. - `dmode' specifies behavior when the key overlaps, by the following values: `VL_DOVER', - which means the specified value overwrites the existing one, `VL_DKEEP', which means the - existing value is kept, `VL_DCAT', which means the specified value is concatenated at the - end of the existing value, `VL_DDUP', which means duplication of keys is allowed and the - specified value is added as the last one, `VL_DDUPR', which means duplication of keys is - allowed and the specified value is added as the first one. - If successful, the return value is true, else, it is false. - The cursor becomes unavailable due to updating database. */ -int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); - - -/* Delete a record. - `villa' specifies a database handle connected as a writer. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is true, else, it is false. False is returned when no - record corresponds to the specified key. - When the key of duplicated records is specified, the first record of the same key is deleted. - The cursor becomes unavailable due to updating database. */ -int vlout(VILLA *villa, const char *kbuf, int ksiz); - - -/* Retrieve a record. - `villa' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to - the specified key. - When the key of duplicated records is specified, the value of the first record of the same - key is selected. Because an additional zero code is appended at the end of the region of the - return value, the return value can be treated as a character string. Because the region of - the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp); - - -/* Get the size of the value of a record. - `villa' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is the size of the value of the corresponding record, else, - it is -1. If multiple records correspond, the size of the first is returned. */ -int vlvsiz(VILLA *villa, const char *kbuf, int ksiz); - - -/* Get the number of records corresponding a key. - `villa' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - The return value is the number of corresponding records. If no record corresponds, 0 is - returned. */ -int vlvnum(VILLA *villa, const char *kbuf, int ksiz); - - -/* Store plural records corresponding a key. - `villa' specifies a database handle connected as a writer. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `vals' specifies a list handle of values. The list should not be empty. - If successful, the return value is true, else, it is false. - The cursor becomes unavailable due to updating database. */ -int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals); - - -/* Delete all records corresponding a key. - `villa' specifies a database handle connected as a writer. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is true, else, it is false. False is returned when no - record corresponds to the specified key. - The cursor becomes unavailable due to updating database. */ -int vloutlist(VILLA *villa, const char *kbuf, int ksiz); - - -/* Retrieve values of all records corresponding a key. - `villa' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - If successful, the return value is a list handle of the values of the corresponding records, - else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. - Because the handle of the return value is opened with the function `cblistopen', it should - be closed with the function `cblistclose' if it is no longer in use. */ -CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz); - - -/* Retrieve concatenated values of all records corresponding a key. - `villa' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the concatenated values of - the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds - to the specified key. Because an additional zero code is appended at the end of the region of - the return value, the return value can be treated as a character string. Because the region - of the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp); - - -/* Move the cursor to the first record. - `villa' specifies a database handle. - If successful, the return value is true, else, it is false. False is returned if there is - no record in the database. */ -int vlcurfirst(VILLA *villa); - - -/* Move the cursor to the last record. - `villa' specifies a database handle. - If successful, the return value is true, else, it is false. False is returned if there is - no record in the database. */ -int vlcurlast(VILLA *villa); - - -/* Move the cursor to the previous record. - `villa' specifies a database handle. - If successful, the return value is true, else, it is false. False is returned if there is - no previous record. */ -int vlcurprev(VILLA *villa); - - -/* Move the cursor to the next record. - `villa' specifies a database handle. - If successful, the return value is true, else, it is false. False is returned if there is - no next record. */ -int vlcurnext(VILLA *villa); - - -/* Move the cursor to a position around a record. - `villa' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `jmode' specifies detail adjustment: `VL_JFORWARD', which means that the cursor is set to - the first record of the same key and that the cursor is set to the next substitute if - completely matching record does not exist, `VL_JBACKWARD', which means that the cursor is - set to the last record of the same key and that the cursor is set to the previous substitute - if completely matching record does not exist. - If successful, the return value is true, else, it is false. False is returned if there is - no record corresponding the condition. */ -int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode); - - -/* Get the key of the record where the cursor is. - `villa' specifies a database handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the key of the corresponding - record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. - Because an additional zero code is appended at the end of the region of the - return value, the return value can be treated as a character string. Because the region of - the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -char *vlcurkey(VILLA *villa, int *sp); - - -/* Get the value of the record where the cursor is. - `villa' specifies a database handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to - the cursor. - Because an additional zero code is appended at the end of the region of the - return value, the return value can be treated as a character string. Because the region of - the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -char *vlcurval(VILLA *villa, int *sp); - - -/* Insert a record around the cursor. - `villa' specifies a database handle connected as a writer. - `vbuf' specifies the pointer to the region of a value. - `vsiz' specifies the size of the region of the value. If it is negative, the size is - assigned with `strlen(vbuf)'. - `cpmode' specifies detail adjustment: `VL_CPCURRENT', which means that the value of the - current record is overwritten, `VL_CPBEFORE', which means that a new record is inserted before - the current record, `VL_CPAFTER', which means that a new record is inserted after the current - record. - If successful, the return value is true, else, it is false. False is returned when no record - corresponds to the cursor. - After insertion, the cursor is moved to the inserted record. */ -int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode); - - -/* Delete the record where the cursor is. - `villa' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. False is returned when no record - corresponds to the cursor. - After deletion, the cursor is moved to the next record if possible. */ -int vlcurout(VILLA *villa); - - -/* Set the tuning parameters for performance. - `villa' specifies a database handle. - `lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is not more - than 0, the default value is specified. - `nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is not - more than 0, the default value is specified. - `lcnum' specifies the max number of caching leaf nodes. If it is not more than 0, the - default value is specified. - `ncnum' specifies the max number of caching non-leaf nodes. If it is not more than 0, the - default value is specified. - The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning - parameters are not saved in a database, you should specify them every opening a database. */ -void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum); - - -/* Set the size of the free block pool of a database handle. - `villa' specifies a database handle connected as a writer. - `size' specifies the size of the free block pool of a database. - If successful, the return value is true, else, it is false. - The default size of the free block pool is 256. If the size is greater, the space efficiency - of overwriting values is improved with the time efficiency sacrificed. */ -int vlsetfbpsiz(VILLA *villa, int size); - - -/* Synchronize updating contents with the file and the device. - `villa' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. - This function is useful when another process uses the connected database file. This function - should not be used while the transaction is activated. */ -int vlsync(VILLA *villa); - - -/* Optimize a database. - `villa' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. - In an alternating succession of deleting and storing with overwrite or concatenate, - dispensable regions accumulate. This function is useful to do away with them. This function - should not be used while the transaction is activated. */ -int vloptimize(VILLA *villa); - - -/* Get the name of a database. - `villa' specifies a database handle. - If successful, the return value is the pointer to the region of the name of the database, - else, it is `NULL'. - Because the region of the return value is allocated with the `malloc' call, it should be - released with the `free' call if it is no longer in use. */ -char *vlname(VILLA *villa); - - -/* Get the size of a database file. - `villa' specifies a database handle. - If successful, the return value is the size of the database file, else, it is -1. - Because of the I/O buffer, the return value may be less than the hard size. */ -int vlfsiz(VILLA *villa); - - -/* Get the number of the leaf nodes of B+ tree. - `villa' specifies a database handle. - If successful, the return value is the number of the leaf nodes, else, it is -1. */ -int vllnum(VILLA *villa); - - -/* Get the number of the non-leaf nodes of B+ tree. - `villa' specifies a database handle. - If successful, the return value is the number of the non-leaf nodes, else, it is -1. */ -int vlnnum(VILLA *villa); - - -/* Get the number of the records stored in a database. - `villa' specifies a database handle. - If successful, the return value is the number of the records stored in the database, else, - it is -1. */ -int vlrnum(VILLA *villa); - - -/* Check whether a database handle is a writer or not. - `villa' specifies a database handle. - The return value is true if the handle is a writer, false if not. */ -int vlwritable(VILLA *villa); - - -/* Check whether a database has a fatal error or not. - `villa' specifies a database handle. - The return value is true if the database has a fatal error, false if not. */ -int vlfatalerror(VILLA *villa); - - -/* Get the inode number of a database file. - `villa' specifies a database handle. - The return value is the inode number of the database file. */ -int vlinode(VILLA *villa); - - -/* Get the last modified time of a database. - `villa' specifies a database handle. - The return value is the last modified time of the database. */ -time_t vlmtime(VILLA *villa); - - -/* Begin the transaction. - `villa' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. - Because this function does not perform mutual exclusion control in multi-thread, the - application is responsible for it. Only one transaction can be activated with a database - handle at the same time. */ -int vltranbegin(VILLA *villa); - - -/* Commit the transaction. - `villa' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. - Updating a database in the transaction is fixed when it is committed successfully. */ -int vltrancommit(VILLA *villa); - - -/* Abort the transaction. - `villa' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. - Updating a database in the transaction is discarded when it is aborted. The state of the - database is rollbacked to before transaction. */ -int vltranabort(VILLA *villa); - - -/* Remove a database file. - `name' specifies the name of a database file. - If successful, the return value is true, else, it is false. */ -int vlremove(const char *name); - - -/* Repair a broken database file. - `name' specifies the name of a database file. - `cmp' specifies the comparing function of the database file. - If successful, the return value is true, else, it is false. - There is no guarantee that all records in a repaired database file correspond to the original - or expected state. */ -int vlrepair(const char *name, VLCFUNC cmp); - - -/* Dump all records as endian independent data. - `villa' specifies a database handle. - `name' specifies the name of an output file. - If successful, the return value is true, else, it is false. */ -int vlexportdb(VILLA *villa, const char *name); - - -/* Load all records from endian independent data. - `villa' specifies a database handle connected as a writer. The database of the handle must - be empty. - `name' specifies the name of an input file. - If successful, the return value is true, else, it is false. */ -int vlimportdb(VILLA *villa, const char *name); - - - -/************************************************************************************************* - * features for experts - *************************************************************************************************/ - - -/* Number of division of the database for Vista. */ -#define vlcrdnum (*vlcrdnumptr()) - - -/* Get the pointer of the variable of the number of division of the database for Vista. - The return value is the pointer of the variable. */ -int *vlcrdnumptr(void); - - -/* Synchronize updating contents on memory. - `villa' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. */ -int vlmemsync(VILLA *villa); - - -/* Synchronize updating contents on memory, not physically. - `villa' specifies a database handle connected as a writer. - If successful, the return value is true, else, it is false. */ -int vlmemflush(VILLA *villa); - - -/* Refer to volatile cache of a value of a record. - `villa' specifies a database handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to - the specified key. - Because the region of the return value is volatile and it may be spoiled by another operation - of the database, the data should be copied into another involatile buffer immediately. */ -const char *vlgetcache(VILLA *villa, const char *kbuf, int ksiz, int *sp); - - -/* Refer to volatile cache of the key of the record where the cursor is. - `villa' specifies a database handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the key of the corresponding - record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. - Because the region of the return value is volatile and it may be spoiled by another operation - of the database, the data should be copied into another involatile buffer immediately. */ -const char *vlcurkeycache(VILLA *villa, int *sp); - - -/* Refer to volatile cache of the value of the record where the cursor is. - `villa' specifies a database handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to - the cursor. - Because an additional zero code is appended at the end of the region of the - return value, the return value can be treated as a character string. Because the region of - the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -const char *vlcurvalcache(VILLA *villa, int *sp); - - -/* Get a multiple cursor handle. - `villa' specifies a database handle connected as a reader. - The return value is a multiple cursor handle or `NULL' if it is not successful. - The returned object is should be closed before the database handle is closed. Even if plural - cursors are fetched out of a database handle, they does not share the locations with each - other. Note that this function can be used only if the database handle is connected as a - reader. */ -VLMULCUR *vlmulcuropen(VILLA *villa); - - -/* Close a multiple cursor handle. - `mulcur' specifies a multiple cursor handle. */ -void vlmulcurclose(VLMULCUR *mulcur); - - -/* Move a multiple cursor to the first record. - `mulcur' specifies a multiple cursor handle. - If successful, the return value is true, else, it is false. False is returned if there is - no record in the database. */ -int vlmulcurfirst(VLMULCUR *mulcur); - - -/* Move a multiple cursor to the last record. - `mulcur' specifies a multiple cursor handle. - If successful, the return value is true, else, it is false. False is returned if there is - no record in the database. */ -int vlmulcurlast(VLMULCUR *mulcur); - - -/* Move a multiple cursor to the previous record. - `mulcur' specifies a multiple cursor handle. - If successful, the return value is true, else, it is false. False is returned if there is - no previous record. */ -int vlmulcurprev(VLMULCUR *mulcur); - - -/* Move a multiple cursor to the next record. - `mulcur' specifies a multiple cursor handle. - If successful, the return value is true, else, it is false. False is returned if there is - no next record. */ -int vlmulcurnext(VLMULCUR *mulcur); - - -/* Move a multiple cursor to a position around a record. - `mulcur' specifies a multiple cursor handle. - `kbuf' specifies the pointer to the region of a key. - `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned - with `strlen(kbuf)'. - `jmode' specifies detail adjustment: `VL_JFORWARD', which means that the cursor is set to - the first record of the same key and that the cursor is set to the next substitute if - completely matching record does not exist, `VL_JBACKWARD', which means that the cursor is - set to the last record of the same key and that the cursor is set to the previous substitute - if completely matching record does not exist. - If successful, the return value is true, else, it is false. False is returned if there is - no record corresponding the condition. */ -int vlmulcurjump(VLMULCUR *mulcur, const char *kbuf, int ksiz, int jmode); - - -/* Get the key of the record where a multiple cursor is. - `mulcur' specifies a multiple cursor handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the key of the corresponding - record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. - Because an additional zero code is appended at the end of the region of the - return value, the return value can be treated as a character string. Because the region of - the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -char *vlmulcurkey(VLMULCUR *mulcur, int *sp); - - -/* Get the value of the record where a multiple cursor is. - `mulcur' specifies a multiple cursor handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to - the cursor. - Because an additional zero code is appended at the end of the region of the - return value, the return value can be treated as a character string. Because the region of - the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -char *vlmulcurval(VLMULCUR *mulcur, int *sp); - - -/* Refer to volatile cache of the key of the record where a multiple cursor is. - `mulcur' specifies a multiple cursor handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the key of the corresponding - record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. - Because the region of the return value is volatile and it may be spoiled by another operation - of the database, the data should be copied into another involatile buffer immediately. */ -const char *vlmulcurkeycache(VLMULCUR *mulcur, int *sp); - - -/* Refer to volatile cache of the value of the record where a multiple cursor is. - `mulcur' specifies a multiple cursor handle. - `sp' specifies the pointer to a variable to which the size of the region of the return - value is assigned. If it is `NULL', it is not used. - If successful, the return value is the pointer to the region of the value of the - corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to - the cursor. - Because an additional zero code is appended at the end of the region of the - return value, the return value can be treated as a character string. Because the region of - the return value is allocated with the `malloc' call, it should be released with the `free' - call if it is no longer in use. */ -const char *vlmulcurvalcache(VLMULCUR *mulcur, int *sp); - - -/* Get flags of a database. - `villa' specifies a database handle. - The return value is the flags of a database. */ -int vlgetflags(VILLA *villa); - - -/* Set flags of a database. - `villa' specifies a database handle connected as a writer. - `flags' specifies flags to set. Least ten bits are reserved for internal use. - If successful, the return value is true, else, it is false. */ -int vlsetflags(VILLA *villa, int flags); - - - -#undef MYEXTERN - -#if defined(__cplusplus) /* export for C++ */ -} -#endif - -#endif /* duplication check */ - - -/* END OF FILE */ Copied: box/trunk/qdbm/villa.h (from rev 2716, box/trunk/qdbm/villa.h) =================================================================== --- box/trunk/qdbm/villa.h (rev 0) +++ box/trunk/qdbm/villa.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,758 @@ +/************************************************************************************************* + * The advanced API of QDBM + * 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. + *************************************************************************************************/ + + +#ifndef _VILLA_H /* duplication check */ +#define _VILLA_H + +#if defined(__cplusplus) /* export for C++ */ +extern "C" { +#endif + + +#include +#include +#include +#include + + +#if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) +#define MYEXTERN extern __declspec(dllimport) +#else +#define MYEXTERN extern +#endif + + + +/************************************************************************************************* + * API + *************************************************************************************************/ + + +#define VL_LEVELMAX 64 /* max level of B+ tree */ + +typedef struct { /* type of structure for a record */ + CBDATUM *key; /* datum of the key */ + CBDATUM *first; /* datum of the first value */ + CBLIST *rest; /* list of the rest values */ +} VLREC; + +typedef struct { /* type of structure for index of a page */ + int pid; /* ID number of the referring page */ + CBDATUM *key; /* threshold key of the page */ +} VLIDX; + +typedef struct { /* type of structure for a leaf page */ + int id; /* ID number of the leaf */ + int dirty; /* whether to be written back */ + CBLIST *recs; /* list of records */ + int prev; /* ID number of the previous leaf */ + int next; /* ID number of the next leaf */ +} VLLEAF; + +typedef struct { /* type of structure for a node page */ + int id; /* ID number of the node */ + int dirty; /* whether to be written back */ + int heir; /* ID of the child before the first index */ + CBLIST *idxs; /* list of indexes */ +} VLNODE; + +/* type of the pointer to a comparing function. + `aptr' specifies the pointer to the region of one key. + `asiz' specifies the size of the region of one key. + `bptr' specifies the pointer to the region of the other key. + `bsiz' specifies the size of the region of the other key. + The return value is positive if the former is big, negative if the latter is big, 0 if both + are equivalent. */ +typedef int (*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz); +MYEXTERN VLCFUNC VL_CMPLEX; /* lexical comparing function */ +MYEXTERN VLCFUNC VL_CMPINT; /* native integer comparing function */ +MYEXTERN VLCFUNC VL_CMPNUM; /* big endian number comparing function */ +MYEXTERN VLCFUNC VL_CMPDEC; /* decimal string comparing function */ + +typedef struct { /* type of structure for a database handle */ + DEPOT *depot; /* internal database handle */ + VLCFUNC cmp; /* pointer to the comparing function */ + int wmode; /* whether to be writable */ + int cmode; /* compression mode for leaves */ + int root; /* ID number of the root page */ + int last; /* ID number of the last leaf */ + int lnum; /* number of leaves */ + int nnum; /* number of nodes */ + int rnum; /* number of records */ + CBMAP *leafc; /* cache for leaves */ + CBMAP *nodec; /* cache for nodes */ + int hist[VL_LEVELMAX]; /* array history of visited nodes */ + int hnum; /* number of elements of the history */ + int hleaf; /* ID number of the leaf referred by the history */ + int lleaf; /* ID number of the last visited leaf */ + int curleaf; /* ID number of the leaf where the cursor is */ + int curknum; /* index of the key where the cursor is */ + int curvnum; /* index of the value where the cursor is */ + int leafrecmax; /* max number of records in a leaf */ + int nodeidxmax; /* max number of indexes in a node */ + int leafcnum; /* max number of caching leaves */ + int nodecnum; /* max number of caching nodes */ + int avglsiz; /* average size of each leave */ + int avgnsiz; /* average size of each node */ + int tran; /* whether in the transaction */ + int rbroot; /* root for rollback */ + int rblast; /* last for rollback */ + int rblnum; /* lnum for rollback */ + int rbnnum; /* nnum for rollback */ + int rbrnum; /* rnum for rollback */ +} VILLA; + +typedef struct { /* type of structure for a multiple cursor handle */ + VILLA *villa; /* database handle */ + int curleaf; /* ID number of the leaf where the cursor is */ + int curknum; /* index of the key where the cursor is */ + int curvnum; /* index of the value where the cursor is */ +} VLMULCUR; + +enum { /* enumeration for open modes */ + VL_OREADER = 1 << 0, /* open as a reader */ + VL_OWRITER = 1 << 1, /* open as a writer */ + VL_OCREAT = 1 << 2, /* a writer creating */ + VL_OTRUNC = 1 << 3, /* a writer truncating */ + VL_ONOLCK = 1 << 4, /* open without locking */ + VL_OLCKNB = 1 << 5, /* lock without blocking */ + VL_OZCOMP = 1 << 6, /* compress leaves with ZLIB */ + VL_OYCOMP = 1 << 7, /* compress leaves with LZO */ + VL_OXCOMP = 1 << 8 /* compress leaves with BZIP2 */ +}; + +enum { /* enumeration for write modes */ + VL_DOVER, /* overwrite the existing value */ + VL_DKEEP, /* keep the existing value */ + VL_DCAT, /* concatenate values */ + VL_DDUP, /* allow duplication of keys */ + VL_DDUPR /* allow duplication with reverse order */ +}; + +enum { /* enumeration for jump modes */ + VL_JFORWARD, /* step forward */ + VL_JBACKWARD /* step backward */ +}; + +enum { /* enumeration for insertion modes */ + VL_CPCURRENT, /* overwrite the current record */ + VL_CPBEFORE, /* insert before the current record */ + VL_CPAFTER /* insert after the current record */ +}; + + +/* Get a database handle. + `name' specifies the name of a database file. + `omode' specifies the connection mode: `VL_OWRITER' as a writer, `VL_OREADER' as a reader. + If the mode is `VL_OWRITER', the following may be added by bitwise or: `VL_OCREAT', which + means it creates a new database if not exist, `VL_OTRUNC', which means it creates a new + database regardless if one exists, `VL_OZCOMP', which means leaves in the database are + compressed with ZLIB, `VL_OYCOMP', which means leaves in the database are compressed with LZO, + `VL_OXCOMP', which means leaves in the database are compressed with BZIP2. Both of + `VL_OREADER' and `VL_OWRITER' can be added to by bitwise or: `VL_ONOLCK', which means it opens + a database file without file locking, or `VL_OLCKNB', which means locking is performed without + blocking. + `cmp' specifies a comparing function: `VL_CMPLEX' comparing keys in lexical order, + `VL_CMPINT' comparing keys as objects of `int' in native byte order, `VL_CMPNUM' comparing + keys as numbers of big endian, `VL_CMPDEC' comparing keys as decimal strings. Any function + based on the declaration of the type `VLCFUNC' can be assigned to the comparing function. + The comparing function should be kept same in the life of a database. + The return value is the database handle or `NULL' if it is not successful. + While connecting as a writer, an exclusive lock is invoked to the database file. + While connecting as a reader, a shared lock is invoked to the database file. The thread + blocks until the lock is achieved. `VL_OZCOMP', `VL_OYCOMP', and `VL_OXCOMP' are available + only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `VL_ONOLCK' is used, the + application is responsible for exclusion control. */ +VILLA *vlopen(const char *name, int omode, VLCFUNC cmp); + + +/* Close a database handle. + `villa' specifies a database handle. + If successful, the return value is true, else, it is false. + Because the region of a closed handle is released, it becomes impossible to use the handle. + Updating a database is assured to be written when the handle is closed. If a writer opens + a database but does not close it appropriately, the database will be broken. If the + transaction is activated and not committed, it is aborted. */ +int vlclose(VILLA *villa); + + +/* Store a record. + `villa' specifies a database handle connected as a writer. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region of the value. If it is negative, the size is + assigned with `strlen(vbuf)'. + `dmode' specifies behavior when the key overlaps, by the following values: `VL_DOVER', + which means the specified value overwrites the existing one, `VL_DKEEP', which means the + existing value is kept, `VL_DCAT', which means the specified value is concatenated at the + end of the existing value, `VL_DDUP', which means duplication of keys is allowed and the + specified value is added as the last one, `VL_DDUPR', which means duplication of keys is + allowed and the specified value is added as the first one. + If successful, the return value is true, else, it is false. + The cursor becomes unavailable due to updating database. */ +int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); + + +/* Delete a record. + `villa' specifies a database handle connected as a writer. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is true, else, it is false. False is returned when no + record corresponds to the specified key. + When the key of duplicated records is specified, the first record of the same key is deleted. + The cursor becomes unavailable due to updating database. */ +int vlout(VILLA *villa, const char *kbuf, int ksiz); + + +/* Retrieve a record. + `villa' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to + the specified key. + When the key of duplicated records is specified, the value of the first record of the same + key is selected. Because an additional zero code is appended at the end of the region of the + return value, the return value can be treated as a character string. Because the region of + the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp); + + +/* Get the size of the value of a record. + `villa' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is the size of the value of the corresponding record, else, + it is -1. If multiple records correspond, the size of the first is returned. */ +int vlvsiz(VILLA *villa, const char *kbuf, int ksiz); + + +/* Get the number of records corresponding a key. + `villa' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + The return value is the number of corresponding records. If no record corresponds, 0 is + returned. */ +int vlvnum(VILLA *villa, const char *kbuf, int ksiz); + + +/* Store plural records corresponding a key. + `villa' specifies a database handle connected as a writer. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `vals' specifies a list handle of values. The list should not be empty. + If successful, the return value is true, else, it is false. + The cursor becomes unavailable due to updating database. */ +int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals); + + +/* Delete all records corresponding a key. + `villa' specifies a database handle connected as a writer. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is true, else, it is false. False is returned when no + record corresponds to the specified key. + The cursor becomes unavailable due to updating database. */ +int vloutlist(VILLA *villa, const char *kbuf, int ksiz); + + +/* Retrieve values of all records corresponding a key. + `villa' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + If successful, the return value is a list handle of the values of the corresponding records, + else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. + Because the handle of the return value is opened with the function `cblistopen', it should + be closed with the function `cblistclose' if it is no longer in use. */ +CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz); + + +/* Retrieve concatenated values of all records corresponding a key. + `villa' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the concatenated values of + the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds + to the specified key. Because an additional zero code is appended at the end of the region of + the return value, the return value can be treated as a character string. Because the region + of the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp); + + +/* Move the cursor to the first record. + `villa' specifies a database handle. + If successful, the return value is true, else, it is false. False is returned if there is + no record in the database. */ +int vlcurfirst(VILLA *villa); + + +/* Move the cursor to the last record. + `villa' specifies a database handle. + If successful, the return value is true, else, it is false. False is returned if there is + no record in the database. */ +int vlcurlast(VILLA *villa); + + +/* Move the cursor to the previous record. + `villa' specifies a database handle. + If successful, the return value is true, else, it is false. False is returned if there is + no previous record. */ +int vlcurprev(VILLA *villa); + + +/* Move the cursor to the next record. + `villa' specifies a database handle. + If successful, the return value is true, else, it is false. False is returned if there is + no next record. */ +int vlcurnext(VILLA *villa); + + +/* Move the cursor to a position around a record. + `villa' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `jmode' specifies detail adjustment: `VL_JFORWARD', which means that the cursor is set to + the first record of the same key and that the cursor is set to the next substitute if + completely matching record does not exist, `VL_JBACKWARD', which means that the cursor is + set to the last record of the same key and that the cursor is set to the previous substitute + if completely matching record does not exist. + If successful, the return value is true, else, it is false. False is returned if there is + no record corresponding the condition. */ +int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode); + + +/* Get the key of the record where the cursor is. + `villa' specifies a database handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the key of the corresponding + record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. + Because an additional zero code is appended at the end of the region of the + return value, the return value can be treated as a character string. Because the region of + the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +char *vlcurkey(VILLA *villa, int *sp); + + +/* Get the value of the record where the cursor is. + `villa' specifies a database handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to + the cursor. + Because an additional zero code is appended at the end of the region of the + return value, the return value can be treated as a character string. Because the region of + the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +char *vlcurval(VILLA *villa, int *sp); + + +/* Insert a record around the cursor. + `villa' specifies a database handle connected as a writer. + `vbuf' specifies the pointer to the region of a value. + `vsiz' specifies the size of the region of the value. If it is negative, the size is + assigned with `strlen(vbuf)'. + `cpmode' specifies detail adjustment: `VL_CPCURRENT', which means that the value of the + current record is overwritten, `VL_CPBEFORE', which means that a new record is inserted before + the current record, `VL_CPAFTER', which means that a new record is inserted after the current + record. + If successful, the return value is true, else, it is false. False is returned when no record + corresponds to the cursor. + After insertion, the cursor is moved to the inserted record. */ +int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode); + + +/* Delete the record where the cursor is. + `villa' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. False is returned when no record + corresponds to the cursor. + After deletion, the cursor is moved to the next record if possible. */ +int vlcurout(VILLA *villa); + + +/* Set the tuning parameters for performance. + `villa' specifies a database handle. + `lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is not more + than 0, the default value is specified. + `nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is not + more than 0, the default value is specified. + `lcnum' specifies the max number of caching leaf nodes. If it is not more than 0, the + default value is specified. + `ncnum' specifies the max number of caching non-leaf nodes. If it is not more than 0, the + default value is specified. + The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning + parameters are not saved in a database, you should specify them every opening a database. */ +void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum); + + +/* Set the size of the free block pool of a database handle. + `villa' specifies a database handle connected as a writer. + `size' specifies the size of the free block pool of a database. + If successful, the return value is true, else, it is false. + The default size of the free block pool is 256. If the size is greater, the space efficiency + of overwriting values is improved with the time efficiency sacrificed. */ +int vlsetfbpsiz(VILLA *villa, int size); + + +/* Synchronize updating contents with the file and the device. + `villa' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. + This function is useful when another process uses the connected database file. This function + should not be used while the transaction is activated. */ +int vlsync(VILLA *villa); + + +/* Optimize a database. + `villa' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. + In an alternating succession of deleting and storing with overwrite or concatenate, + dispensable regions accumulate. This function is useful to do away with them. This function + should not be used while the transaction is activated. */ +int vloptimize(VILLA *villa); + + +/* Get the name of a database. + `villa' specifies a database handle. + If successful, the return value is the pointer to the region of the name of the database, + else, it is `NULL'. + Because the region of the return value is allocated with the `malloc' call, it should be + released with the `free' call if it is no longer in use. */ +char *vlname(VILLA *villa); + + +/* Get the size of a database file. + `villa' specifies a database handle. + If successful, the return value is the size of the database file, else, it is -1. + Because of the I/O buffer, the return value may be less than the hard size. */ +int vlfsiz(VILLA *villa); + + +/* Get the number of the leaf nodes of B+ tree. + `villa' specifies a database handle. + If successful, the return value is the number of the leaf nodes, else, it is -1. */ +int vllnum(VILLA *villa); + + +/* Get the number of the non-leaf nodes of B+ tree. + `villa' specifies a database handle. + If successful, the return value is the number of the non-leaf nodes, else, it is -1. */ +int vlnnum(VILLA *villa); + + +/* Get the number of the records stored in a database. + `villa' specifies a database handle. + If successful, the return value is the number of the records stored in the database, else, + it is -1. */ +int vlrnum(VILLA *villa); + + +/* Check whether a database handle is a writer or not. + `villa' specifies a database handle. + The return value is true if the handle is a writer, false if not. */ +int vlwritable(VILLA *villa); + + +/* Check whether a database has a fatal error or not. + `villa' specifies a database handle. + The return value is true if the database has a fatal error, false if not. */ +int vlfatalerror(VILLA *villa); + + +/* Get the inode number of a database file. + `villa' specifies a database handle. + The return value is the inode number of the database file. */ +int vlinode(VILLA *villa); + + +/* Get the last modified time of a database. + `villa' specifies a database handle. + The return value is the last modified time of the database. */ +time_t vlmtime(VILLA *villa); + + +/* Begin the transaction. + `villa' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. + Because this function does not perform mutual exclusion control in multi-thread, the + application is responsible for it. Only one transaction can be activated with a database + handle at the same time. */ +int vltranbegin(VILLA *villa); + + +/* Commit the transaction. + `villa' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. + Updating a database in the transaction is fixed when it is committed successfully. */ +int vltrancommit(VILLA *villa); + + +/* Abort the transaction. + `villa' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. + Updating a database in the transaction is discarded when it is aborted. The state of the + database is rollbacked to before transaction. */ +int vltranabort(VILLA *villa); + + +/* Remove a database file. + `name' specifies the name of a database file. + If successful, the return value is true, else, it is false. */ +int vlremove(const char *name); + + +/* Repair a broken database file. + `name' specifies the name of a database file. + `cmp' specifies the comparing function of the database file. + If successful, the return value is true, else, it is false. + There is no guarantee that all records in a repaired database file correspond to the original + or expected state. */ +int vlrepair(const char *name, VLCFUNC cmp); + + +/* Dump all records as endian independent data. + `villa' specifies a database handle. + `name' specifies the name of an output file. + If successful, the return value is true, else, it is false. */ +int vlexportdb(VILLA *villa, const char *name); + + +/* Load all records from endian independent data. + `villa' specifies a database handle connected as a writer. The database of the handle must + be empty. + `name' specifies the name of an input file. + If successful, the return value is true, else, it is false. */ +int vlimportdb(VILLA *villa, const char *name); + + + +/************************************************************************************************* + * features for experts + *************************************************************************************************/ + + +/* Number of division of the database for Vista. */ +#define vlcrdnum (*vlcrdnumptr()) + + +/* Get the pointer of the variable of the number of division of the database for Vista. + The return value is the pointer of the variable. */ +int *vlcrdnumptr(void); + + +/* Synchronize updating contents on memory. + `villa' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. */ +int vlmemsync(VILLA *villa); + + +/* Synchronize updating contents on memory, not physically. + `villa' specifies a database handle connected as a writer. + If successful, the return value is true, else, it is false. */ +int vlmemflush(VILLA *villa); + + +/* Refer to volatile cache of a value of a record. + `villa' specifies a database handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to + the specified key. + Because the region of the return value is volatile and it may be spoiled by another operation + of the database, the data should be copied into another involatile buffer immediately. */ +const char *vlgetcache(VILLA *villa, const char *kbuf, int ksiz, int *sp); + + +/* Refer to volatile cache of the key of the record where the cursor is. + `villa' specifies a database handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the key of the corresponding + record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. + Because the region of the return value is volatile and it may be spoiled by another operation + of the database, the data should be copied into another involatile buffer immediately. */ +const char *vlcurkeycache(VILLA *villa, int *sp); + + +/* Refer to volatile cache of the value of the record where the cursor is. + `villa' specifies a database handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to + the cursor. + Because an additional zero code is appended at the end of the region of the + return value, the return value can be treated as a character string. Because the region of + the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +const char *vlcurvalcache(VILLA *villa, int *sp); + + +/* Get a multiple cursor handle. + `villa' specifies a database handle connected as a reader. + The return value is a multiple cursor handle or `NULL' if it is not successful. + The returned object is should be closed before the database handle is closed. Even if plural + cursors are fetched out of a database handle, they does not share the locations with each + other. Note that this function can be used only if the database handle is connected as a + reader. */ +VLMULCUR *vlmulcuropen(VILLA *villa); + + +/* Close a multiple cursor handle. + `mulcur' specifies a multiple cursor handle. */ +void vlmulcurclose(VLMULCUR *mulcur); + + +/* Move a multiple cursor to the first record. + `mulcur' specifies a multiple cursor handle. + If successful, the return value is true, else, it is false. False is returned if there is + no record in the database. */ +int vlmulcurfirst(VLMULCUR *mulcur); + + +/* Move a multiple cursor to the last record. + `mulcur' specifies a multiple cursor handle. + If successful, the return value is true, else, it is false. False is returned if there is + no record in the database. */ +int vlmulcurlast(VLMULCUR *mulcur); + + +/* Move a multiple cursor to the previous record. + `mulcur' specifies a multiple cursor handle. + If successful, the return value is true, else, it is false. False is returned if there is + no previous record. */ +int vlmulcurprev(VLMULCUR *mulcur); + + +/* Move a multiple cursor to the next record. + `mulcur' specifies a multiple cursor handle. + If successful, the return value is true, else, it is false. False is returned if there is + no next record. */ +int vlmulcurnext(VLMULCUR *mulcur); + + +/* Move a multiple cursor to a position around a record. + `mulcur' specifies a multiple cursor handle. + `kbuf' specifies the pointer to the region of a key. + `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned + with `strlen(kbuf)'. + `jmode' specifies detail adjustment: `VL_JFORWARD', which means that the cursor is set to + the first record of the same key and that the cursor is set to the next substitute if + completely matching record does not exist, `VL_JBACKWARD', which means that the cursor is + set to the last record of the same key and that the cursor is set to the previous substitute + if completely matching record does not exist. + If successful, the return value is true, else, it is false. False is returned if there is + no record corresponding the condition. */ +int vlmulcurjump(VLMULCUR *mulcur, const char *kbuf, int ksiz, int jmode); + + +/* Get the key of the record where a multiple cursor is. + `mulcur' specifies a multiple cursor handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the key of the corresponding + record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. + Because an additional zero code is appended at the end of the region of the + return value, the return value can be treated as a character string. Because the region of + the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +char *vlmulcurkey(VLMULCUR *mulcur, int *sp); + + +/* Get the value of the record where a multiple cursor is. + `mulcur' specifies a multiple cursor handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to + the cursor. + Because an additional zero code is appended at the end of the region of the + return value, the return value can be treated as a character string. Because the region of + the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +char *vlmulcurval(VLMULCUR *mulcur, int *sp); + + +/* Refer to volatile cache of the key of the record where a multiple cursor is. + `mulcur' specifies a multiple cursor handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the key of the corresponding + record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. + Because the region of the return value is volatile and it may be spoiled by another operation + of the database, the data should be copied into another involatile buffer immediately. */ +const char *vlmulcurkeycache(VLMULCUR *mulcur, int *sp); + + +/* Refer to volatile cache of the value of the record where a multiple cursor is. + `mulcur' specifies a multiple cursor handle. + `sp' specifies the pointer to a variable to which the size of the region of the return + value is assigned. If it is `NULL', it is not used. + If successful, the return value is the pointer to the region of the value of the + corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to + the cursor. + Because an additional zero code is appended at the end of the region of the + return value, the return value can be treated as a character string. Because the region of + the return value is allocated with the `malloc' call, it should be released with the `free' + call if it is no longer in use. */ +const char *vlmulcurvalcache(VLMULCUR *mulcur, int *sp); + + +/* Get flags of a database. + `villa' specifies a database handle. + The return value is the flags of a database. */ +int vlgetflags(VILLA *villa); + + +/* Set flags of a database. + `villa' specifies a database handle connected as a writer. + `flags' specifies flags to set. Least ten bits are reserved for internal use. + If successful, the return value is true, else, it is false. */ +int vlsetflags(VILLA *villa, int flags); + + + +#undef MYEXTERN + +#if defined(__cplusplus) /* export for C++ */ +} +#endif + +#endif /* duplication check */ + + +/* END OF FILE */ Deleted: box/trunk/qdbm/vista.c =================================================================== --- box/trunk/qdbm/vista.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/vista.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,171 +0,0 @@ -/************************************************************************************************* - * Implementation of Vista - * 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. - *************************************************************************************************/ - - -#define QDBM_INTERNAL 1 -#define _VISTA_C 1 - -#include "vista.h" -#include "myconf.h" - - - -/************************************************************************************************* - * macros to convert Depot to Curia - *************************************************************************************************/ - - -#define DEPOT CURIA - -#define \ - dpopen(name, omode, bnum) \ - cropen(name, omode, ((bnum / vlcrdnum) * 2), vlcrdnum) - -#define \ - dpclose(db) \ - crclose(db) - -#define \ - dpput(db, kbuf, ksiz, vbuf, vsiz, dmode) \ - crput(db, kbuf, ksiz, vbuf, vsiz, dmode) - -#define \ - dpout(db, kbuf, ksiz) \ - crout(db, kbuf, ksiz) - -#define \ - dpget(db, kbuf, ksiz, start, max, sp) \ - crget(db, kbuf, ksiz, start, max, sp) - -#define \ - dpgetwb(db, kbuf, ksiz, start, max, vbuf) \ - crgetwb(db, kbuf, ksiz, start, max, vbuf) - -#define \ - dpvsiz(db, kbuf, ksiz) \ - crvsiz(db, kbuf, ksiz) - -#define \ - dpiterinit(db) \ - criterinit(db) - -#define \ - dpiternext(db, sp) \ - criternext(db, sp) - -#define \ - dpsetalign(db, align) \ - crsetalign(db, align) - -#define \ - dpsetfbpsiz(db, size) \ - crsetfbpsiz(db, size) - -#define \ - dpsync(db) \ - crsync(db) - -#define \ - dpoptimize(db, bnum) \ - croptimize(db, bnum) - -#define \ - dpname(db) \ - crname(db) - -#define \ - dpfsiz(db) \ - crfsiz(db) - -#define \ - dpbnum(db) \ - crbnum(db) - -#define \ - dpbusenum(db) \ - crbusenum(db) - -#define \ - dprnum(db) \ - crrnum(db) - -#define \ - dpwritable(db) \ - crwritable(db) - -#define \ - dpfatalerror(db) \ - crfatalerror(db) - -#define \ - dpinode(db) \ - crinode(db) - -#define \ - dpmtime(db) \ - crmtime(db) - -#define \ - dpfdesc(db) \ - crfdesc(db) - -#define \ - dpremove(db) \ - crremove(db) - -#define \ - dprepair(db) \ - crrepair(db) - -#define \ - dpexportdb(db, name) \ - crexportdb(db, name) - -#define \ - dpimportdb(db, name) \ - crimportdb(db, name) - -#define \ - dpsnaffle(db, name) \ - crsnaffle(db, name) - -#define \ - dpmemsync(db) \ - crmemsync(db) - -#define \ - dpmemflush(db) \ - crmemflush(db) - -#define \ - dpgetflags(db) \ - crgetflags(db) - -#define \ - dpsetflags(db, flags) \ - crsetflags(db, flags) - - - -/************************************************************************************************* - * including real implementation - *************************************************************************************************/ - - -#include "villa.c" - - - -/* END OF FILE */ Copied: box/trunk/qdbm/vista.c (from rev 2716, box/trunk/qdbm/vista.c) =================================================================== --- box/trunk/qdbm/vista.c (rev 0) +++ box/trunk/qdbm/vista.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,171 @@ +/************************************************************************************************* + * Implementation of Vista + * 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. + *************************************************************************************************/ + + +#define QDBM_INTERNAL 1 +#define _VISTA_C 1 + +#include "vista.h" +#include "myconf.h" + + + +/************************************************************************************************* + * macros to convert Depot to Curia + *************************************************************************************************/ + + +#define DEPOT CURIA + +#define \ + dpopen(name, omode, bnum) \ + cropen(name, omode, ((bnum / vlcrdnum) * 2), vlcrdnum) + +#define \ + dpclose(db) \ + crclose(db) + +#define \ + dpput(db, kbuf, ksiz, vbuf, vsiz, dmode) \ + crput(db, kbuf, ksiz, vbuf, vsiz, dmode) + +#define \ + dpout(db, kbuf, ksiz) \ + crout(db, kbuf, ksiz) + +#define \ + dpget(db, kbuf, ksiz, start, max, sp) \ + crget(db, kbuf, ksiz, start, max, sp) + +#define \ + dpgetwb(db, kbuf, ksiz, start, max, vbuf) \ + crgetwb(db, kbuf, ksiz, start, max, vbuf) + +#define \ + dpvsiz(db, kbuf, ksiz) \ + crvsiz(db, kbuf, ksiz) + +#define \ + dpiterinit(db) \ + criterinit(db) + +#define \ + dpiternext(db, sp) \ + criternext(db, sp) + +#define \ + dpsetalign(db, align) \ + crsetalign(db, align) + +#define \ + dpsetfbpsiz(db, size) \ + crsetfbpsiz(db, size) + +#define \ + dpsync(db) \ + crsync(db) + +#define \ + dpoptimize(db, bnum) \ + croptimize(db, bnum) + +#define \ + dpname(db) \ + crname(db) + +#define \ + dpfsiz(db) \ + crfsiz(db) + +#define \ + dpbnum(db) \ + crbnum(db) + +#define \ + dpbusenum(db) \ + crbusenum(db) + +#define \ + dprnum(db) \ + crrnum(db) + +#define \ + dpwritable(db) \ + crwritable(db) + +#define \ + dpfatalerror(db) \ + crfatalerror(db) + +#define \ + dpinode(db) \ + crinode(db) + +#define \ + dpmtime(db) \ + crmtime(db) + +#define \ + dpfdesc(db) \ + crfdesc(db) + +#define \ + dpremove(db) \ + crremove(db) + +#define \ + dprepair(db) \ + crrepair(db) + +#define \ + dpexportdb(db, name) \ + crexportdb(db, name) + +#define \ + dpimportdb(db, name) \ + crimportdb(db, name) + +#define \ + dpsnaffle(db, name) \ + crsnaffle(db, name) + +#define \ + dpmemsync(db) \ + crmemsync(db) + +#define \ + dpmemflush(db) \ + crmemflush(db) + +#define \ + dpgetflags(db) \ + crgetflags(db) + +#define \ + dpsetflags(db, flags) \ + crsetflags(db, flags) + + + +/************************************************************************************************* + * including real implementation + *************************************************************************************************/ + + +#include "villa.c" + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/vista.h =================================================================== --- box/trunk/qdbm/vista.h 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/vista.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,138 +0,0 @@ -/************************************************************************************************* - * The extended advanced API of QDBM - * 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. - *************************************************************************************************/ - - -#ifndef _VISTA_H /* duplication check */ -#define _VISTA_H - -#if defined(__cplusplus) /* export for C++ */ -extern "C" { -#endif - - - -/************************************************************************************************* - * macros to borrow symbols from Villa - *************************************************************************************************/ - - -#include -#include -#include -#include - -#define VLREC VSTREC -#define VLIDX VSTIDX -#define VLLEAF VSTLEAF -#define VLNODE VSTNODE -#define VLCFUNC VSTCFUNC - -#define VL_CMPLEX VST_CMPLEX -#define VL_CMPINT VST_CMPINT -#define VL_CMPNUM VST_CMPNUM -#define VL_CMPDEC VST_CMPDEC - -#define VILLA VISTA - -#define VL_OREADER VST_OREADER -#define VL_OWRITER VST_OWRITER -#define VL_OCREAT VST_OCREAT -#define VL_OTRUNC VST_OTRUNC -#define VL_ONOLCK VST_ONOLCK -#define VL_OLCKNB VST_OLCKNB -#define VL_OZCOMP VST_OZCOMP - -#define VL_DOVER VST_DOVER -#define VL_DKEEP VST_DKEEP -#define VL_DCAT VST_DCAT -#define VL_DDUP VST_DDUP - -#define VL_JFORWARD VST_JFORWARD -#define VL_JBACKWARD VST_JBACKWARD - -#define vlopen vstopen -#define vlclose vstclose -#define vlput vstput -#define vlout vstout -#define vlget vstget -#define vlvsiz vstvsiz -#define vlvnum vstvnum -#define vlputlist vstputlist -#define vloutlist vstoutlist -#define vlgetlist vstgetlist -#define vlgetcat vstgetcat -#define vlcurfirst vstcurfirst -#define vlcurlast vstcurlast -#define vlcurprev vstcurprev -#define vlcurnext vstcurnext -#define vlcurjump vstcurjump -#define vlcurkey vstcurkey -#define vlcurval vstcurval -#define vlcurput vstcurput -#define vlcurout vstcurout -#define vlsettuning vstsettuning -#define vlsync vstsync -#define vloptimize vstoptimize -#define vlname vstname -#define vlfsiz vstfsiz -#define vllnum vstlnum -#define vlnnum vstnnum -#define vlrnum vstrnum -#define vlwritable vstwritable -#define vlfatalerror vstfatalerror -#define vlinode vstinode -#define vlmtime vstmtime -#define vltranbegin vsttranbegin -#define vltrancommit vsttrancommit -#define vltranabort vsttranabort -#define vlremove vstremove -#define vlrepair vstrepair -#define vlexportdb vstexportdb -#define vlimportdb vstimportdb -#define vlcrdnumptr vstcrdnumptr -#define vlmemsync vstmemsync -#define vlmemflush vstmemflush -#define vlgetcache vstgetcache -#define vlcurkeycache vstcurkeycache -#define vlcurvalcache vstcurvalcache -#define vlmulcuropen vstmulcuropen -#define vlmulcurclose vstmulcurclose -#define vlmulcurfirst vstmulcurfirst -#define vlmulcurlast vstmulcurlast -#define vlmulcurprev vstmulcurprev -#define vlmulcurnext vstmulcurnext -#define vlmulcurjump vstmulcurjump -#define vlmulcurkey vstmulcurkey -#define vlmulcurval vstmulcurval -#define vlmulcurkeycache vstmulcurkeycache -#define vlmulcurvalcache vstmulcurvalcache -#define vlsetfbpsiz vstsetfbpsiz -#define vlgetflags vstgetflags -#define vlsetflags vstsetflags - -#if !defined(_VISTA_C) -#include -#endif - - - -#if defined(__cplusplus) /* export for C++ */ -} -#endif - -#endif /* duplication check */ - - -/* END OF FILE */ Copied: box/trunk/qdbm/vista.h (from rev 2716, box/trunk/qdbm/vista.h) =================================================================== --- box/trunk/qdbm/vista.h (rev 0) +++ box/trunk/qdbm/vista.h 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,138 @@ +/************************************************************************************************* + * The extended advanced API of QDBM + * 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. + *************************************************************************************************/ + + +#ifndef _VISTA_H /* duplication check */ +#define _VISTA_H + +#if defined(__cplusplus) /* export for C++ */ +extern "C" { +#endif + + + +/************************************************************************************************* + * macros to borrow symbols from Villa + *************************************************************************************************/ + + +#include +#include +#include +#include + +#define VLREC VSTREC +#define VLIDX VSTIDX +#define VLLEAF VSTLEAF +#define VLNODE VSTNODE +#define VLCFUNC VSTCFUNC + +#define VL_CMPLEX VST_CMPLEX +#define VL_CMPINT VST_CMPINT +#define VL_CMPNUM VST_CMPNUM +#define VL_CMPDEC VST_CMPDEC + +#define VILLA VISTA + +#define VL_OREADER VST_OREADER +#define VL_OWRITER VST_OWRITER +#define VL_OCREAT VST_OCREAT +#define VL_OTRUNC VST_OTRUNC +#define VL_ONOLCK VST_ONOLCK +#define VL_OLCKNB VST_OLCKNB +#define VL_OZCOMP VST_OZCOMP + +#define VL_DOVER VST_DOVER +#define VL_DKEEP VST_DKEEP +#define VL_DCAT VST_DCAT +#define VL_DDUP VST_DDUP + +#define VL_JFORWARD VST_JFORWARD +#define VL_JBACKWARD VST_JBACKWARD + +#define vlopen vstopen +#define vlclose vstclose +#define vlput vstput +#define vlout vstout +#define vlget vstget +#define vlvsiz vstvsiz +#define vlvnum vstvnum +#define vlputlist vstputlist +#define vloutlist vstoutlist +#define vlgetlist vstgetlist +#define vlgetcat vstgetcat +#define vlcurfirst vstcurfirst +#define vlcurlast vstcurlast +#define vlcurprev vstcurprev +#define vlcurnext vstcurnext +#define vlcurjump vstcurjump +#define vlcurkey vstcurkey +#define vlcurval vstcurval +#define vlcurput vstcurput +#define vlcurout vstcurout +#define vlsettuning vstsettuning +#define vlsync vstsync +#define vloptimize vstoptimize +#define vlname vstname +#define vlfsiz vstfsiz +#define vllnum vstlnum +#define vlnnum vstnnum +#define vlrnum vstrnum +#define vlwritable vstwritable +#define vlfatalerror vstfatalerror +#define vlinode vstinode +#define vlmtime vstmtime +#define vltranbegin vsttranbegin +#define vltrancommit vsttrancommit +#define vltranabort vsttranabort +#define vlremove vstremove +#define vlrepair vstrepair +#define vlexportdb vstexportdb +#define vlimportdb vstimportdb +#define vlcrdnumptr vstcrdnumptr +#define vlmemsync vstmemsync +#define vlmemflush vstmemflush +#define vlgetcache vstgetcache +#define vlcurkeycache vstcurkeycache +#define vlcurvalcache vstcurvalcache +#define vlmulcuropen vstmulcuropen +#define vlmulcurclose vstmulcurclose +#define vlmulcurfirst vstmulcurfirst +#define vlmulcurlast vstmulcurlast +#define vlmulcurprev vstmulcurprev +#define vlmulcurnext vstmulcurnext +#define vlmulcurjump vstmulcurjump +#define vlmulcurkey vstmulcurkey +#define vlmulcurval vstmulcurval +#define vlmulcurkeycache vstmulcurkeycache +#define vlmulcurvalcache vstmulcurvalcache +#define vlsetfbpsiz vstsetfbpsiz +#define vlgetflags vstgetflags +#define vlsetflags vstsetflags + +#if !defined(_VISTA_C) +#include +#endif + + + +#if defined(__cplusplus) /* export for C++ */ +} +#endif + +#endif /* duplication check */ + + +/* END OF FILE */ Deleted: box/trunk/qdbm/vlmgr.c =================================================================== --- box/trunk/qdbm/vlmgr.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/vlmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,968 +0,0 @@ -/************************************************************************************************* - * Utility for debugging Villa and its applications - * 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 -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -char *hextoobj(const char *str, int *sp); -char *dectoiobj(const char *str, int *sp); -int runcreate(int argc, char **argv); -int runput(int argc, char **argv); -int runout(int argc, char **argv); -int runget(int argc, char **argv); -int runlist(int argc, char **argv); -int runoptimize(int argc, char **argv); -int runinform(int argc, char **argv); -int runremove(int argc, char **argv); -int runrepair(int argc, char **argv); -int runexportdb(int argc, char **argv); -int runimportdb(int argc, char **argv); -void pdperror(const char *name); -void printobj(const char *obj, int size); -void printobjhex(const char *obj, int size); -int docreate(const char *name, int cmode); -int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, - int dmode, VLCFUNC cmp); -int doout(const char *name, const char *kbuf, int ksiz, VLCFUNC cmp, int lb); -int doget(const char *name, int opts, const char *kbuf, int ksiz, VLCFUNC cmp, - int lb, int ox, int nb); -int dolist(const char *name, int opts, const char *tbuf, int tsiz, const char *bbuf, int bsiz, - VLCFUNC cmp, int ki, int kb, int vb, int ox, int gt, int lt, int max, int desc); -int dooptimize(const char *name); -int doinform(const char *name, int opts); -int doremove(const char *name); -int dorepair(const char *name, VLCFUNC cmp); -int doexportdb(const char *name, const char *file, VLCFUNC cmp); -int doimportdb(const char *name, const char *file, VLCFUNC cmp); - - -/* main routine */ -int main(int argc, char **argv){ - char *env; - int rv; - cbstdiobin(); - progname = argv[0]; - if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "create")){ - rv = runcreate(argc, argv); - } else if(!strcmp(argv[1], "put")){ - rv = runput(argc, argv); - } else if(!strcmp(argv[1], "out")){ - rv = runout(argc, argv); - } else if(!strcmp(argv[1], "get")){ - rv = runget(argc, argv); - } else if(!strcmp(argv[1], "list")){ - rv = runlist(argc, argv); - } else if(!strcmp(argv[1], "optimize")){ - rv = runoptimize(argc, argv); - } else if(!strcmp(argv[1], "inform")){ - rv = runinform(argc, argv); - } else if(!strcmp(argv[1], "remove")){ - rv = runremove(argc, argv); - } else if(!strcmp(argv[1], "repair")){ - rv = runrepair(argc, argv); - } else if(!strcmp(argv[1], "exportdb")){ - rv = runexportdb(argc, argv); - } else if(!strcmp(argv[1], "importdb")){ - rv = runimportdb(argc, argv); - } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ - printf("Powered by QDBM version %s on %s%s\n", - dpversion, dpsysname, dpisreentrant ? " (reentrant)" : ""); - printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); - rv = 0; - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: administration utility for Villa\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s create [-cz|-cy|-cx] name\n", progname); - fprintf(stderr, " %s put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat|-dup] name key val\n", progname); - fprintf(stderr, " %s out [-l] [-kx|-ki] name key\n", progname); - fprintf(stderr, " %s get [-nl] [-l] [-kx|-ki] [-ox] [-n] name key\n", progname); - fprintf(stderr, " %s list [-nl] [-k|-v] [-kx|-ki] [-ox] [-top key] [-bot key] [-gt] [-lt]" - " [-max num] [-desc] name\n", progname); - fprintf(stderr, " %s optimize name\n", progname); - fprintf(stderr, " %s inform [-nl] name\n", progname); - fprintf(stderr, " %s remove name\n", progname); - fprintf(stderr, " %s repair [-ki] name\n", progname); - fprintf(stderr, " %s exportdb [-ki] name file\n", progname); - fprintf(stderr, " %s importdb [-ki] name file\n", progname); - fprintf(stderr, " %s version\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* create a binary object from a hexadecimal string */ -char *hextoobj(const char *str, int *sp){ - char *buf, mbuf[3]; - int len, i, j; - len = strlen(str); - if(!(buf = malloc(len + 1))) return NULL; - j = 0; - for(i = 0; i < len; i += 2){ - while(strchr(" \n\r\t\f\v", str[i])){ - i++; - } - if((mbuf[0] = str[i]) == '\0') break; - if((mbuf[1] = str[i+1]) == '\0') break; - mbuf[2] = '\0'; - buf[j++] = (char)strtol(mbuf, NULL, 16); - } - buf[j] = '\0'; - *sp = j; - return buf; -} - - -/* create a integer object from a decimal string */ -char *dectoiobj(const char *str, int *sp){ - char *buf; - int num; - num = atoi(str); - if(!(buf = malloc(sizeof(int)))) return NULL; - *(int *)buf = num; - *sp = sizeof(int); - return buf; -} - - -/* parse arguments of create command */ -int runcreate(int argc, char **argv){ - char *name; - int i, cmode, rv; - name = NULL; - cmode = 0; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-cz")){ - cmode |= VL_OZCOMP; - } else if(!strcmp(argv[i], "-cy")){ - cmode |= VL_OYCOMP; - } else if(!strcmp(argv[i], "-cx")){ - cmode |= VL_OXCOMP; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = docreate(name, cmode); - return rv; -} - - -/* parse arguments of put command */ -int runput(int argc, char **argv){ - char *name, *key, *val, *kbuf, *vbuf; - int i, kx, ki, vx, vi, vf, ksiz, vsiz, rv; - int dmode; - name = NULL; - kx = FALSE; - ki = FALSE; - vx = FALSE; - vi = FALSE; - vf = FALSE; - key = NULL; - val = NULL; - dmode = VL_DOVER; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else if(!strcmp(argv[i], "-vx")){ - vx = TRUE; - } else if(!strcmp(argv[i], "-vi")){ - vi = TRUE; - } else if(!strcmp(argv[i], "-vf")){ - vf = TRUE; - } else if(!strcmp(argv[i], "-keep")){ - dmode = VL_DKEEP; - } else if(!strcmp(argv[i], "-cat")){ - dmode = VL_DCAT; - } else if(!strcmp(argv[i], "-dup")){ - dmode = VL_DDUP; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else if(!val){ - val = argv[i]; - } else { - usage(); - } - } - if(!name || !key || !val) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(vx){ - vbuf = hextoobj(val, &vsiz); - } else if(vi){ - vbuf = dectoiobj(val, &vsiz); - } else if(vf){ - vbuf = cbreadfile(val, &vsiz); - } else { - vbuf = cbmemdup(val, -1); - vsiz = -1; - } - if(kbuf && vbuf){ - rv = doput(name, kbuf, ksiz, vbuf, vsiz, dmode, ki ? VL_CMPINT : VL_CMPLEX); - } else { - if(vf){ - fprintf(stderr, "%s: %s: cannot read\n", progname, val); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - } - rv = 1; - } - free(kbuf); - free(vbuf); - return rv; -} - - -/* parse arguments of out command */ -int runout(int argc, char **argv){ - char *name, *key, *kbuf; - int i, kx, ki, lb, ksiz, rv; - name = NULL; - kx = FALSE; - ki = FALSE; - lb = FALSE; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-l")){ - lb = TRUE; - } else if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(kbuf){ - rv = doout(name, kbuf, ksiz, ki ? VL_CMPINT : VL_CMPLEX, lb); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* parse arguments of get command */ -int runget(int argc, char **argv){ - char *name, *key, *kbuf; - int i, opts, lb, kx, ki, ox, nb, ksiz, rv; - name = NULL; - opts = 0; - lb = FALSE; - kx = FALSE; - ki = FALSE; - ox = FALSE; - nb = FALSE; - key = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-nl")){ - opts |= VL_ONOLCK; - } else if(!strcmp(argv[i], "-l")){ - lb = TRUE; - } else if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else if(!strcmp(argv[i], "-n")){ - nb = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!key){ - key = argv[i]; - } else { - usage(); - } - } - if(!name || !key) usage(); - if(kx){ - kbuf = hextoobj(key, &ksiz); - } else if(ki){ - kbuf = dectoiobj(key, &ksiz); - } else { - kbuf = cbmemdup(key, -1); - ksiz = -1; - } - if(kbuf){ - rv = doget(name, opts, kbuf, ksiz, ki ? VL_CMPINT : VL_CMPLEX, lb, ox, nb); - } else { - fprintf(stderr, "%s: out of memory\n", progname); - rv = 1; - } - free(kbuf); - return rv; -} - - -/* parse arguments of list command */ -int runlist(int argc, char **argv){ - char *name, *top, *bot, *tbuf, *bbuf, *nstr; - int i, opts, kb, vb, kx, ki, ox, gt, lt, max, desc, tsiz, bsiz, rv; - name = NULL; - opts = 0; - kb = FALSE; - vb = FALSE; - kx = FALSE; - ki = FALSE; - ox = FALSE; - gt = FALSE; - lt = FALSE; - max = -1; - desc = FALSE; - top = NULL; - bot = NULL; - nstr = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-nl")){ - opts |= VL_ONOLCK; - } else if(!strcmp(argv[i], "-k")){ - kb = TRUE; - } else if(!strcmp(argv[i], "-v")){ - vb = TRUE; - } else if(!strcmp(argv[i], "-kx")){ - kx = TRUE; - } else if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else if(!strcmp(argv[i], "-ox")){ - ox = TRUE; - } else if(!strcmp(argv[i], "-top")){ - if(++i >= argc) usage(); - top = argv[i]; - } else if(!strcmp(argv[i], "-bot")){ - if(++i >= argc) usage(); - bot = argv[i]; - } else if(!strcmp(argv[i], "-gt")){ - gt = TRUE; - } else if(!strcmp(argv[i], "-lt")){ - lt = TRUE; - } else if(!strcmp(argv[i], "-max")){ - if(++i >= argc) usage(); - max = atoi(argv[i]); - } else if(!strcmp(argv[i], "-desc")){ - desc = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - tbuf = NULL; - bbuf = NULL; - if(kx){ - if(top) tbuf = hextoobj(top, &tsiz); - if(bot) bbuf = hextoobj(bot, &bsiz); - } else if(ki){ - if(top) tbuf = dectoiobj(top, &tsiz); - if(bot) bbuf = dectoiobj(bot, &bsiz); - } else { - if(top){ - tbuf = cbmemdup(top, -1); - tsiz = strlen(tbuf); - } - if(bot){ - bbuf = cbmemdup(bot, -1); - bsiz = strlen(bbuf); - } - } - rv = dolist(name, opts, tbuf, tsiz, bbuf, bsiz, ki ? VL_CMPINT : VL_CMPLEX, ki, - kb, vb, ox, gt, lt, max, desc); - free(tbuf); - free(bbuf); - return rv; -} - - -/* parse arguments of optimize command */ -int runoptimize(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dooptimize(name); - return rv; -} - - -/* parse arguments of inform command */ -int runinform(int argc, char **argv){ - char *name; - int i, opts, rv; - name = NULL; - opts = 0; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-nl")){ - opts |= VL_ONOLCK; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doinform(name, opts); - return rv; -} - - -/* parse arguments of remove command */ -int runremove(int argc, char **argv){ - char *name; - int i, rv; - name = NULL; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - usage(); - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doremove(name); - return rv; -} - - -/* parse arguments of repair command */ -int runrepair(int argc, char **argv){ - char *name; - int i, ki, rv; - name = NULL; - ki = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = dorepair(name, ki ? VL_CMPINT : VL_CMPLEX); - return rv; -} - - -/* parse arguments of exportdb command */ -int runexportdb(int argc, char **argv){ - char *name, *file; - int i, ki, rv; - name = NULL; - file = NULL; - ki = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - if(!name || !file) usage(); - rv = doexportdb(name, file, ki ? VL_CMPINT : VL_CMPLEX); - return rv; -} - - -/* parse arguments of importdb command */ -int runimportdb(int argc, char **argv){ - char *name, *file; - int i, ki, rv; - name = NULL; - file = NULL; - ki = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-ki")){ - ki = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!file){ - file = argv[i]; - } else { - usage(); - } - } - if(!name || !file) usage(); - rv = doimportdb(name, file, ki ? VL_CMPINT : VL_CMPLEX); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* print an object */ -void printobj(const char *obj, int size){ - int i; - for(i = 0; i < size; i++){ - putchar(obj[i]); - } -} - - -/* print an object as a hexadecimal string */ -void printobjhex(const char *obj, int size){ - int i; - for(i = 0; i < size; i++){ - printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); - } -} - - -/* perform create command */ -int docreate(const char *name, int cmode){ - VILLA *villa; - int omode; - omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; - if(!(villa = vlopen(name, omode, VL_CMPLEX))){ - pdperror(name); - return 1; - } - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform put command */ -int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, - int dmode, VLCFUNC cmp){ - VILLA *villa; - if(!(villa = vlopen(name, VL_OWRITER, cmp))){ - pdperror(name); - return 1; - } - if(!vlput(villa, kbuf, ksiz, vbuf, vsiz, dmode)){ - pdperror(name); - vlclose(villa); - return 1; - } - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform out command */ -int doout(const char *name, const char *kbuf, int ksiz, VLCFUNC cmp, int lb){ - VILLA *villa; - if(!(villa = vlopen(name, VL_OWRITER, cmp))){ - pdperror(name); - return 1; - } - if(lb){ - if(!vloutlist(villa, kbuf, ksiz)){ - pdperror(name); - vlclose(villa); - return 1; - } - } else { - if(!vlout(villa, kbuf, ksiz)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform get command */ -int doget(const char *name, int opts, const char *kbuf, int ksiz, VLCFUNC cmp, - int lb, int ox, int nb){ - VILLA *villa; - CBLIST *vals; - char *vbuf; - int vsiz; - if(!(villa = vlopen(name, VL_OREADER | opts, cmp))){ - pdperror(name); - return 1; - } - if(lb){ - if(!(vals = vlgetlist(villa, kbuf, ksiz))){ - pdperror(name); - vlclose(villa); - return 1; - } - while((vbuf = cblistshift(vals, &vsiz)) != NULL){ - if(ox){ - printobjhex(vbuf, vsiz); - } else { - printobj(vbuf, vsiz); - } - free(vbuf); - putchar('\n'); - } - cblistclose(vals); - } else { - if(!(vbuf = vlget(villa, kbuf, ksiz, &vsiz))){ - pdperror(name); - vlclose(villa); - return 1; - } - if(ox){ - printobjhex(vbuf, vsiz); - } else { - printobj(vbuf, vsiz); - } - free(vbuf); - if(!nb) putchar('\n'); - } - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform list command */ -int dolist(const char *name, int opts, const char *tbuf, int tsiz, const char *bbuf, int bsiz, - VLCFUNC cmp, int ki, int kb, int vb, int ox, int gt, int lt, int max, int desc){ - VILLA *villa; - char *kbuf, *vbuf; - int ksiz, vsiz, show, rv; - if(!(villa = vlopen(name, VL_OREADER | opts, cmp))){ - pdperror(name); - return 1; - } - if(max < 0) max = vlrnum(villa); - if(desc){ - if(bbuf){ - vlcurjump(villa, bbuf, bsiz, VL_JBACKWARD); - } else { - vlcurlast(villa); - } - show = 0; - while(show < max && (kbuf = vlcurkey(villa, &ksiz)) != NULL){ - if(bbuf && lt){ - if(cmp(kbuf, ksiz, bbuf, bsiz) == 0){ - free(kbuf); - vlcurnext(villa); - continue; - } - lt = FALSE; - } - if(tbuf){ - rv = cmp(kbuf, ksiz, tbuf, tsiz); - if(rv < 0 || (gt && rv == 0)){ - free(kbuf); - break; - } - } - if(!(vbuf = vlcurval(villa, &vsiz))){ - free(kbuf); - break; - } - if(ox){ - if(!vb) printobjhex(kbuf, ksiz); - if(!kb && !vb) putchar('\t'); - if(!kb) printobjhex(vbuf, vsiz); - } else { - if(!vb) printobj(kbuf, ksiz); - if(!kb && !vb) putchar('\t'); - if(!kb) printobj(vbuf, vsiz); - } - putchar('\n'); - free(kbuf); - free(vbuf); - show++; - vlcurprev(villa); - } - } else { - if(tbuf){ - vlcurjump(villa, tbuf, tsiz, VL_JFORWARD); - } else { - vlcurfirst(villa); - } - show = 0; - while(show < max && (kbuf = vlcurkey(villa, &ksiz)) != NULL){ - if(tbuf && gt){ - if(cmp(kbuf, ksiz, tbuf, tsiz) == 0){ - free(kbuf); - vlcurnext(villa); - continue; - } - gt = FALSE; - } - if(bbuf){ - rv = cmp(kbuf, ksiz, bbuf, bsiz); - if(rv > 0 || (lt && rv == 0)){ - free(kbuf); - break; - } - } - if(!(vbuf = vlcurval(villa, &vsiz))){ - free(kbuf); - break; - } - if(ox){ - if(!vb) printobjhex(kbuf, ksiz); - if(!kb && !vb) putchar('\t'); - if(!kb) printobjhex(vbuf, vsiz); - } else { - if(!vb) printobj(kbuf, ksiz); - if(!kb && !vb) putchar('\t'); - if(!kb) printobj(vbuf, vsiz); - } - putchar('\n'); - free(kbuf); - free(vbuf); - show++; - vlcurnext(villa); - } - } - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform optimize command */ -int dooptimize(const char *name){ - VILLA *villa; - if(!(villa = vlopen(name, VL_OWRITER, VL_CMPLEX))){ - pdperror(name); - return 1; - } - if(!vloptimize(villa)){ - pdperror(name); - vlclose(villa); - return 1; - } - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform inform command */ -int doinform(const char *name, int opts){ - VILLA *villa; - char *tmp; - if(!(villa = vlopen(name, VL_OREADER | opts, VL_CMPLEX))){ - pdperror(name); - return 1; - } - tmp = vlname(villa); - printf("name: %s\n", tmp ? tmp : "(null)"); - free(tmp); - printf("file size: %d\n", vlfsiz(villa)); - printf("leaf nodes: %d\n", vllnum(villa)); - printf("non-leaf nodes: %d\n", vlnnum(villa)); - printf("records: %d\n", vlrnum(villa)); - printf("inode number: %d\n", vlinode(villa)); - printf("modified time: %.0f\n", (double)vlmtime(villa)); - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform remove command */ -int doremove(const char *name){ - if(!vlremove(name)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform repair command */ -int dorepair(const char *name, VLCFUNC cmp){ - if(!vlrepair(name, cmp)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform exportdb command */ -int doexportdb(const char *name, const char *file, VLCFUNC cmp){ - VILLA *villa; - if(!(villa = vlopen(name, VL_OREADER, cmp))){ - pdperror(name); - return 1; - } - if(!vlexportdb(villa, file)){ - pdperror(name); - vlclose(villa); - return 1; - } - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return 0; -} - - -/* perform importdb command */ -int doimportdb(const char *name, const char *file, VLCFUNC cmp){ - VILLA *villa; - if(!(villa = vlopen(name, VL_OWRITER | VL_OCREAT | VL_OTRUNC, cmp))){ - pdperror(name); - return 1; - } - if(!vlimportdb(villa, file)){ - pdperror(name); - vlclose(villa); - return 1; - } - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/vlmgr.c (from rev 2716, box/trunk/qdbm/vlmgr.c) =================================================================== --- box/trunk/qdbm/vlmgr.c (rev 0) +++ box/trunk/qdbm/vlmgr.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,968 @@ +/************************************************************************************************* + * Utility for debugging Villa and its applications + * 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 +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +char *hextoobj(const char *str, int *sp); +char *dectoiobj(const char *str, int *sp); +int runcreate(int argc, char **argv); +int runput(int argc, char **argv); +int runout(int argc, char **argv); +int runget(int argc, char **argv); +int runlist(int argc, char **argv); +int runoptimize(int argc, char **argv); +int runinform(int argc, char **argv); +int runremove(int argc, char **argv); +int runrepair(int argc, char **argv); +int runexportdb(int argc, char **argv); +int runimportdb(int argc, char **argv); +void pdperror(const char *name); +void printobj(const char *obj, int size); +void printobjhex(const char *obj, int size); +int docreate(const char *name, int cmode); +int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, + int dmode, VLCFUNC cmp); +int doout(const char *name, const char *kbuf, int ksiz, VLCFUNC cmp, int lb); +int doget(const char *name, int opts, const char *kbuf, int ksiz, VLCFUNC cmp, + int lb, int ox, int nb); +int dolist(const char *name, int opts, const char *tbuf, int tsiz, const char *bbuf, int bsiz, + VLCFUNC cmp, int ki, int kb, int vb, int ox, int gt, int lt, int max, int desc); +int dooptimize(const char *name); +int doinform(const char *name, int opts); +int doremove(const char *name); +int dorepair(const char *name, VLCFUNC cmp); +int doexportdb(const char *name, const char *file, VLCFUNC cmp); +int doimportdb(const char *name, const char *file, VLCFUNC cmp); + + +/* main routine */ +int main(int argc, char **argv){ + char *env; + int rv; + cbstdiobin(); + progname = argv[0]; + if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "create")){ + rv = runcreate(argc, argv); + } else if(!strcmp(argv[1], "put")){ + rv = runput(argc, argv); + } else if(!strcmp(argv[1], "out")){ + rv = runout(argc, argv); + } else if(!strcmp(argv[1], "get")){ + rv = runget(argc, argv); + } else if(!strcmp(argv[1], "list")){ + rv = runlist(argc, argv); + } else if(!strcmp(argv[1], "optimize")){ + rv = runoptimize(argc, argv); + } else if(!strcmp(argv[1], "inform")){ + rv = runinform(argc, argv); + } else if(!strcmp(argv[1], "remove")){ + rv = runremove(argc, argv); + } else if(!strcmp(argv[1], "repair")){ + rv = runrepair(argc, argv); + } else if(!strcmp(argv[1], "exportdb")){ + rv = runexportdb(argc, argv); + } else if(!strcmp(argv[1], "importdb")){ + rv = runimportdb(argc, argv); + } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ + printf("Powered by QDBM version %s on %s%s\n", + dpversion, dpsysname, dpisreentrant ? " (reentrant)" : ""); + printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); + rv = 0; + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: administration utility for Villa\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s create [-cz|-cy|-cx] name\n", progname); + fprintf(stderr, " %s put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat|-dup] name key val\n", progname); + fprintf(stderr, " %s out [-l] [-kx|-ki] name key\n", progname); + fprintf(stderr, " %s get [-nl] [-l] [-kx|-ki] [-ox] [-n] name key\n", progname); + fprintf(stderr, " %s list [-nl] [-k|-v] [-kx|-ki] [-ox] [-top key] [-bot key] [-gt] [-lt]" + " [-max num] [-desc] name\n", progname); + fprintf(stderr, " %s optimize name\n", progname); + fprintf(stderr, " %s inform [-nl] name\n", progname); + fprintf(stderr, " %s remove name\n", progname); + fprintf(stderr, " %s repair [-ki] name\n", progname); + fprintf(stderr, " %s exportdb [-ki] name file\n", progname); + fprintf(stderr, " %s importdb [-ki] name file\n", progname); + fprintf(stderr, " %s version\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* create a binary object from a hexadecimal string */ +char *hextoobj(const char *str, int *sp){ + char *buf, mbuf[3]; + int len, i, j; + len = strlen(str); + if(!(buf = malloc(len + 1))) return NULL; + j = 0; + for(i = 0; i < len; i += 2){ + while(strchr(" \n\r\t\f\v", str[i])){ + i++; + } + if((mbuf[0] = str[i]) == '\0') break; + if((mbuf[1] = str[i+1]) == '\0') break; + mbuf[2] = '\0'; + buf[j++] = (char)strtol(mbuf, NULL, 16); + } + buf[j] = '\0'; + *sp = j; + return buf; +} + + +/* create a integer object from a decimal string */ +char *dectoiobj(const char *str, int *sp){ + char *buf; + int num; + num = atoi(str); + if(!(buf = malloc(sizeof(int)))) return NULL; + *(int *)buf = num; + *sp = sizeof(int); + return buf; +} + + +/* parse arguments of create command */ +int runcreate(int argc, char **argv){ + char *name; + int i, cmode, rv; + name = NULL; + cmode = 0; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-cz")){ + cmode |= VL_OZCOMP; + } else if(!strcmp(argv[i], "-cy")){ + cmode |= VL_OYCOMP; + } else if(!strcmp(argv[i], "-cx")){ + cmode |= VL_OXCOMP; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = docreate(name, cmode); + return rv; +} + + +/* parse arguments of put command */ +int runput(int argc, char **argv){ + char *name, *key, *val, *kbuf, *vbuf; + int i, kx, ki, vx, vi, vf, ksiz, vsiz, rv; + int dmode; + name = NULL; + kx = FALSE; + ki = FALSE; + vx = FALSE; + vi = FALSE; + vf = FALSE; + key = NULL; + val = NULL; + dmode = VL_DOVER; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else if(!strcmp(argv[i], "-vx")){ + vx = TRUE; + } else if(!strcmp(argv[i], "-vi")){ + vi = TRUE; + } else if(!strcmp(argv[i], "-vf")){ + vf = TRUE; + } else if(!strcmp(argv[i], "-keep")){ + dmode = VL_DKEEP; + } else if(!strcmp(argv[i], "-cat")){ + dmode = VL_DCAT; + } else if(!strcmp(argv[i], "-dup")){ + dmode = VL_DDUP; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else if(!val){ + val = argv[i]; + } else { + usage(); + } + } + if(!name || !key || !val) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(vx){ + vbuf = hextoobj(val, &vsiz); + } else if(vi){ + vbuf = dectoiobj(val, &vsiz); + } else if(vf){ + vbuf = cbreadfile(val, &vsiz); + } else { + vbuf = cbmemdup(val, -1); + vsiz = -1; + } + if(kbuf && vbuf){ + rv = doput(name, kbuf, ksiz, vbuf, vsiz, dmode, ki ? VL_CMPINT : VL_CMPLEX); + } else { + if(vf){ + fprintf(stderr, "%s: %s: cannot read\n", progname, val); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + } + rv = 1; + } + free(kbuf); + free(vbuf); + return rv; +} + + +/* parse arguments of out command */ +int runout(int argc, char **argv){ + char *name, *key, *kbuf; + int i, kx, ki, lb, ksiz, rv; + name = NULL; + kx = FALSE; + ki = FALSE; + lb = FALSE; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-l")){ + lb = TRUE; + } else if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(kbuf){ + rv = doout(name, kbuf, ksiz, ki ? VL_CMPINT : VL_CMPLEX, lb); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* parse arguments of get command */ +int runget(int argc, char **argv){ + char *name, *key, *kbuf; + int i, opts, lb, kx, ki, ox, nb, ksiz, rv; + name = NULL; + opts = 0; + lb = FALSE; + kx = FALSE; + ki = FALSE; + ox = FALSE; + nb = FALSE; + key = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-nl")){ + opts |= VL_ONOLCK; + } else if(!strcmp(argv[i], "-l")){ + lb = TRUE; + } else if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else if(!strcmp(argv[i], "-n")){ + nb = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!key){ + key = argv[i]; + } else { + usage(); + } + } + if(!name || !key) usage(); + if(kx){ + kbuf = hextoobj(key, &ksiz); + } else if(ki){ + kbuf = dectoiobj(key, &ksiz); + } else { + kbuf = cbmemdup(key, -1); + ksiz = -1; + } + if(kbuf){ + rv = doget(name, opts, kbuf, ksiz, ki ? VL_CMPINT : VL_CMPLEX, lb, ox, nb); + } else { + fprintf(stderr, "%s: out of memory\n", progname); + rv = 1; + } + free(kbuf); + return rv; +} + + +/* parse arguments of list command */ +int runlist(int argc, char **argv){ + char *name, *top, *bot, *tbuf, *bbuf, *nstr; + int i, opts, kb, vb, kx, ki, ox, gt, lt, max, desc, tsiz, bsiz, rv; + name = NULL; + opts = 0; + kb = FALSE; + vb = FALSE; + kx = FALSE; + ki = FALSE; + ox = FALSE; + gt = FALSE; + lt = FALSE; + max = -1; + desc = FALSE; + top = NULL; + bot = NULL; + nstr = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-nl")){ + opts |= VL_ONOLCK; + } else if(!strcmp(argv[i], "-k")){ + kb = TRUE; + } else if(!strcmp(argv[i], "-v")){ + vb = TRUE; + } else if(!strcmp(argv[i], "-kx")){ + kx = TRUE; + } else if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else if(!strcmp(argv[i], "-ox")){ + ox = TRUE; + } else if(!strcmp(argv[i], "-top")){ + if(++i >= argc) usage(); + top = argv[i]; + } else if(!strcmp(argv[i], "-bot")){ + if(++i >= argc) usage(); + bot = argv[i]; + } else if(!strcmp(argv[i], "-gt")){ + gt = TRUE; + } else if(!strcmp(argv[i], "-lt")){ + lt = TRUE; + } else if(!strcmp(argv[i], "-max")){ + if(++i >= argc) usage(); + max = atoi(argv[i]); + } else if(!strcmp(argv[i], "-desc")){ + desc = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + tbuf = NULL; + bbuf = NULL; + if(kx){ + if(top) tbuf = hextoobj(top, &tsiz); + if(bot) bbuf = hextoobj(bot, &bsiz); + } else if(ki){ + if(top) tbuf = dectoiobj(top, &tsiz); + if(bot) bbuf = dectoiobj(bot, &bsiz); + } else { + if(top){ + tbuf = cbmemdup(top, -1); + tsiz = strlen(tbuf); + } + if(bot){ + bbuf = cbmemdup(bot, -1); + bsiz = strlen(bbuf); + } + } + rv = dolist(name, opts, tbuf, tsiz, bbuf, bsiz, ki ? VL_CMPINT : VL_CMPLEX, ki, + kb, vb, ox, gt, lt, max, desc); + free(tbuf); + free(bbuf); + return rv; +} + + +/* parse arguments of optimize command */ +int runoptimize(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dooptimize(name); + return rv; +} + + +/* parse arguments of inform command */ +int runinform(int argc, char **argv){ + char *name; + int i, opts, rv; + name = NULL; + opts = 0; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-nl")){ + opts |= VL_ONOLCK; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doinform(name, opts); + return rv; +} + + +/* parse arguments of remove command */ +int runremove(int argc, char **argv){ + char *name; + int i, rv; + name = NULL; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + usage(); + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doremove(name); + return rv; +} + + +/* parse arguments of repair command */ +int runrepair(int argc, char **argv){ + char *name; + int i, ki, rv; + name = NULL; + ki = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = dorepair(name, ki ? VL_CMPINT : VL_CMPLEX); + return rv; +} + + +/* parse arguments of exportdb command */ +int runexportdb(int argc, char **argv){ + char *name, *file; + int i, ki, rv; + name = NULL; + file = NULL; + ki = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + if(!name || !file) usage(); + rv = doexportdb(name, file, ki ? VL_CMPINT : VL_CMPLEX); + return rv; +} + + +/* parse arguments of importdb command */ +int runimportdb(int argc, char **argv){ + char *name, *file; + int i, ki, rv; + name = NULL; + file = NULL; + ki = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-ki")){ + ki = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!file){ + file = argv[i]; + } else { + usage(); + } + } + if(!name || !file) usage(); + rv = doimportdb(name, file, ki ? VL_CMPINT : VL_CMPLEX); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* print an object */ +void printobj(const char *obj, int size){ + int i; + for(i = 0; i < size; i++){ + putchar(obj[i]); + } +} + + +/* print an object as a hexadecimal string */ +void printobjhex(const char *obj, int size){ + int i; + for(i = 0; i < size; i++){ + printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); + } +} + + +/* perform create command */ +int docreate(const char *name, int cmode){ + VILLA *villa; + int omode; + omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; + if(!(villa = vlopen(name, omode, VL_CMPLEX))){ + pdperror(name); + return 1; + } + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform put command */ +int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, + int dmode, VLCFUNC cmp){ + VILLA *villa; + if(!(villa = vlopen(name, VL_OWRITER, cmp))){ + pdperror(name); + return 1; + } + if(!vlput(villa, kbuf, ksiz, vbuf, vsiz, dmode)){ + pdperror(name); + vlclose(villa); + return 1; + } + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform out command */ +int doout(const char *name, const char *kbuf, int ksiz, VLCFUNC cmp, int lb){ + VILLA *villa; + if(!(villa = vlopen(name, VL_OWRITER, cmp))){ + pdperror(name); + return 1; + } + if(lb){ + if(!vloutlist(villa, kbuf, ksiz)){ + pdperror(name); + vlclose(villa); + return 1; + } + } else { + if(!vlout(villa, kbuf, ksiz)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform get command */ +int doget(const char *name, int opts, const char *kbuf, int ksiz, VLCFUNC cmp, + int lb, int ox, int nb){ + VILLA *villa; + CBLIST *vals; + char *vbuf; + int vsiz; + if(!(villa = vlopen(name, VL_OREADER | opts, cmp))){ + pdperror(name); + return 1; + } + if(lb){ + if(!(vals = vlgetlist(villa, kbuf, ksiz))){ + pdperror(name); + vlclose(villa); + return 1; + } + while((vbuf = cblistshift(vals, &vsiz)) != NULL){ + if(ox){ + printobjhex(vbuf, vsiz); + } else { + printobj(vbuf, vsiz); + } + free(vbuf); + putchar('\n'); + } + cblistclose(vals); + } else { + if(!(vbuf = vlget(villa, kbuf, ksiz, &vsiz))){ + pdperror(name); + vlclose(villa); + return 1; + } + if(ox){ + printobjhex(vbuf, vsiz); + } else { + printobj(vbuf, vsiz); + } + free(vbuf); + if(!nb) putchar('\n'); + } + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform list command */ +int dolist(const char *name, int opts, const char *tbuf, int tsiz, const char *bbuf, int bsiz, + VLCFUNC cmp, int ki, int kb, int vb, int ox, int gt, int lt, int max, int desc){ + VILLA *villa; + char *kbuf, *vbuf; + int ksiz, vsiz, show, rv; + if(!(villa = vlopen(name, VL_OREADER | opts, cmp))){ + pdperror(name); + return 1; + } + if(max < 0) max = vlrnum(villa); + if(desc){ + if(bbuf){ + vlcurjump(villa, bbuf, bsiz, VL_JBACKWARD); + } else { + vlcurlast(villa); + } + show = 0; + while(show < max && (kbuf = vlcurkey(villa, &ksiz)) != NULL){ + if(bbuf && lt){ + if(cmp(kbuf, ksiz, bbuf, bsiz) == 0){ + free(kbuf); + vlcurnext(villa); + continue; + } + lt = FALSE; + } + if(tbuf){ + rv = cmp(kbuf, ksiz, tbuf, tsiz); + if(rv < 0 || (gt && rv == 0)){ + free(kbuf); + break; + } + } + if(!(vbuf = vlcurval(villa, &vsiz))){ + free(kbuf); + break; + } + if(ox){ + if(!vb) printobjhex(kbuf, ksiz); + if(!kb && !vb) putchar('\t'); + if(!kb) printobjhex(vbuf, vsiz); + } else { + if(!vb) printobj(kbuf, ksiz); + if(!kb && !vb) putchar('\t'); + if(!kb) printobj(vbuf, vsiz); + } + putchar('\n'); + free(kbuf); + free(vbuf); + show++; + vlcurprev(villa); + } + } else { + if(tbuf){ + vlcurjump(villa, tbuf, tsiz, VL_JFORWARD); + } else { + vlcurfirst(villa); + } + show = 0; + while(show < max && (kbuf = vlcurkey(villa, &ksiz)) != NULL){ + if(tbuf && gt){ + if(cmp(kbuf, ksiz, tbuf, tsiz) == 0){ + free(kbuf); + vlcurnext(villa); + continue; + } + gt = FALSE; + } + if(bbuf){ + rv = cmp(kbuf, ksiz, bbuf, bsiz); + if(rv > 0 || (lt && rv == 0)){ + free(kbuf); + break; + } + } + if(!(vbuf = vlcurval(villa, &vsiz))){ + free(kbuf); + break; + } + if(ox){ + if(!vb) printobjhex(kbuf, ksiz); + if(!kb && !vb) putchar('\t'); + if(!kb) printobjhex(vbuf, vsiz); + } else { + if(!vb) printobj(kbuf, ksiz); + if(!kb && !vb) putchar('\t'); + if(!kb) printobj(vbuf, vsiz); + } + putchar('\n'); + free(kbuf); + free(vbuf); + show++; + vlcurnext(villa); + } + } + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform optimize command */ +int dooptimize(const char *name){ + VILLA *villa; + if(!(villa = vlopen(name, VL_OWRITER, VL_CMPLEX))){ + pdperror(name); + return 1; + } + if(!vloptimize(villa)){ + pdperror(name); + vlclose(villa); + return 1; + } + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform inform command */ +int doinform(const char *name, int opts){ + VILLA *villa; + char *tmp; + if(!(villa = vlopen(name, VL_OREADER | opts, VL_CMPLEX))){ + pdperror(name); + return 1; + } + tmp = vlname(villa); + printf("name: %s\n", tmp ? tmp : "(null)"); + free(tmp); + printf("file size: %d\n", vlfsiz(villa)); + printf("leaf nodes: %d\n", vllnum(villa)); + printf("non-leaf nodes: %d\n", vlnnum(villa)); + printf("records: %d\n", vlrnum(villa)); + printf("inode number: %d\n", vlinode(villa)); + printf("modified time: %.0f\n", (double)vlmtime(villa)); + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform remove command */ +int doremove(const char *name){ + if(!vlremove(name)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform repair command */ +int dorepair(const char *name, VLCFUNC cmp){ + if(!vlrepair(name, cmp)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform exportdb command */ +int doexportdb(const char *name, const char *file, VLCFUNC cmp){ + VILLA *villa; + if(!(villa = vlopen(name, VL_OREADER, cmp))){ + pdperror(name); + return 1; + } + if(!vlexportdb(villa, file)){ + pdperror(name); + vlclose(villa); + return 1; + } + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return 0; +} + + +/* perform importdb command */ +int doimportdb(const char *name, const char *file, VLCFUNC cmp){ + VILLA *villa; + if(!(villa = vlopen(name, VL_OWRITER | VL_OCREAT | VL_OTRUNC, cmp))){ + pdperror(name); + return 1; + } + if(!vlimportdb(villa, file)){ + pdperror(name); + vlclose(villa); + return 1; + } + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/vltest.c =================================================================== --- box/trunk/qdbm/vltest.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/vltest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,1507 +0,0 @@ -/************************************************************************************************* - * Test cases of Villa - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - -#define RECBUFSIZ 32 /* buffer for records */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -int runwrite(int argc, char **argv); -int runread(int argc, char **argv); -int runrdup(int argc, char **argv); -int runcombo(int argc, char **argv); -int runwicked(int argc, char **argv); -int printfflush(const char *format, ...); -void pdperror(const char *name); -int myrand(void); -int dowrite(const char *name, int rnum, int ii, int cmode, - int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp); -int doread(const char *name, int ii, int vc); -int dordup(const char *name, int rnum, int pnum, int ii, int cmode, int cc, - int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp); -int docombo(const char *name, int cmode); -int dowicked(const char *name, int rnum, int cb, int cmode); - - -/* main routine */ -int main(int argc, char **argv){ - char *env; - int rv; - cbstdiobin(); - if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "write")){ - rv = runwrite(argc, argv); - } else if(!strcmp(argv[1], "read")){ - rv = runread(argc, argv); - } else if(!strcmp(argv[1], "rdup")){ - rv = runrdup(argc, argv); - } else if(!strcmp(argv[1], "combo")){ - rv = runcombo(argc, argv); - } else if(!strcmp(argv[1], "wicked")){ - rv = runwicked(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: test cases for Villa\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum]" - " [-fbp num] name rnum\n", progname); - fprintf(stderr, " %s read [-int] [-vc] name\n", progname); - fprintf(stderr, " %s rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum]" - " [-fbp num] name rnum pnum\n", progname); - fprintf(stderr, " %s combo [-cz|-cy|-cx] name\n", progname); - fprintf(stderr, " %s wicked [-c] [-cz|-cy|-cx] name rnum\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of write command */ -int runwrite(int argc, char **argv){ - char *name, *rstr; - int i, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp, rv; - name = NULL; - rstr = NULL; - rnum = 0; - ii = FALSE; - cmode = 0; - lrecmax = -1; - nidxmax = -1; - lcnum = -1; - ncnum = -1; - fbp = -1; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-int")){ - ii = TRUE; - } else if(!strcmp(argv[i], "-cz")){ - cmode |= VL_OZCOMP; - } else if(!strcmp(argv[i], "-cy")){ - cmode |= VL_OYCOMP; - } else if(!strcmp(argv[i], "-cx")){ - cmode |= VL_OXCOMP; - } else if(!strcmp(argv[i], "-tune")){ - if(++i >= argc) usage(); - lrecmax = atoi(argv[i]); - if(++i >= argc) usage(); - nidxmax = atoi(argv[i]); - if(++i >= argc) usage(); - lcnum = atoi(argv[i]); - if(++i >= argc) usage(); - ncnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-fbp")){ - if(++i >= argc) usage(); - fbp = atoi(argv[i]); - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = dowrite(name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp); - return rv; -} - - -/* parse arguments of read command */ -int runread(int argc, char **argv){ - char *name; - int i, ii, vc, rv; - name = NULL; - ii = FALSE; - vc = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-int")){ - ii = TRUE; - } else if(!strcmp(argv[i], "-vc")){ - vc = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doread(name, ii, vc); - return rv; -} - - -/* parse arguments of rdup command */ -int runrdup(int argc, char **argv){ - char *name, *rstr, *pstr; - int i, rnum, pnum, ii, cmode, cc, lrecmax, nidxmax, lcnum, ncnum, fbp, rv; - name = NULL; - rstr = NULL; - pstr = NULL; - rnum = 0; - pnum = 0; - ii = FALSE; - cmode = 0; - cc = FALSE; - lrecmax = -1; - nidxmax = -1; - lcnum = -1; - ncnum = -1; - fbp = -1; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-int")){ - ii = TRUE; - } else if(!strcmp(argv[i], "-cz")){ - cmode |= VL_OZCOMP; - } else if(!strcmp(argv[i], "-cy")){ - cmode |= VL_OYCOMP; - } else if(!strcmp(argv[i], "-cx")){ - cmode |= VL_OXCOMP; - } else if(!strcmp(argv[i], "-cc")){ - cc = TRUE; - } else if(!strcmp(argv[i], "-tune")){ - if(++i >= argc) usage(); - lrecmax = atoi(argv[i]); - if(++i >= argc) usage(); - nidxmax = atoi(argv[i]); - if(++i >= argc) usage(); - lcnum = atoi(argv[i]); - if(++i >= argc) usage(); - ncnum = atoi(argv[i]); - } else if(!strcmp(argv[i], "-fbp")){ - if(++i >= argc) usage(); - fbp = atoi(argv[i]); - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else if(!pstr){ - pstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr || !pstr) usage(); - rnum = atoi(rstr); - pnum = atoi(pstr); - if(rnum < 1 || pnum < 1) usage(); - rv = dordup(name, rnum, pnum, ii, cmode, cc, lrecmax, nidxmax, lcnum, ncnum, fbp); - return rv; -} - - -/* parse arguments of combo command */ -int runcombo(int argc, char **argv){ - char *name; - int i, cmode, rv; - name = NULL; - cmode = 0; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-cz")){ - cmode |= VL_OZCOMP; - } else if(!strcmp(argv[i], "-cy")){ - cmode |= VL_OYCOMP; - } else if(!strcmp(argv[i], "-cx")){ - cmode |= VL_OXCOMP; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = docombo(name, cmode); - return rv; -} - - -/* parse arguments of wicked command */ -int runwicked(int argc, char **argv){ - char *name, *rstr; - int i, cb, cmode, rnum, rv; - name = NULL; - rstr = NULL; - cb = FALSE; - cmode = 0; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-c")){ - cb = TRUE; - } else if(!strcmp(argv[i], "-cz")){ - cmode |= VL_OZCOMP; - } else if(!strcmp(argv[i], "-cy")){ - cmode |= VL_OYCOMP; - } else if(!strcmp(argv[i], "-cx")){ - cmode |= VL_OXCOMP; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else if(!rstr){ - rstr = argv[i]; - } else { - usage(); - } - } - if(!name || !rstr) usage(); - rnum = atoi(rstr); - if(rnum < 1) usage(); - rv = dowicked(name, rnum, cb, cmode); - return rv; -} - - -/* print formatted string and flush the buffer */ -int printfflush(const char *format, ...){ - va_list ap; - int rv; - va_start(ap, format); - rv = vprintf(format, ap); - if(fflush(stdout) == EOF) rv = -1; - va_end(ap); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* pseudo random number generator */ -int myrand(void){ - static int cnt = 0; - if(cnt == 0) srand(time(NULL)); - return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; -} - - -/* perform write command */ -int dowrite(const char *name, int rnum, int ii, int cmode, - int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp){ - VILLA *villa; - int i, omode, err, len; - char buf[RECBUFSIZ]; - printfflush("\n name=%s rnum=%d int=%d cmode=%d " - "lrecmax=%d nidxmax=%d lcnum=%d ncnum=%d fbp=%d\n\n", - name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp); - /* open a database */ - omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; - if(!(villa = vlopen(name, omode, ii ? VL_CMPINT : VL_CMPLEX))){ - pdperror(name); - return 1; - } - err = FALSE; - /* set tuning parameters */ - if(lrecmax > 0) vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum); - if(fbp >= 0) vlsetfbpsiz(villa, fbp); - /* loop for each record */ - for(i = 1; i <= rnum; i++){ - /* store a record */ - if(ii){ - if(!vlput(villa, (char *)&i, sizeof(int), (char *)&i, sizeof(int), VL_DOVER)){ - pdperror(name); - err = TRUE; - break; - } - } else { - len = sprintf(buf, "%08d", i); - if(!vlput(villa, buf, len, buf, len, VL_DOVER)){ - pdperror(name); - err = TRUE; - break; - } - } - /* print progression */ - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return 0; -} - - -/* perform read command */ -int doread(const char *name, int ii, int vc){ - VILLA *villa; - int i, rnum, err, len; - const char *cval; - char buf[RECBUFSIZ], *val; - printfflush("\n name=%s int=%d\n\n", name, ii); - /* open a database */ - if(!(villa = vlopen(name, VL_OREADER, ii ? VL_CMPINT : VL_CMPLEX))){ - pdperror(name); - return 1; - } - /* get the number of records */ - rnum = vlrnum(villa); - err = FALSE; - /* loop for each record */ - for(i = 1; i <= rnum; i++){ - /* retrieve a record */ - if(ii){ - if(vc){ - if(!(cval = vlgetcache(villa, (char *)&i, sizeof(int), NULL))){ - pdperror(name); - err = TRUE; - break; - } - } else { - if(!(val = vlget(villa, (char *)&i, sizeof(int), NULL))){ - pdperror(name); - err = TRUE; - break; - } - free(val); - } - } else { - len = sprintf(buf, "%08d", i); - if(vc){ - if(!(cval = vlgetcache(villa, buf, len, NULL))){ - pdperror(name); - err = TRUE; - break; - } - } else { - if(!(val = vlget(villa, buf, len, NULL))){ - pdperror(name); - err = TRUE; - break; - } - free(val); - } - } - /* print progression */ - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d)\n", i); - } - } - } - /* close the database */ - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return 0; -} - - -/* perform rdup command */ -int dordup(const char *name, int rnum, int pnum, int ii, int cmode, int cc, - int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp){ - VILLA *villa; - int i, omode, err, dmode, vi, len; - char buf[RECBUFSIZ]; - printfflush("\n name=%s rnum=%d int=%d cmode=%d " - "lrecmax=%d nidxmax=%d lcnum=%d ncnum=%d fbp=%d\n\n", - name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp); - omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; - if(!(villa = vlopen(name, omode, ii ? VL_CMPINT : VL_CMPLEX))){ - pdperror(name); - return 1; - } - err = FALSE; - if(lrecmax > 0) vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum); - if(fbp >= 0) vlsetfbpsiz(villa, fbp); - for(i = 1; i <= rnum; i++){ - dmode = i % 3 == 0 ? VL_DDUPR : VL_DDUP; - if(cc && myrand() % 2 == 0) dmode = VL_DCAT; - vi = myrand() % pnum + 1; - if(ii){ - if(!vlput(villa, (char *)&vi, sizeof(int), (char *)&vi, sizeof(int), dmode)){ - pdperror(name); - err = TRUE; - break; - } - } else { - len = sprintf(buf, "%08d", vi); - if(!vlput(villa, buf, len, buf, len, dmode)){ - pdperror(name); - err = TRUE; - break; - } - } - if(rnum > 250 && i % (rnum / 250) == 0){ - putchar('.'); - fflush(stdout); - if(i == rnum || i % (rnum / 10) == 0){ - printfflush(" (%08d: fsiz=%d lnum=%d nnum=%d)\n", - i, vlfsiz(villa), vllnum(villa), vlnnum(villa)); - } - } - } - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return 0; -} - - -/* perform combo command */ -int docombo(const char *name, int cmode){ - VILLA *villa; - VLMULCUR **mulcurs; - char buf[RECBUFSIZ], *vbuf, *kbuf; - int i, j, omode, len, vsiz, ksiz, fsiz, lnum, nnum, rnum; - CBLIST *alist, *dlist; - const char *ap, *dp; - printfflush("\n name=%s cmode=%d\n\n", name, cmode); - printfflush("Creating a database with VL_CMPLEX ... "); - omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; - if(!(villa = vlopen(name, omode, VL_CMPLEX))){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Setting tuning parameters with 3, 4, 16, 16 ... "); - vlsettuning(villa, 3, 4, 16, 16); - printfflush("ok\n"); - printfflush("Adding 100 records with VL_DOVER ... "); - for(i = 1; i <= 100; i++){ - len = sprintf(buf, "%08d", i); - if(!vlput(villa, buf, len, buf, len, VL_DOVER)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking records ... "); - for(i = 1; i <= 100; i++){ - len = sprintf(buf, "%08d", i); - if(!(vbuf = vlget(villa, buf, len, &vsiz))){ - pdperror(name); - vlclose(villa); - return 1; - } - free(vbuf); - if(vsiz != 8 || vlvsiz(villa, buf, len) != 8){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - vlclose(villa); - return 1; - } - if(vlvnum(villa, buf, len) != 1){ - fprintf(stderr, "%s: %s: invalid vnum\n", progname, name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Deleting x1 - x5 records ... "); - for(i = 1; i <= 100; i++){ - if(i % 10 < 1 || i % 10 > 5) continue; - len = sprintf(buf, "%08d", i); - if(!vlout(villa, buf, len)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Adding 100 records with VL_DOVER ... "); - for(i = 1; i <= 100; i++){ - len = sprintf(buf, "%08d", i); - if(!vlput(villa, buf, len, buf, len, VL_DOVER)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Deleting x1 - x5 records ... "); - for(i = 1; i <= 100; i++){ - if(i % 10 < 1 || i % 10 > 5) continue; - len = sprintf(buf, "%08d", i); - if(!vlout(villa, buf, len)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Checking number of records ... "); - if(vlrnum(villa) != 50){ - fprintf(stderr, "%s: %s: invalid rnum\n", progname, name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 100 records with VL_DDUP ... "); - for(i = 1; i <= 100; i++){ - len = sprintf(buf, "%08d", i); - if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Deleting x6 - x0 records ... "); - for(i = 1; i <= 100; i++){ - if(i % 10 >= 1 && i % 10 <= 5) continue; - len = sprintf(buf, "%08d", i); - if(!vlout(villa, buf, len)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Optimizing the database ... "); - if(!vloptimize(villa)){ - pdperror(name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Checking number of records ... "); - if(vlrnum(villa) != 100){ - fprintf(stderr, "%s: %s: invalid rnum\n", progname, name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Checking records ... "); - for(i = 1; i <= 100; i++){ - len = sprintf(buf, "%08d", i); - if(!(vbuf = vlget(villa, buf, len, &vsiz))){ - pdperror(name); - vlclose(villa); - return 1; - } - free(vbuf); - if(vsiz != 8){ - fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); - vlclose(villa); - return 1; - } - if(vlvnum(villa, buf, len) != 1){ - fprintf(stderr, "%s: %s: invalid vnum\n", progname, name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Deleting x6 - x0 records ... "); - for(i = 1; i <= 100; i++){ - if(i % 10 >= 1 && i % 10 <= 5) continue; - len = sprintf(buf, "%08d", i); - if(!vlout(villa, buf, len)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Scanning with the cursor in ascending order ... "); - if(!vlcurfirst(villa)){ - pdperror(name); - vlclose(villa); - return 1; - } - i = 0; - do { - kbuf = NULL; - vbuf = NULL; - if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ - pdperror(name); - free(kbuf); - free(vbuf); - vlclose(villa); - return 1; - } - free(kbuf); - free(vbuf); - i++; - } while(vlcurnext(villa)); - if(i != 50){ - fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); - vlclose(villa); - return 1; - } - if(dpecode != DP_ENOITEM){ - pdperror(name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Scanning with the cursor in decending order ... "); - if(!vlcurlast(villa)){ - pdperror(name); - vlclose(villa); - return 1; - } - i = 0; - do { - kbuf = NULL; - vbuf = NULL; - if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ - pdperror(name); - free(kbuf); - free(vbuf); - vlclose(villa); - return 1; - } - free(kbuf); - free(vbuf); - i++; - } while(vlcurprev(villa)); - if(i != 50){ - fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); - vlclose(villa); - return 1; - } - if(dpecode != DP_ENOITEM){ - pdperror(name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 50 random records with VL_DDUPR ... "); - for(i = 0; i < 50; i++){ - len = sprintf(buf, "%08d", myrand() % 100 + 1); - if(!vlput(villa, buf, len, buf, len, VL_DDUPR)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Deleting 80 random records ... "); - i = 0; - while(i < 80){ - len = sprintf(buf, "%08d", myrand() % 100 + 1); - if(!vlout(villa, buf, len)){ - if(dpecode == DP_ENOITEM) continue; - pdperror(name); - vlclose(villa); - return 1; - } - i++; - } - printfflush("ok\n"); - alist = cblistopen(); - dlist = cblistopen(); - printfflush("Scanning with the cursor in ascending order ... "); - if(!vlcurfirst(villa)){ - pdperror(name); - vlclose(villa); - return 1; - } - i = 0; - do { - kbuf = NULL; - vbuf = NULL; - if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ - pdperror(name); - cblistclose(alist); - cblistclose(dlist); - free(kbuf); - free(vbuf); - vlclose(villa); - return 1; - } - cblistpush(alist, kbuf, ksiz); - free(kbuf); - free(vbuf); - i++; - } while(vlcurnext(villa)); - if(i != 20){ - fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); - cblistclose(alist); - cblistclose(dlist); - vlclose(villa); - return 1; - } - if(dpecode != DP_ENOITEM){ - pdperror(name); - cblistclose(alist); - cblistclose(dlist); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Scanning with the cursor in decending order ... "); - if(!vlcurlast(villa)){ - pdperror(name); - cblistclose(alist); - cblistclose(dlist); - vlclose(villa); - return 1; - } - i = 0; - do { - kbuf = NULL; - vbuf = NULL; - if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ - pdperror(name); - free(kbuf); - free(vbuf); - cblistclose(alist); - cblistclose(dlist); - vlclose(villa); - return 1; - } - cblistunshift(dlist, kbuf, ksiz); - free(kbuf); - free(vbuf); - i++; - } while(vlcurprev(villa)); - if(i != 20){ - fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); - cblistclose(alist); - cblistclose(dlist); - vlclose(villa); - return 1; - } - if(dpecode != DP_ENOITEM){ - pdperror(name); - cblistclose(alist); - cblistclose(dlist); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Matching result of ascending scan and desending scan ... "); - for(i = 0; i < cblistnum(alist); i++){ - ap = cblistval(alist, i, NULL); - dp = cblistval(dlist, i, NULL); - if(strcmp(ap, dp)){ - fprintf(stderr, "%s: %s: not match\n", progname, name); - cblistclose(alist); - cblistclose(dlist); - vlclose(villa); - return 1; - } - } - cblistsort(alist); - for(i = 0; i < cblistnum(alist); i++){ - ap = cblistval(alist, i, NULL); - dp = cblistval(dlist, i, NULL); - if(strcmp(ap, dp)){ - fprintf(stderr, "%s: %s: not match\n", progname, name); - cblistclose(alist); - cblistclose(dlist); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - cblistclose(alist); - cblistclose(dlist); - printfflush("Resetting tuning parameters with 41, 80, 32, 32 ... "); - vlsettuning(villa, 41, 80, 32, 32); - printfflush("ok\n"); - printfflush("Adding 1000 random records with VL_DDUP ... "); - for(i = 0; i < 1000; i++){ - len = sprintf(buf, "%08d", myrand() % 1000 + 1); - if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Resetting tuning parameters with 8, 5, 16, 16 ... "); - vlsettuning(villa, 8, 5, 16, 16); - printfflush("ok\n"); - printfflush("Adding 1000 random records with VL_DDUP ... "); - for(i = 0; i < 1000; i++){ - len = sprintf(buf, "%08d", myrand() % 1000 + 1); - if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Beginning the transaction ... "); - if(!vltranbegin(villa)){ - pdperror(name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 100 random records with VL_DDUP ... "); - for(i = 0; i < 100; i++){ - len = sprintf(buf, "%08d", myrand() % 1000 + 1); - if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Scanning and checking ... "); - i = 0; - for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){ - if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){ - pdperror(name); - free(kbuf); - vlclose(villa); - return 1; - } - free(vbuf); - free(kbuf); - i++; - } - if(i != vlrnum(villa)){ - fprintf(stderr, "%s: %s: invalid\n", progname, name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Committing the transaction ... "); - if(!vltrancommit(villa)){ - pdperror(name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Scanning and checking ... "); - i = 0; - for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){ - if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){ - pdperror(name); - free(kbuf); - vlclose(villa); - return 1; - } - free(vbuf); - free(kbuf); - i++; - } - if(i != vlrnum(villa)){ - fprintf(stderr, "%s: %s: invalid\n", progname, name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - lnum = vllnum(villa); - nnum = vlnnum(villa); - rnum = vlrnum(villa); - fsiz = vlfsiz(villa); - printfflush("Beginning the transaction ... "); - if(!vltranbegin(villa)){ - pdperror(name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 100 random records with VL_DDUP ... "); - for(i = 0; i < 100; i++){ - len = sprintf(buf, "%08d", myrand() % 1000 + 1); - if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Aborting the transaction ... "); - if(!vltranabort(villa)){ - pdperror(name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Checking rollback ... "); - if(vlfsiz(villa) != fsiz || vllnum(villa) != lnum || - vlnnum(villa) != nnum || vlrnum(villa) != rnum){ - fprintf(stderr, "%s: %s: invalid\n", progname, name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Scanning and checking ... "); - i = 0; - for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){ - if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){ - pdperror(name); - free(kbuf); - vlclose(villa); - return 1; - } - free(vbuf); - free(kbuf); - i++; - } - if(i != vlrnum(villa)){ - fprintf(stderr, "%s: %s: invalid\n", progname, name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Closing the database ... "); - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Creating a database with VL_CMPLEX ... "); - omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; - if(!(villa = vlopen(name, omode, VL_CMPLEX))){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Setting tuning parameters with 5, 6, 16, 16 ... "); - vlsettuning(villa, 5, 6, 16, 16); - printfflush("ok\n"); - printfflush("Adding 3 * 3 records with VL_DDUP ... "); - for(i = 0; i < 3; i++){ - for(j = 0; j < 3; j++){ - len = sprintf(buf, "%08d", j); - if(!vlput(villa, buf, len, buf, -1, VL_DDUP)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - } - printfflush("ok\n"); - printfflush("Inserting records with the cursor ... "); - if(!vlcurjump(villa, "00000001", -1, VL_JFORWARD) || - !vlcurput(villa, "first", -1, VL_CPAFTER) || !vlcurput(villa, "second", -1, VL_CPAFTER) || - !vlcurnext(villa) || - !vlcurput(villa, "third", -1, VL_CPAFTER) || - strcmp(vlcurvalcache(villa, NULL), "third") || - !vlcurput(villa, "fourth", -1, VL_CPCURRENT) || - strcmp(vlcurvalcache(villa, NULL), "fourth") || - !vlcurjump(villa, "00000001", -1, VL_JFORWARD) || - strcmp(vlcurvalcache(villa, NULL), "00000001") || - !vlcurput(villa, "one", -1, VL_CPBEFORE) || !vlcurput(villa, "two", -1, VL_CPBEFORE) || - !vlcurput(villa, "three", -1, VL_CPBEFORE) || !vlcurput(villa, "five", -1, VL_CPBEFORE) || - !vlcurnext(villa) || - !vlcurput(villa, "four", -1, VL_CPBEFORE) || - strcmp(vlcurvalcache(villa, NULL), "four") || - !vlcurjump(villa, "00000001*", -1, VL_JBACKWARD) || - strcmp(vlcurvalcache(villa, NULL), "00000001") || - !vlcurput(villa, "omega", -1, VL_CPAFTER) || - strcmp(vlcurkeycache(villa, NULL), "00000001") || - strcmp(vlcurvalcache(villa, NULL), "omega") || - !vlcurjump(villa, "00000000*", -1, VL_JFORWARD) || - !vlcurput(villa, "alpha", -1, VL_CPBEFORE) || - strcmp(vlcurvalcache(villa, NULL), "alpha") || - !vlcurprev(villa) || - strcmp(vlcurkeycache(villa, NULL), "00000000") || - strcmp(vlcurvalcache(villa, NULL), "00000000") || - !vlcurput(villa, "before", -1, VL_CPAFTER) || - strcmp(vlcurvalcache(villa, NULL), "before") || - !vlcurjump(villa, "00000001*", -1, VL_JFORWARD) || - !vlcurput(villa, "after", -1, VL_CPBEFORE) || - strcmp(vlcurvalcache(villa, NULL), "after") || - !vlcurfirst(villa) || - strcmp(vlcurvalcache(villa, NULL), "00000000") || - !vlcurput(villa, "top", -1, VL_CPBEFORE) || - strcmp(vlcurvalcache(villa, NULL), "top") || - !vlcurlast(villa) || - !vlcurput(villa, "bottom", -1, VL_CPAFTER) || - strcmp(vlcurvalcache(villa, NULL), "bottom")){ - fprintf(stderr, "%s: %s: invalid\n", progname, name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Deleting records with the cursor ... "); - if(!vlcurjump(villa, "00000000*", -1, VL_JBACKWARD) || - strcmp(vlcurvalcache(villa, NULL), "before") || - !vlcurout(villa) || - strcmp(vlcurvalcache(villa, NULL), "alpha") || - !vlcurout(villa) || - strcmp(vlcurvalcache(villa, NULL), "five") || - !vlcurfirst(villa) || !vlcurnext(villa) || - !vlcurout(villa) || !vlcurout(villa) || !vlcurout(villa) || - strcmp(vlcurvalcache(villa, NULL), "five") || - !vlcurprev(villa) || - strcmp(vlcurvalcache(villa, NULL), "top") || - !vlcurout(villa) || - strcmp(vlcurvalcache(villa, NULL), "five") || - !vlcurjump(villa, "00000002", -1, VL_JBACKWARD) || - strcmp(vlcurvalcache(villa, NULL), "bottom") || - !vlcurout(villa) || - !vlcurjump(villa, "00000001", -1, VL_JBACKWARD) || - !vlcurout(villa) || - !vlcurout(villa) || !vlcurout(villa) || !vlcurout(villa) || - strcmp(vlcurkeycache(villa, NULL), "00000002") || - strcmp(vlcurvalcache(villa, NULL), "00000002") || - !vlcurout(villa) || vlcurout(villa) || - !vlcurfirst(villa) || - strcmp(vlcurvalcache(villa, NULL), "five")){ - fprintf(stderr, "%s: %s: invalid\n", progname, name); - vlclose(villa); - return 1; - } - vlcurfirst(villa); - while(vlcurout(villa)){ - free(vlcurval(villa, NULL)); - } - if(vlrnum(villa) != 0){ - printf("%d\n", vlrnum(villa)); - fprintf(stderr, "%s: %s: invalid\n", progname, name); - vlclose(villa); - return 1; - } - for(i = 0; i < 1000; i++){ - len = sprintf(buf, "%08d", i); - if(!vlput(villa, buf, len, buf, -1, VL_DKEEP)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - for(i = 200; i < 800; i++){ - len = sprintf(buf, "%08d", i); - if(!vlout(villa, buf, len)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - vlcurfirst(villa); - while(vlcurout(villa)){ - free(vlcurval(villa, NULL)); - } - if(vlrnum(villa) != 0){ - printf("%d\n", vlrnum(villa)); - fprintf(stderr, "%s: %s: invalid\n", progname, name); - vlclose(villa); - return 1; - } - printfflush("ok\n"); - printfflush("Adding 3 * 100 records with VL_DDUP ... "); - for(i = 1; i <= 100; i++){ - len = sprintf(buf, "%08d", i); - for(j = 0; j < 3; j++){ - if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ - pdperror(name); - vlclose(villa); - return 1; - } - } - } - printfflush("ok\n"); - printfflush("Closing the database ... "); - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Opening the database as a reader ... "); - if(!(villa = vlopen(name, VL_OREADER, VL_CMPLEX))){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("Opening multiple cursors ... "); - mulcurs = cbmalloc(sizeof(VLMULCUR *) * 8); - for(i = 0; i < 8; i++){ - if(!(mulcurs[i] = vlmulcuropen(villa))){ - pdperror(name); - vlclose(villa); - return 1; - } - } - printfflush("ok\n"); - printfflush("Scanning multiple cursors ... "); - for(i = 0; i < 8; i++){ - if(i % 2 == 0){ - vlmulcurfirst(mulcurs[i]); - } else { - vlmulcurlast(mulcurs[i]); - } - } - for(i = 0; i < 300; i++){ - for(j = 0; j < 8; j++){ - if(j % 2 == 0){ - if(!(vbuf = vlmulcurkey(mulcurs[j], &vsiz))){ - pdperror(name); - vlclose(villa); - return 1; - } - free(vbuf); - vlmulcurnext(mulcurs[j]); - } else { - if(!(vbuf = vlmulcurval(mulcurs[j], &vsiz))){ - pdperror(name); - vlclose(villa); - return 1; - } - free(vbuf); - vlmulcurprev(mulcurs[j]); - } - } - } - printfflush("ok\n"); - printfflush("Closing multiple cursors ... "); - for(i = 0; i < 8; i++){ - vlmulcurclose(mulcurs[i]); - } - free(mulcurs); - printfflush("ok\n"); - printfflush("Closing the database ... "); - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - printfflush("ok\n"); - printfflush("all ok\n\n"); - return 0; -} - - -/* perform wicked command */ -int dowicked(const char *name, int rnum, int cb, int cmode){ - VILLA *villa; - CBMAP *map; - int i, j, omode, len, err, ksiz, vsiz, tran, mksiz, mvsiz, rsiz; - const char *mkbuf, *mvbuf; - char buf[32], *kbuf, *vbuf; - CBLIST *list; - printfflush("\n name=%s rnum=%d\n\n", name, rnum); - omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; - if(!(villa = vlopen(name, omode, VL_CMPLEX))){ - pdperror(name); - return 1; - } - err = FALSE; - tran = FALSE; - vlsettuning(villa, 5, 10, 64, 64); - map = NULL; - if(cb) map = cbmapopen(); - for(i = 1; i <= rnum; i++){ - len = sprintf(buf, "%08d", myrand() % rnum + 1); - switch(cb ? (myrand() % 5) : myrand() % 16){ - case 0: - putchar('O'); - if(!vlput(villa, buf, len, buf, len, VL_DOVER)) err = TRUE; - if(map) cbmapput(map, buf, len, buf, len, TRUE); - break; - case 1: - putchar('K'); - if(!vlput(villa, buf, len, buf, len, VL_DKEEP) && dpecode != DP_EKEEP) err = TRUE; - if(map) cbmapput(map, buf, len, buf, len, FALSE); - break; - case 2: - putchar('C'); - if(!vlput(villa, buf, len, buf, len, VL_DCAT)) err = TRUE; - if(map) cbmapputcat(map, buf, len, buf, len); - break; - case 3: - putchar('D'); - if(!vlout(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE; - if(map) cbmapout(map, buf, len); - break; - case 4: - putchar('G'); - if((vbuf = vlget(villa, buf, len, NULL)) != NULL){ - free(vbuf); - } else if(dpecode != DP_ENOITEM){ - err = TRUE; - } - break; - case 5: - putchar('V'); - if(vlvsiz(villa, buf, len) < 0 && dpecode != DP_ENOITEM) err = TRUE; - if(!vlvnum(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE; - break; - case 6: - putchar('X'); - list = cblistopen(); - cblistpush(list, buf, len); - cblistpush(list, buf, len); - if(!vlputlist(villa, buf, len, list)) err = TRUE; - cblistclose(list); - break; - case 7: - putchar('Y'); - if(!vloutlist(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE; - break; - case 8: - putchar('Z'); - if((list = vlgetlist(villa, buf, len)) != NULL){ - cblistclose(list); - } else if(dpecode != DP_ENOITEM){ - err = TRUE; - } - if((vbuf = vlgetcat(villa, buf, len, NULL)) != NULL){ - free(vbuf); - } else if(dpecode != DP_ENOITEM){ - err = TRUE; - } - break; - case 9: - putchar('Q'); - if(vlcurjump(villa, buf, len, VL_JFORWARD)){ - for(j = 0; j < 3 && (kbuf = vlcurkey(villa, &ksiz)); j++){ - if(VL_CMPLEX(buf, len, kbuf, ksiz) > 0) err = TRUE; - if(strcmp(vlcurkeycache(villa, NULL), kbuf)) err = TRUE; - if((vbuf = vlcurval(villa, &vsiz)) != NULL){ - if(strcmp(vlcurvalcache(villa, NULL), vbuf)) err = TRUE; - free(vbuf); - } else { - err = TRUE; - } - free(kbuf); - if(!vlcurnext(villa) && dpecode != DP_ENOITEM) err = TRUE; - } - } else { - if(dpecode != DP_ENOITEM) err = TRUE; - } - break; - case 10: - putchar('W'); - if(vlcurjump(villa, buf, len, VL_JBACKWARD)){ - for(j = 0; j < 3 && (kbuf = vlcurkey(villa, &ksiz)); j++){ - if(VL_CMPLEX(buf, len, kbuf, ksiz) < 0) err = TRUE; - if(strcmp(vlcurkeycache(villa, NULL), kbuf)) err = TRUE; - if((vbuf = vlcurval(villa, &vsiz)) != NULL){ - if(strcmp(vlcurvalcache(villa, NULL), vbuf)) err = TRUE; - free(vbuf); - } else { - err = TRUE; - } - free(kbuf); - if(!vlcurprev(villa) && dpecode != DP_ENOITEM) err = TRUE; - } - } else { - if(dpecode != DP_ENOITEM) err = TRUE; - } - break; - case 11: - putchar('L'); - if(myrand() % 3 == 0 && - !vlcurjump(villa, buf, len, i % 3 == 0 ? VL_JFORWARD : VL_JBACKWARD) && - dpecode != DP_ENOITEM) err = TRUE; - for(j = myrand() % 5; j >= 0; j--){ - switch(myrand() % 6){ - case 0: - if(!vlcurput(villa, buf, len, VL_CPAFTER) && dpecode != DP_ENOITEM) err = TRUE; - break; - case 1: - if(!vlcurput(villa, buf, len, VL_CPBEFORE) && dpecode != DP_ENOITEM) err = TRUE; - break; - case 2: - if(!vlcurput(villa, buf, len, VL_CPCURRENT) && dpecode != DP_ENOITEM) err = TRUE; - break; - default: - if(!vlcurout(villa)){ - if(dpecode != DP_ENOITEM) err = TRUE; - break; - } - break; - } - } - break; - case 12: - if(tran ? myrand() % 32 != 0 : myrand() % 1024 != 0){ - putchar('N'); - break; - } - putchar('T'); - if(tran){ - if(myrand() % 5 == 0){ - if(!vltranabort(villa)) err = TRUE; - } else { - if(!vltrancommit(villa)) err = TRUE; - } - tran = FALSE; - } else { - if(!vltranbegin(villa)) err = TRUE; - tran = TRUE; - } - break; - default: - putchar('P'); - if(!vlput(villa, buf, len, buf, len, myrand() % 3 == 0 ? VL_DDUPR : VL_DDUP)) err = TRUE; - break; - } - if(i % 50 == 0) printfflush(" (%08d)\n", i); - if(err){ - pdperror(name); - break; - } - } - if(tran){ - if(!vltranabort(villa)) err = TRUE; - } - if(!vloptimize(villa)){ - pdperror(name); - err = TRUE; - } - if((rnum = vlrnum(villa)) == -1){ - pdperror(name); - err = TRUE; - } - if(!vlcurfirst(villa)){ - pdperror(name); - err = TRUE; - } - i = 0; - do { - kbuf = NULL; - vbuf = NULL; - if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz)) || - ksiz != 8 || vsiz % 8 != 0 || vlvnum(villa, kbuf, ksiz) < 1){ - pdperror(name); - free(kbuf); - free(vbuf); - err = TRUE; - break; - } - free(kbuf); - free(vbuf); - i++; - } while(vlcurnext(villa)); - if(i != rnum){ - fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); - err = TRUE; - } - if(dpecode != DP_ENOITEM){ - pdperror(name); - err = TRUE; - } - if(!vlcurlast(villa)){ - pdperror(name); - err = TRUE; - } - i = 0; - do { - kbuf = NULL; - vbuf = NULL; - if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz)) || - ksiz != 8 || vsiz % 8 != 0 || vlvnum(villa, kbuf, ksiz) < 1){ - pdperror(name); - free(kbuf); - free(vbuf); - err = TRUE; - break; - } - free(kbuf); - free(vbuf); - i++; - } while(vlcurprev(villa)); - if(i != rnum){ - fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); - err = TRUE; - } - if(dpecode != DP_ENOITEM){ - pdperror(name); - err = TRUE; - } - if(map){ - printfflush("Matching records ... "); - cbmapiterinit(map); - while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){ - mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz); - if(!(vbuf = vlget(villa, mkbuf, mksiz, &rsiz))){ - pdperror(name); - err = TRUE; - break; - } - if(rsiz != mvsiz || memcmp(vbuf, mvbuf, rsiz)){ - fprintf(stderr, "%s: %s: unmatched record\n", progname, name); - free(vbuf); - err = TRUE; - break; - } - free(vbuf); - } - cbmapclose(map); - if(!err) printfflush("ok\n"); - } - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - if(!err) printfflush("ok\n\n"); - return err ? 1 : 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/vltest.c (from rev 2716, box/trunk/qdbm/vltest.c) =================================================================== --- box/trunk/qdbm/vltest.c (rev 0) +++ box/trunk/qdbm/vltest.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,1507 @@ +/************************************************************************************************* + * Test cases of Villa + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + +#define RECBUFSIZ 32 /* buffer for records */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +int runwrite(int argc, char **argv); +int runread(int argc, char **argv); +int runrdup(int argc, char **argv); +int runcombo(int argc, char **argv); +int runwicked(int argc, char **argv); +int printfflush(const char *format, ...); +void pdperror(const char *name); +int myrand(void); +int dowrite(const char *name, int rnum, int ii, int cmode, + int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp); +int doread(const char *name, int ii, int vc); +int dordup(const char *name, int rnum, int pnum, int ii, int cmode, int cc, + int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp); +int docombo(const char *name, int cmode); +int dowicked(const char *name, int rnum, int cb, int cmode); + + +/* main routine */ +int main(int argc, char **argv){ + char *env; + int rv; + cbstdiobin(); + if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "write")){ + rv = runwrite(argc, argv); + } else if(!strcmp(argv[1], "read")){ + rv = runread(argc, argv); + } else if(!strcmp(argv[1], "rdup")){ + rv = runrdup(argc, argv); + } else if(!strcmp(argv[1], "combo")){ + rv = runcombo(argc, argv); + } else if(!strcmp(argv[1], "wicked")){ + rv = runwicked(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: test cases for Villa\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum]" + " [-fbp num] name rnum\n", progname); + fprintf(stderr, " %s read [-int] [-vc] name\n", progname); + fprintf(stderr, " %s rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum]" + " [-fbp num] name rnum pnum\n", progname); + fprintf(stderr, " %s combo [-cz|-cy|-cx] name\n", progname); + fprintf(stderr, " %s wicked [-c] [-cz|-cy|-cx] name rnum\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of write command */ +int runwrite(int argc, char **argv){ + char *name, *rstr; + int i, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp, rv; + name = NULL; + rstr = NULL; + rnum = 0; + ii = FALSE; + cmode = 0; + lrecmax = -1; + nidxmax = -1; + lcnum = -1; + ncnum = -1; + fbp = -1; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-int")){ + ii = TRUE; + } else if(!strcmp(argv[i], "-cz")){ + cmode |= VL_OZCOMP; + } else if(!strcmp(argv[i], "-cy")){ + cmode |= VL_OYCOMP; + } else if(!strcmp(argv[i], "-cx")){ + cmode |= VL_OXCOMP; + } else if(!strcmp(argv[i], "-tune")){ + if(++i >= argc) usage(); + lrecmax = atoi(argv[i]); + if(++i >= argc) usage(); + nidxmax = atoi(argv[i]); + if(++i >= argc) usage(); + lcnum = atoi(argv[i]); + if(++i >= argc) usage(); + ncnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-fbp")){ + if(++i >= argc) usage(); + fbp = atoi(argv[i]); + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = dowrite(name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp); + return rv; +} + + +/* parse arguments of read command */ +int runread(int argc, char **argv){ + char *name; + int i, ii, vc, rv; + name = NULL; + ii = FALSE; + vc = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-int")){ + ii = TRUE; + } else if(!strcmp(argv[i], "-vc")){ + vc = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doread(name, ii, vc); + return rv; +} + + +/* parse arguments of rdup command */ +int runrdup(int argc, char **argv){ + char *name, *rstr, *pstr; + int i, rnum, pnum, ii, cmode, cc, lrecmax, nidxmax, lcnum, ncnum, fbp, rv; + name = NULL; + rstr = NULL; + pstr = NULL; + rnum = 0; + pnum = 0; + ii = FALSE; + cmode = 0; + cc = FALSE; + lrecmax = -1; + nidxmax = -1; + lcnum = -1; + ncnum = -1; + fbp = -1; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-int")){ + ii = TRUE; + } else if(!strcmp(argv[i], "-cz")){ + cmode |= VL_OZCOMP; + } else if(!strcmp(argv[i], "-cy")){ + cmode |= VL_OYCOMP; + } else if(!strcmp(argv[i], "-cx")){ + cmode |= VL_OXCOMP; + } else if(!strcmp(argv[i], "-cc")){ + cc = TRUE; + } else if(!strcmp(argv[i], "-tune")){ + if(++i >= argc) usage(); + lrecmax = atoi(argv[i]); + if(++i >= argc) usage(); + nidxmax = atoi(argv[i]); + if(++i >= argc) usage(); + lcnum = atoi(argv[i]); + if(++i >= argc) usage(); + ncnum = atoi(argv[i]); + } else if(!strcmp(argv[i], "-fbp")){ + if(++i >= argc) usage(); + fbp = atoi(argv[i]); + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else if(!pstr){ + pstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr || !pstr) usage(); + rnum = atoi(rstr); + pnum = atoi(pstr); + if(rnum < 1 || pnum < 1) usage(); + rv = dordup(name, rnum, pnum, ii, cmode, cc, lrecmax, nidxmax, lcnum, ncnum, fbp); + return rv; +} + + +/* parse arguments of combo command */ +int runcombo(int argc, char **argv){ + char *name; + int i, cmode, rv; + name = NULL; + cmode = 0; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-cz")){ + cmode |= VL_OZCOMP; + } else if(!strcmp(argv[i], "-cy")){ + cmode |= VL_OYCOMP; + } else if(!strcmp(argv[i], "-cx")){ + cmode |= VL_OXCOMP; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = docombo(name, cmode); + return rv; +} + + +/* parse arguments of wicked command */ +int runwicked(int argc, char **argv){ + char *name, *rstr; + int i, cb, cmode, rnum, rv; + name = NULL; + rstr = NULL; + cb = FALSE; + cmode = 0; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-c")){ + cb = TRUE; + } else if(!strcmp(argv[i], "-cz")){ + cmode |= VL_OZCOMP; + } else if(!strcmp(argv[i], "-cy")){ + cmode |= VL_OYCOMP; + } else if(!strcmp(argv[i], "-cx")){ + cmode |= VL_OXCOMP; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else if(!rstr){ + rstr = argv[i]; + } else { + usage(); + } + } + if(!name || !rstr) usage(); + rnum = atoi(rstr); + if(rnum < 1) usage(); + rv = dowicked(name, rnum, cb, cmode); + return rv; +} + + +/* print formatted string and flush the buffer */ +int printfflush(const char *format, ...){ + va_list ap; + int rv; + va_start(ap, format); + rv = vprintf(format, ap); + if(fflush(stdout) == EOF) rv = -1; + va_end(ap); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* pseudo random number generator */ +int myrand(void){ + static int cnt = 0; + if(cnt == 0) srand(time(NULL)); + return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; +} + + +/* perform write command */ +int dowrite(const char *name, int rnum, int ii, int cmode, + int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp){ + VILLA *villa; + int i, omode, err, len; + char buf[RECBUFSIZ]; + printfflush("\n name=%s rnum=%d int=%d cmode=%d " + "lrecmax=%d nidxmax=%d lcnum=%d ncnum=%d fbp=%d\n\n", + name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp); + /* open a database */ + omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; + if(!(villa = vlopen(name, omode, ii ? VL_CMPINT : VL_CMPLEX))){ + pdperror(name); + return 1; + } + err = FALSE; + /* set tuning parameters */ + if(lrecmax > 0) vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum); + if(fbp >= 0) vlsetfbpsiz(villa, fbp); + /* loop for each record */ + for(i = 1; i <= rnum; i++){ + /* store a record */ + if(ii){ + if(!vlput(villa, (char *)&i, sizeof(int), (char *)&i, sizeof(int), VL_DOVER)){ + pdperror(name); + err = TRUE; + break; + } + } else { + len = sprintf(buf, "%08d", i); + if(!vlput(villa, buf, len, buf, len, VL_DOVER)){ + pdperror(name); + err = TRUE; + break; + } + } + /* print progression */ + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return 0; +} + + +/* perform read command */ +int doread(const char *name, int ii, int vc){ + VILLA *villa; + int i, rnum, err, len; + const char *cval; + char buf[RECBUFSIZ], *val; + printfflush("\n name=%s int=%d\n\n", name, ii); + /* open a database */ + if(!(villa = vlopen(name, VL_OREADER, ii ? VL_CMPINT : VL_CMPLEX))){ + pdperror(name); + return 1; + } + /* get the number of records */ + rnum = vlrnum(villa); + err = FALSE; + /* loop for each record */ + for(i = 1; i <= rnum; i++){ + /* retrieve a record */ + if(ii){ + if(vc){ + if(!(cval = vlgetcache(villa, (char *)&i, sizeof(int), NULL))){ + pdperror(name); + err = TRUE; + break; + } + } else { + if(!(val = vlget(villa, (char *)&i, sizeof(int), NULL))){ + pdperror(name); + err = TRUE; + break; + } + free(val); + } + } else { + len = sprintf(buf, "%08d", i); + if(vc){ + if(!(cval = vlgetcache(villa, buf, len, NULL))){ + pdperror(name); + err = TRUE; + break; + } + } else { + if(!(val = vlget(villa, buf, len, NULL))){ + pdperror(name); + err = TRUE; + break; + } + free(val); + } + } + /* print progression */ + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d)\n", i); + } + } + } + /* close the database */ + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return 0; +} + + +/* perform rdup command */ +int dordup(const char *name, int rnum, int pnum, int ii, int cmode, int cc, + int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp){ + VILLA *villa; + int i, omode, err, dmode, vi, len; + char buf[RECBUFSIZ]; + printfflush("\n name=%s rnum=%d int=%d cmode=%d " + "lrecmax=%d nidxmax=%d lcnum=%d ncnum=%d fbp=%d\n\n", + name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp); + omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; + if(!(villa = vlopen(name, omode, ii ? VL_CMPINT : VL_CMPLEX))){ + pdperror(name); + return 1; + } + err = FALSE; + if(lrecmax > 0) vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum); + if(fbp >= 0) vlsetfbpsiz(villa, fbp); + for(i = 1; i <= rnum; i++){ + dmode = i % 3 == 0 ? VL_DDUPR : VL_DDUP; + if(cc && myrand() % 2 == 0) dmode = VL_DCAT; + vi = myrand() % pnum + 1; + if(ii){ + if(!vlput(villa, (char *)&vi, sizeof(int), (char *)&vi, sizeof(int), dmode)){ + pdperror(name); + err = TRUE; + break; + } + } else { + len = sprintf(buf, "%08d", vi); + if(!vlput(villa, buf, len, buf, len, dmode)){ + pdperror(name); + err = TRUE; + break; + } + } + if(rnum > 250 && i % (rnum / 250) == 0){ + putchar('.'); + fflush(stdout); + if(i == rnum || i % (rnum / 10) == 0){ + printfflush(" (%08d: fsiz=%d lnum=%d nnum=%d)\n", + i, vlfsiz(villa), vllnum(villa), vlnnum(villa)); + } + } + } + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return 0; +} + + +/* perform combo command */ +int docombo(const char *name, int cmode){ + VILLA *villa; + VLMULCUR **mulcurs; + char buf[RECBUFSIZ], *vbuf, *kbuf; + int i, j, omode, len, vsiz, ksiz, fsiz, lnum, nnum, rnum; + CBLIST *alist, *dlist; + const char *ap, *dp; + printfflush("\n name=%s cmode=%d\n\n", name, cmode); + printfflush("Creating a database with VL_CMPLEX ... "); + omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; + if(!(villa = vlopen(name, omode, VL_CMPLEX))){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Setting tuning parameters with 3, 4, 16, 16 ... "); + vlsettuning(villa, 3, 4, 16, 16); + printfflush("ok\n"); + printfflush("Adding 100 records with VL_DOVER ... "); + for(i = 1; i <= 100; i++){ + len = sprintf(buf, "%08d", i); + if(!vlput(villa, buf, len, buf, len, VL_DOVER)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking records ... "); + for(i = 1; i <= 100; i++){ + len = sprintf(buf, "%08d", i); + if(!(vbuf = vlget(villa, buf, len, &vsiz))){ + pdperror(name); + vlclose(villa); + return 1; + } + free(vbuf); + if(vsiz != 8 || vlvsiz(villa, buf, len) != 8){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + vlclose(villa); + return 1; + } + if(vlvnum(villa, buf, len) != 1){ + fprintf(stderr, "%s: %s: invalid vnum\n", progname, name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Deleting x1 - x5 records ... "); + for(i = 1; i <= 100; i++){ + if(i % 10 < 1 || i % 10 > 5) continue; + len = sprintf(buf, "%08d", i); + if(!vlout(villa, buf, len)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Adding 100 records with VL_DOVER ... "); + for(i = 1; i <= 100; i++){ + len = sprintf(buf, "%08d", i); + if(!vlput(villa, buf, len, buf, len, VL_DOVER)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Deleting x1 - x5 records ... "); + for(i = 1; i <= 100; i++){ + if(i % 10 < 1 || i % 10 > 5) continue; + len = sprintf(buf, "%08d", i); + if(!vlout(villa, buf, len)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Checking number of records ... "); + if(vlrnum(villa) != 50){ + fprintf(stderr, "%s: %s: invalid rnum\n", progname, name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 100 records with VL_DDUP ... "); + for(i = 1; i <= 100; i++){ + len = sprintf(buf, "%08d", i); + if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Deleting x6 - x0 records ... "); + for(i = 1; i <= 100; i++){ + if(i % 10 >= 1 && i % 10 <= 5) continue; + len = sprintf(buf, "%08d", i); + if(!vlout(villa, buf, len)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Optimizing the database ... "); + if(!vloptimize(villa)){ + pdperror(name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Checking number of records ... "); + if(vlrnum(villa) != 100){ + fprintf(stderr, "%s: %s: invalid rnum\n", progname, name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Checking records ... "); + for(i = 1; i <= 100; i++){ + len = sprintf(buf, "%08d", i); + if(!(vbuf = vlget(villa, buf, len, &vsiz))){ + pdperror(name); + vlclose(villa); + return 1; + } + free(vbuf); + if(vsiz != 8){ + fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); + vlclose(villa); + return 1; + } + if(vlvnum(villa, buf, len) != 1){ + fprintf(stderr, "%s: %s: invalid vnum\n", progname, name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Deleting x6 - x0 records ... "); + for(i = 1; i <= 100; i++){ + if(i % 10 >= 1 && i % 10 <= 5) continue; + len = sprintf(buf, "%08d", i); + if(!vlout(villa, buf, len)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Scanning with the cursor in ascending order ... "); + if(!vlcurfirst(villa)){ + pdperror(name); + vlclose(villa); + return 1; + } + i = 0; + do { + kbuf = NULL; + vbuf = NULL; + if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ + pdperror(name); + free(kbuf); + free(vbuf); + vlclose(villa); + return 1; + } + free(kbuf); + free(vbuf); + i++; + } while(vlcurnext(villa)); + if(i != 50){ + fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); + vlclose(villa); + return 1; + } + if(dpecode != DP_ENOITEM){ + pdperror(name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Scanning with the cursor in decending order ... "); + if(!vlcurlast(villa)){ + pdperror(name); + vlclose(villa); + return 1; + } + i = 0; + do { + kbuf = NULL; + vbuf = NULL; + if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ + pdperror(name); + free(kbuf); + free(vbuf); + vlclose(villa); + return 1; + } + free(kbuf); + free(vbuf); + i++; + } while(vlcurprev(villa)); + if(i != 50){ + fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); + vlclose(villa); + return 1; + } + if(dpecode != DP_ENOITEM){ + pdperror(name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 50 random records with VL_DDUPR ... "); + for(i = 0; i < 50; i++){ + len = sprintf(buf, "%08d", myrand() % 100 + 1); + if(!vlput(villa, buf, len, buf, len, VL_DDUPR)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Deleting 80 random records ... "); + i = 0; + while(i < 80){ + len = sprintf(buf, "%08d", myrand() % 100 + 1); + if(!vlout(villa, buf, len)){ + if(dpecode == DP_ENOITEM) continue; + pdperror(name); + vlclose(villa); + return 1; + } + i++; + } + printfflush("ok\n"); + alist = cblistopen(); + dlist = cblistopen(); + printfflush("Scanning with the cursor in ascending order ... "); + if(!vlcurfirst(villa)){ + pdperror(name); + vlclose(villa); + return 1; + } + i = 0; + do { + kbuf = NULL; + vbuf = NULL; + if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ + pdperror(name); + cblistclose(alist); + cblistclose(dlist); + free(kbuf); + free(vbuf); + vlclose(villa); + return 1; + } + cblistpush(alist, kbuf, ksiz); + free(kbuf); + free(vbuf); + i++; + } while(vlcurnext(villa)); + if(i != 20){ + fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); + cblistclose(alist); + cblistclose(dlist); + vlclose(villa); + return 1; + } + if(dpecode != DP_ENOITEM){ + pdperror(name); + cblistclose(alist); + cblistclose(dlist); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Scanning with the cursor in decending order ... "); + if(!vlcurlast(villa)){ + pdperror(name); + cblistclose(alist); + cblistclose(dlist); + vlclose(villa); + return 1; + } + i = 0; + do { + kbuf = NULL; + vbuf = NULL; + if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ + pdperror(name); + free(kbuf); + free(vbuf); + cblistclose(alist); + cblistclose(dlist); + vlclose(villa); + return 1; + } + cblistunshift(dlist, kbuf, ksiz); + free(kbuf); + free(vbuf); + i++; + } while(vlcurprev(villa)); + if(i != 20){ + fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); + cblistclose(alist); + cblistclose(dlist); + vlclose(villa); + return 1; + } + if(dpecode != DP_ENOITEM){ + pdperror(name); + cblistclose(alist); + cblistclose(dlist); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Matching result of ascending scan and desending scan ... "); + for(i = 0; i < cblistnum(alist); i++){ + ap = cblistval(alist, i, NULL); + dp = cblistval(dlist, i, NULL); + if(strcmp(ap, dp)){ + fprintf(stderr, "%s: %s: not match\n", progname, name); + cblistclose(alist); + cblistclose(dlist); + vlclose(villa); + return 1; + } + } + cblistsort(alist); + for(i = 0; i < cblistnum(alist); i++){ + ap = cblistval(alist, i, NULL); + dp = cblistval(dlist, i, NULL); + if(strcmp(ap, dp)){ + fprintf(stderr, "%s: %s: not match\n", progname, name); + cblistclose(alist); + cblistclose(dlist); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + cblistclose(alist); + cblistclose(dlist); + printfflush("Resetting tuning parameters with 41, 80, 32, 32 ... "); + vlsettuning(villa, 41, 80, 32, 32); + printfflush("ok\n"); + printfflush("Adding 1000 random records with VL_DDUP ... "); + for(i = 0; i < 1000; i++){ + len = sprintf(buf, "%08d", myrand() % 1000 + 1); + if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Resetting tuning parameters with 8, 5, 16, 16 ... "); + vlsettuning(villa, 8, 5, 16, 16); + printfflush("ok\n"); + printfflush("Adding 1000 random records with VL_DDUP ... "); + for(i = 0; i < 1000; i++){ + len = sprintf(buf, "%08d", myrand() % 1000 + 1); + if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Beginning the transaction ... "); + if(!vltranbegin(villa)){ + pdperror(name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 100 random records with VL_DDUP ... "); + for(i = 0; i < 100; i++){ + len = sprintf(buf, "%08d", myrand() % 1000 + 1); + if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Scanning and checking ... "); + i = 0; + for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){ + if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){ + pdperror(name); + free(kbuf); + vlclose(villa); + return 1; + } + free(vbuf); + free(kbuf); + i++; + } + if(i != vlrnum(villa)){ + fprintf(stderr, "%s: %s: invalid\n", progname, name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Committing the transaction ... "); + if(!vltrancommit(villa)){ + pdperror(name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Scanning and checking ... "); + i = 0; + for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){ + if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){ + pdperror(name); + free(kbuf); + vlclose(villa); + return 1; + } + free(vbuf); + free(kbuf); + i++; + } + if(i != vlrnum(villa)){ + fprintf(stderr, "%s: %s: invalid\n", progname, name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + lnum = vllnum(villa); + nnum = vlnnum(villa); + rnum = vlrnum(villa); + fsiz = vlfsiz(villa); + printfflush("Beginning the transaction ... "); + if(!vltranbegin(villa)){ + pdperror(name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 100 random records with VL_DDUP ... "); + for(i = 0; i < 100; i++){ + len = sprintf(buf, "%08d", myrand() % 1000 + 1); + if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Aborting the transaction ... "); + if(!vltranabort(villa)){ + pdperror(name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Checking rollback ... "); + if(vlfsiz(villa) != fsiz || vllnum(villa) != lnum || + vlnnum(villa) != nnum || vlrnum(villa) != rnum){ + fprintf(stderr, "%s: %s: invalid\n", progname, name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Scanning and checking ... "); + i = 0; + for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){ + if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){ + pdperror(name); + free(kbuf); + vlclose(villa); + return 1; + } + free(vbuf); + free(kbuf); + i++; + } + if(i != vlrnum(villa)){ + fprintf(stderr, "%s: %s: invalid\n", progname, name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Closing the database ... "); + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Creating a database with VL_CMPLEX ... "); + omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; + if(!(villa = vlopen(name, omode, VL_CMPLEX))){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Setting tuning parameters with 5, 6, 16, 16 ... "); + vlsettuning(villa, 5, 6, 16, 16); + printfflush("ok\n"); + printfflush("Adding 3 * 3 records with VL_DDUP ... "); + for(i = 0; i < 3; i++){ + for(j = 0; j < 3; j++){ + len = sprintf(buf, "%08d", j); + if(!vlput(villa, buf, len, buf, -1, VL_DDUP)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + } + printfflush("ok\n"); + printfflush("Inserting records with the cursor ... "); + if(!vlcurjump(villa, "00000001", -1, VL_JFORWARD) || + !vlcurput(villa, "first", -1, VL_CPAFTER) || !vlcurput(villa, "second", -1, VL_CPAFTER) || + !vlcurnext(villa) || + !vlcurput(villa, "third", -1, VL_CPAFTER) || + strcmp(vlcurvalcache(villa, NULL), "third") || + !vlcurput(villa, "fourth", -1, VL_CPCURRENT) || + strcmp(vlcurvalcache(villa, NULL), "fourth") || + !vlcurjump(villa, "00000001", -1, VL_JFORWARD) || + strcmp(vlcurvalcache(villa, NULL), "00000001") || + !vlcurput(villa, "one", -1, VL_CPBEFORE) || !vlcurput(villa, "two", -1, VL_CPBEFORE) || + !vlcurput(villa, "three", -1, VL_CPBEFORE) || !vlcurput(villa, "five", -1, VL_CPBEFORE) || + !vlcurnext(villa) || + !vlcurput(villa, "four", -1, VL_CPBEFORE) || + strcmp(vlcurvalcache(villa, NULL), "four") || + !vlcurjump(villa, "00000001*", -1, VL_JBACKWARD) || + strcmp(vlcurvalcache(villa, NULL), "00000001") || + !vlcurput(villa, "omega", -1, VL_CPAFTER) || + strcmp(vlcurkeycache(villa, NULL), "00000001") || + strcmp(vlcurvalcache(villa, NULL), "omega") || + !vlcurjump(villa, "00000000*", -1, VL_JFORWARD) || + !vlcurput(villa, "alpha", -1, VL_CPBEFORE) || + strcmp(vlcurvalcache(villa, NULL), "alpha") || + !vlcurprev(villa) || + strcmp(vlcurkeycache(villa, NULL), "00000000") || + strcmp(vlcurvalcache(villa, NULL), "00000000") || + !vlcurput(villa, "before", -1, VL_CPAFTER) || + strcmp(vlcurvalcache(villa, NULL), "before") || + !vlcurjump(villa, "00000001*", -1, VL_JFORWARD) || + !vlcurput(villa, "after", -1, VL_CPBEFORE) || + strcmp(vlcurvalcache(villa, NULL), "after") || + !vlcurfirst(villa) || + strcmp(vlcurvalcache(villa, NULL), "00000000") || + !vlcurput(villa, "top", -1, VL_CPBEFORE) || + strcmp(vlcurvalcache(villa, NULL), "top") || + !vlcurlast(villa) || + !vlcurput(villa, "bottom", -1, VL_CPAFTER) || + strcmp(vlcurvalcache(villa, NULL), "bottom")){ + fprintf(stderr, "%s: %s: invalid\n", progname, name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Deleting records with the cursor ... "); + if(!vlcurjump(villa, "00000000*", -1, VL_JBACKWARD) || + strcmp(vlcurvalcache(villa, NULL), "before") || + !vlcurout(villa) || + strcmp(vlcurvalcache(villa, NULL), "alpha") || + !vlcurout(villa) || + strcmp(vlcurvalcache(villa, NULL), "five") || + !vlcurfirst(villa) || !vlcurnext(villa) || + !vlcurout(villa) || !vlcurout(villa) || !vlcurout(villa) || + strcmp(vlcurvalcache(villa, NULL), "five") || + !vlcurprev(villa) || + strcmp(vlcurvalcache(villa, NULL), "top") || + !vlcurout(villa) || + strcmp(vlcurvalcache(villa, NULL), "five") || + !vlcurjump(villa, "00000002", -1, VL_JBACKWARD) || + strcmp(vlcurvalcache(villa, NULL), "bottom") || + !vlcurout(villa) || + !vlcurjump(villa, "00000001", -1, VL_JBACKWARD) || + !vlcurout(villa) || + !vlcurout(villa) || !vlcurout(villa) || !vlcurout(villa) || + strcmp(vlcurkeycache(villa, NULL), "00000002") || + strcmp(vlcurvalcache(villa, NULL), "00000002") || + !vlcurout(villa) || vlcurout(villa) || + !vlcurfirst(villa) || + strcmp(vlcurvalcache(villa, NULL), "five")){ + fprintf(stderr, "%s: %s: invalid\n", progname, name); + vlclose(villa); + return 1; + } + vlcurfirst(villa); + while(vlcurout(villa)){ + free(vlcurval(villa, NULL)); + } + if(vlrnum(villa) != 0){ + printf("%d\n", vlrnum(villa)); + fprintf(stderr, "%s: %s: invalid\n", progname, name); + vlclose(villa); + return 1; + } + for(i = 0; i < 1000; i++){ + len = sprintf(buf, "%08d", i); + if(!vlput(villa, buf, len, buf, -1, VL_DKEEP)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + for(i = 200; i < 800; i++){ + len = sprintf(buf, "%08d", i); + if(!vlout(villa, buf, len)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + vlcurfirst(villa); + while(vlcurout(villa)){ + free(vlcurval(villa, NULL)); + } + if(vlrnum(villa) != 0){ + printf("%d\n", vlrnum(villa)); + fprintf(stderr, "%s: %s: invalid\n", progname, name); + vlclose(villa); + return 1; + } + printfflush("ok\n"); + printfflush("Adding 3 * 100 records with VL_DDUP ... "); + for(i = 1; i <= 100; i++){ + len = sprintf(buf, "%08d", i); + for(j = 0; j < 3; j++){ + if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ + pdperror(name); + vlclose(villa); + return 1; + } + } + } + printfflush("ok\n"); + printfflush("Closing the database ... "); + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Opening the database as a reader ... "); + if(!(villa = vlopen(name, VL_OREADER, VL_CMPLEX))){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("Opening multiple cursors ... "); + mulcurs = cbmalloc(sizeof(VLMULCUR *) * 8); + for(i = 0; i < 8; i++){ + if(!(mulcurs[i] = vlmulcuropen(villa))){ + pdperror(name); + vlclose(villa); + return 1; + } + } + printfflush("ok\n"); + printfflush("Scanning multiple cursors ... "); + for(i = 0; i < 8; i++){ + if(i % 2 == 0){ + vlmulcurfirst(mulcurs[i]); + } else { + vlmulcurlast(mulcurs[i]); + } + } + for(i = 0; i < 300; i++){ + for(j = 0; j < 8; j++){ + if(j % 2 == 0){ + if(!(vbuf = vlmulcurkey(mulcurs[j], &vsiz))){ + pdperror(name); + vlclose(villa); + return 1; + } + free(vbuf); + vlmulcurnext(mulcurs[j]); + } else { + if(!(vbuf = vlmulcurval(mulcurs[j], &vsiz))){ + pdperror(name); + vlclose(villa); + return 1; + } + free(vbuf); + vlmulcurprev(mulcurs[j]); + } + } + } + printfflush("ok\n"); + printfflush("Closing multiple cursors ... "); + for(i = 0; i < 8; i++){ + vlmulcurclose(mulcurs[i]); + } + free(mulcurs); + printfflush("ok\n"); + printfflush("Closing the database ... "); + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + printfflush("ok\n"); + printfflush("all ok\n\n"); + return 0; +} + + +/* perform wicked command */ +int dowicked(const char *name, int rnum, int cb, int cmode){ + VILLA *villa; + CBMAP *map; + int i, j, omode, len, err, ksiz, vsiz, tran, mksiz, mvsiz, rsiz; + const char *mkbuf, *mvbuf; + char buf[32], *kbuf, *vbuf; + CBLIST *list; + printfflush("\n name=%s rnum=%d\n\n", name, rnum); + omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; + if(!(villa = vlopen(name, omode, VL_CMPLEX))){ + pdperror(name); + return 1; + } + err = FALSE; + tran = FALSE; + vlsettuning(villa, 5, 10, 64, 64); + map = NULL; + if(cb) map = cbmapopen(); + for(i = 1; i <= rnum; i++){ + len = sprintf(buf, "%08d", myrand() % rnum + 1); + switch(cb ? (myrand() % 5) : myrand() % 16){ + case 0: + putchar('O'); + if(!vlput(villa, buf, len, buf, len, VL_DOVER)) err = TRUE; + if(map) cbmapput(map, buf, len, buf, len, TRUE); + break; + case 1: + putchar('K'); + if(!vlput(villa, buf, len, buf, len, VL_DKEEP) && dpecode != DP_EKEEP) err = TRUE; + if(map) cbmapput(map, buf, len, buf, len, FALSE); + break; + case 2: + putchar('C'); + if(!vlput(villa, buf, len, buf, len, VL_DCAT)) err = TRUE; + if(map) cbmapputcat(map, buf, len, buf, len); + break; + case 3: + putchar('D'); + if(!vlout(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE; + if(map) cbmapout(map, buf, len); + break; + case 4: + putchar('G'); + if((vbuf = vlget(villa, buf, len, NULL)) != NULL){ + free(vbuf); + } else if(dpecode != DP_ENOITEM){ + err = TRUE; + } + break; + case 5: + putchar('V'); + if(vlvsiz(villa, buf, len) < 0 && dpecode != DP_ENOITEM) err = TRUE; + if(!vlvnum(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE; + break; + case 6: + putchar('X'); + list = cblistopen(); + cblistpush(list, buf, len); + cblistpush(list, buf, len); + if(!vlputlist(villa, buf, len, list)) err = TRUE; + cblistclose(list); + break; + case 7: + putchar('Y'); + if(!vloutlist(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE; + break; + case 8: + putchar('Z'); + if((list = vlgetlist(villa, buf, len)) != NULL){ + cblistclose(list); + } else if(dpecode != DP_ENOITEM){ + err = TRUE; + } + if((vbuf = vlgetcat(villa, buf, len, NULL)) != NULL){ + free(vbuf); + } else if(dpecode != DP_ENOITEM){ + err = TRUE; + } + break; + case 9: + putchar('Q'); + if(vlcurjump(villa, buf, len, VL_JFORWARD)){ + for(j = 0; j < 3 && (kbuf = vlcurkey(villa, &ksiz)); j++){ + if(VL_CMPLEX(buf, len, kbuf, ksiz) > 0) err = TRUE; + if(strcmp(vlcurkeycache(villa, NULL), kbuf)) err = TRUE; + if((vbuf = vlcurval(villa, &vsiz)) != NULL){ + if(strcmp(vlcurvalcache(villa, NULL), vbuf)) err = TRUE; + free(vbuf); + } else { + err = TRUE; + } + free(kbuf); + if(!vlcurnext(villa) && dpecode != DP_ENOITEM) err = TRUE; + } + } else { + if(dpecode != DP_ENOITEM) err = TRUE; + } + break; + case 10: + putchar('W'); + if(vlcurjump(villa, buf, len, VL_JBACKWARD)){ + for(j = 0; j < 3 && (kbuf = vlcurkey(villa, &ksiz)); j++){ + if(VL_CMPLEX(buf, len, kbuf, ksiz) < 0) err = TRUE; + if(strcmp(vlcurkeycache(villa, NULL), kbuf)) err = TRUE; + if((vbuf = vlcurval(villa, &vsiz)) != NULL){ + if(strcmp(vlcurvalcache(villa, NULL), vbuf)) err = TRUE; + free(vbuf); + } else { + err = TRUE; + } + free(kbuf); + if(!vlcurprev(villa) && dpecode != DP_ENOITEM) err = TRUE; + } + } else { + if(dpecode != DP_ENOITEM) err = TRUE; + } + break; + case 11: + putchar('L'); + if(myrand() % 3 == 0 && + !vlcurjump(villa, buf, len, i % 3 == 0 ? VL_JFORWARD : VL_JBACKWARD) && + dpecode != DP_ENOITEM) err = TRUE; + for(j = myrand() % 5; j >= 0; j--){ + switch(myrand() % 6){ + case 0: + if(!vlcurput(villa, buf, len, VL_CPAFTER) && dpecode != DP_ENOITEM) err = TRUE; + break; + case 1: + if(!vlcurput(villa, buf, len, VL_CPBEFORE) && dpecode != DP_ENOITEM) err = TRUE; + break; + case 2: + if(!vlcurput(villa, buf, len, VL_CPCURRENT) && dpecode != DP_ENOITEM) err = TRUE; + break; + default: + if(!vlcurout(villa)){ + if(dpecode != DP_ENOITEM) err = TRUE; + break; + } + break; + } + } + break; + case 12: + if(tran ? myrand() % 32 != 0 : myrand() % 1024 != 0){ + putchar('N'); + break; + } + putchar('T'); + if(tran){ + if(myrand() % 5 == 0){ + if(!vltranabort(villa)) err = TRUE; + } else { + if(!vltrancommit(villa)) err = TRUE; + } + tran = FALSE; + } else { + if(!vltranbegin(villa)) err = TRUE; + tran = TRUE; + } + break; + default: + putchar('P'); + if(!vlput(villa, buf, len, buf, len, myrand() % 3 == 0 ? VL_DDUPR : VL_DDUP)) err = TRUE; + break; + } + if(i % 50 == 0) printfflush(" (%08d)\n", i); + if(err){ + pdperror(name); + break; + } + } + if(tran){ + if(!vltranabort(villa)) err = TRUE; + } + if(!vloptimize(villa)){ + pdperror(name); + err = TRUE; + } + if((rnum = vlrnum(villa)) == -1){ + pdperror(name); + err = TRUE; + } + if(!vlcurfirst(villa)){ + pdperror(name); + err = TRUE; + } + i = 0; + do { + kbuf = NULL; + vbuf = NULL; + if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz)) || + ksiz != 8 || vsiz % 8 != 0 || vlvnum(villa, kbuf, ksiz) < 1){ + pdperror(name); + free(kbuf); + free(vbuf); + err = TRUE; + break; + } + free(kbuf); + free(vbuf); + i++; + } while(vlcurnext(villa)); + if(i != rnum){ + fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); + err = TRUE; + } + if(dpecode != DP_ENOITEM){ + pdperror(name); + err = TRUE; + } + if(!vlcurlast(villa)){ + pdperror(name); + err = TRUE; + } + i = 0; + do { + kbuf = NULL; + vbuf = NULL; + if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz)) || + ksiz != 8 || vsiz % 8 != 0 || vlvnum(villa, kbuf, ksiz) < 1){ + pdperror(name); + free(kbuf); + free(vbuf); + err = TRUE; + break; + } + free(kbuf); + free(vbuf); + i++; + } while(vlcurprev(villa)); + if(i != rnum){ + fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); + err = TRUE; + } + if(dpecode != DP_ENOITEM){ + pdperror(name); + err = TRUE; + } + if(map){ + printfflush("Matching records ... "); + cbmapiterinit(map); + while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){ + mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz); + if(!(vbuf = vlget(villa, mkbuf, mksiz, &rsiz))){ + pdperror(name); + err = TRUE; + break; + } + if(rsiz != mvsiz || memcmp(vbuf, mvbuf, rsiz)){ + fprintf(stderr, "%s: %s: unmatched record\n", progname, name); + free(vbuf); + err = TRUE; + break; + } + free(vbuf); + } + cbmapclose(map); + if(!err) printfflush("ok\n"); + } + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + if(!err) printfflush("ok\n\n"); + return err ? 1 : 0; +} + + + +/* END OF FILE */ Deleted: box/trunk/qdbm/vltsv.c =================================================================== --- box/trunk/qdbm/vltsv.c 2010-08-27 18:33:13 UTC (rev 2716) +++ box/trunk/qdbm/vltsv.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -1,261 +0,0 @@ -/************************************************************************************************* - * Mutual converter between a database of Villa and a TSV text - * 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 -#include -#include -#include -#include -#include - -#undef TRUE -#define TRUE 1 /* boolean true */ -#undef FALSE -#define FALSE 0 /* boolean false */ - - -/* for RISC OS */ -#if defined(__riscos__) || defined(__riscos) -#include -int __riscosify_control = __RISCOSIFY_NO_PROCESS; -#endif - - -/* global variables */ -const char *progname; /* program name */ - - -/* function prototypes */ -int main(int argc, char **argv); -void usage(void); -int runimport(int argc, char **argv); -int runexport(int argc, char **argv); -void pdperror(const char *name); -char *getl(void); -int doimport(const char *name, int bin); -int doexport(const char *name, int bin); - - -/* main routine */ -int main(int argc, char **argv){ - int rv; - cbstdiobin(); - progname = argv[0]; - if(argc < 2) usage(); - rv = 0; - if(!strcmp(argv[1], "import")){ - rv = runimport(argc, argv); - } else if(!strcmp(argv[1], "export")){ - rv = runexport(argc, argv); - } else { - usage(); - } - return rv; -} - - -/* print the usage and exit */ -void usage(void){ - fprintf(stderr, "%s: mutual converter between TSV and Villa database\n", progname); - fprintf(stderr, "\n"); - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s import [-bin] name\n", progname); - fprintf(stderr, " %s export [-bin] name\n", progname); - fprintf(stderr, "\n"); - exit(1); -} - - -/* parse arguments of import command */ -int runimport(int argc, char **argv){ - char *name; - int i, bin, rv; - name = NULL; - bin = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-bin")){ - bin = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doimport(name, bin); - return rv; -} - - -/* parse arguments of export command */ -int runexport(int argc, char **argv){ - char *name; - int i, bin, rv; - name = NULL; - bin = FALSE; - for(i = 2; i < argc; i++){ - if(!name && argv[i][0] == '-'){ - if(!strcmp(argv[i], "-bin")){ - bin = TRUE; - } else { - usage(); - } - } else if(!name){ - name = argv[i]; - } else { - usage(); - } - } - if(!name) usage(); - rv = doexport(name, bin); - return rv; -} - - -/* print an error message */ -void pdperror(const char *name){ - fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); -} - - -/* read a line */ -char *getl(void){ - char *buf; - int c, len, blen; - buf = NULL; - len = 0; - blen = 256; - while((c = getchar()) != EOF){ - if(blen <= len) blen *= 2; - buf = cbrealloc(buf, blen + 1); - if(c == '\n') c = '\0'; - buf[len++] = c; - if(c == '\0') break; - } - if(!buf) return NULL; - buf[len] = '\0'; - return buf; -} - - -/* perform import command */ -int doimport(const char *name, int bin){ - VILLA *villa; - char *buf, *kbuf, *vbuf, *ktmp, *vtmp; - int i, err, ktsiz, vtsiz; - /* open a database */ - if(!(villa = vlopen(name, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){ - pdperror(name); - return 1; - } - /* loop for each line */ - err = FALSE; - for(i = 1; (buf = getl()) != NULL; i++){ - kbuf = buf; - if((vbuf = strchr(buf, '\t')) != NULL){ - *vbuf = '\0'; - vbuf++; - /* store a record */ - if(bin){ - ktmp = cbbasedecode(kbuf, &ktsiz); - vtmp = cbbasedecode(vbuf, &vtsiz); - if(!vlput(villa, ktmp, ktsiz, vtmp, vtsiz, VL_DDUP)){ - pdperror(name); - err = TRUE; - } - free(vtmp); - free(ktmp); - } else { - if(!vlput(villa, kbuf, -1, vbuf, -1, VL_DDUP)){ - pdperror(name); - err = TRUE; - break; - } - } - } else { - fprintf(stderr, "%s: %s: invalid format in line %d\n", progname, name, i); - } - free(buf); - if(err) break; - } - /* close the database */ - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return err ? 1 : 0; -} - - -/* perform export command */ -int doexport(const char *name, int bin){ - VILLA *villa; - char *kbuf, *vbuf, *tmp; - int err, ksiz, vsiz; - /* open a database */ - if(!(villa = vlopen(name, VL_OREADER, VL_CMPLEX))){ - pdperror(name); - return 1; - } - /* initialize the cursor */ - vlcurfirst(villa); - /* loop for each key */ - err = FALSE; - while((kbuf = vlcurkey(villa, &ksiz)) != NULL){ - /* retrieve a value with a key */ - if(!(vbuf = vlcurval(villa, &vsiz))){ - pdperror(name); - free(kbuf); - err = TRUE; - break; - } - /* output data */ - if(bin){ - tmp = cbbaseencode(kbuf, ksiz); - printf("%s\t", tmp); - free(tmp); - tmp = cbbaseencode(vbuf, vsiz); - printf("%s\n", tmp); - free(tmp); - } else { - printf("%s\t%s\n", kbuf, vbuf); - } - /* free resources */ - free(vbuf); - free(kbuf); - /* step the cursor */ - vlcurnext(villa); - } - /* check whether all records were retrieved */ - if(dpecode != DP_ENOITEM){ - pdperror(name); - err = TRUE; - } - /* close the database */ - if(!vlclose(villa)){ - pdperror(name); - return 1; - } - return 0; -} - - - -/* END OF FILE */ Copied: box/trunk/qdbm/vltsv.c (from rev 2716, box/trunk/qdbm/vltsv.c) =================================================================== --- box/trunk/qdbm/vltsv.c (rev 0) +++ box/trunk/qdbm/vltsv.c 2010-10-18 20:34:25 UTC (rev 2794) @@ -0,0 +1,261 @@ +/************************************************************************************************* + * Mutual converter between a database of Villa and a TSV text + * 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 +#include +#include +#include +#include +#include + +#undef TRUE +#define TRUE 1 /* boolean true */ +#undef FALSE +#define FALSE 0 /* boolean false */ + + +/* for RISC OS */ +#if defined(__riscos__) || defined(__riscos) +#include +int __riscosify_control = __RISCOSIFY_NO_PROCESS; +#endif + + +/* global variables */ +const char *progname; /* program name */ + + +/* function prototypes */ +int main(int argc, char **argv); +void usage(void); +int runimport(int argc, char **argv); +int runexport(int argc, char **argv); +void pdperror(const char *name); +char *getl(void); +int doimport(const char *name, int bin); +int doexport(const char *name, int bin); + + +/* main routine */ +int main(int argc, char **argv){ + int rv; + cbstdiobin(); + progname = argv[0]; + if(argc < 2) usage(); + rv = 0; + if(!strcmp(argv[1], "import")){ + rv = runimport(argc, argv); + } else if(!strcmp(argv[1], "export")){ + rv = runexport(argc, argv); + } else { + usage(); + } + return rv; +} + + +/* print the usage and exit */ +void usage(void){ + fprintf(stderr, "%s: mutual converter between TSV and Villa database\n", progname); + fprintf(stderr, "\n"); + fprintf(stderr, "usage:\n"); + fprintf(stderr, " %s import [-bin] name\n", progname); + fprintf(stderr, " %s export [-bin] name\n", progname); + fprintf(stderr, "\n"); + exit(1); +} + + +/* parse arguments of import command */ +int runimport(int argc, char **argv){ + char *name; + int i, bin, rv; + name = NULL; + bin = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-bin")){ + bin = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doimport(name, bin); + return rv; +} + + +/* parse arguments of export command */ +int runexport(int argc, char **argv){ + char *name; + int i, bin, rv; + name = NULL; + bin = FALSE; + for(i = 2; i < argc; i++){ + if(!name && argv[i][0] == '-'){ + if(!strcmp(argv[i], "-bin")){ + bin = TRUE; + } else { + usage(); + } + } else if(!name){ + name = argv[i]; + } else { + usage(); + } + } + if(!name) usage(); + rv = doexport(name, bin); + return rv; +} + + +/* print an error message */ +void pdperror(const char *name){ + fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); +} + + +/* read a line */ +char *getl(void){ + char *buf; + int c, len, blen; + buf = NULL; + len = 0; + blen = 256; + while((c = getchar()) != EOF){ + if(blen <= len) blen *= 2; + buf = cbrealloc(buf, blen + 1); + if(c == '\n') c = '\0'; + buf[len++] = c; + if(c == '\0') break; + } + if(!buf) return NULL; + buf[len] = '\0'; + return buf; +} + + +/* perform import command */ +int doimport(const char *name, int bin){ + VILLA *villa; + char *buf, *kbuf, *vbuf, *ktmp, *vtmp; + int i, err, ktsiz, vtsiz; + /* open a database */ + if(!(villa = vlopen(name, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){ + pdperror(name); + return 1; + } + /* loop for each line */ + err = FALSE; + for(i = 1; (buf = getl()) != NULL; i++){ + kbuf = buf; + if((vbuf = strchr(buf, '\t')) != NULL){ + *vbuf = '\0'; + vbuf++; + /* store a record */ + if(bin){ + ktmp = cbbasedecode(kbuf, &ktsiz); + vtmp = cbbasedecode(vbuf, &vtsiz); + if(!vlput(villa, ktmp, ktsiz, vtmp, vtsiz, VL_DDUP)){ + pdperror(name); + err = TRUE; + } + free(vtmp); + free(ktmp); + } else { + if(!vlput(villa, kbuf, -1, vbuf, -1, VL_DDUP)){ + pdperror(name); + err = TRUE; + break; + } + } + } else { + fprintf(stderr, "%s: %s: invalid format in line %d\n", progname, name, i); + } + free(buf); + if(err) break; + } + /* close the database */ + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return err ? 1 : 0; +} + + +/* perform export command */ +int doexport(const char *name, int bin){ + VILLA *villa; + char *kbuf, *vbuf, *tmp; + int err, ksiz, vsiz; + /* open a database */ + if(!(villa = vlopen(name, VL_OREADER, VL_CMPLEX))){ + pdperror(name); + return 1; + } + /* initialize the cursor */ + vlcurfirst(villa); + /* loop for each key */ + err = FALSE; + while((kbuf = vlcurkey(villa, &ksiz)) != NULL){ + /* retrieve a value with a key */ + if(!(vbuf = vlcurval(villa, &vsiz))){ + pdperror(name); + free(kbuf); + err = TRUE; + break; + } + /* output data */ + if(bin){ + tmp = cbbaseencode(kbuf, ksiz); + printf("%s\t", tmp); + free(tmp); + tmp = cbbaseencode(vbuf, vsiz); + printf("%s\n", tmp); + free(tmp); + } else { + printf("%s\t%s\n", kbuf, vbuf); + } + /* free resources */ + free(vbuf); + free(kbuf); + /* step the cursor */ + vlcurnext(villa); + } + /* check whether all records were retrieved */ + if(dpecode != DP_ENOITEM){ + pdperror(name); + err = TRUE; + } + /* close the database */ + if(!vlclose(villa)){ + pdperror(name); + return 1; + } + return 0; +} + + + +/* END OF FILE */ From subversion at boxbackup.org Wed Oct 20 18:57:51 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Wed, 20 Oct 2010 18:57:51 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2795 - box/trunk/bin/bbackupquery Message-ID: <20101020175751.05DD116AE41@www.boxbackup.org> Author: chris Date: 2010-10-20 18:57:50 +0100 (Wed, 20 Oct 2010) New Revision: 2795 Modified: box/trunk/bin/bbackupquery/BackupQueries.cpp Log: Fix missing closing parenthesis after bbackupquery pwd outputs object ID. Modified: box/trunk/bin/bbackupquery/BackupQueries.cpp =================================================================== --- box/trunk/bin/bbackupquery/BackupQueries.cpp 2010-10-18 20:34:25 UTC (rev 2794) +++ box/trunk/bin/bbackupquery/BackupQueries.cpp 2010-10-20 17:57:50 UTC (rev 2795) @@ -737,7 +737,8 @@ { // Simple implementation, so do it here BOX_INFO(GetCurrentDirectoryName() << " (" << - BOX_FORMAT_OBJECTID(GetCurrentDirectoryID())); + BOX_FORMAT_OBJECTID(GetCurrentDirectoryID()) << + ")"); } break; From subversion at boxbackup.org Wed Oct 20 18:59:05 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Wed, 20 Oct 2010 18:59:05 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2796 - box/RELEASE/0.11/bin/bbackupquery Message-ID: <20101020175905.7A3E316AE61@www.boxbackup.org> Author: chris Date: 2010-10-20 18:59:05 +0100 (Wed, 20 Oct 2010) New Revision: 2796 Modified: box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp Log: Fix missing closing parenthesis after bbackupquery pwd outputs object ID. (merges [2795] from trunk) Modified: box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp =================================================================== --- box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp 2010-10-20 17:57:50 UTC (rev 2795) +++ box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp 2010-10-20 17:59:05 UTC (rev 2796) @@ -325,7 +325,8 @@ { // Simple implementation, so do it here BOX_INFO(GetCurrentDirectoryName() << " (" << - BOX_FORMAT_OBJECTID(GetCurrentDirectoryID())); + BOX_FORMAT_OBJECTID(GetCurrentDirectoryID()) << + ")"); } break; From trac at boxbackup.org Wed Oct 20 19:00:44 2010 From: trac at boxbackup.org (Box Backup) Date: Wed, 20 Oct 2010 18:00:44 -0000 Subject: [Box Backup-commit] #76: "pwd" not working In-Reply-To: <042.c82e111f2207068e17613d342cea7a54@boxbackup.org> References: <042.c82e111f2207068e17613d342cea7a54@boxbackup.org> Message-ID: <051.5ac9d7c2f216886d593003eb0ce61e18@boxbackup.org> #76: "pwd" not working ---------------------+------------------------------------------------------ Reporter: achim | Type: defect Status: new | Priority: minor Milestone: | Component: bbackupquery Version: 0.11rc2 | Keywords: ---------------------+------------------------------------------------------ Changes (by chris): * cc: achim+box@? (added) Comment: Hi Achim, Please could you provide more info? It works for me: {{{ query > pwd INFO: /Test1 (0x2 }}} (apart from the missing final parenthesis, which I've just fixed). -- Ticket URL: Box Backup An open source, completely automatic on-line backup system for UNIX. From subversion at boxbackup.org Wed Oct 20 19:02:07 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Wed, 20 Oct 2010 19:02:07 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2797 - box/trunk/bin/bbackupquery Message-ID: <20101020180207.E332916AE7F@www.boxbackup.org> Author: chris Date: 2010-10-20 19:02:07 +0100 (Wed, 20 Oct 2010) New Revision: 2797 Modified: box/trunk/bin/bbackupquery/BackupQueries.cpp Log: Show the output of "pwd" at NOTICE level, so that it gets displayed in release builds as well. Modified: box/trunk/bin/bbackupquery/BackupQueries.cpp =================================================================== --- box/trunk/bin/bbackupquery/BackupQueries.cpp 2010-10-20 17:59:05 UTC (rev 2796) +++ box/trunk/bin/bbackupquery/BackupQueries.cpp 2010-10-20 18:02:07 UTC (rev 2797) @@ -736,7 +736,7 @@ case Command_pwd: { // Simple implementation, so do it here - BOX_INFO(GetCurrentDirectoryName() << " (" << + BOX_NOTICE(GetCurrentDirectoryName() << " (" << BOX_FORMAT_OBJECTID(GetCurrentDirectoryID()) << ")"); } From subversion at boxbackup.org Wed Oct 20 19:02:41 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Wed, 20 Oct 2010 19:02:41 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2798 - box/RELEASE/0.11/bin/bbackupquery Message-ID: <20101020180241.21A8316AE9F@www.boxbackup.org> Author: chris Date: 2010-10-20 19:02:40 +0100 (Wed, 20 Oct 2010) New Revision: 2798 Modified: box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp Log: Show the output of "pwd" at NOTICE level, so that it gets displayed in release builds as well, thanks to Achim for pointing this out. (merges [2797] from trunk) Modified: box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp =================================================================== --- box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp 2010-10-20 18:02:07 UTC (rev 2797) +++ box/RELEASE/0.11/bin/bbackupquery/BackupQueries.cpp 2010-10-20 18:02:40 UTC (rev 2798) @@ -324,7 +324,7 @@ case Command_pwd: { // Simple implementation, so do it here - BOX_INFO(GetCurrentDirectoryName() << " (" << + BOX_NOTICE(GetCurrentDirectoryName() << " (" << BOX_FORMAT_OBJECTID(GetCurrentDirectoryID()) << ")"); } From trac at boxbackup.org Wed Oct 20 19:03:39 2010 From: trac at boxbackup.org (Box Backup) Date: Wed, 20 Oct 2010 18:03:39 -0000 Subject: [Box Backup-commit] #76: "pwd" not working In-Reply-To: <042.c82e111f2207068e17613d342cea7a54@boxbackup.org> References: <042.c82e111f2207068e17613d342cea7a54@boxbackup.org> Message-ID: <051.e55c682a5bf115f302296d5f706f9f2e@boxbackup.org> #76: "pwd" not working ---------------------+------------------------------------------------------ Reporter: achim | Type: defect Status: closed | Priority: minor Milestone: | Component: bbackupquery Version: 0.11rc2 | Resolution: fixed Keywords: | ---------------------+------------------------------------------------------ Changes (by chris): * status: new => closed * resolution: => fixed Comment: OK, I guess it was at INFO level which is not displayed by default in release builds. Changed to NOTICE level, which is. `bbackupquery -q` will still not show it, however. Thanks for the report! -- Ticket URL: Box Backup An open source, completely automatic on-line backup system for UNIX. From trac at boxbackup.org Wed Oct 20 19:21:41 2010 From: trac at boxbackup.org (Box Backup) Date: Wed, 20 Oct 2010 18:21:41 -0000 Subject: [Box Backup-commit] #75: Restore times wrong, times on store correct In-Reply-To: <042.5704aa61abe7b503a533346538413ddb@boxbackup.org> References: <042.5704aa61abe7b503a533346538413ddb@boxbackup.org> Message-ID: <051.80cf407029b4e6a2e8a7f9a9a5b31ff7@boxbackup.org> #75: Restore times wrong, times on store correct ---------------------------------+------------------------------------------ Reporter: achim | Owner: ben Type: defect | Status: new Priority: normal | Milestone: Component: bbackupd | Version: trunk Keywords: restore times wrong | ---------------------------------+------------------------------------------ Changes (by chris): * keywords: Restore times wrong => restore times wrong Old description: > Testing incremental backups with a file that is automatically updated > every 10 minutes with the following batch file: > > echo %date% %time% >> f:\root\timetest.txt > > It appears that the times during which the file is backed up and to which > the ctime/mtime is set during restore is not working correct: > > Actual time of the backup according to the file's content (GMT +2): > Test 2: 07/09/2010 15:10:00,06 > Test 3: 07/09/2010 16:10:00,59 > Test 4: 07/09/2010 17:10:00,28 > > This is consistent with the information shown in the bb store when using > "list -T" (note the expected 2 hour GMT offset): > 0000aa0c f--o-- 2010-09-07T13:10:02 00006 timetest.txt > 0000aa0d f--o-- 2010-09-07T14:10:02 00006 timetest.txt > 0000aa0e f--o-- 2010-09-07T15:10:02 00006 timetest.txt > > However, after restoring those files, ctime/mtime shows a wrong offset to > the store time (+10 GMT) and the local time (+8): > 07/09/2010 23:10 2.816.941 test2.txt > 08/09/2010 00:10 2.817.091 test3.txt > 08/09/2010 01:10 2.817.241 test4.txt New description: Testing incremental backups with a file that is automatically updated every 10 minutes with the following batch file: {{{ echo %date% %time% >> f:\root\timetest.txt }}} It appears that the times during which the file is backed up and to which the ctime/mtime is set during restore is not working correct: Actual time of the backup according to the file's content (GMT +2): {{{ Test 2: 07/09/2010 15:10:00,06 Test 3: 07/09/2010 16:10:00,59 Test 4: 07/09/2010 17:10:00,28 }}} This is consistent with the information shown in the bb store when using "list -T" (note the expected 2 hour GMT offset): {{{ 0000aa0c f--o-- 2010-09-07T13:10:02 00006 timetest.txt 0000aa0d f--o-- 2010-09-07T14:10:02 00006 timetest.txt 0000aa0e f--o-- 2010-09-07T15:10:02 00006 timetest.txt }}} However, after restoring those files, ctime/mtime shows a wrong offset to the store time (+10 GMT) and the local time (+8): {{{ 07/09/2010 23:10 2.816.941 test2.txt 08/09/2010 00:10 2.817.091 test3.txt 08/09/2010 01:10 2.817.241 test4.txt }}} -- Comment: Improve formatting of bug description -- Ticket URL: Box Backup An open source, completely automatic on-line backup system for UNIX. From subversion at boxbackup.org Fri Oct 22 15:18:00 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Fri, 22 Oct 2010 15:18:00 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2799 - box/trunk/lib/win32 Message-ID: <20101022141800.87D0D16A702@www.boxbackup.org> Author: invisnet Date: 2010-10-22 15:17:59 +0100 (Fri, 22 Oct 2010) New Revision: 2799 Modified: box/trunk/lib/win32/emu.cpp Log: This should fix Trac #14. Modified: box/trunk/lib/win32/emu.cpp =================================================================== --- box/trunk/lib/win32/emu.cpp 2010-10-20 18:02:40 UTC (rev 2798) +++ box/trunk/lib/win32/emu.cpp 2010-10-22 14:17:59 UTC (rev 2799) @@ -654,7 +654,7 @@ { conv.HighPart = fi.nFileSizeHigh; conv.LowPart = fi.nFileSizeLow; - st->st_size = (_off_t)conv.QuadPart; + st->st_size = conv.QuadPart; } // at the mo From trac at boxbackup.org Fri Oct 22 15:19:30 2010 From: trac at boxbackup.org (Box Backup) Date: Fri, 22 Oct 2010 14:19:30 -0000 Subject: [Box Backup-commit] #14: Fix large file issues on Windows In-Reply-To: <042.3eee109473edd48dcd0eac41e8f306bb@boxbackup.org> References: <042.3eee109473edd48dcd0eac41e8f306bb@boxbackup.org> Message-ID: <051.59913e82080f9550816b264057c65e38@boxbackup.org> #14: Fix large file issues on Windows ------------------------------------------------+--------------------------- Reporter: chris | Owner: chris Type: defect | Status: new Priority: normal | Milestone: 0.11 Component: bbackupd | Version: 0.10 Keywords: windows large files 2gb corruption | ------------------------------------------------+--------------------------- Comment(by invisnet): I think this should be fixed with #2799. -- Ticket URL: Box Backup An open source, completely automatic on-line backup system for UNIX. From subversion at boxbackup.org Sat Oct 23 19:18:16 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sat, 23 Oct 2010 19:18:16 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2800 - box/invisnet/vs2010/0.11/lib/common Message-ID: <20101023181816.41A1516ACA4@www.boxbackup.org> Author: invisnet Date: 2010-10-23 19:18:15 +0100 (Sat, 23 Oct 2010) New Revision: 2800 Modified: box/invisnet/vs2010/0.11/lib/common/makeexception.pl.in Log: Need to be able to inherit from generated exception class Modified: box/invisnet/vs2010/0.11/lib/common/makeexception.pl.in =================================================================== --- box/invisnet/vs2010/0.11/lib/common/makeexception.pl.in 2010-10-22 14:17:59 UTC (rev 2799) +++ box/invisnet/vs2010/0.11/lib/common/makeexception.pl.in 2010-10-23 18:18:15 UTC (rev 2800) @@ -114,7 +114,7 @@ return mMessage; } -private: +protected: unsigned int mSubType; std::string mMessage; }; From subversion at boxbackup.org Tue Oct 26 21:08:48 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Tue, 26 Oct 2010 21:08:48 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2801 - in box/invisnet/vs2010/0.11/lib: backupclient common server Message-ID: <20101026200848.94B5416AAB4@www.boxbackup.org> Author: invisnet Date: 2010-10-26 21:08:47 +0100 (Tue, 26 Oct 2010) New Revision: 2801 Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupClientCryptoKeys.h box/invisnet/vs2010/0.11/lib/backupclient/BackupClientFileAttributes.h box/invisnet/vs2010/0.11/lib/backupclient/BackupClientMakeExcludeList.h box/invisnet/vs2010/0.11/lib/backupclient/BackupClientRestore.h box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.h box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.h box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilename.h box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.h box/invisnet/vs2010/0.11/lib/backupclient/RunStatusProvider.h box/invisnet/vs2010/0.11/lib/common/BoxPlatform.h box/invisnet/vs2010/0.11/lib/common/makeexception.pl.in box/invisnet/vs2010/0.11/lib/server/makeprotocol.pl.in Log: Allow lib/backupclient to be compiled into a DLL. Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupClientCryptoKeys.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupClientCryptoKeys.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupClientCryptoKeys.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -49,7 +49,7 @@ #define BACKUPCRYPTOKEYS_FILE_AES_KEY_LENGTH 32 -void BackupClientCryptoKeys_Setup(const std::string& rKeyMaterialFilename); +BOX_FUNC(void) BackupClientCryptoKeys_Setup(const std::string& rKeyMaterialFilename); #endif // BACKUPCLIENTCRYTOKEYS__H Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupClientFileAttributes.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupClientFileAttributes.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupClientFileAttributes.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -25,7 +25,7 @@ // Created: 2003/10/07 // // -------------------------------------------------------------------------- -class BackupClientFileAttributes : public StreamableMemBlock +BOX_CLASS BackupClientFileAttributes : public StreamableMemBlock { public: BackupClientFileAttributes(); Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupClientMakeExcludeList.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupClientMakeExcludeList.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupClientMakeExcludeList.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -13,7 +13,7 @@ class ExcludeList; class Configuration; -ExcludeList *BackupClientMakeExcludeList(const Configuration &rConfig, const char *DefiniteName, const char *RegexName, +extern BOX_FUNC(ExcludeList *) BackupClientMakeExcludeList(const Configuration &rConfig, const char *DefiniteName, const char *RegexName, const char *AlwaysIncludeDefiniteName = 0, const char *AlwaysIncludeRegexName = 0); // -------------------------------------------------------------------------- Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupClientRestore.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupClientRestore.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupClientRestore.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -22,7 +22,7 @@ Restore_CompleteWithErrors, }; -int BackupClientRestore(BackupProtocolClient &rConnection, +extern BOX_FUNC(int) BackupClientRestore(BackupProtocolClient &rConnection, int64_t DirectoryID, const char *LocalDirectoryName, bool PrintDots = false, Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -12,7 +12,7 @@ #include "Configuration.h" -extern const ConfigurationVerify BackupDaemonConfigVerify; +extern BOX_EXPORT const ConfigurationVerify BackupDaemonConfigVerify; #endif // BACKUPDAEMONCONFIGVERIFY__H Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreDirectory.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -27,7 +27,7 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -class BackupStoreDirectory +BOX_CLASS BackupStoreDirectory { public: BackupStoreDirectory(); @@ -38,7 +38,7 @@ public: ~BackupStoreDirectory(); - class Entry + BOX_CLASS Entry { public: friend class BackupStoreDirectory; @@ -158,7 +158,7 @@ const StreamableMemBlock &GetAttributes() const {return mAttributes;} box_time_t GetAttributesModTime() const {return mAttributesModTime;} - class Iterator + BOX_CLASS Iterator { public: Iterator(const BackupStoreDirectory &rDir) Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFile.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -48,7 +48,7 @@ // Created: 2006/01/19 // // -------------------------------------------------------------------------- -class DiffTimer +BOX_CLASS DiffTimer { public: DiffTimer(); @@ -67,10 +67,10 @@ // Created: 2003/08/28 // // -------------------------------------------------------------------------- -class BackupStoreFile +BOX_CLASS BackupStoreFile { public: - class DecodedStream : public IOStream + BOX_CLASS DecodedStream : public IOStream { friend class BackupStoreFile; private: @@ -182,7 +182,7 @@ static void DiffTimerExpired(); // Building blocks - class EncodingBuffer + BOX_CLASS EncodingBuffer { public: EncodingBuffer(); Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFileEncodeStream.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -42,7 +42,7 @@ // Created: 8/12/03 // // -------------------------------------------------------------------------- -class BackupStoreFileEncodeStream : public IOStream +BOX_CLASS BackupStoreFileEncodeStream : public IOStream { public: BackupStoreFileEncodeStream(); @@ -55,7 +55,7 @@ BackupStoreFileCreation::BlocksAvailableEntry *mpStartBlock; // may be null } RecipeInstruction; - class Recipe : public std::vector + BOX_CLASS Recipe : public std::vector { // NOTE: This class is rather tied in with the implementation of diffing. public: Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilename.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilename.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilename.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -40,7 +40,7 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -class BackupStoreFilename /* : public BackupStoreFilename_base */ +BOX_CLASS BackupStoreFilename /* : public BackupStoreFilename_base */ { private: std::string mEncryptedName; Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/BackupStoreFilenameClear.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -22,7 +22,7 @@ // Created: 2003/08/26 // // -------------------------------------------------------------------------- -class BackupStoreFilenameClear : public BackupStoreFilename +BOX_CLASS BackupStoreFilenameClear : public BackupStoreFilename { public: BackupStoreFilenameClear(); Modified: box/invisnet/vs2010/0.11/lib/backupclient/RunStatusProvider.h =================================================================== --- box/invisnet/vs2010/0.11/lib/backupclient/RunStatusProvider.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/backupclient/RunStatusProvider.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -19,7 +19,7 @@ // Created: 2005/11/15 // // -------------------------------------------------------------------------- -class RunStatusProvider +BOX_CLASS RunStatusProvider { public: virtual ~RunStatusProvider() { } Modified: box/invisnet/vs2010/0.11/lib/common/BoxPlatform.h =================================================================== --- box/invisnet/vs2010/0.11/lib/common/BoxPlatform.h 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/common/BoxPlatform.h 2010-10-26 20:08:47 UTC (rev 2801) @@ -40,6 +40,21 @@ #endif #endif +#ifdef BOXBACKUP_EXPORTS + #define BOX_CLASS class __declspec(dllexport) + #define BOX_EXPORT __declspec(dllexport) + #define BOX_FUNC(ret) __declspec(dllexport) ret +#elif defined BOXBACKUP_IMPORTS + #define BOX_CLASS class __declspec(dllimport) + #define BOX_EXPORT __declspec(dllimport) + #define BOX_FUNC(ret) __declspec(dllexport) ret +#else + #define BOX_CLASS class + #define BOX_EXPORT + #define BOX_FUNC(ret) ret +#endif + + #ifdef HAVE_SYS_TYPES_H #include #endif @@ -180,7 +195,7 @@ #endif // Solaris has no dirfd(x) macro or function, and we need one for -// intercept tests. We cannot define macros with arguments directly +// intercept tests. We cannot define macros with arguments directly // using AC_DEFINE, so do it here instead of in configure.ac. #if ! defined PLATFORM_CLIB_FNS_INTERCEPTION_IMPOSSIBLE && ! HAVE_DECL_DIRFD Modified: box/invisnet/vs2010/0.11/lib/common/makeexception.pl.in =================================================================== --- box/invisnet/vs2010/0.11/lib/common/makeexception.pl.in 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/common/makeexception.pl.in 2010-10-26 20:08:47 UTC (rev 2801) @@ -43,6 +43,8 @@ close EXCEPTION_DESC; +$class_decl = ("DLL" eq $ARGV[1]) ? "BOX_CLASS" : "class"; + # write the code print "Generating $class exception...\n"; @@ -68,7 +70,7 @@ // Created: autogen // // -------------------------------------------------------------------------- -class ${class}Exception : public BoxException +$class_decl ${class}Exception : public BoxException { public: ${class}Exception(unsigned int SubType, Modified: box/invisnet/vs2010/0.11/lib/server/makeprotocol.pl.in =================================================================== --- box/invisnet/vs2010/0.11/lib/server/makeprotocol.pl.in 2010-10-23 18:18:15 UTC (rev 2800) +++ box/invisnet/vs2010/0.11/lib/server/makeprotocol.pl.in 2010-10-26 20:08:47 UTC (rev 2801) @@ -32,13 +32,15 @@ -my ($type, $file) = @ARGV; +my ($type, $file, $decl) = @ARGV; if($type ne 'Server' && $type ne 'Client') { die "Neither Server or Client is specified on command line\n"; } +my $class_decl = ("DLL" eq $decl) ? "BOX_CLASS" : "class"; + open IN, $file or die "Can't open input file $file\n"; print "Making $type protocol classes from $file...\n"; @@ -314,7 +316,7 @@ for my $cmd (@cmd_list) { print H <<__E; -class $classname_base$cmd : public $derive_objects_from +$class_decl $classname_base$cmd : public $derive_objects_from { public: $classname_base$cmd(); @@ -553,7 +555,7 @@ # finally, the protocol object itself print H <<__E; -class $classname_base : public Protocol +$class_decl $classname_base : public Protocol { public: $classname_base(IOStream &rStream); From subversion at boxbackup.org Tue Oct 26 21:10:44 2010 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Tue, 26 Oct 2010 21:10:44 +0100 (BST) Subject: [Box Backup-commit] COMMIT r2802 - box/invisnet/vs2010/0.11/lib/common Message-ID: <20101026201044.5D0E316AAD6@www.boxbackup.org> Author: invisnet Date: 2010-10-26 21:10:43 +0100 (Tue, 26 Oct 2010) New Revision: 2802 Modified: box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp Log: Properly fix parsing so we stay within bounds. Modified: box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp =================================================================== --- box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp 2010-10-26 20:08:47 UTC (rev 2801) +++ box/invisnet/vs2010/0.11/lib/common/FdGetLine.cpp 2010-10-26 20:10:43 UTC (rev 2802) @@ -176,6 +176,9 @@ { // Remove whitespace size_t size = r.size(); + if(0 == size) + return ""; + size_t begin = 0; while(begin < size && iw(r[begin])) { @@ -183,17 +186,17 @@ } // Check for comment char, but char before must be whitespace + if(r[begin] == '#') + return ""; + size_t end = begin; - while(end < size) + while(++end < size) { - if(r[end] == '#' && (end == 0 || (iw(r[end-1])))) - { + if(r[end] == '#' && iw(r[end-1])) break; - } - end++; } - for(end--; end > begin && iw(r[end]); end--); + while(--end > begin && iw(r[end])) end--; // Return a sub string return r.substr(begin, end - begin + 1);