summaryrefslogtreecommitdiff
path: root/ipl/procs/packunpk.icn
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-01-27 23:51:56 +0000
committerIgor Pashev <pashev.igor@gmail.com>2013-01-27 23:51:56 +0000
commit6ab0c0f5bf14ed9c15370407b9ee7e0b4b089ae1 (patch)
tree926065cf45450116098db664e3c61dced9e1f21a /ipl/procs/packunpk.icn
downloadicon-6ab0c0f5bf14ed9c15370407b9ee7e0b4b089ae1.tar.gz
Initial upstream version 9.4.3upstream/9.4.3
Diffstat (limited to 'ipl/procs/packunpk.icn')
-rw-r--r--ipl/procs/packunpk.icn134
1 files changed, 134 insertions, 0 deletions
diff --git a/ipl/procs/packunpk.icn b/ipl/procs/packunpk.icn
new file mode 100644
index 0000000..3babbf3
--- /dev/null
+++ b/ipl/procs/packunpk.icn
@@ -0,0 +1,134 @@
+############################################################################
+#
+# File: packunpk.icn
+#
+# Subject: Procedures to pack and unpack decimal strings
+#
+# Author: C. Tenaglia (modified by Richard L. Goerwitz)
+#
+# Date: May 2, 2001
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+#
+# Version: 1.2
+#
+############################################################################
+#
+# Integers written directly as strings occupy much more space
+# than they need to. One easy way to shrink them a bit is to "pack"
+# them, i.e. convert each decimal digit into a four-byte binary
+# code, and pack these four-bit chunks into eight-bit characters,
+# which can be written to a file.
+#
+# Interestingly, packing decimal strings in this manner lends
+# itself to unpacking by treating each character as a base-10
+# integer, and then converting it to base-16. Say we have an input
+# string "99." Pack() would convert it to an internal representation
+# of char(16*9 + 9), i.e. char(153). Unpack would treat this
+# char(153) representation as a base-10 integer, and convert it to
+# base 16 (i.e. 10r153 -> 16r99). The 99 is, of course, what we
+# started with.
+#
+# Note that two unpack routines are provided here: The first, by
+# Tanaglia, utilizes convert.icn from the IPL. The second, by
+# Goerwitz, does not. They utilize very different methods, but both
+# amount to basically the same thing. Goerwitz's routine returns an
+# integer, though, and has no "width" argument.
+#
+############################################################################
+#
+# Links: convert
+#
+############################################################################
+
+link convert
+
+procedure pack(num,width)
+
+ local int, sign, prep, packed, word
+
+ int := integer(num) | fail
+ # There's really no need to store the sign if it's positive, UNLESS
+ # you are using this program to store packed decimal integers for
+ # access by other programs on certain mainframes that always store
+ # the sign.
+ # if int < 0 then sign := "=" else sign := "<"
+ if int < 0 then sign := "=" else sign := ""
+ prep := string(abs(int)) || sign
+ packed := ""
+ if (*prep % 2) ~= 0 then prep := "0" || prep
+
+ prep ? {
+ while word := move(2) do {
+ if pos(0)
+ then packed ||:= char(integer(word[1])*16 + ord(word[2])-48)
+ else packed ||:= char(integer(word[1])*16 + integer(word[2]))
+ }
+ }
+
+ /width := *packed
+ return right(packed, width, "\0")
+
+end
+
+
+
+procedure unpack(val,width)
+
+ # THIS PROCEDURE UNPACKS A VALUE INTO A STRING-INTEGER. USING THIS
+ # CODE SEGMENT REQUIRES LINKING WITH RADCON FROM THE IPL.
+
+ local tmp, number, tens, ones, sign
+
+ tmp := ""
+ sign := 1
+
+ every number := ord(!val) do
+ tmp ||:= right(map(radcon(number,10,16),&lcase,&ucase),2,"0")
+
+ if tmp[-1] == ("B" | "D") then {
+ sign := -1
+ # In this configuration, the sign field is only present if the
+ # integer is negative. If you have set up pack to register posi-
+ # tive values in the sign field, place the following line after
+ # the "if-then" expression.
+ tmp[-1] := ""
+ }
+ tmp *:= sign
+ /width := *string(tmp)
+
+ return right(string(tmp), width)
+
+end
+
+
+
+procedure unpack2(val)
+
+ # THIS PROCEDURE UNPACKS A VALUE INTO AN STRING-INTEGER.
+ # Note: Unpack2 assumes that pack is not recording positive
+ # sign values.
+
+ local unpacked, int
+
+ unpacked := ""
+ val ? {
+ while int := ord(move(1)) do {
+ unpacked ||:= string(iand(2r11110000,int) / 16)
+ if pos(0) then {
+ if iand(2r00001111,int) = 13 then {
+ unpacked := "-" || unpacked
+ break
+ }
+ }
+ unpacked ||:= string(iand(2r00001111,int))
+ }
+ }
+
+ return integer(unpacked)
+
+end