Difference between revisions of "FreeArc/Standard API for compression libraries"

From HaskellWiki
Jump to: navigation, search
m
Line 74: Line 74:
 
return CLS_OK;
 
return CLS_OK;
 
}
 
}
}
 
  +
  +
default:
  +
return CLS_ERROR_NOT_IMPLEMENTED;
  +
}
 
}
 
</pre-cpp>
 
</pre-cpp>
   
Line 111: Line 115:
 
ClsMain(CLS_INIT, cb, NULL);
 
ClsMain(CLS_INIT, cb, NULL);
 
int ret = ClsMain(CLS_COMPRESS, cb, NULL);
 
int ret = ClsMain(CLS_COMPRESS, cb, NULL);
}
 
  +
ClsMain(CLS_DONE, cb, NULL);
  +
  +
return ret;
  +
}
 
</pre-cpp>
 
</pre-cpp>

Revision as of 15:47, 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>

  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;
       }
   default:
       return CLS_ERROR_NOT_IMPLEMENTED;
   }

} </pre-cpp>


Minimal host: <pre-cpp>

  1. include <stdlib.h>
  2. include <io.h>
  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_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);
   ClsMain(CLS_INIT, cb, NULL);
   int ret = ClsMain(CLS_COMPRESS, cb, NULL);
   ClsMain(CLS_DONE, cb, NULL);
   return ret;

} </pre-cpp>