'I came across this the other day and thought it was worth passing along. It
'works just as-is with PowerBASIC. I changed a couple of instances of
'CNT=CNT+1 to the more efficient INCR CNT statement. - Frank Cox
'-----------------------------------------------------------------------------
DECLARE SUB PackTxt (text$)
' Super Text/String Packer/Unpacker for QB4.5
' Originally by Greg Estabrooks
' Slightly changed by Hauke Daempfling
'(small note: all documentation is by Hauke :) )
'This program (or rather the PackTxt sub) packs/unpacks
' strings to about 52% of their original size. All I can say is
' that this is one of the best code snippets I've ever seen. :)
' Actually, it's brilliant :).
' I changed it from its original version in the following ways:
' 1) The sub adds CHR$(255) to a packed string to indicate that
' it is packed. (For automatic packing/unpacking)
' 2) The sub checks if the values of the characters in the string are
' between 32 and 127 to reduce errors while packing.
' 3) Last but not least, I've added some documatation.
'Usage is very simple. Take a string (A$, for example) and call PackTxt:
' A$ = "This is a test string for the text packer."
' PackTxt A$
'The string will be packed and CHR$(255) added to the beginning to indicate
'that it is packed. To unpack a string just call PackTxt again:
' PackTxt A$
'There. That's all there is to it. Have fun :)
'PackTxt SUB begins here
DEFINT A-Z
'This sub packs strings to about 52% of their original size. The sub
' automatically checks if the string is packed or not and unpacks/packs
' it accordingly. (neat, huh?)
' Don't play around with the dictionary or you can lower the packing
' ratio (when I got it there was a single space missing and that
' reduced the ratio by about 10%!).
' NOTE: text$ may only contain ASCII characters with the values 32-127!
SUB PackTxt (text$)
'the commets here are cluttered up... delete them if you want
'The dictionary... it may look like junk, but it is pretty much the heart
' of the packer (so don't mess it up :) )
d1$ = " e as tinthouerhet anreesr d onn or o i y wo tontyo. neisarte"
d2$ = "ed, ctiy bat snd fal pensestvengitu talehaurllcousa mf dfoof "
d3$ = "siril hmeg om Icehironsasiossbedepe rli Tetel nicho lilprcactut"
d4$ = "Thpaeceachh wige ebuaisursulmawaotowtsmploI solyee Cunm rtieno S"
d5$ = "diwhs.rafincademe.irplk ury Pwoacos gams,duayavucColamowe Aoopu"
Dict$ = d1$ + d2$ + d3$ + d4$ + d5$
IF LEN(Dict$) 320 THEN 'just to check...
PRINT "PACKING ERROR: Dictionary has the wrong size"
EXIT SUB
END IF
IF NOT LEFT$(text$, 1) = CHR$(255) THEN 'check if the string is packed
'the string isn't packed so pack it...
IF LEN(text$) < 4 THEN EXIT SUB 'no use with strings less than 4 chars.
FOR a = 1 TO LEN(text$) 'check if there are any characters
v = ASC(MID$(text$, a, 1)) ' with values out of range (they
IF v 127 THEN EXIT SUB ' _cannot_ be packed otherwise)
NEXT a
DO
incr cnt 'read pointer in text$
char$ = MID$(text$, cnt, 2) 'characters to be checked for in Dict$
IF cnt = LEN(text$) THEN 'if the end of the string has been reached
text$ = CHR$(255) + temp$ + CHR$(ASC(MID$(text$, cnt, 1)) - 32)
EXIT SUB '^^^^ add the last character
END IF
xx = 1 'read pointer in Dict$
ReDo:
x = INSTR(xx, Dict$, char$)
IF x THEN 'if the characters from text$ are in Dict$
IF (x \ 2) = (x / 2) THEN 'if the instr of the characters can't be
xx = x + 1 ' divided by 2 then look again (it needs
GOTO ReDo ' to be divided so it can be packed)
END IF
temp$ = temp$ + CHR$((x \ 2) + 96) 'add the instr of the characters
incr cnt ' in Dict$ to temp$ (note that
'^^^ characters shouldn't ' it's stored so that it's more
' be compressed twice ' than 95)
ELSE
'if the characters aren't found store the first character
'(note that it's less than 95 and that cnt is only moved up _1_)
temp$ = temp$ + CHR$(ASC(MID$(text$, cnt, 1)) - 32)
END IF
LOOP WHILE cnt < LEN(text$)
text$ = CHR$(255) + temp$ 'copy temp$ into text$ and add CHR$(255)
EXIT SUB ' to indicate a packed string
ELSE
'text$ is packed so unpack it
comp$ = RIGHT$(text$, LEN(text$) - 1) 'remove CHR$(255)
text$ = "" 're-init text$
FOR x = 1 TO LEN(comp$)
char = ASC(MID$(comp$, x, 1))
IF char > 95 THEN 'if char > 95 then char is the instr of the
' unpacked characters in Dict$, remember?
text$ = text$ + MID$(Dict$, (char - 96) * 2 + 1, 2)
ELSE 'if the characters weren't found in Dict$ they were stored
' with a value less than 95 (most are found, though)
text$ = text$ + CHR$(ASC(MID$(comp$, x, 1)) + 32)
END IF
NEXT x
END IF
END SUB
--- Msgedsq 2.2e
---------------
* Origin: THE BIG ELECTRIC CAT Melville Sask *SDS* *PDN* (1:140/53)
|