'STRING Function Package - Bill McDaniel 11/15/2013
' A set of String manipulation functions
' These are based on the built-in SUBSTR$ function
' which is sensitive to the OPTION BASE setting. 
' So each function forces it to 1 and these functions
' assume the first character in a string is character 1
'  ===========================
' LEFT$ extracts the leftmost characters from a string
' if n is greater than length of a$ whole string is returned
def LEFT$(a$,n)
  ob$ = substr$("10",1,1)     
  option base 1
  n = max(1, min(n,len(a$)))   ' normalize n
  left$ = substr$(a$,1,n)
  if ob$ = "0" then option base 0
end def

'===========================
'RIGHT$ extracts the rightmost characters from a string
' if n is greater than length of a$ whole string is returned
def RIGHT$(a$,n)
  ob$ = substr$("10",1,1)          
  option base 1
  n = max(1, min(n,len(a$)))    ' normalize n
  right$ = substr$(a$,len(a$)-(n-1),len(a$))
  if ob$ = "0" then option base 0
end def

' ===========================
' MID$ extracts the middle characters from a string
' extracts from char n for m chars ... different from substr$
' if n is greater than length of a$ whole string is returned
' if less than m chars left, rest of string returned
def MID$(a$,n,m)
  ob$ = substr$("10",1,1)
  option base 1
  if n < 1 or m < 1 or a$ = "" then 
    mid$ = ""
  else
    n = max(1,min(n,len(a$)))      ' normalize n
    x = max(1,min(m+n-1,len(a$)))  ' normalize x
    mid$ = substr$(a$,n,x)
  end if
  if ob$ = "0" then option base 0
end def 

' =================================
' LTRIM$ returns a string with no leading blanks
def LTRIM$(a$)
  for i = 1 to len(a$)
    c$ = left$(a$,1)
    if c$ = " " then 
      a$ = right$(a$,len(a$)-1)
    else
      break i
    end if
  next i
  if a$ = " " then a$ = ""
  ltrim$ = a$
end def

' =====================================
' RTRIM$ returns a string with no trailing blanks
def RTRIM$(a$)
  for i = 1 to len(a$)
    c$ = right$(a$,1)
    if c$ = " " then
      a$ = left$(a$,len(a$)-1)
    else
      break i
    end if
  next i
  if a$ = " " then a$ = ""
  rtrim$ = a$
end def

' =======================================
' TRIM$ returns a string with no blanks in front or behind
def TRIM$(a$)
  trim$ = ltrim$(rtrim$(a$))
end def

' ===========================
' INSTR returns index of first matching string
' if needle is not found, 0 is returned
' if parms are outside scope of haystack, then -1 returned
def INSTR(needle$,haystack$,sp)
  ob$ = substr$("10",1,1)    
  option base 1
  instr = 0
  if len(needle$) > len(haystack$) or needle$ = "" or sp < 1 then 
    instr = -1
  else
    for i = sp to len(haystack$)- len(needle$)+1
      ep = i+(len(needle$)-1)
      extract$ = substr$(haystack$,i,ep)
      if needle$ = extract$ then 
        instr = i
        break i
      end if
    next i
  end if 
  if ob$ = "0" then option base 0
end def 

' =======================================
' STRING$ returns a string of chars of specified length 
def STRING$(l,f$)
  for i = 1 to l
    s$ = s$ & f$
  next i
  string$ = s$
end def

' =======================================
' PARSE parses a string and tokenizes it into an array
' The string is parsed using a string of stop chars
' Each token is placed in an element of the passed array
' The array is cleared first and parse returns the number of 
' elements that were loaded. If the array was too small,
' parsing will stop and the returned number will be negative
def PARSE(s$,p$,a$())
  ob$ = substr$("10",1,1)      
  option base 1                ' set base to 1
  get dim a$ xsize x           ' get the array size
  for i = 1 to x               ' clear the array
    a$(i) = ""
  next i

  if s$ = "" then              ' if s$ is null
    n=0                        ' nothing is returned
  else
    n = 1                        ' init the element number
    for i = 1 to len(s$)         ' scan the string
      c$ = mid$(s$,i,1)          ' get a char from the string
      if instr(c$,p$,1) <= 0 then' is it a stop char?
        if startanother then     ' no...do we start a token?
          n = n + 1                 ' yes...increment element
          startanother = 0          '    and turn off the flag
        end if
        a$(n) = a$(n) & c$       ' add the char to the token
      else
        if n = x then            ' yes...are we out of array?
          n = -n                    'yes...negate the return
          break i                   '  then exit the loop
        else
          if a$(n) <> "" then       'no...start a new one?
            startanother = 1        '  yes...just set flag
          end if
        end if
      end if
    next i                    ' finish scanning the string
  end if

  parse = n               ' and set the return code
  if ob$ = "0" then option base 0
end def

