Personal tools

FreeArc/Standard API for compression libraries

From HaskellWiki

< FreeArc(Difference between revisions)
Jump to: navigation, search
(Minimal implementation)

Revision as of 13:21, 30 September 2008

Idea: [at forum]


// 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, "")

// 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)
    case CLS_COMPRESS:
        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)
    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:
        return CLS_OK;

int main ()
    return ClsMain(CLS_COMPRESS, cb, NULL);