FreeArc/Standard API for compression libraries
From HaskellWiki
(Difference between revisions)
Revision as of 13:21, 30 September 2008
Idea: [at encode.ru forum]
Header:
// Operations const int CLS_INIT = 1; // Called once on DLL load const int CLS_DONE = 2; // Called once before DLL unload const int CLS_COMPRESS = 3; // Requests to compress data using i/o via callbacks const int CLS_DECOMPRESS = 4; // Requests to decompress data using i/o via callbacks // Callbacks const int CLS_READ = 1000; // Read data into buffer ptr:n. Use CLS_READ+i to read i'th stream. Retcode: <0 - error, 0 - EOF, >0 - amount of data read const int CLS_WRITE = 2000; // Write data from buffer ptr:n. CLS_WRITE+i also works. Retcode: the same const int CLS_MALLOC = 1; // Alloc n bytes and make *ptr point to this area const int CLS_FREE = 2; // Free ptr previously allocated by CLS_MALLOC const int CLS_PARAMETERS = 3; // Put ASCIIZ parameters string into buffer ptr:n // INIT-stage callbacks const int CLS_ID = 4; // Identify itself with unique ASCIIZ string at ptr (for example, "lzma.7zip.org") // Error codes const int CLS_OK = 0; // ALL RIGHT const int CLS_ERROR_GENERAL = -1; // Unclassified error const int CLS_ERROR_NOT_IMPLEMENTED = -2; // Requested feature isn't supported const int CLS_ERROR_NOT_ENOUGH_MEMORY = -3; // Memory allocation failed const int CLS_ERROR_READ = -4; const int CLS_ERROR_WRITE = -5; const int CLS_ERROR_ONLY_DECOMPRESS = -6; // This DLL supports only decompression const int CLS_ERROR_INVALID_COMPRESSOR = -7; // Invalid compression method parameters const int CLS_ERROR_BAD_COMPRESSED_DATA = -8; // Data can't be decompressed const int CLS_ERROR_NO_MORE_DATA_REQUIRED = -9; // Required part of data was already decompressed const int CLS_ERROR_OUTBLOCK_TOO_SMALL = -10; // Output block size in (de)compressMem is not enough for all output data // Type of callback passed to ClsMain typedef int CLS_CALLBACK(void* instance, int op, void *ptr, int n); /* to do: - check versions and backward/forward compatibility - allow multiple codecs in same dll. this may be solved by ClsMain2, ClsMain3... exported but this may be not enough for some more complex scenarios - codecs need to know how much memory for compression / decompression are they supposed to use. - some codecs might handle multithreading in a smarter way than splitting streams. - Also there're threading issues (like, application allowing to use up to N threads) and whether dll is thread-safe or not (if not, it can be secured by loading multiple instances of dll - might be a useful feature as many experimental compressors are not really incapsulated). - Some interface methods are required for initialization and model flush (which are not the same as there might be some precalculation required only once). - what about detectors and filters - */
Simplest codec:
#include "cls.h"
int ClsMain (int op, CLS_CALLBACK cb, void* instance)
{
switch(op)
{
case CLS_COMPRESS:
case CLS_DECOMPRESS:
const int BUFSIZE = 4096;
char buf[BUFSIZE];
for (int len; (len=cb(instance, CLS_READ, buf, BUFSIZE)) != 0; )
{
if (len<0) return len; // Return errcode on error
int ret = cb(instance, CLS_WRITE, buf, len);
if (ret!=len) return ret<0? ret : CLS_ERROR_WRITE;
}
}
return CLS_OK;
}
Minimal host:
#include "cls.h"
int cb(void* instance, int op, void *ptr, int n)
{
switch(op)
{
case CLS_READ:
return read(0,ptr,n);
case CLS_WRITE:
return write(1,ptr,n);
case CLS_MALLOC:
*(void**)ptr = malloc(n);
return *(void**)ptr? CLS_OK : CLS_ERROR_NO_MEMORY;
case CLS_FREE:
free(ptr)
return CLS_OK;
default:
return CLS_ERROR_NOT_IMPLEMENTED;
}
}
int main ()
{
return ClsMain(CLS_COMPRESS, cb, NULL);
}
