home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / ipl / packs / ibpag2 / outbits.icn < prev    next >
Text File  |  2000-07-29  |  3KB  |  101 lines

  1. ############################################################################
  2. #
  3. #    Name:     outbits.icn
  4. #
  5. #    Title:     output variable-length characters in byte-size chunks
  6. #
  7. #    Author:     Richard L. Goerwitz
  8. #
  9. #    Version: 1.5
  10. #
  11. ############################################################################
  12. #
  13. #  In any number of instances (e.g. when outputting variable-length
  14. #  characters or fixed-length encoded strings), the programmer must
  15. #  fit variable and/or non-byte-sized blocks into standard 8-bit
  16. #  bytes.  Outbits() performs this task.
  17. #
  18. #  Pass to outbits(i, len) an integer i, and a length parameter (len),
  19. #  and outbits will suspend byte-sized chunks of i converted to
  20. #  characters (most significant bits first) until there is not enough
  21. #  left of i to fill up an 8-bit character.  The remaining portion is
  22. #  stored in a buffer until outbits() is called again, at which point
  23. #  the buffer is combined with the new i and then output in the same
  24. #  manner as before.  The buffer is flushed by calling outbits() with
  25. #  a null i argument.  Note that len gives the number of bits there
  26. #  are in i (or at least the number of bits you want preserved; those
  27. #  that are discarded are the most significant ones). 
  28. #
  29. #  A trivial example of how outbits() might be used:
  30. #
  31. #      outtext := open("some.file.name","w")
  32. #      l := [1,2,3,4]
  33. #      every writes(outtext, outbits(!l,3))
  34. #      writes(outtext, outbits(&null,3))           # flush buffer
  35. #
  36. #  List l may be reconstructed with inbits() (see inbits.icn):
  37. #
  38. #      intext := open("some.file.name")
  39. #      l := []
  40. #      while put(l, inbits(intext, 3))
  41. #
  42. #  Note that outbits() is a generator, while inbits() is not.
  43. #
  44. ############################################################################
  45. #
  46. #  Links: none
  47. #  See also: inbits.icn
  48. #
  49. ############################################################################
  50.  
  51.  
  52. procedure outbits(i, len)
  53.  
  54.     local old_part, new_part, window, old_byte_mask
  55.     static old_i, old_len, byte_length, byte_mask
  56.     initial {
  57.     old_i := old_len := 0
  58.     byte_length := 8
  59.     byte_mask := (2^byte_length)-1
  60.     }
  61.  
  62.     old_byte_mask := (0 < 2^old_len - 1) | 0
  63.     window := byte_length - old_len
  64.     old_part := ishift(iand(old_i, old_byte_mask), window)
  65.  
  66.     # If we have a no-arg invocation, then flush buffer (old_i).
  67.     if /i then {
  68.     if old_len > 0 then {
  69.         old_i := old_len := 0
  70.         return char(old_part)
  71.     } else {
  72.         old_i := old_len := 0
  73.         fail
  74.     }
  75.     } else {
  76.     new_part := ishift(i, window-len)
  77.     len -:= (len >= window) | {
  78.         old_len +:= len
  79.         old_i := ior(ishift(old_part, len-window), i)
  80.         fail
  81.     }
  82. #    For debugging purposes.
  83. #    write("old_byte_mask = ", old_byte_mask)
  84. #    write("window = ", image(window))
  85. #    write("old_part = ", image(old_part))
  86. #    write("new_part = ", image(new_part))
  87. #    write("outputting ", image(ior(old_part, new_part)))
  88.     suspend char(ior(old_part, new_part))
  89.     }
  90.  
  91.     until len < byte_length do {
  92.     suspend char(iand(ishift(i, byte_length-len), byte_mask))
  93.     len -:= byte_length
  94.     }
  95.  
  96.     old_len := len
  97.     old_i := i
  98.     fail
  99.  
  100. end
  101.