home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1993 #2
/
Image.iso
/
database
/
pk4pak.zip
/
PACKMAN.SC
< prev
next >
Wrap
Text File
|
1993-02-05
|
17KB
|
452 lines
;============================================================================
; (c) Copyright Elect Software International Inc., 1992, Toronto. Anyone can
; use this code for anything as long as it is not resold as a software
; development resource, as long as the copyright notice isn't removed, as
; long as changes are clearly marked as to authorship, and as long as users
; indemnify Elect from any liability.
; Comments welcome. Henrik Bechmann, CIS:72701,3717; Tel:416-534-8176.
;============================================================================
; PackMan Version 1.11 January, 1993
;==============================================================================
; PACKMAN DESCRIPTION
;==============================================================================
; PackMan is a generic array packing utility. It packs arrays or dyanarrays into
; strings (blobs), and unpacks them.
;
; PackMan converts arrays or dynarrays into packed strings for convenient
; storage (in other arrays or dynarrays for instance). It also unpacks them
; back to specified arrays or dynarrays for subsequent access.
;
; Arrays are expected to be initialized when packed, and properly dimensioned
; when targeted for unpacking.
;
; Data types handled:
; -------------------
; D = Date
; L = Logical (True or False)
; A = Alphanumeric (length 1 to 255)
; M = Memo (length > 255)
; Z = Zero length string (length = 0, ie. blank) (type converted internally)
; B = Blank $,N,S or D: type kept in value slot
; N = Numeric
;
; Packed string format:
; ---------------------
; Description length Conversion/notes
;------------- ------- ----------------
; HEADER:
; Array type 2 (none) (AY or DY)
; Next conversion type 1 Asc() (1 = Numval(), 2 = Asc())
; Number of elements 5 Asc() on first char, or NumVal()
; Next conversion type 1 Asc() (1 = Numval(), 2 = Asc())
; Spec list length 5 Asc() on first char, or NumVal()
; SPECIFICATIONS FOR ELEMENTS:
; Spec list: ? concatenated spec packets
; Spec packet: ? depends on contents
; Element type 1 (none) D,L,A,M,N,Z
; Element index length 1 Asc() (for DY only)
; Element index string ? (none) (for DY only)
; Value string length 1, or ? for M/Z Asc(), or Numval() for M or Z
; For M or Z the length is
; StrVal(Length) + ","
; ELEMENT VALUES:
; Element value list ? data types above, in StrVal() form
;
; NOTE: Roughly 10% speed improvement can be gained by exploding
; PackMan!PackValue() and PackMan!UnpackValue() inline.
;==============================================================================
; PACKMAN INTERFACE
;==============================================================================
; PackMan.Constructor()
; Packman.Destructor()
; PackMan.PackAnyArrayFrom(AnyArray) ; returns AnyArrayVar
; PackMan.UnPackAnyArrayFrom(AnyArrayVar,AnyArray) ; must dimension AnyArray first
; PackMan.GetArrayType(AnyArrayVar) ; returns "AY" or "DY"
; PackMan.GetArraySize(AnyArrayVar) ; returns number of elements
; PackMan.AddArrayElementTo(AnyArrayVar,ElementValue)
; PackMan.AddDynarrayElementTo(AnyArrayVar,ElementIndex,ElementValue)
; PackMan.GetElementValueFrom(AnyArrayVar,ElementIndex) ; returns ElementValue
;==============================================================================
; PACKMAN IMPLEMENTATION
;==============================================================================
Proc PackMan.Constructor()
PackMan.IsActive = True
EndProc ; PackMan.Constructor
Proc PackMan.Destructor()
Release Vars
PackMan.IsActive
EndProc ; PackMan.Destructor
Proc PackMan.PackAnyArrayFrom(AnyArray)
Private
ArrayType,
nElements,
SpecListLength,
SpecList,
ValueList,
Element,
ElementType,
ElementValue,
ElementLength
ArrayType = Type(AnyArray) ; "AY" or "DY"
If ArrayType = "AY" Then
nElements = ArraySize(AnyArray)
Else
nElements = DynarraySize(AnyArray)
Endif
SpecList = ""
ValueList = ""
If ArrayType = "AY" Then
For Element From 1 to nElements
ElementValue = AnyArray[Element]
PackMan!PackValue()
SpecList =
SpecList +
ElementType +
IIf(Search(ElementType,"MZ") > 0,
Strval(ElementLength) + ",",
Chr(ElementLength))
EndFor
Else
ForEach Element in AnyArray
ElementValue = AnyArray[Element]
PackMan!PackValue()
SpecList =
SpecList +
ElementType +
Chr(Len(Element)) +
Element +
IIf(Search(ElementType,"MZ") > 0,
Strval(ElementLength) + ",",
Chr(ElementLength))
EndForEach
Endif
SpecListLength = Len(SpecList)
Return ArrayType +
IIf(nElements < 1 or nElements > 255,
Chr(1) + Format("W5",nElements),Chr(2) + Chr(nElements) + Spaces(4)) +
IIf(SpecListLength < 1 or SpecListLength > 255,
Chr(1) + Format("W5",SpecListLength),Chr(2) +
Chr(SpecListLength) + Spaces(4)) +
SpecList +
ValueList
EndProc ; PackMan.PackAnyArrayFrom(AnyArray)
; Called by PackMan.PackAnyArrayFrom() and PackMan.AddArrayElementTo()
Proc PackMan!PackValue()
ElementType = Substr(Type(ElementValue),1,1)
If Search(ElementType,"AM") = 0 Then
ElementValue = StrVal(ElementValue)
ElementLength = Len(ElementValue)
If ElementLength = 0 And Search(ElementType,"N$SD") > 0 Then
ElementValue = ElementType
ElementType = "B"
ElementLength = 1
Endif
Else
ElementLength = Len(ElementValue)
If ElementLength = 0 Then
ElementType = "Z"
Endif
Endif
ValueList = ValueList + ElementValue
EndProc ; PackMan!PackValue
Proc PackMan.UnPackAnyArrayFrom(AnyArrayVar,AnyArray)
Private
ArrayType,
nElements,
SpecListLength,
SpecList,
SpecListPointer,
SpecListSeparator,
ValueList,
ValueListPointer,
ValueLength,
Element,
ElementLength,
ElementType,
i
ArrayType = Substr(AnyArrayVar,1,2)
nElements = IIf(Asc(Substr(AnyArrayVar,3,1)) = 1,
NumVal(Substr(AnyArrayVar,4,5)),
Asc(Substr(AnyArrayVar,4,1)))
SpecListLength = IIf(Asc(Substr(AnyArrayVar,9,1)) = 1,
NumVal(Substr(AnyArrayVar,10,5)),
Asc(Substr(AnyArrayVar,10,1)))
SpecList = Substr(AnyArrayVar,15,SpecListLength)
SpecListPointer = 1
ValueListPointer = 14 + SpecListLength + 1
If ArrayType = "AY" Then
For Element From 1 To nElements
ElementType = Substr(SpecList,SpecListPointer,1)
SpecListPointer = SpecListPointer + 1
PackMan!UnpackValue()
EndFor
Else
For i From 1 To nElements
ElementType = Substr(SpecList,SpecListPointer,1)
ElementLength = Asc(Substr(SpecList,SpecListPointer + 1,1))
Element = Substr(SpecList,SpecListPointer + 2,ElementLength)
SpecListPointer = SpecListPointer + 2 + ElementLength
PackMan!UnpackValue()
EndFor
Endif
EndProc ; PackMan.UnPackAnyArrayFrom(AnyArrayVar,AnyArray)
Proc PackMan!UnpackValue()
If Search(ElementType,"MZ") > 0 Then
SpecListSeparator = SearchFrom(",",SpecList,SpecListPointer)
ValueLength = NumVal(Substr(SpecList,SpecListPointer,
SpecListSeparator - SpecListPointer))
SpecListPointer = SpecListSeparator + 1
If ElementType = "Z" Then
ElementType = "A"
EndIf
Else
ValueLength = Asc(Substr(SpecList,SpecListPointer,1))
SpecListPointer = SpecListPointer + 1
Endif
Switch
Case ElementType = "A" or ElementType = "M":
AnyArray[Element] =
Substr(AnyArrayVar,ValueListPointer,ValueLength)
Case ElementType = "N":
AnyArray[Element] =
NumVal(Substr(AnyArrayVar,ValueListPointer,ValueLength))
Case ElementType = "B":
ElementType = Substr(AnyArrayVar,ValueListPointer,ValueLength)
If ElementType = "D" Then
AnyArray[Element] = BlankDate()
Else
AnyArray[Element] = BlankNum()
Endif
Case ElementType = "L":
AnyArray[Element] =
IIf(Substr(AnyArrayVar,ValueListPointer,ValueLength) = "True",
True,False)
Case ElementType = "D":
AnyArray[Element] =
DateVal(Substr(AnyArrayVar,ValueListPointer,ValueLength))
OtherWise:
Debug ; Unexpected data type in unpack
EndSwitch
ValueListPointer = ValueListPointer + ValueLength
EndProc ; PackMan!UnpackValue
Proc PackMan.GetArrayType(AnyArrayVar)
Return Substr(AnyArrayVar,1,2)
EndProc ; PackMan.GetArrayType
Proc PackMan.GetArraySize(AnyArrayVar)
Return IIf(Asc(Substr(AnyArrayVar,3,1)) = 1,
NumVal(Substr(AnyArrayVar,4,5)),
Asc(Substr(AnyArrayVar,4,1)))
EndProc ; PackMan.GetArraySize(AnyArrayVar)
Proc PackMan.AddArrayElementTo(AnyArrayVar,ElementValue)
Private
ArrayType,
SpecList,
SpecListLength,
ValueList,
ValuePointer,
ElementType,
ElementLength,
nElements
If Substr(AnyArrayVar,1,2) <> "AY" Then
Return AnyArrayVar
Endif
ArrayType = Substr(AnyArrayVar,1,2)
nElements = IIf(Asc(Substr(AnyArrayVar,3,1)) = 1,
NumVal(Substr(AnyArrayVar,4,5)),
Asc(Substr(AnyArrayVar,4,1)))
nElements = nElements + 1
SpecListLength = IIf(Asc(Substr(AnyArrayVar,9,1)) = 1,
NumVal(Substr(AnyArrayVar,10,5)),
Asc(Substr(AnyArrayVar,10,1)))
SpecList = Substr(AnyArrayVar,15,SpecListLength)
ValuePointer = 14 + SpecListLength + 1
ValueList = Substr(AnyArrayVar,ValuePointer,
Len(AnyArrayVar) - ValuePointer + 1)
PackMan!PackValue()
SpecList =
SpecList +
ElementType +
IIf(Search(ElementType,"MZ") > 0,
Strval(ElementLength) + ",",
Chr(ElementLength))
SpecListLength = Len(SpecList)
Return ArrayType +
IIf(nElements < 1 or nElements > 255,
Chr(1) + Format("W5",nElements),Chr(2) + Chr(nElements) + Spaces(4)) +
IIf(SpecListLength < 1 or SpecListLength > 255,
Chr(1) + Format("W5",SpecListLength),Chr(2) +
Chr(SpecListLength) + Spaces(4)) +
SpecList +
ValueList
EndProc ; PackMan.AddArrayElementTo
Proc PackMan.AddDynarrayElementTo(AnyArrayVar,ElementIndex,ElementValue)
Private
ArrayType,
SpecList,
SpecListLength,
ValueList,
ValuePointer,
ElementType,
ElementLength,
nElements
If Substr(AnyArrayVar,1,2) <> "DY" Then
Return AnyArrayVar
Endif
ArrayType = Substr(AnyArrayVar,1,2)
nElements = IIf(Asc(Substr(AnyArrayVar,3,1)) = 1,
NumVal(Substr(AnyArrayVar,4,5)),
Asc(Substr(AnyArrayVar,4,1)))
nElements = nElements + 1
SpecListLength = IIf(Asc(Substr(AnyArrayVar,9,1)) = 1,
NumVal(Substr(AnyArrayVar,10,5)),
Asc(Substr(AnyArrayVar,10,1)))
SpecList = Substr(AnyArrayVar,15,SpecListLength)
ValuePointer = 14 + SpecListLength + 1
ValueList = Substr(AnyArrayVar,ValuePointer,
Len(AnyArrayVar) - ValuePointer + 1)
PackMan!PackValue()
ElementIndex = StrVal(ElementIndex)
SpecList =
SpecList +
ElementType +
Chr(Len(ElementIndex)) +
ElementIndex +
IIf(Search(ElementType,"MZ") > 0,
Strval(ElementLength) + ",",
Chr(ElementLength))
SpecListLength = Len(SpecList)
Return ArrayType +
IIf(nElements < 1 or nElements > 255,
Chr(1) + Format("W5",nElements),Chr(2) + Chr(nElements) + Spaces(4)) +
IIf(SpecListLength < 1 or SpecListLength > 255,
Chr(1) + Format("W5",SpecListLength),Chr(2) +
Chr(SpecListLength) + Spaces(4)) +
SpecList +
ValueList
EndProc ; PackMan.AddDynarrayElementTo
Proc PackMan.GetElementValueFrom(AnyArrayVar,ElementIndex)
Private
ArrayType,
TestIndex,
SpecPointer,
ValuePointer,
ValueLengthPointer,
ValueLength,
SpecListLength,
SeparatorPointer,
ElementIndexLength,
ElementType,
ElementValue
ArrayType = Substr(AnyArrayVar,1,2)
SpecListLength = IIf(Asc(Substr(AnyArrayVar,9,1)) = 1,
NumVal(Substr(AnyArrayVar,10,5)),
Asc(Substr(AnyArrayVar,10,1)))
SpecPointer = 15
ValuePointer = 15 + SpecListLength
If ArrayType = "AY" Then
For i From 1 To ElementIndex - 1 ; Get next SpecPointer and ValuePointer
ElementType = Substr(AnyArrayVar,SpecPointer,1)
If Search(ElementType,"MZ") > 0 Then
SeparatorPointer = SearchFrom(",",AnyArrayVar,SpecPointer + 1)
ValuePointer = ValuePointer +
NumVal(Substr(AnyArrayVar,SpecPointer,
SeparatorPointer - SpecPointer))
SpecPointer = SeparatorPointer + 1
Else
ValuePointer = ValuePointer +
Asc(Substr(AnyArrayVar,SpecPointer + 1,1))
SpecPointer = SpecPointer + 2
Endif
EndFor
ElementType = Substr(AnyArrayVar,SpecPointer,1)
SpecPointer = SpecPointer + 1
If Search(ElementType,"MZ") > 0 Then
SeparatorPointer = SearchFrom(",",AnyArrayVar,SpecPointer)
ValueLength =
NumVal(Substr(AnyArrayVar,SpecPointer,
SeparatorPointer - SpecPointer))
If ElementType = "Z" Then
ElementType = "A"
Endif
Else
ValueLength = Asc(Substr(AnyArrayVar,SpecPointer,1))
Endif
Else
ElementIndex = Upper(StrVal(ElementIndex))
ElementIndexLength = Asc(Substr(AnyArrayVar,SpecPointer + 1,1))
ValueLengthPointer = SpecPointer + 2 + ElementIndexLength
TestIndex = Substr(AnyArrayVar,SpecPointer + 2,ElementIndexLength)
While ElementIndex <> TestIndex
ElementType = Substr(AnyArrayVar,SpecPointer,1)
If Search(ElementType,"MZ") > 0 Then
SeparatorPointer =
SearchFrom(",",AnyArrayVar,ValueLengthPointer)
ValuePointer = ValuePointer +
NumVal(Substr(AnyArrayVar,ValueLengthPointer,
SeparatorPointer - ValueLengthPointer))
SpecPointer = SeparatorPointer + 1
Else
ValuePointer = ValuePointer +
Asc(Substr(AnyArrayVar,ValueLengthPointer,1))
SpecPointer = ValueLengthPointer + 1
Endif
ElementIndexLength = Asc(Substr(AnyArrayVar,SpecPointer + 1,1))
ValueLengthPointer = SpecPointer + 2 + ElementIndexLength
TestIndex = Substr(AnyArrayVar,SpecPointer + 2,ElementIndexLength)
EndWhile
ElementType = Substr(AnyArrayVar,SpecPointer,1)
If Search(ElementType,"MZ") > 0 Then
SeparatorPointer = SearchFrom(",",AnyArrayVar,ValueLengthPointer)
ValueLength =
NumVal(Substr(AnyArrayVar,ValueLengthPointer,
SeparatorPointer - ValueLengthPointer))
If ElementType = "Z" Then
ElementType = "A"
Endif
Else
ValueLength = Asc(Substr(AnyArrayVar,ValueLengthPointer,1))
Endif
EndIf
Switch
Case ElementType = "A" or ElementType = "M":
ElementValue =
Substr(AnyArrayVar,ValuePointer,ValueLength)
Case ElementType = "N":
ElementValue =
NumVal(Substr(AnyArrayVar,ValuePointer,ValueLength))
Case ElementType = "B":
ElementType = Substr(AnyArrayVar,ValueListPointer,ValueLength)
If ElementType = "D" Then
AnyArray[Element] = BlankDate()
Else
AnyArray[Element] = BlankNum()
Endif
Case ElementType = "L":
ElementValue =
IIf(Substr(AnyArrayVar,ValuePointer,ValueLength) = "True",
True,False)
Case ElementType = "D":
ElementValue =
DateVal(Substr(AnyArrayVar,ValuePointer,ValueLength))
Otherwise:
Debug ; unknown data type in PackMan.GetElementValueFrom
EndSwitch
Return ElementValue
EndProc ; PackMan.GetElementValueFrom