home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 568a.lha / compress.library_v1.0 / programmers / compress_lib.prodoc.pp / compress_lib.prodoc
Text File  |  1991-11-03  |  15KB  |  283 lines

  1.                              compress.library
  2.                         Programmer's Documentation
  3.                                 Version 1.0
  4.                             (C) 1991 Bryan Ford
  5.  
  6.     This is the programmer's documentation for the compress.library
  7. specification.  It may be freely distributed, with or without my own
  8. compress.library, as long as the files listed below remain intact and
  9. unchanged.  If you would like to see something changed in or added to the
  10. specification, contact me and I'll try my best to accomodate your needs.  I
  11. just don't want incompatible libraries floating around.
  12.  
  13.     These are the files that must be included in the programmers'
  14. distribution:
  15.  
  16.   compress_lib.prodoc   (this file)
  17.   compress_lib.fd
  18.      include (dir)
  19.           pragmas (dir)
  20.             compress.h
  21.           clib (dir)
  22.             compress_protos.h
  23.           libraries (dir)
  24.             compress.h
  25.      ainclude (dir)
  26.           libraries (dir)
  27.             compress.i
  28.  
  29.     The .fd file is for all you die-hard BASIC programmers.  :-)
  30.  
  31.     The 'include' directory contains C definition header files modeled
  32. after Commodore's directory structure.  'libraries/compress.h' contains the
  33. general tag definitions need to call the compress.library.
  34. 'clib/compress_protos.h' contains prototypes for the compress.library's
  35. functions, and 'pragmas/compress.h' contains function pragmas for SAS/C.
  36. (Sorry, I haven't written any stubs yet.  I'm lazy.)
  37.  
  38.     The file 'ainclude/libraries/compress.i' contains the definitions
  39. needed to call the compress.library from assembly language, including the
  40. appropriate LIBDEF's.
  41.  
  42.     There are just three main functions you will need to use in the
  43. compress.library:  CompressInfo(), Compress(), and Decompress().  The
  44. function CompressInfo() allows you to obtain various information on the
  45. compress.library, while the Compress() and Decompress() functions perform
  46. the actual compression and decompression operations.
  47.  
  48.     Most compress.library functions use TagItem arrays (tag lists) as
  49. defined in the include files for Kickstart 2.0.  This does not necessarily
  50. mean that the compress.library will only work on 2.0.  (My implementation,
  51. at least, works under pre-2.0.)
  52.  
  53.                               CompressInfo()
  54.                               ~~~~~~~~~~~~~~
  55.  
  56.     The first function, CompressInfo(), accepts a pointer (in A0) to a
  57. tag list which you must create, and fills it in with information about the
  58. compress.library.  The tags for this function are defined in
  59. libraries/compress.(h|i).  Basically, you create a TagItem array and
  60. initialize the ti_Tag field of each to specify the information you want,
  61. then call CompressInfo() with the tag list, and when it returns, your
  62. TagItem array has been filled in with appropriate information.  Not all of
  63. the tags may be supported in a given compress.library.  Therefore, you must
  64. initialize all your ti_Data fields in your tag list to 0 before calling
  65. CompressInfo(), and be prepared to find values of 0 in the array after the
  66. call.
  67.  
  68.     Most of the information available through CompressInfo() is pretty
  69. much self-explanatory.  The CS_xxxName tags return pointers to strings
  70. within compress.library's memory space.  These will remain valid at least
  71. until CloseLibrary().  The ProgramName is the name of the library or
  72. implementation, the AuthorName is the name of the programmer that created
  73. the library, and the AlgoName tells briefly what algorithm the library
  74. uses.  These three names are intended for user information only, and should
  75. not be interpreted by a program in any way.
  76.  
  77.     The CompSpeed and DecompSpeed fields allow the application to get
  78. an idea of how fast the compressor and decompressor are.  When the library
  79. is first loaded, the compress.library should run a very brief benchmark of
  80. some kind to find out how fast compression and decompression go on the
  81. machine it's running on.  Then, after each call of Compress() or
  82. Decompress(), the estimated value should be updated (probably with a
  83. combination of the new value and the previous value, to average the
  84. estimate over multiple runs).
  85.  
  86.     The CS_AsyncComp and CS_AsyncDecomp tags are used by a program to
  87. determine whether or not the compress.library supports the asynchronous
  88. compression function calls.  Unless the compress.library returns a nonzero
  89. value in these tag, the alternate function entrypoints must be assumed to
  90. not exist.  The asynchronous function calls are described in detail later.
  91.  
  92.     The CS_BlockComp and CS_BlockDecomp tags are used to determine
  93. whether or not the compress.library supports multiblock compression and
  94. decompression requests.  These flagf work the same way as CS_AsyncComp and
  95. CS_AsyncDecomp.  Multiblock operations are described in detail later.
  96.  
  97.                          Single-block Compression
  98.                          ~~~~~~~~~~~~~~~~~~~~~~~~
  99.  
  100.     To actually compress and decompress data, a program must call the
  101. Compress() and Decompress() functions.  As with CompressInfo(), they both
  102. accept pointers to TagItem arrays (in A0).  However, in this case, *you*
  103. must initialize the ti_Data fields in the array, and the Compress() and
  104. Decompress() functions do not change them.
  105.  
  106.     To compress a block of data, you must pass Compress() a tag list
  107. with at least three items:  the input data (CS_InputBuffer), the size of
  108. the input data (CS_InputSize), and a buffer to write the compressed data
  109. into.  The output buffer must be AT LEAST as large as the input buffer.
  110. Also, both the input buffer and the output buffer must be longword aligned.
  111.  
  112.     When you have these fields set up, just call Compress().  If the
  113. compression is successful, it will return a positive number indicating the
  114. number of bytes used in the destination buffer.  If you write the buffer to
  115. disk or copy it somewhere else, you must copy at least this number of bytes
  116. starting at the beginning of the output buffer you supplied.  Also, no
  117. matter how much of the output data you actually store (you might want to
  118. store an integral number of longwords or something), you must remember the
  119. EXACT number of output bytes returned to pass to the Decompress() function.
  120. If the compression failed, a negative error value is returned (one of
  121. CSERR_xxxx).  Common failures are CSERR_NOMEMORY (not enough memory) and
  122. CSERR_NOCOMPRESSION (the data is uncompressible with this algorithm).
  123.  
  124.     When you want to decompress a block of data you previously
  125. compressed, you must call Decompress().  Again, you must pass it a tag list
  126. with at least three items:  the input buffer with the compressed data
  127. (CS_InputBuffer), the number of bytes used in the input buffer
  128. (CS_InputSize), and a pointer to the output buffer (CS_OutputBuffer).  The
  129. CS_InputSize that you pass must be the EXACT same value (not rounded up or
  130. anything) that was returned by Compress().  Also, CS_OutputBuffer must be
  131. at least the size of the input data you originally gave to Compress().
  132. Therefore, along with any compressed data, you will also have to store the
  133. original (decompressed) size, so you can allocate a big enough block later,
  134. and the exact compressed size.  Decompress() returns the final decompressed
  135. size (you should make sure it's equal to the size you originally gave to
  136. Compress()), or else a negative error code if the call failed.  Common
  137. errors for Decompress are CSERR_NOMEMORY (not enough memory) and
  138. CSERR_INCOMPATIBLE (the block was compressed with a different, incompatible
  139. compress.library).  A decompressor must always be able to recognize its own
  140. type of compressed data, and must return CSERR_INCOMPATIBLE if a call is
  141. made to decompress an unknown data format.
  142.  
  143.                              Optional Features
  144.                              ~~~~~~~~~~~~~~~~~
  145.  
  146.     Besides the standard three-function compression available in any
  147. compress.library, libraries have the option of supporting some extended
  148. features.  These features may not be relied on by applications (they must
  149. check first with CompressInfo() to make sure the features are available).
  150. Currently the only two extended features defined are asynchronous
  151. compression/decompression, and blocked data streams.
  152.  
  153.     The method of compression - normal, asynchronous, blocked,
  154. asynchronous blocked, etc.  - should not affect the format of the
  155. compressed data.  Therefore, a program should be able to compress some data
  156. in one mode and decompress it in another.
  157.  
  158.     Note that, as of this version of this document, my compress.library
  159. supports neither of these extended features.  Don't worry though - it will
  160. soon.
  161.  
  162.                           Asynchronous Processing
  163.                           ~~~~~~~~~~~~~~~~~~~~~~~
  164.  
  165.     If a previous call to CompressInfo() returned nonzero in a
  166. CS_AsyncSupport tag, an extended set of compression and decompression
  167. functions is available which allows the program to start a compression
  168. operation, and have it complete in the background, thereby allowing the
  169. program to keep responding to events such as user interaction.  (i.e.  the
  170. program doesn't "freeze" while it's working on data.) Remember that a
  171. compress.library may support asynchronous compression but not asynchronous
  172. decompression, or vice versa:  don't assume that because it supports one,
  173. it also supports the other.
  174.  
  175.     To use this feature, simply call the CompressStart() or
  176. DecompressStart() functions just as you would Compress() or Decompress().
  177. However, instead of returning when the operation is finished, these
  178. functions return immediately (or very soon at least).  Instead of returning
  179. the final size or error code, these functions return a handle, which could
  180. be anything - you should just treat it as a longword value.  Null may be a
  181. valid return handle for these functions - you should not NOT check for null
  182. return codes here.  All errors will be returned from the CompressEnd()
  183. function.  Any call to one of these functions must be paired with one call
  184. to CompressEnd(), below.  After the function returns, you can go about your
  185. business, as long as your business doesn't involve touching the input or
  186. output buffers you gave the function.
  187.  
  188.     You may periodically check to see if an operation is finished by
  189. calling CompressCheck() with the handle in d0.  The function will return
  190. nonzero (true) if the operation is finished or zero (false) if it is still
  191. in progress.
  192.  
  193.     When your program is ready and needs the results of the compression
  194. or decompression operation, it should call CompressEnd() with the handle in
  195. D0.  If the operation had already finished, this function will return very
  196. quicky.  If the operation is still in progress, it will Wait() until it
  197. finishes.  After this function returns, the handle is no longer valid.
  198. This function returns the final results of the operation just like the
  199. normal Compress() or Decompress() function calls would.
  200.  
  201.     If you need to know exactly when a compression operation finishes,
  202. you may put another tag, CS_AsyncMsg, into the tag list you send to the
  203. CompressStart() or DecompressStart() call.  The ti_Data field must point to
  204. a valid Exec Message structure.  When the operation is complete, the
  205. message will be ReplyMsg()'d.  Note that this message, if given, will
  206. ALWAYS be replied, even on a failure.  If you call CompressEnd() before the
  207. operation is finished and it must wait for it to complete, the message will
  208. still be replied at the end of the operation just before returning.
  209.  
  210.                                Blocked Data
  211.                                ~~~~~~~~~~~~
  212.  
  213.     Compressing single memory blocks at a time is fine for small pieces
  214. of data, or if you have plenty of memory.  However, memory tends to quickly
  215. run out if you start compressing large streams of data.  It is often much
  216. more convenient and memory-efficient to work with the source and
  217. destination data streams on a piece-by-piece basis, copying blocks to and
  218. from disk as needed.  The compress.library specification has facilities for
  219. blocked data in compression and decompression (although libraries don't
  220. necessarily have to support it).  Applications must be able to fall back on
  221. simple one-piece compression if the compress.library they're trying to use
  222. doesn't support blocked data streams.  (Usually this can be handled by
  223. simply dividing the data into several independently compressed pieces.)
  224.  
  225.     Before trying to use blocked data in compression or decompression,
  226. the application must first make sure the library supports it by calling
  227. CompressInfo() and requesting the CS_BlockComp and/or CS_BlockDecomp flags,
  228. depending on the needs.  (Remember to initialize the ti_Data fields to
  229. zero.) If the flag remains zero, the application must not try to use
  230. blocked data.
  231.  
  232.     To use blocked data during compression or decompression, instead of
  233. providing CS_InputBuffer, CS_InputSize, and CS_OutputBuffer in the tag
  234. list, the program simply supplies the tag CS_IOHook which points to a
  235. standard Hook structure as defined in "utility/hooks.h".  (Although this
  236. structure was introduced in Kickstart 2.0, 2.0 is not necessarily required
  237. to use the structure.)
  238.  
  239.     During compression, the IOHook will be called whenever more input
  240. data is required, or whenever the output buffer fills up and a new output
  241. buffer is required.  The Hook is called using standard Hook calling
  242. conventions, with A1 pointing to a CompressIOMsg as defined in
  243. "libraries/compress.h".  The first longword, Command, the library fills in
  244. to tell the hook routine what to do.  Currently it may be only
  245. CIOMC_NEXTSOURCE, requesting a new bufferful of source data, or
  246. CIOMC_NEXTDEST, requesting a new empty destination buffer.  The hook
  247. routine must then fill in the BlockPtr and BlockSize fields of the message
  248. with the address and size of a new buffer, and then return 0.  If an error
  249. occurs and the hook needs to abort the operation, it can return a negative
  250. return code, and the operation will immediately stop and the return code
  251. will be passed back to the application.
  252.  
  253.     All buffers supplied through the IOHook must be on longword
  254. boundaries, and their size must be evenly divisible by four.  The only
  255. exception to this is the very LAST block of source data, where the size may
  256. be anything.  After source data runs out, the hook must return 0 on the
  257. next CIOMC_NEXTSOURCE request.  During decompression, remember that you
  258. must supply the EXACT number of bytes to the decompressor that the
  259. compressor gave you.  Don't supply any extra garbage bytes.
  260.  
  261.     The return code from the Compress() or Decompress() call (or
  262. CompressEnd(), if you're using asynchronous processing) is exactly the same
  263. as it normally is:  a negative error code, or the total number of bytes
  264. sent to the destination.  After compression, the total destination size can
  265. be used to find the number of bytes used in the last output buffer which,
  266. as I said before, you must know for decompression.  (Just subtract the
  267. total number of bytes in previous, complete blocks.)
  268.  
  269.                                Contacting Me
  270.                                ~~~~~~~~~~~~~
  271.  
  272.     I can be contacted for comments, suggestions, or flames at any of
  273. the addresses below.
  274.  
  275.     Bryan Ford
  276.     27104 Ballif Hall
  277.     Salt Lake City, UT 84112
  278.     (801) 585-4619
  279.     baf0863@cc.utah.edu
  280.     baf0863@utahcca.bitnet
  281.  
  282. Have fun!
  283.