Author Topic: UBOUND for Dynamic Arrays  (Read 1301 times)

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2476
    • View Profile
UBOUND for Dynamic Arrays
« on: August 20, 2023, 09:10:05 PM »
First off, I'm assuming there's not a huge need for this kind of thing.

I'm working on a problem where I need a UBOUND function that operates on single-dimensioned dynamic arrays.

The macro that I came up with won't work with arrays of strings because those are not single-dimensioned arrays.

And I don't need one for strings right now anyway.  😉 

My macro seems like it should work on most common single-dimensioned data types.  We'll see ...

Below is an easy to follow demonstration for your toolbox.


Code: [Select]
'===============================================================================================
' BACKGROUND:
'
' BCX does not have a LBOUND function because the true LBOUND of every BCX array is ZERO.
' BCX does have the UBOUND function but it only works on single-dimensioned STATIC arrays
'
' The macro below will return the number of cells in a DYNAMIC single-dimensioned array.
' By simple observation, the internal CreateArr function adds 2 extra cells to the requested
' memory. That is why my macro (below) subtracts 2 from the result.
'
' This specific example was sucessfully tested using Lcc-Win32, Pelles C, MSVC, Mingw, and Clang
'
' Embarcadero C++ reported one too many on all four of the samples.  Beware of Dragons ...
'===============================================================================================

MACRO DYN_UBOUND(i, t) = (LONG)(_msize((i))/SIZEOF(t)-2)

TYPE foo
    member_1 AS INTEGER
    member_2 AS SINGLE
    member_3 AS DOUBLE
END TYPE

DIM DYNAMIC AAA [10] AS foo
DIM DYNAMIC BBB [20] AS INTEGER
DIM DYNAMIC CCC [30] AS SINGLE
DIM DYNAMIC DDD [40] AS DOUBLE
 

PRINT DYN_UBOUND(AAA, foo)          ' AAA is the Array Name, the datatype is foo
PRINT DYN_UBOUND(BBB, INTEGER)      ' BBB is the Array Name, the datatype is INTEGER
PRINT DYN_UBOUND(CCC, SINGLE)       ' CCC is the Array Name, the datatype is SINGLE
PRINT DYN_UBOUND(DDD, DOUBLE)       ' DDD is the Array Name, the datatype is DOUBLE

PAUSE

OUTPUT:


 10
 20
 30
 40

Press any key to continue . . .






MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2476
    • View Profile
Re: UBOUND for Dynamic Arrays
« Reply #1 on: June 25, 2024, 10:29:31 PM »
Earlier today, I posted an improved version of DYN_UBOUND() but I removed it a little while later.

It finally came to me how I could create an improved UBOUND() function that would work reliably
for static and dynamic one-dimensional arrays of any kind of datatype. I have finished implementing
it and the new UBOUND() will make its debut when I release BCX 8.1.1. 

Below is the initial test that I used for the new UBOUND() function:

Code: [Select]
TYPE foo
    member_1 AS INTEGER
    member_2 AS SINGLE
    member_3 AS DOUBLE
END TYPE

DIM DYNAMIC  AAA [10] AS foo         ' This is a dynamic array - the number of cells CAN be changed.
DIM DYNAMIC  BBB [20] AS INTEGER     '                     --- Ditto ---
DIM DYNAMIC  CCC [30] AS SINGLE      '                     --- Ditto ---
DIM DYNAMIC  DDD [40] AS DOUBLE      '                     --- Ditto ---

'=====================================================================================================
DIM          EEE [50] AS ULONGLONG   ' This is a static array - the number of cells CANNOT be changed
DIM          FFF [60] AS STRING      '                     --- Ditto ---

PRINT "AAA [10] Cells run from 0 to", UBOUND (AAA)   
PRINT "BBB [20] Cells run from 0 to", UBOUND (BBB) 
PRINT "CCC [30] Cells run from 0 to", UBOUND (CCC)
PRINT "DDD [40] Cells run from 0 to", UBOUND (DDD)
PRINT "EEE [50] Cells run from 0 to", UBOUND (EEE) 
PRINT "FFF [60] Cells run from 0 to", UBOUND (FFF) 

PAUSE


OUTPUT:


AAA [10] Cells run from 0 to 9
BBB [20] Cells run from 0 to 19
CCC [30] Cells run from 0 to 29
DDD [40] Cells run from 0 to 39
EEE [50] Cells run from 0 to 49
FFF [60] Cells run from 0 to 59

Press any key to continue . . .


A more comprehensive test for the new UBOUND() was compiling BED, which
makes copious use of the UBOUND() function throughout its modules.  All went well.


For the truly curious, the following macros are what I assembled to do the magic:

Code: [Select]
#define s_ubound(t)(int)(sizeof((t))/sizeof((t[0]))-1)
#define d_ubound(i)(int)(_msize((i))/sizeof(i[0])-3)
#define ubound(x)((int)s_ubound(x)<2?d_ubound(x):s_ubound(x))




« Last Edit: June 25, 2024, 11:48:22 PM by MrBcx »

jcfuller

  • Sr. Member
  • ****
  • Posts: 420
    • View Profile
Re: UBOUND for Dynamic Arrays
« Reply #2 on: June 26, 2024, 05:10:02 AM »
Isn't _msize Microsoft only?

James

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2476
    • View Profile
Re: UBOUND for Dynamic Arrays
« Reply #3 on: June 26, 2024, 08:38:59 AM »
Isn't _msize Microsoft only?

James

As in Windows, yes. 

MSVC, Pelles, Lcc-Win32, and Gcc WinApi libraries all support _msize and produce consistent results.

CLANG 32/64 will spit up warnings but produces identical results as the other compilers. 
BCX 8.1.1 will disable those warnings.  They can be easily enabled using the BCX $WARNINGS_ON directive.

Embarcadero exports _msize for 32-bit only and requires specifically #including <malloc.h>

#if !defined(_WIN64)   
_SIZE_T     _RTLENTRY _EXPFUNC stackavail  (void);
int         _RTLENTRY _EXPFUNC _heapadd    (void * __block, _SIZE_T __size);
int         _RTLENTRY _EXPFUNC _heapchk    (void);
int         _RTLENTRY _EXPFUNC _heapmin    (void);
int         _RTLENTRY _EXPFUNC _heapset    (unsigned int __fill);
int         _RTLENTRY _EXPFUNC _heapwalk   (_HEAPINFO *__entry);
int         _RTLENTRY _EXPFUNC _rtl_heapwalk (_HEAPINFO *__entry);
void *      _RTLENTRY _EXPFUNC _expand     (void * __block, _SIZE_T __size);
_SIZE_T     _RTLENTRY _EXPFUNC _msize      (void * __block );
#endif /* _WIN64 */


Embarcadero is a bit inconsistent with the results, sometimes adding one to the expected value.

On Linux and MacOS, WINE likely has you covered.


The bottom line:


BCX users who are making apps for the Windows OS and who need a more robust version
of the UBOUND() function should find the new version more useful than the previous version.




« Last Edit: June 26, 2024, 10:07:28 AM by MrBcx »

Quin

  • Full Member
  • ***
  • Posts: 195
    • View Profile
    • Quin's site
Re: UBOUND for Dynamic Arrays
« Reply #4 on: June 27, 2024, 11:56:04 AM »
Quite nice!

Also allow me to say, this sort of open communication with the users is one of the things drawing me to BCX the most

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2476
    • View Profile
Re: UBOUND for Dynamic Arrays
« Reply #5 on: June 27, 2024, 12:43:05 PM »
Quite nice!

Also allow me to say, this sort of open communication with the users is one of the things drawing me to BCX the most

Quin -- Nice of you to say.

Like many forums, we sometimes lock horns and butt heads but generally it's one big !&@%#$ kumbaya.    ;D

Quin

  • Full Member
  • ***
  • Posts: 195
    • View Profile
    • Quin's site
Re: UBOUND for Dynamic Arrays
« Reply #6 on: June 27, 2024, 01:48:53 PM »
Sure seems like it!
Also using an open source compiler where the dev can communicate about the internals of a function as opposed to a comertial one like I'm used to helps a lot.