Wanted: Advice on dangerous practices!

Everything else that doesn't fall into one of the other PB categories.
RichardL
Enthusiast
Enthusiast
Posts: 532
Joined: Sat Sep 11, 2004 11:54 am
Location: UK

Wanted: Advice on dangerous practices!

Post by RichardL »

I posted this in the Coding area and did not get any responses. Anyone here want to take a look and comment?


My current project requires me to QUICKLY insert and delete strings in a one dimensional array. The array can be many thousands of elements and the strings can be from zero length to a several hundred bytes.
Moving most of the strings in an array can take time.

To speed things up when inserting and deleting elements I decided to adjust the string pointer table, the base of which is returned by @Array$() and has an array of N+1 long pointers if the string array has been dimensioned with ‘N’ elements.

Having made this work in a specific application I wanted to make the solution more general and wrote the two procedures here; which do what I want.

Code: Select all

; WARNING: Experimental code; untidy, untested and possibly unsafe 
; ================================================================ 

; Declare Procedures 
Declare.l InsertS(*BaseAddress,Offset.l) 
Declare.l DeleteS(*BaseAddress,Offset.l) 
Declare.l ShowData() 

; Create string array with some data 
Global Elements                   ; Needed gor testing 
Elements.l = 11 
Dim a$(Elements)                  ; Produces a$(0) to a$(11) 

; Some test data 
a$(0)="Start" 
a$(1)="Tom" 
a$(3)="Harry" 
a$(6)="Six" 
a$(Elements)="End" 

*t = @a$()                        ; LEGAL   : Base address of array of pointers to strings 
Debug "Dim ?? "+Str(PeekL(*t-8))  ; SUSPECT :For a one dimesioned array this contains the array size 
Debug "" 

ShowData() 
Debug DeleteS(@a$(),3)            ; Delete element number 
ShowData() 

z = 1 
Debug InsertS(@a$(),z)            ; Insert element number 
a$(z)="New item" 
ShowData() 
End 


Procedure InsertS(*BaseAddress,Offset.l) 
  ; Starting at the specified element move 
  ; all the string pointers up by one 
  
  Protected *a, *b, Elements.l, x.l, t.l, Result 
  
  Result = 1                               ; Default to OK 
  Elements = PeekL(*BaseAddress-8)         ; Find # of elements **** 
  If (Offset>0) And (Offset<=Elements)     ; Check the Offset is in range 
    
    *a = Elements                          ; Build pointer to last table entry 
    *a * 4 
    *a + *BaseAddress 
    *b = *a - 4 
    
    Offset + 1                             ; Move pointers UP... 
    For x = Elements To Offset Step-1 
      t = PeekL(*b) 
      PokeL(*a,t) 
      *a - 4 
      *b - 4 
    Next 
    PokeL(*a,0)                            ; NULL pointer = no string asigned at insert point 
  Else 
    Result=0 
  EndIf 
  
  ProcedureReturn Result 
EndProcedure 

Procedure DeleteS(*BaseAddress,Offset.l) 
  
  Protected *a, *b, Elements.l, x.l, t.l, Result 
  
  Result=1 
  Elements = PeekL(*BaseAddress-8)         ; **** 
  If (Offset>=0) And (Offset<Elements) 
    
    *a = Offset 
    *a * 4 
    *a + *BaseAddress 
    *b = *a + 4 
    
    Elements - 1 
    For x = Offset To Elements 
      t = PeekL(*b) 
      PokeL(*a,t) 
      *a + 4 
      *b + 4 
    Next 
    PokeL(*a,0) 
  Else 
    Result=0 
  EndIf 
  
  ProcedureReturn Result 
EndProcedure 

Procedure ShowData() 
  ; Show the pointer values for the array and the string where they point 
  
  *t = @a$()                 ; Base address of pointers 
  For n = 0 To Elements      ; 
    *a = PeekL(*t+(n*4))     ; Get the pointer value 
    d$=Str(n)+"  "+Hex(*a)   ; Start result string 
    If *a                    ; If valid pointer... 
      d$+" >"+PeekS(*a)      ;   add the string 
    EndIf 
    Debug d$                 ; Show result 
  Next 
  Debug "============================" 
EndProcedure 
I am well aware that this approach could be unstable if the string management is changed in later revision of PB and this is strictly a one dimension array solution.

Both procedures require the size of the array which I could pass as a variable, but it would be neater if they could find it themselves. See the lines marked ‘*****” in the listings.

Three questions:

1. Is the structure of PB stable enough for me to find the size of the array in this way?
2. Are there any published notes regarding the way single and multi-dimensioned arrays are stored in memory?
3. The InsertS(…) procedure will orphan the last string in the array. Will this present a problem when / if PB tidies up its string space? (I well remember the complex Garbage Collect functions in the early Commodore Basics