Page 1 of 1

OpenOffice BASIC: Create an independent copy of an array.

PostPosted: Thu May 17, 2018 10:07 pm
by Lupp
I have to apologize for insufficient verification of the code. It did not work correctly in an example "JeJe" provided.
I will replace it now with a slightly reworked version working correctly for me in LibO V6.0.3 and also in AOO V4.1.5.
Be careful, please. I cannot give any guarantee. Errors still expected!

In addition I attach a .ods file containing the test by JeJe, the reworked code, and an enhanced version for arrays up to 5 dimensions.
(11.81 KiB) Downloaded 96 times

Start of the original text:

Arrays (and structures) are generally assigned to variables by reference in OpenOffice BASIC (and beyond). Hence I am only talking about arrays. I will recap in short what "by reference" means.

If the variable A is declared by A(0 To 3, 1 To 2) e.g. and you make an assignmen B = A then accessing B does exactly the same as accessing A. A(1,2) = 3 will force B(1,2) to also have the value 3. A subsequent B(1,2) = "Z" will cause A(1,2) to return "Z".

This is often the desired behaviour. Think alone of storage efficiency. It involves, however, that an array passed to a routine (Sub, Function) via a parameter specified with the ByVal clause also only can get the reference where it is not of high importance if this reference is primarily one to the varibale you access the array with or directly to the array.

On the other hand there are cases where you want to create a new array B and to only inititialize it with the contents of A while both the names actually shall give access to two arrays whose elements can be changed independently afterwards.

Since I today considered this anew and got an idea how to avoid the need of copying elments one by one explicitly in a way I not yet had seen, I want to present the solution to you and to request for your comments and criticisms. See code below.

Code: Select all   Expand viewCollapse view
Function createArrayCopy2D(p2D)
REM Returns a reference to a newly created copy of the passed array.
REM BE CAREFUL! This is not based on profound knowledge of any specifications
REM for LibreOffice BASIC, not to speak of any knowledge of its interpreter's code.
REM This is based on speculative testing. New testers please report contradictory results.
If NOT IsArray(p2D)  Then Exit Function
If NOT (dimensionality(p2D)=2) Then Exit Function
dummy = p2D
l = Array(Lbound(dummy,1), Lbound(dummy,2)
u = Array(Ubound(dummy,1), Ubound(dummy,2)
Redim Preserve dummy(l(0) To u(0), l(1) To u(1))
REM The Redim command does not test if any dimnsion is actually changed.
REM By way of precaution it creates a copy with ReferenceCounter=1
REM and decrements the ReferenceCounter of the source by 1.
REM This way the calling position will get returned a reference to the copy
REM while the source array wherever referenced in advance will be unchanged.
createArrayCopy2D = dummy
End Function

Function dimensionality(pArray)
REM Returns the dimensionality of an array.
dim d As Long ' The code relies on the initialization with 0.
If NOT IsArray(pArray) Then Exit Function
On Local Error Goto doneExit
REM Below the Ubound() function is only used to raise an error when needed.
REM Its result, if returned, gets annulled.
    d = Ubound(pArray, d+1)*0 + d + 1
dimensionality = d
End Function

This is specialized to arrays of exactly 2 dimensions. To do it for only one or for more dimensions (up to a reasonable limit) is also feasible.

Re: OpenOffice BASIC: Create an independent copy of an array

PostPosted: Thu May 17, 2018 11:07 pm
by JeJe
Doesn't work here - try this test code.

Code: Select all   Expand viewCollapse view

sub tmp

dim aa(0 to 50,0 to 40)

aa(10,10) =80
dim bb(0 to 50,0 to 40)
bb = createArrayCopy2D(aa)
aa(10,10) =50
msgbox bb(10,10) 'result is 50 not 80
end sub

Re: OpenOffice BASIC: Create an independent copy of an array

PostPosted: Thu May 17, 2018 11:52 pm
by JeJe
On Windows the CopyMemory Api function is a way of copying all the values in one array to another... but testing that, it works for a single item of an array but not the whole array. So - presumably OO array items aren't stored in contiguous memory locations.

I notice if you make an assignment array2 = array1 and then Erase array1 then array2 isn't erased. OO array variables appear to be pointers to an array and its maybe not possible to do what you want to do here. OO is alway going to be copying the pointer to the array... never making a new array.

Re: OpenOffice BASIC: Create an independent copy of an array

PostPosted: Fri May 18, 2018 12:22 am
by Lupp
Hallo JeJe,

Thank yopu very much for testing - and bashful apologies for my prematurely pasting insufficiently verified code.

I do not fully understand the problem. When I wrote and tested the functions (And it worked!) there were a few more assignment of the relevant array to different variables, among them a few indexed variables (array elements). Probably this has influenced parts of the environment.

Since i don't know a documentation on which I might base further development, I could only try a solution based on guessing again. Now there is an intermediary variable inside the relevant function serving to give access to the original array over a bridge that is burnt finally when the function is left.

And now your test suggests correct working - for the example.
I would not yet rely on the method with crucial tasks.

Please see the reworked code contained in the .ods I will attach now to my first post.

Apologies again!

Re: OpenOffice BASIC: Create an independent copy of an array

PostPosted: Fri May 18, 2018 12:57 am
by JeJe
That works... redim preserve creates a new copy of the array - well spotted. This seems to work too...

Code: Select all   Expand viewCollapse view

dim aa(0 to 50,0 to 40), bb(0 to 50,0 to 40)
aa(10,10) =80
bb = aa
redim preserve bb(0 to 50,0 to 40) 'or redim preserve aa
aa(10,10) =50
msgbox aa(10,10)
msgbox bb(10,10)