home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / OL.LZH / PROCS.LZH / PACKUNPK.ICN < prev    next >
Text File  |  1991-09-05  |  4KB  |  129 lines

  1. ############################################################################
  2. #
  3. #    Name:     packunpk.icn
  4. #
  5. #    Title:     Pack and unpack packed-decimal strings
  6. #
  7. #    Author:     C. Tenaglia (modified by Richard L. Goerwitz)
  8. #
  9. #    Version: 1.2
  10. #
  11. #    Date:     June 1, 1991
  12. #
  13. ############################################################################
  14. #
  15. #      Integers written directly as strings occupy much more space
  16. #  than they need to.  One easy way to shrink them a bit is to "pack"
  17. #  them, i.e.  convert each decimal digit into a four-byte binary
  18. #  code, and pack these four-bit chunks into eight-bit characters,
  19. #  which can be written to a file.
  20. #
  21. #      Interestingly, packing decimal strings in this manner lends
  22. #  itself to unpacking by treating each character as a base-10
  23. #  integer, and then converting it to base-16.  Say we have an input
  24. #  string "99."  Pack() would convert it to an internal representation
  25. #  of char(16*9 + 9), i.e. char(153).  Unpack would treat this
  26. #  char(153) representation as a base-10 integer, and convert it to
  27. #  base 16 (i.e. 10r153 -> 16r99).  The 99 is, of course, what we
  28. #  started with.
  29. #
  30. #      Note that two unpack routines are provided here:  The first, by
  31. #  Tanaglia, utilizes radcon.icn from the IPL.  The second, by
  32. #  Goerwitz, does not.  They utilize very different methods, but both
  33. #  amount to basically the same thing.  Goerwitz's routine returns an
  34. #  integer, though, and has no "width" argument.
  35. #
  36. ############################################################################
  37. #
  38. #  Links:  radcon.icn
  39. #
  40. ############################################################################
  41.  
  42. link radcon
  43.  
  44. procedure pack(num,width)     
  45.  
  46.     local int, sign, prep, packed, word
  47.  
  48.     int := integer(num) | fail
  49.     # There's really no need to store the sign if it's positive, UNLESS
  50.     # you are using this program to store packed decimal integers for
  51.     # access by other programs on certain mainframes that always store
  52.     # the sign.
  53.     # if int < 0 then sign := "=" else sign := "<"
  54.     if int < 0 then sign := "=" else sign := ""
  55.     prep   := string(abs(int)) || sign
  56.     packed := ""
  57.     if (*prep % 2) ~= 0 then prep := "0" || prep
  58.  
  59.     prep ? {
  60.     while word := move(2) do {
  61.         if pos(0)
  62.         then packed ||:= char(integer(word[1])*16 + ord(word[2])-48)
  63.         else packed ||:= char(integer(word[1])*16 + integer(word[2]))
  64.     }
  65.     }
  66.  
  67.     /width := *packed
  68.     return right(packed, width, "\0")
  69.  
  70. end
  71.  
  72.  
  73.  
  74. procedure unpack(val,width)   
  75.  
  76.     # THIS PROCEDURE UNPACKS A VALUE INTO A STRING-INTEGER. USING THIS
  77.     # CODE SEGMENT REQUIRES LINKING WITH RADCON FROM THE IPL.
  78.  
  79.     local tmp, number, tens, ones, sign
  80.  
  81.     tmp  := ""
  82.     sign := 1
  83.  
  84.     every number := ord(!val) do
  85.     tmp ||:= right(map(radcon(number,10,16),&lcase,&ucase),2,"0")
  86.  
  87.     if tmp[-1] == ("B" | "D") then {
  88.     sign := -1
  89.     # In this configuration, the sign field is only present if the
  90.     # integer is negative.  If you have set up pack to register posi-
  91.     # tive values in the sign field, place the following line after
  92.     # the "if-then" expression.
  93.     tmp[-1] :=  ""
  94.     }
  95.     tmp    *:= sign
  96.     /width  := *string(tmp)
  97.  
  98.     return right(string(tmp), width)
  99.  
  100. end
  101.  
  102.  
  103.  
  104. procedure unpack2(val)
  105.  
  106.     # THIS PROCEDURE UNPACKS A VALUE INTO AN STRING-INTEGER.
  107.     # Note:  Unpack2 assumes that pack is not recording positive
  108.     # sign values.
  109.  
  110.     local unpacked, int
  111.  
  112.     unpacked := ""
  113.     val ? {
  114.     while int := ord(move(1)) do {
  115.         unpacked ||:= string(iand(2r11110000,int) / 16)
  116.         if pos(0) then {
  117.         if iand(2r00001111,int) = 13 then {
  118.             unpacked := "-" || unpacked
  119.             break
  120.         }
  121.         }
  122.         unpacked ||:= string(iand(2r00001111,int))
  123.     }
  124.     }
  125.  
  126.     return integer(unpacked)
  127.  
  128. end
  129.