TIP: Click on subject to list as thread! ANSI
echo: power_bas
to: WHOEVER CARES
from: FRANK COX
date: 1996-06-04 13:47:00
subject: Text packer

'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)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.