dadlldate-line

DLL Usage Description

Library: dadlldataline

This library contains the following functions:

  • scan.sepa : scan a dataline in separator format
  • scan.fix : scan a dataline in fixed length format
  • concat.sepa: print a dataline in separator format (will not be implemented)
  • concat.fix : print a dataline in fixed length format (not yet implemented)

DLL Prototypes

function extern concat.fix(
                ref string dataline(),
                long offset,
                const long spos(,),
                const long leng(,),
                long index, ... )

pre   : let variable part of argument list be arg1, ..., argn (n >= 0)
        let the types of these arguments be typei (1 <= i <= n)

space reserved for dataline is long enough to contain result
AND offset >= 1
AND length_of_array(spos) >= n
AND length_of_array(leng) >= n
AND FORALL i: 1 <= i <= length_of_array(spos) : spos(i) >= 1
AND FORALL i: 1 <= i <= length_of_array(leng) : leng(i) >= 0

post  : FORALL i: 1 <= i <= n:
        - dataline(offset+spos(i)-1; leng(i)) =
          ( typei = string ? argi : str$(argi) )
desc  : This is a rather operational description and certainly not
        formally correct. Problems:
        - overlapping arguments: if for some arguments the place where
          they should come in the result string do overlap the above
          statement should hold for at least one of these arguments.
          So it is not defined in what order the arguments should be
          placed into the string.
        - if len(argi) > leng(i) (typei = string) then argi should be
          truncated.

        if len(str$(argi)) > leng(i) (typei = numeric) then
        str$(argi) should be truncated (and hopefully its only
        loosing precision).

function extern long scan.fix(
                const string dataline(),
                ref long offset,
                const long spos(,),
                const long leng(,),
                long index,
                long llen, ... )

pre   : let variable part of argument list be arg1, ..., argn (n >= 0)
        let the types of these arguments be typei (1 <= i <= n)

        offset >= 1
        AND length_of_array(spos) = length_of_array(leng) >= n
        AND FORALL i: 1 <= i <= n : spos(i) >= 0
        AND FORALL i: 1 <= i <= n : leng(i) >= 0
        AND FORALL i: 1 <= i <= n : spos(i) = 0 => leng(i) = 0
        AND llen = MAX j: 1 <= j <= n : spos(j) + leng(j) - 1
        return: len(line) >= offset + llen - 1
        or (len(line) >= offset + spos(n) - 1 and typen = string)

post  : ret ==>
        FORALL i: 1 <= i <= n and spos(i) > 0:
           typei = string ==> argi = dataline(offset+spos(i)-1;leng(i))
           typei = double ==> argi = val(  ,, )
           typei = long   ==> argi = lval( ,, )

        AND FORALL i: 1 <= i <= n and spos(i) = 0: argi = old(argi)
        AND offset = old(offset) + llen
        desc: In contrast to the function concat.fix this function
        does not have problems with overlapping fields.
        Note that fields that have an spos of 0 may not be changed,
        nor emptied (this is to skip multiline fields).

function extern long scan.sepa(
                const string dataline(),
                ref long offset,
                string sepa(1),
                string encl(1), ... )

pre   : let variable part of argument list be arg1, ..., argn (n >= 0)
        let the types of these arguments be typei (1 <= i <= n)

        offset >= 1
        AND len(sepa) = 1

return: The number of arguments that could be filled
 (thus 0 <= retval <= n)

post  : FORALL i: 1 <= i <= retval:
            typei = long   ==> argi = lval(SUBSTR(i)) AND
            typei = double ==> argi = val(SUBSTR(i)) AND
            typei = string and (encl =  "" or SUBSTR(i) = "")
                           ==> argi = SUBSTR(i) AND
            typei = string and encl <> ""
                           ==> argi = SUBSTR(2; len(SUBSTR(i)-2))

        offset = old(offset) + SEPA.OCC(retval) - 1

desc  : where SUBSTR(i) is defined as:
        dataline(offset+SEPA.OCC(i-1); SEPA.OCC(i)-SEPA.OCC(i-1)-1)
        (informally: the substring between the (i-1)th and the ith
         separator)

        and where SEPA.OCC is defined as:
        SEPA.OCC(0) = 0
        SEPA.OCC(1) = pos(dataline(offset), sepa)
        SEPA.OCC(n) = SEPA.OCC(n-1) +
                      pos(dataline(offset+SEPA.OCC(n-1)), sepa)
        (as long as this pos is positive and not considering separators
         occuring between enclosing characters)
        SEPA.OCC(m) = len(dataline) - offset + 2
        (otherwise)
        (informally: the ith occurence of the separator in
         dataline(offset) or the index just after the end of the
         string, if not existing)

        Thus this function splits dataline into substrings separated
        by the separator sepa. The substrings are assigned (if
        necessary using the conversion functions lval or val) to the
        arguments. The offset is placed behind the last substring
        scanned (or if this last substring is followed by a separator
        behind this separator).
        The return value indicates how many arguments could be scanned
        and thus will be limited by:
         - the number of variable arguments
         - the number of separators occuring in dataline (from
           position offset on)

        If encl <> "" string arguments must be either:
          - enclosed by the enclosing character encl
          - empty (ie 2 separators occur on subsequent positions)
        Note that it is possible that a string is scanned in several
        phases and thus, that offset should be just behind the
        separator after the nth argument (and not on it)