String Operators.txt

Warning: if you clip this code into your program, look out for possible html code slipping in.

REM   STRING OPERATORS.TXT
REM
REM   This file contains as much of the string handling capability in Vesta
REM   Multi-Tasking Basic as can be implemented for the SBC2000-074 board.
REM
REM   This file does not contain a standalone application ... it contains
REM   subroutines and functions only and must be included by a file which
REM   has the main application.
REM
REM   Author: Andrew Jonathan Fine
REM
REM   Copyright 1998 Vesta Technology, Inc.
REM   All rights reserved.


CONSTANT STRING_SIZE_MAX     AS INTEGER = 254
CONSTANT STRING_INDEX_MAX    AS INTEGER = 253
CONSTANT STRING_LENGTH_BYTES AS INTEGER = 2
CONSTANT STRING_SINGLE_BYTE  AS INTEGER = 1




REM ---
REM - Versions of EEPROM_DPEEK and DPOKE. If you have handlers for timers or
REM - other ON events which access the EEPROM, you should declare these
REM - routines to be VITAL.
REM ---
FUNCTION   EEPROM_DPEEK (s AS INTEGER) AS INTEGER
  EEPROM_DPEEK = (256 * EEPROM_PEEK(s + 1)) OR EEPROM_PEEK (s)
END


REM   Since division is signed, we can't do a direct divide by 256 in this
REM   routine. For this reason, we divide by 2, mask off the high bit to get a
REM   positive argument, then divide by 128.
SUBROUTINE EEPROM_DPOKE (s AS INTEGER, i AS INTEGER)
  EEPROM_POKE (s, i)		: REM   Poke the low byte
  i = (i / 2) AND 0x7F80	: REM   Force positive before main divide
  EEPROM_POKE (s + 1, i / 128)	: REM   Poke the high byte
END



REM ---
REM - How many bytes are in s?
REM ---
FUNCTION s_len (s AS INTEGER) AS INTEGER
  s_len = EEPROM_DPEEK (s)

  IF s_len < 0
    s_len = 0
    RETURN
  ENDIF

  IF s_len > STRING_SIZE_MAX
    s_len = STRING_SIZE_MAX
  ENDIF
END



REM ---
REM - How many bytes are in s?
REM ---
FUNCTION s_max (s AS INTEGER) AS INTEGER
  s_max = EEPROM_DPEEK (s)
  s_max = s_max - 1

  IF s_max < 0
    s_max = 0
    RETURN
  ENDIF

  IF s_max > STRING_INDEX_MAX
    s_max = STRING_INDEX_MAX
  ENDIF
END



REM ---
REM - Set the size of string s 
REM ---
SUBROUTINE s_set_size (s AS INTEGER, size AS INTEGER)
  IF size < 0
    size = 0
  ENDIF

  IF size > STRING_SIZE_MAX
    size = STRING_SIZE_MAX
  ENDIF

  EEPROM_DPOKE (s, size)
END


REM ---
REM - Create a single byte string s from character c
REM ---
SUBROUTINE s_chr (s AS INTEGER, c AS INTEGER)
  s_set_size   (s, 1)
  EEPROM_POKE  (s + STRING_LENGTH_BYTES, c)
END 



REM ---
REM - Construct a string by appending a character 
REM - to it.
REM ---
SUBROUTINE s_cons (s AS INTEGER, c AS INTEGER)
  IF s_len (s) = 0
    s_chr (s, c)
    RETURN
  ENDIF

  IF s_len (s) >= STRING_INDEX_MAX
    RETURN
  ENDIF

  EEPROM_DPOKE (s, s_len(s) + 1)

  s = s + STRING_LENGTH_BYTES + s_max (s)
  EEPROM_POKE  (s, c)
END



REM ---
REM - Send string to current PIPE PRINT device
REM ---
SUBROUTINE s_print (x AS INTEGER)
  LOCAL i as INTEGER

  IF s_len(x) = 0
    RETURN
  ENDIF

  i = s_max (x)
  x = x + STRING_LENGTH_BYTES

  DO WHILE i >= 0
    PRINT CHR (EEPROM_PEEK (x))
    i = i - 1
    x = x + 1
  LOOP
END



REM ---
REM - x <-- y
REM ---
SUBROUTINE s_assign (x AS INTEGER, y AS INTEGER)
  LOCAL l AS INTEGER

  FOR l = s_len(y) TO -1 STEP -1
    EEPROM_POKE (X, EEPROM_PEEK (Y))
    X = X + 1
    Y = Y + 1
  NEXT
END



REM ---
REM - i <-- 0 <= i < |x|
REM --- 
FUNCTION   s_limit (x as INTEGER, i as INTEGER) AS INTEGER
  IF i > s_max (x)
    s_limit = s_max (x)
    RETURN
  ENDIF

  IF i < 0
    s_limit = 0
    RETURN
  ENDIF

  s_limit   = i
END



REM ---
REM - Specific case |y| == |{a,b}|:  x {a, b} <-- y
REM ---
SUBROUTINE s_cat_fill    (x AS INTEGER, y AS INTEGER, a AS INTEGER, b AS INTEGER)
  LOCAL incr AS INTEGER
  LOCAL idx  AS INTEGER

  x = x + STRING_LENGTH_BYTES + a
  y = y + STRING_LENGTH_BYTES

  IF a <= b
    incr =  1
  ELSE
    incr = -1
  ENDIF

  FOR IDX = a TO b STEP incr
    EEPROM_POKE (x, EEPROM_PEEK (y))
    x = x + incr
    y = y + 1
  NEXT
END



REM ---
REM - x {$} <-- y
REM ---
SUBROUTINE s_cat (x AS INTEGER, y AS INTEGER, a AS INTEGER)
  a = s_limit (x, a)

  IF a > STRING_INDEX_MAX
    RETURN
  ENDIF

  a = a + 1

  IF s_len (y) = 0
    RETURN
  ENDIF

  IF s_len (x) = 0
    s_assign (x, y)
    RETURN
  ENDIF 

  IF ((a + s_len (y)) > STRING_INDEX_MAX)
    s_cat_fill (x, y, a, STRING_INDEX_MAX)
    s_set_size (x, STRING_SIZE_MAX)
  ELSE
    s_cat_fill (x, y, a, a  + s_max (y))
    s_set_size (x, s_len(x) + s_len (y))
  ENDIF
END



REM ---
REM - x {$} <-- reverse(y)
REM ---
SUBROUTINE s_rappend (x AS INTEGER, y AS INTEGER)
  LOCAL index  AS INTEGER
  LOCAL letter AS INTEGER
  LOCAL eos    AS INTEGER

  FOR index = s_max(y) to 0 step -1
    letter = EEPROM_PEEK (y + STRING_LENGTH_BYTES + index)
    s_cons (x, letter)
  NEXT
END



REM ---
REM - What is the ASCII value for first byte of s?
REM ---
FUNCTION   s_asc (s AS INTEGER) AS INTEGER
  IF s_len (s)
    s_asc = EEPROM_PEEK (s + STRING_LENGTH_BYTES)
  ENDIF
END



REM ---
REM - What is the ASCII value of i'th byte of s?
REM ---
FUNCTION   s_byte  (s AS INTEGER, i AS INTEGER) AS INTEGER
  IF i < 0
    s_byte = 0
    RETURN
  ENDIF

  IF i <= s_max (s)
    s_byte = EEPROM_PEEK (s + i + STRING_LENGTH_BYTES)
  ENDIF
END



REM ---
REM - x <-- y {i}
REM ---
SUBROUTINE s_pick  (x AS INTEGER, y AS INTEGER, i AS INTEGER)
  IF s_len (y) = 0
    s_set_size (x, 0)
    RETURN
  ENDIF

  s_chr (x, s_byte (y, i))
END


REM ---
REM - return |{a,b}| 
REM ---
FUNCTION   s_interval (a AS INTEGER, b AS INTEGER) AS INTEGER
  s_interval = ABS (b - a) + 1
END



REM ---
REM - x <-- y {a, b}
REM ---
SUBROUTINE s_substring (x AS INTEGER, y AS INTEGER, a AS INTEGER, b AS INTEGER)
  LOCAL dir   AS INTEGER
  LOCAL index AS INTEGER

  a = s_limit (y, a)
  b = s_limit (y, b)

  IF a = b
    s_chr (x, s_byte (y, a))
    RETURN
  ENDIF

  IF a <= b
    dir =  1
  ELSE
    dir = -1
  ENDIF

  s_set_size (x, s_interval (a, b))    : REM set length of new string

  x = x + STRING_LENGTH_BYTES   
  y = y + STRING_LENGTH_BYTES

  FOR index = a TO b STEP dir
    EEPROM_POKE (x, EEPROM_PEEK (y + index))
    x = x + 1
  NEXT
END 



REM ---
REM - Get string from current PIPE INPUT device
REM ---
SUBROUTINE s_input (x AS INTEGER)
  LOCAL i      as INTEGER
  LOCAL letter as INTEGER
  LOCAL where  as INTEGER

  i = 0
  s_set_size (x, 0)
  
  DO WHILE i <= STRING_INDEX_MAX
    letter = INKEY ()

    IF letter = 13
      EXIT
    ENDIF

    IF letter >= 0  
      where = x + STRING_LENGTH_BYTES + i
      EEPROM_POKE  (where, letter)
      i = i + 1
    ENDIF
  LOOP

  s_set_size (x, i)
END


REM ---
REM - x {t, t + size - 1} <-- x {f, f + size - 1}
REM ---
SUBROUTINE s_sub_shift (s AS INTEGER, t AS INTEGER, f AS INTEGER, size AS INTEGER)
  s = s + STRING_LENGTH_BYTES

  IF f <  0
    f = 0
  ENDIF

  IF f >  STRING_INDEX_MAX
    f = STRING_INDEX_MAX
  ENDIF

  IF t < 0
    t = 0
  ENDIF

  IF t >  STRING_INDEX_MAX
    t = STRING_INDEX_MAX
  ENDIF
    
  IF f <= t
    IF (f - size) < 0
      size = f + 1
    ENDIF
  ENDIF

  IF f >= t
    IF (f + size) > STRING_INDEX_MAX
      size = STRING_INDEX_MAX - f + 1
    ENDIF
  ENDIF 

  DO WHILE size > 0
    EEPROM_POKE (s + t, EEPROM_PEEK (s + f))
    t    = t    + 1
    f    = f    + 1
    size = size - 1
  LOOP
END 

REM ---
REM - Restricted case |y| == |{a,b}|, 0 <= a < |x|, 0 <= b < |x| :  x {a, b} <-- y
REM ---
SUBROUTINE s_fwd_replace (x   AS INTEGER, 
                          y   AS INTEGER, 
                          a   AS INTEGER, 
                          b   AS INTEGER)
  LOCAL index    AS INTEGER
  LOCAL letter   AS INTEGER
  a = s_limit (x, a)
  b = s_limit (x, b)
  y = y + STRING_LENGTH_BYTES

  FOR index = a TO b
    letter = EEPROM_PEEK (y)
    EEPROM_POKE (x + STRING_LENGTH_BYTES + index, letter)
    y = y + 1
  NEXT
END



REM ---
REM - Restricted case |y| == |{a,b}|, 0 <= a < |x|, 0 <= b < |x| :  x {a, b} <-- y
REM ---
SUBROUTINE s_rvs_replace (x   AS INTEGER, 
                          y   AS INTEGER, 
                          a   AS INTEGER, 
                          b   AS INTEGER)
  LOCAL index  AS INTEGER
  LOCAL letter AS INTEGER
  a = s_limit (x, a)
  b = s_limit (x, b)
  y = y + STRING_LENGTH_BYTES + s_max (y)

  FOR index = a TO b 
    letter = EEPROM_PEEK (y)
    EEPROM_POKE (x + STRING_LENGTH_BYTES + index, letter)
    y = y - 1
  NEXT
END
 


REM ---
REM - General case:  x {a, b} <-- y
REM --- 
SUBROUTINE s_replace (x AS INTEGER, y AS INTEGER, a AS INTEGER, b AS INTEGER)
  LOCAL difference AS INTEGER
  LOCAL magnitude  AS INTEGER
  LOCAL temp       AS INTEGER
  LOCAL reversal   AS INTEGER

  IF b < a
    reversal = 1
  ELSE
    reversal = 0
  ENDIF

  IF a > s_max (x)
    IF b > s_max (x)
      IF reversal
        s_rappend (x, y)                        : REM degenerate cases implies catenation
      ELSE
        s_cat     (x, y, a)
      ENDIF
      RETURN
    ENDIF
  ENDIF

  a         = s_limit (x, a)
  b         = s_limit (x, b)
  magnitude = s_interval (a, b)
  
  IF s_len (x) <= magnitude
    s_assign (x, y)                             : REM degenerate case implies replacement
    RETURN
  ENDIF

  IF s_len (y) = 0
    difference = s_len (x) - magnitude          : REM degenerate case simplifies deletion
    
    IF (a <= b)
      s_sub_shift (x, a, b + 1, difference)     : REM (direction of interval is irrelevant)
    ELSE
      s_sub_shift (x, b, a + 1, difference)
    ENDIF

    s_set_size  (x, difference)
    RETURN
  ENDIF

  IF s_len (y) = 1
    IF magnitude = 1
      magnitude  = x + STRING_LENGTH_BYTES + a  : REM degenerate case (single char replace)
      difference = EEPROM_PEEK (y + STRING_LENGTH_BYTES) 
      EEPROM_POKE (magnitude, difference)       : REM (NOTE, reuse variables)
      RETURN                 
    ENDIF
  ENDIF

  IF b < a
    temp = a                                    : REM the following cases are general.
    a    = b                                    : REM this condition makes them respond
    b    = temp                                 : REM symmetrically with respect to interval
  ENDIF

  IF s_len (y) < magnitude
    difference = magnitude - s_len (y)          : REM net delete of string
    s_sub_shift   (x, b + 1 - difference, b + 1, s_max (x) - b)
    s_set_size    (x, s_len(x)  - difference)   
  ENDIF

  IF s_len (y) > magnitude                         
    difference   = s_len (y) - magnitude        : REM net increase of string
    s_sub_shift   (x, s_max (x), s_max (x) - difference, difference)
    s_set_size    (x, s_len (x) + difference)  
  ENDIF

  IF reversal
    s_rvs_replace (x, y, a, a + s_max (y))
  ELSE
    s_fwd_replace (x, y, a, a + s_max (y))
  ENDIF
END

 

VestaTech Home

© 2002 Vesta Technology