Difference between revisions of "FreeArc/Standard API for compression libraries"
(Minimal implementation) |
(+cls.zip, fixed compile errors) |
||
Line 1: | Line 1: | ||
− | Idea: |
+ | 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 80: | ||
Minimal host: |
Minimal host: |
||
<pre-cpp> |
<pre-cpp> |
||
+ | #include <stdlib.h> |
||
+ | #include <io.h> |
||
+ | |||
#include "cls.h" |
#include "cls.h" |
||
Line 91: | Line 95: | ||
case CLS_MALLOC: |
case CLS_MALLOC: |
||
*(void**)ptr = malloc(n); |
*(void**)ptr = malloc(n); |
||
− | return *(void**)ptr? CLS_OK : |
+ | 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: <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>
- 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>
- 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);
} </pre-cpp>