Personal tools

FreeArc/Standard API for compression libraries

From HaskellWiki

< FreeArc(Difference between revisions)
Jump to: navigation, search
(Minimal implementation)
 
(+cls.zip, fixed compile errors)
Line 1: Line 1:
Idea: [[http://encode.ru/forum/showthread.php?t=182 at encode.ru forum]]
+
Idea: [http://encode.ru/forum/showthread.php?t=182 at encode.ru forum]
  +
Download sources: [http://www.haskell.org/bz/cls.zip]
   
 
Header:
 
Header:
Line 79: Line 79:
 
Minimal host:
 
Minimal host:
 
<pre-cpp>
 
<pre-cpp>
  +
#include <stdlib.h>
  +
#include <io.h>
  +
 
#include "cls.h"
 
#include "cls.h"
   
Line 91: Line 94:
 
case CLS_MALLOC:
 
case CLS_MALLOC:
 
*(void**)ptr = malloc(n);
 
*(void**)ptr = malloc(n);
return *(void**)ptr? CLS_OK : CLS_ERROR_NO_MEMORY;
+
return *(void**)ptr? CLS_OK : CLS_ERROR_NOT_ENOUGH_MEMORY;
 
case CLS_FREE:
 
case CLS_FREE:
free(ptr)
+
free(ptr);
 
return CLS_OK;
 
return CLS_OK;
 
default:
 
default:
 
return CLS_ERROR_NOT_IMPLEMENTED;
 
return CLS_ERROR_NOT_IMPLEMENTED;
 
}
 
}
}
+
}
   
 
int main ()
 
int main ()
 
{
 
{
  +
extern int ClsMain (int op, CLS_CALLBACK cb, void* instance);
 
return ClsMain(CLS_COMPRESS, cb, NULL);
 
return ClsMain(CLS_COMPRESS, cb, NULL);
 
}
 
}

Revision as of 13:36, 30 September 2008

Idea: at encode.ru forum Download sources: [1]

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 <stdlib.h>
#include <io.h>

#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_NOT_ENOUGH_MEMORY;
    case CLS_FREE:
        free(ptr);
        return CLS_OK;
    default:
        return CLS_ERROR_NOT_IMPLEMENTED;
    }
}

int main ()
{
    extern int ClsMain (int op, CLS_CALLBACK cb, void* instance);
    return ClsMain(CLS_COMPRESS, cb, NULL);
}