Oxygen Basic

Programming => Example Code => Data Processing => Topic started by: Charles Pegge on October 29, 2010, 08:39:11 PM

Title: Elastic String Array
Post by: Charles Pegge on October 29, 2010, 08:39:11 PM
Two classes For the string library:

StringArray works like a dynamic array of dynamic strings. It does not need to be dimensioned or redimensioned, though it should be freed when no longer required.

TextArray is derived from StringArray and supports loading and saving files. When a file is loaded, each line is assigned to a location in the array (with crlf stripped).

Getting and Putting is acheived by using pseudovariables. They look just like normal array assignments (though always using round brackets, not square ones).

Example:

TextArray t

t.line(1)="Hello"

print t.line(1)

t.load "prog.o2bas"

t.save "temp.o2bas"


I use these classes in the Opengl Edit project.

Charles

Code: [Select]
'Newer version further on
Title: Re: Elastic String Array
Post by: kryton9 on November 08, 2010, 06:24:26 PM
You got a nice stl like container, actually even nicer there Charles. One additional thing would be an iterator, but not as STL does it.
Paradox the old Borland Language used to have a really nice command named scan.

So you could have:
TextArray t
t.load "prog.o2bas"
scan t
  ..it would go through each line of t here
  and do operations...
endscan
Title: Re: Elastic String Array
Post by: kryton9 on December 05, 2010, 12:19:55 AM
Charles, are these in the latest oxygen download? I can't seem to find them in there.
Title: Re: Elastic String Array
Post by: Charles Pegge on December 05, 2010, 03:16:02 AM
Hi Kent,

I don't have a set location for it yet. The current location is examples/gui/stringutil.inc as it is being tested with the opengl controls. (PortViewer2.o2bas)

The classes do not have built-in iterators but traversing the text is quite simple

e=txt.lastline
for i=1 to e
  s=txt.line i
  ...
next

Charles

Code: [Select]

string cr=chr(13)+chr(10)
string tab=chr(9)



'Elastic String array

'----------------
class StringArray
'================

  protected
  en as sys
  mx as sys
  list as bstring

  public

  method length(byval i as sys) as sys
  '===================================
  if i>mx then return 0
  bstring * t : &t=?list
  if i>0 then return len t[i]
  end method


  method line(byval i as sys, byval s as bstring)
  '=============================================
  sys a
  if i>en then
    a=(i+4096-en)*4
    en=4096+i
    list+=nuls a
  end if
  bstring * t : &t=?list
  if i>0 then
    t[i]=s
    if mx<i then mx=i
  end if
  end method


  method insert(byval i as sys, byval s as bstring)
  '================================================
  sys a,e
  if i>mx+1 then exit method
  mx+=1
  en+=1
  if i>0 then
    a=i*4-4 'strings below i
    list=left(list,a)+nuls(4)+mid(list,a+1) 'alter list of pointers only
    bstring * t : &t=?list
    'e=?list+a : *e=0 'nullify slot before assigning string
    t[i]=s
  end if
  end method


  method delete(byval i as sys)
  '============================
  if en=0 then exit method
  if mx=0 then exit method
  if i>mx then exit method
  en-=1 : mx-=1
  if i>0 then
    sys a
    bstring * t : &t=?list
    'a=i*4-4+&t : frees *a
    a=?t[i] : frees a
    't[i]=""
    a=i*4-4
    list=left(list,a)+mid(list,a+5) 'alter list of pointers only
    mx-=1
  end if
  end method


  method line(byval i as sys) as bstring
  '=====================================
  bstring * t : &t=?list
  if i>0 then
    if i<=mx  then return t[i]
  end if
  end method

  '-----------------------
  method LastLine() as sys
  '=======================
  return mx
  end method


  method locate(w as string, i as sys, j as sys) as sys
  '====================================================
  'case insensitive
  'returns linepos i and charpos j
  '
  sys e
  string s,k
  k=lcase w
  e=mx
  if i<1 then i=1
  if j<1 then j=1
  do
    if i>e then exit do
    s=lcase line(i)
    if len s then j=instr j,s,k else j=0
    if j then return i else j=1
    i+=1
  end do
  i=0 : j=0
  end method


  method free()
  '============
  sys i, q=?list
  for i=1 to mx
    frees *q : q+=4
  next
  frees ?list : ?list=0
  en=0 : mx=0
  end method

end class


'--------------
class TextArray
'==============

  has StringArray

  method load(n as string) as sys
  '==============================
  sys i=0, a=1, b=1, et=0
  string s=getfile n
  do
    b=instr a,s,cr
    if b=0 then
      b=len(s)+1 : et=1
      if b=1 then return 0
    end if
    i+=1 : line(i)=mid s,a,b-a
    if et then
      if a=b then i-=1 : mx-=1 'null line at end
      return i 'number of lines
    end if
    a=b+2
  end do
  end method 

  method save(n as string) as sys
  '==============================
  sys i=1, la, ls, le, e
  string s="" : e=mx
  do
    if i>e then exit do
    le=length(i)+2
    if la+le>ls then
      s+=nuls le+0x10000 'add more space to buffer
      ls+=le+0x10000
    end if
    mid(s,la)=line(i)+cr
    la+=le
    i+=1
  end do
  putfile n,left s,la-1
  end method 

end class



'------------------------------------
sub skiplspace(s as string, i as sys)
'====================================
  sys e=len s
  sys a
  do
    if i>e then exit do
    a=asc s,i
    if a>32 then exit do
  end do
end sub

'-------------------------------------------------
function getword(s as string, b as sys) as string
'=================================================
  'b=1
  sys a,c,d,bb,bc
  a=0
  bb=b
  do
    c=asc s,b
    if c=0 then exit do
    if c>32 then exit do
    b+=1
  end do
  bc=b
  do
    c=asc s,b
    if c<=32 then exit do
    if c=34 or c=96 then
      do
        b+=1
        d=asc s,b
        if d=0 or d=c then b+=1 : jmp fwd done
      end do
    end if
    if c<48 then
      if c=35 then jmp fwd more '#
      if b=bc then b+=1
      exit do
    end if
    if c<58 then jmp fwd more
    if c<64 then
      if b=bc then b+=1
      exit do
    end if
    if c<92 then jmp fwd more
    if c<97 then
      if c=95 then jmp fwd more ' underscore
      if b=bc then b+=1
      exit do     
    end if
    if c<123 then jmp fwd more
    if c<128 then
      if b=bc then b+=1
      exit do     
    end if
    '
    more:
    '
    b+=1
  end do
  '
  done:
  '
  if b=bb then function="" else function=mid s,bb,b-bb
end function

Title: Re: Elastic String Array
Post by: efgee on November 02, 2011, 12:11:15 PM
Charles,

testing the textarray class with this:

Code: [Select]
' string_array.o2bas
'
' Test of StringArray and TextArray
' efgee

$FileName "string_array.exe"

includepath "..\..\inc\"
include "StringUtil.inc"

TextArray t
t.load "string_array.o2bas"

e=t.lastline
for i=1 to e
  print t.line(i)
next

t.save "temp.o2bas"


and the first char (') is missing in the temp file.
Title: Re: Elastic String Array
Post by: Charles Pegge on November 02, 2011, 01:27:27 PM
Hi Frank,

I checked the save method and found a missing offset, highlighted here in black.

  method save(n as string) as sys
  '==============================
  sys i=1, la=1, ls, le, e
  string s="" : e=mx
  do
    if i>e then exit do
    le=length(i)+2
    if la+le>ls then
      s+=nuls le+0x10000 'add more space to buffer
      ls+=le+0x10000
    end if
    mid(s,la)=line(i)+cr
    la+=le
    i+=1
  end do
  putfile n,left s,la-1
  end method 


Thanks!

Charles
Title: Re: Elastic String Array
Post by: efgee on November 02, 2011, 03:02:34 PM
Thanks

This did the trick.


Was wondering about the variable names:

"FileOffset" for "la" would have been my next guess  :D


BTW: If the variable names would be more expressive (instead of "la", "le" etc.) I would have taken a stab at it and tried to fixed it myself - I'm not a genius. As it is right now I have to waste more of your time than I want to  :P



Title: Re: Elastic String Array
Post by: Charles Pegge on November 04, 2011, 10:21:33 AM

You may have noticed, I have a strong bias towards algebra and an aversion to long variable names :)

I find it is much easier to recognise coding patterns when the symbols are kept short. This is useful for recognising repetitive code, which can be compacted into utility functions.

Charles
Title: Re: Elastic String Array
Post by: efgee on November 04, 2011, 04:58:41 PM
Feared that... I'm just the other way around; I like long variable names.

Maybe this is why you and Peter get along so well  ;D

Take care
Title: Re: Elastic String Array
Post by: Charles Pegge on November 04, 2011, 11:22:44 PM

I appreciate long descriptive names are needed for Windows interfacing, but they obfuscate a calculation or formula, which is why short symbolic names are favoured in the sciences.

In my dream IDE, tool tips are used to show descriptions for any symbol.

Charles
Title: Re: Elastic String Array
Post by: Peter on November 05, 2011, 06:43:31 AM
Hi efgee,

Quote
I'm just the other way around; I like long variable names.

is this your way?

Code: [Select]
sys together,we_are_together, some_friends
sys my_dog, my_cat, my_bird
sys we_have_these_animals

together =10
some_friends =-5

we_are_together = together + some_friends
print "we are together: " + we_are_together + " people in the dark forest"

my_dog  =1
my_cat  =1
my_bird =2

we_have_these_animals = my_dog + my_cat + my_bird
print "we have " + we_have_these_animals +" animals at home"
Title: Re: Elastic String Array
Post by: efgee on November 05, 2011, 06:53:20 AM
Peter,
you nailed it.

You might not know, but this will be the new Oxygen coding standard  :D

Title: Re: Elastic String Array
Post by: Peter on November 05, 2011, 07:03:01 AM
LOL
Title: Re: Elastic String Array
Post by: kryton9 on November 05, 2011, 11:40:52 AM
Code: OxygenBasic
  1. sys together, weAreTogether, someFriends
  2. sys myDog, myCat, myBird
  3. sys weHaveTheseAnimals
  4.  
  5. together =10
  6. someFriends =-5
  7.  
  8. weAreTogether = together + someFriends
  9. print "we are together: " + weAreTogether + " people in the dark forest"
  10.  
  11. myDog  =1
  12. myCat  =1
  13. myBird =2
  14.  
  15. weHaveTheseAnimals = myDog + myCat + myBird
  16. print "we have " + weHaveTheseAnimals +" animals at home"

This is very readable and understandable code. The underscores were the problem Peter :)

I like descriptive variable names, but for simple formulas, old 1 character variables are fine.
Title: StringUtil.inc problems
Post by: kryton9 on June 05, 2012, 03:05:27 PM
Charles, I tried to use the StringUtils.inc today and am getting an error that I don't understand. Hope you can help.

Code: OxygenBasic
  1. 'extractText.bas
  2. 'break parts from a bigger text file into sub components
  3. 'by Kent Sarikaya (kryton9) 2012 June
  4.  
  5. include "..\..\inc\StringUtil.inc"
  6.  
  7. TextArray t
  8. string s, s2
  9. s = ""
  10. s2 = ""
  11. t.Load "input.txt"
  12. eof = t.LastLine
  13. for i = 1 to eof
  14.     s = t.Line(i)
  15.     if left( s, 2 ) := "% " then
  16.         s2 += ( s + cr )
  17.     end if
  18. next
  19. putfile "output.txt", s2
  20.  
  21.  
Title: Re: Elastic String Array
Post by: Charles Pegge on June 05, 2012, 06:47:29 PM
Hi Kent,

If you remove the colon on line 15 it will work. := is an assignment operator, and you cant conditionally assign to string functions.


    if left( s, 2 ) = "% " then  ...

Here is a demo using a dynamic TextArray

Code: OxygenBasic
  1. include "..\..\inc\StringUtil.inc"  
  2.  
  3. new TextArray t  
  4.  
  5. t.Lines "one
  6. two
  7. % three
  8. % four
  9. five"
  10.  
  11.  
  12. eof = t.LastLine
  13.  
  14. string s,ou
  15.  
  16. for i = 1 to eof
  17.     s=t.line(i)
  18.     if left(s,2)= "% " then
  19.       ou+=s+cr
  20.     end if
  21. next
  22.  
  23. print ou
  24.  
  25. del t
  26.  

This procedure in a new class:

Code: OxygenBasic
  1. include "..\..\inc\StringUtil.inc"  
  2.  
  3. '====================
  4. Class FilterTextArray
  5. '====================
  6. '
  7. has TextArray
  8. '
  9. method LeftFilter(string k) as string
  10. string s,u
  11. sys i,e=mx
  12. for i = 1 to e
  13.     s=line i
  14.     if left(s,2)=k then
  15.       u+=s+cr
  16.     end if
  17. next
  18. return u
  19. end method
  20. '
  21. end class
  22.  
  23. '--test--
  24.  
  25. new FilterTextArray t
  26.  
  27. t.Lines "one
  28. two
  29. % three
  30. % four
  31. five"
  32.  
  33. print t.LeftFilter "% "
  34.  
  35. del t
  36.  


Charles

PS: A new method for StringArray:

Code: OxygenBasic
  1.  
  2.   method append(string s)
  3.   '======================
  4.  insert mx+1,s
  5.   end method
  6.  
  7.  
Title: Re: Elastic String Array
Post by: kryton9 on June 05, 2012, 09:48:01 PM
Very nice, thanks.

That := is confusing me all the time. I thought in conditionals we needed to use it, like you use == in C.
I see in your examples for conditionals you use it, but not sure when?

Anyways thanks for the troubleshooting and new examples and code.
Title: Re: Elastic String Array
Post by: Charles Pegge on June 05, 2012, 11:58:12 PM
In Oxygen ':=' can be used to force assign in a condtional statement. C alway uses '='.

In C this is normally used to test the zero or non-zero outcome of the assignment

Oxygen also understands '==' and '!='

Code: OxygenBasic
  1. function fn() as sys
  2. return 42
  3. end function
  4.  
  5. a=43
  6.  
  7. if a==fn
  8.    print "equal"
  9. end if
  10.  
  11. if a!=fn
  12.    print "unequal"
  13. end if
  14.  
  15. 'ASSIGN AND BOOLEAN TEST
  16.  
  17. if a:=fn
  18.   print "fn returned non-zero value: new value for a=" a
  19. end if
  20.  

Charles
Title: Re: Elastic String Array
Post by: kryton9 on June 06, 2012, 01:10:01 AM
Ohhhh, so you are assigning and checking a condition at the same time. Ok, now I get it!
Title: Re: Elastic String Array
Post by: Aurel on June 15, 2012, 01:04:37 AM
I just looking into this topic and thinking about interpreter.
Charles what you think...
It would be maybe good idea for interpreter to avoid constant parsing or using translate code
to bytecode - use some sort of array to store all parsed(extracted strings ) into arrays.
So what you think about that?

for example:

a[0]   a[1]   a[2]   a[3]
'print'   'x'     'y'    'string'
Title: Re: Elastic String Array
Post by: Charles Pegge on June 15, 2012, 01:59:01 AM
Hi Aurel,

Yes, reading a string as an array of bytes is easily done and makes parsing much more efficient.

Oops! I see a glitch
I'll get a working example

Charles
Title: Re: Elastic String Array
Post by: Charles Pegge on June 15, 2012, 02:14:13 AM

Code: OxygenBasic
  1. string s="0123456789@abcdefghi"
  2.  
  3. p=strptr(s)
  4. byte b at p
  5.  
  6. print b 'answer 48 '0'
  7.  
  8. indexbase 0
  9.  
  10. print b[1] 'answer 49 '1'
  11.  
  12. 'pointer p can also be moved
  13.  
  14. p+=10
  15.  
  16. print b 'answer 64 '@'
  17.  
Title: Re: Elastic String Array
Post by: Aurel on June 15, 2012, 03:19:22 AM
Hi Charles...
Yes that is cool but i don't understand from where you get this results.
hmmm i see that 48 present 0 ,right?
maybe im not quite clear..uff
In first place i mean as i show
argument1[1024],argument2[1024],argument3[1024]
like:
lineIndex=0 : 'line index -> lndx
argument1[lndx]= "print"
argument2[lndx]= "x"
argument3[lndx]= "y"

without bycode...
how wold this work,for example?
Title: Re: Elastic String Array
Post by: Charles Pegge on June 15, 2012, 03:39:33 AM
I think I see what you mean now. you want to put non-token words into an array to improve parsing efficiency?

You could then encode the array indexes as tokens.

Your byte code would then be a uniform stream of tokens

Am I on the right track, Aurel?

I do something rather similar for string literals in Oxygen. All the literals are stored in the data section, and only their pointers remain in the main code.


Charles
Title: Re: Elastic String Array
Post by: Aurel on June 15, 2012, 04:01:19 AM
Quote
Am I on the right track, Aurel?

I do something rather similar for string literals in Oxygen. All the literals are stored in the data section, and only their pointers remain in the main code.

Yes Charles you right...

In another words:
Get Line of source like a 'print x y'
parse this line into (folowing syntax rules) agruments -> print ,  x  , y
And each argument put into arrays of arguments as i show before.
so if line index is for example 1
index=1  ' <- line number
argument1[1]="print"
argument2[1]="x"
argument3[1]="y"

So i probably must have minimum 32 arrays for arguments,right?
After all parsing is done all this elemnts are completed.
Im interested now how fast this can be executed becuse no more need for parsing again,right?
I hope that im clear now... ;)