FreeArc/Standard API for compression libraries

From HaskellWiki
< FreeArc
Revision as of 13:21, 30 September 2008 by Bulatz (talk | contribs) (Minimal implementation)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Idea: [at encode.ru forum]

Header: <pre-cpp> // 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 -

  • /

</pre-cpp>


Simplest codec: <pre-cpp>

  1. 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;

} </pre-cpp>


Minimal host: <pre-cpp>

  1. 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);

} </pre-cpp>