Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- FlexFile Reference Guide - Norton Guide http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]

   ARRAYS

   FlexFile supports an implementation of strongly typed
   multi-dimensional arrays.  This array system is not to be
   looked at as a replacement for the Clipper array system.
   Clipper's array system is very powerful and it should not be
   construed that FlexFile arrays will supersede the Clipper
   system. Rather, FlexFile arrays should be used when the array
   structure is regular, all the elements are of the same type,
   and the array is very large.

   Under no circumstance should you use FlexFile's "S"tring type array in
   Clipper 5.0x.  Each string element of the array is not handled by the
   VMM system, and, therefore, the Clipper counterpart will take less
   memory.  All other FlexFile arrays can be swapped, when necessary, by
   Clipper's VMM system. 

   Why Use FlexFile Arrays

   FlexFile arrays are the only arrays to use if your array must
   exceed Clipper's limit of 4029 elements.  For example, a
   FlexFile array of logicals allows over 500,000 elements.  In
   addition, each element of FlexFile array is at least six bytes
   smaller than its Clipper counter part and at most thirteen
   bytes and 7 bits smaller.  See Appendix B for a list of the
   sizes of each type of FlexFile array.

   Clipper sees Flexfile arrays as regular variables.  Therefore,
   you pass a Flexfile arrays by value (unless you
   pass-by-reference using the @ symbol) and you can return a
   FlexFile array as though it were a simple Clipper variable.
   Because these arrays are typically large, it is best to pass
   them by reference in order to avoid duplicating their content
   in memory.

   The one exception to this is FlexFile's string type arrays.
   These arrays pose a unique problem which is discuss below (See
   FlexFile String Arrays).




   Array indexes

   A "subscript" or an "index" refers to a particular element of
   an array.  For example, Clipper refers to the third element of
   a single dimensional array as ArrayName[3].  In this case, [3]
   is a subscript of the array ArrayName.

   Subscripts may be passed using either of two different
   methods.  Both methods are valid at any time.  The method to
   use depends largely on whether your array is single or
   multi-dimensional.

   If the array is a single dimensional array, then you define
   and index position into that array exactly as you would
   imagine.  For example, if you want to store 98.6 to the fifth
   element of a single dimensional floating point type array, the
   following line would be fine:


       nTemperature = 98.6
       nPatient = 5
       A_STORE( aTemps, nTemperature, nPatient )


   However, if the array is multi-dimensional it is necessary to
   pass the index via the A_() function.  For example,  if you
   want to store the temperature of the fifth patient on the
   third day:

      A_STORE( aTemps, 98.6, A_( 5, 3 ) )


   It is not wise to try to figure out the actual integer offset
   of an element even though FlexFile would accept it; FlexFile
   does this very fast on its own.  In addition, remember element
   A_( 5, 3 ) is not the same element as A_(3, 5), and rarely, if
   ever, will either array index refer to the fifteenth element
   as it is laid out in memory.




   Understanding FlexFile Arrays

   FlexFile arrays are similar to the arrays in languages such as
   C or Pascal. The array is one block of memory (with the
   exception of string arrays), and each element in the array
   must be of the same type.

   There is an analogy relating multi-dimensional arrays to a set
   of encyclopedias that helps in understanding and describing
   their use.  This analogy is especially helpful in
   understanding arrays that span into the fourth dimension.

   Imagine that you have a character array.  First, do not
   confuse character arrays and string arrays.  A string array is
   an array of pointers that point to strings of varying length
   that reside in random positions in memory.  The string array
   is actually an array of pointers and not an array of strings.
   Each element points to a string of any length.

   A character array is a matrix of one byte storage locations
   where each byte can hold one ASCII character.  In the analogy
   of the encyclopedias, each letter is an element, a group of
   letters that form words make up one row of text.  That one
   line implies the first dimension.  Likewise, A group of lines
   that makes up one page implies the second dimension, a group
   of pages that makes up one volume implies the third dimension,
   and all the volumes in the set of encyclopedias implies the
   fourth dimensions.  We could continue the analogy into the
   fifth dimension: a set of Britannica's next to The World Book
   set implies a magnitude of two in the fifth dimension.

   You will often see, in the Array Function Reference chapter,
   the concept of "wrapping".  For example, A_SCAN() will wrap at
   the end of one line to the beginning of the next, and at the
   end of one page it will wrap to the top of the next page.  All
   functions that work with wrapping look at the array as it is
   laid out in memory.

   It is important to dimension your arrays with this
   understanding in mind:  the last dimension listed in the
   declaration varies the smallest step in memory.  To declare
   the array for an encyclopedia you would want to declare it as
   follows:

       vols := 26
       pages := 150
       lines := 80
       chars := 95
       WorldBook = A_DECLARE( 'C', vols, pages, lines, chars )

   This declaration of a character array is actually illegal
   because the array would exceed memory, however, it is
   important to see how and why the dimensions are in the order
   they are in.  The <chars> variable is last in order to insure
   that each character is next to its proper neighbor in memory.
   As far as A_STORE()ing and A_RETRIEVE()ing each character, the
   layout makes little difference.  However, when you need to do
   something like an A_FILL() (for a blank line), this layout
   becomes critical.

   Lets say, for example, we want the fifth and sixth lines on
   the fifteenth page of the fourth volume to be filled with
   spaces.

      A_FILL( WorldBook, ' ', A_( 4, 15, 5, 1 ), 2 * lines )


   This function fills the 160 characters following the specified
   location.  Because the fill always begins at a point in memory
   and moves to the next set of contiguous positions in memory,
   it becomes critical how the array was declared.  For example,
   if we switch the order of the <lines> and <chars> in the
   declaration, and then perform the A_FILL(), the fill would put
   one space on each line for 160 lines instead of one space for
   each character for 160 characters.

   FlexFile String arrays (pointer arrays)

   Arrays of strings in FlexFile pose a peculiar problem.  When
   the array is declared, FlexFile allocates memory for four
   bytes per element.  These four bytes originally point to
   nothing (null).  When you A_STORE() a string to an element,
   however, new memory is allocated for the string.  This memory
   does not reside within the array, but rather, at some random
   location in memory. FlexFile knows where this is because it
   stores a pointer in the array which points to the new data.

   A problem arises because the array itself is a Clipper
   variable and has the scope of a Clipper variable.  If you
   release this variable or allow it to fall out of scope,
   Clipper does not know that it was pointing to your strings,
   and so, Clipper releases the array of pointers without
   releasing the strings that it points to.  In order to avoid
   this, it is necessary to A_KILL() a string array before
   allowing it to fall out of scope or be released.

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson