/*
 * $Id: array.txt 12724 2009-10-18 23:39:23Z april $
 */

/*
 * The following parts are Copyright of the individual authors.
 * www - http://www.harbour-project.org
 *
 * Copyright 1999 Chen Kedem <niki@actcom.co.il>
 *    Documentation for: ASORT()
 *
 * Copyright 1999 Luiz Rafael Culik <culik@sl.conex.net>
 *    Documentation for: ARRAY(), AADD(), ACLONE(), ACOPY(), ASIZE(),
 *                       ATAIL(), AINS(), ADEL(), AFILL(), ASCAN(), AEVAL()
 *
 * See COPYING for licensing terms.
 *
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      ARRAY()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Create an uninitialized array of specified length
 *  $SYNTAX$
 *      ARRAY( <nElements> [, <nElements>...] ) --> aArray
 *  $ARGUMENTS$
 *      <nElements> is the number of elements in the specified dimension.
 *  $RETURNS$
 *      <aArray> an array of specified dimensions.
 *  $DESCRIPTION$
 *      This function returns an uninitialized array with the length of
 *      <nElements>.
 *
 *      Nested arrays are uninitialized within the same array
 *      pointer reference if additional parameters are specified.
 *
 *      Establishing a memory variable with the same name as the array may
 *      destroy the original array and release the entire contents of the
 *      array. This depends, of course, on the data storage type of either
 *      the array or the variable with the same name as the array.
 *  $EXAMPLES$
 *      PROCEDURE Main()
 *        LOCAL aArray:=Array(10)
 *        LOCAL x
 *        FOR x:=1 to LEN(aArray)
 *          aArray[x]:=Array(x)
 *        NEXT
 *        // Result is: { { NIL }, { NIL, NIL }, ... }
 *      RETURN
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      C(array)
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      AADD(),ADEL(),AFILL(),AINS()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      AADD()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Dynamically add an element to an array
 *  $SYNTAX$
 *      AADD(<aArray>[, <xValue>]) --> Value
 *  $ARGUMENTS$
 *      <aArray> The name of an array
 *
 *      <xValue> Element to add to array <aArray>
 *  $RETURNS$
 *      <Value> if specified <xValue>, <xValue> will return , otherwise this
 *      function returns a NIL value.
 *  $DESCRIPTION$
 *      This function dynamically increases the length of the array named
 *      <aArray> by one element and stores the value of <xValue> to that
 *      newly created element.
 *
 *      <xValue> may be an array reference pointer, which in turn may be
 *      stored to an array's subscript position.
 *  $EXAMPLES$
 *      LOCAL aArray:={}
 *      LOCAL x
 *      AADD(aArray,10)
 *      FOR x:=1 to 10
 *          AADD(aArray,x)
 *      NEXT
 *      // Result is: { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      C
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      AINS(),ASIZE()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      ASIZE()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Adjust the size of an array
 *  $SYNTAX$
 *      ASIZE(<aArray>, <nLen>) --> aTarget
 *  $ARGUMENTS$
 *      <aArray> Name of array to be dynamically altered
 *
 *      <nLen> Numeric value representing the new size of <aArray>
 *  $RETURNS$
 *      <aTarget> an array pointer reference to <aTarget>.
 *  $DESCRIPTION$
 *      This function will dynamically increase or decrease the size of
 *      <aArray> by adjusting the length of the array to <nLen> subscript
 *      positions.
 *
 *      If the length of the array <aArray> is shortened, those former
 *      subscript positions are lost. If the length of the array is
 *      lengthened a NIL value is assigned to the new subscript position.
 *  $EXAMPLES$
 *      aArray := { 1 }          // Result: aArray is { 1 }
 *      ASIZE(aArray, 3)         // Result: aArray is { 1, NIL, NIL }
 *      ASIZE(aArray, 1)         // Result: aArray is { 1 }
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      If HB_COMPAT_C53 is defined, the function generates an Error,
 *      else it will return the array itself.
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      AADD(),ADEL(),AFILL(),AINS()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      ATAIL()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Returns the rightmost element of an array
 *  $SYNTAX$
 *      ATAIL( <aArray> ) --> Element
 *  $ARGUMENTS$
 *      <aArray> is the array.
 *  $RETURNS$
 *      <Element> the expression of the last element in the array.
 *  $DESCRIPTION$
 *      This function return the value of the last element in the array
 *      named <aArray>. This function does not alter the size of the
 *      array or any of the subscript values.
 *  $EXAMPLES$
 *      LOCAL array:= {"Harbour", "is", "Supreme", "Power"}
 *      ? ATAIL(aArray) // Result is "Power"
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      C
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      LEN(),ARRAY(),ASIZE(),AADD()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      AINS()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Insert a NIL value at an array subscript position.
 *  $SYNTAX$
 *      AINS( <aArray>, <nPos> ) --> aTarget
 *  $ARGUMENTS$
 *      <aArray> Array name.
 *
 *      <nPos> Subscript position in <aArray>
 *  $RETURNS$
 *      <aTarget> an array pointer reference.
 *  $DESCRIPTION$
 *      This function inserts a NIL value in the array named <aArray>
 *      at the <nPos>th position.
 *
 *      All array elements starting with the <nPos>th position will be
 *      shifted down one subscript position in the array list and the
 *      last item in the array will be removed completely. In other words,
 *      if an array element were to be inserted at the fifth subscript
 *      position, the element previously in the fifth position would now
 *      be located at the sixth position. The length of the array <aArray>
 *      will remain unchanged.
 *  $EXAMPLES$
 *      LOCAL aArray:={"Harbour","is","Power!","!!!"}
 *      AINS(aArray,4)
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      C
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      AADD(),ACOPY(),ADEL(),AEVAL(),AFILL(),ASIZE()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      ADEL()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Delete an element form an array.
 *  $SYNTAX$
 *      ADEL(<aArray>, <nPos>) --> aTarget
 *  $ARGUMENTS$
 *      <aArray> Name of array from which an element is to be removed.
 *
 *      <nPos>   Subscript of the element to be removed.
 *  $RETURNS$
 *      <aTarget> an array pointer reference.
 *  $DESCRIPTION$
 *      This function deletes the element found at <nPos> subscript position
 *      in the array <aArray>. All elements in the array <aArray> below the
 *      given subscript position <nPos> will move up one position in the
 *      array. In other words, what was formerly the sixth subscript position
 *      will become the fifth subscript position. The length of the array
 *      <aArray> will remain unchanged,as the last element in the array will
 *      become a NIL data type.
 *  $EXAMPLES$
 *     LOCAL aArray
 *      aArray := {"Harbour", "is", "Power"}
 *
 *      ADEL(aArray, 2) // Result: aArray is {"Harbour", "Power"}
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      C
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      ACOPY(),AINS(),AFILL()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      AFILL()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Fill an array with a specified value
 *  $SYNTAX$
 *      AFILL( <aArray>, <xValue>, [<nStart>], [<nCount>] ) --> aTarget
 *  $ARGUMENTS$
 *      <aArray> Name of array to be filled.
 *
 *      <xValue> Expression to be globally filled in <aArray>
 *
 *      <nStart> Subscript starting position
 *
 *      <nCount> Number of subscript to be filled
 *  $RETURNS$
 *      <aTarget> an array pointer.
 *  $DESCRIPTION$
 *      This function will fill each element of an array named <aArray> with
 *      the value <xValue>. If specified, <nStart> denotes the beginning
 *      element to be filled and the array elements will continue to be
 *      filled for <nCount> positions. If Not specified, the value of
 *      <nStart> will be 1, and the value of <nCount> will be the value
 *      of LEN(<aArray>); thus, all subscript positions in the array
 *      <aArray> will be filled with the value of <xValue>.
 *
 *      This function will work on only a single dimension of <aArray>.
 *      If there are array pointer references within a subscript <aArray>,
 *      those values will be lost, since this function will overwrite those
 *      values with new values.
 *  $EXAMPLES$
 *      LOCAL aTest:={Nil,0,1,2}
 *      Afill(aTest,5)
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      C
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      AADD(),AEVAL(),DBSTRUCT(),DIRECTORY()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      ASCAN()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Scan array elements for a specified condition
 *  $SYNTAX$
 *      ASCAN( <aTarget>, <xSearch>, [<nStart>], [<nCount>] ) --> nStoppedAt
 *  $ARGUMENTS$
 *      <aTarget>   Array to be scanned.
 *
 *      <xSearch>   Expression to search for in <aTarget>
 *
 *      <nStart>    Beginning subscript position at which to start the search.
 *
 *      <nCount>    Number of elements to scan with <aTarget>.
 *  $RETURNS$
 *      <nStoppedAt> A numeric value of subscript position where <xSearch>
 *      was found, or 0 if <xSearch> is not found.
 *  $DESCRIPTION$
 *      This function scan the content of array named <aTarget> for the
 *      value of <xSearch>. The return value is the position in the array
 *      <aTarget> in which <xSearch> was found. If it was not found, the
 *      return value will be 0.
 *
 *      If specified, the beginning subscript position at which to start
 *      scanning may be set with the value passed as <nStart>. The default
 *      is 1.
 *
 *      If specified, the number of array elements to scan may be set with
 *      the value passed as <nCount>. The default is the number of elements
 *      in the array <aTarget>.
 *
 *      If <xSearch> is a code block, the operation of the function is
 *      slightly different. Each array subscript pointer reference is
 *      passed to the code block to be evaluated. The scanning routine
 *      will continue until the value obtained from the code block is a
 *      logical true (.T.) or until the end of the array has been reached.
 *  $EXAMPLES$
 *      aDir:=Directory("*.prg")
 *      AScan(aDir,,,{|x,y| x[1]="Test.prg"})
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      This function is not CA-Cl*pper compatible.  CA-Cl*pper ASCAN() is affected by the SET EXACT ON/OFF Condition
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      AEVAL()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      AEVAL()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Evaluates the subscript element of an array
 *  $SYNTAX$
 *      AEVAL(<aArray>, <bBlock>, [<nStart>], [<nCount>]) --> aArray
 *  $ARGUMENTS$
 *      <aArray> Is the array to be evaluated.
 *
 *      <bBlock> Is a code block to evaluate for each element processed.
 *
 *      <nStart> The beginning array element index to evaluate.
 *
 *      <nCount> The number of elements to process.
 *  $RETURNS$
 *      <aArray> an array pointer reference.
 *  $DESCRIPTION$
 *      This function will evaluate and process the subscript elements
 *      in <aArray>. A code block passed as <bBlock> defines the operation
 *      to be executed on each element of the array. All elements in <aArray>
 *      will be evaluated unless specified by a beginning subscript position
 *      in <nStart> for <nCount> elements.
 *
 *      Two parameters are passed to the code block <bBlock>. The individual
 *      elements in an array are the first parameter and the subscript position
 *      is the second.
 *
 *      AEVAL() does not replace a FOR...NEXT loop for processing arrays. If
 *      an array is an autonomous unit, AEVAL() is appropriate. If the array
 *      is to be altered or if elements are to be reevaluated, a FOR...NEXT
 *      loop is more appropriate.
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      C
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      EVAL(),DBEVAL()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      ACOPY()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Copy elements from one array to another
 *  $SYNTAX$
 *      ACOPY( <aSource>, <aTarget>, [<nStart>], [<nCount>], [<nTargetPos>] ) --> aTarget
 *  $ARGUMENTS$
 *      <aSource> is the array to copy elements from.
 *
 *      <aTarget> is the array to copy elements to.
 *
 *      <nStart>  is the beginning subscript position to copy from <aSource>
 *
 *      <nCount>  the number of subscript elements to copy from <aSource>.
 *
 *      <nTargetPos> the starting subscript position in <aTarget> to copy
 *      elements to.
 *  $RETURNS$
 *      <aTarget> an array pointer reference
 *  $DESCRIPTION$
 *      This function copies array elements from <aSource> to <aTarget>.
 *
 *      <nStart> is the beginning element to be copied from <aSource>;
 *      the default is 1.
 *
 *      <nCount> is the number of elements to be copied from <aSource>;
 *      the default is the entire array.
 *
 *      <nTargetPos> is the subscript number in the target array,<aTarget>,
 *       to which array elements are to be copied; the default is 1
 *
 *      This function will copy all data types in <aSource> to <aTarget>.
 *
 *      If an array element in <aSource> is a pointer reference to another
 *      array, that array pointer will be copied to <aTarget>; not all
 *      subdimensions will be copied from one array to the next. This must
 *      be accomplished via the ACLONE() function.
 *
 *      Note:
 *      If array <aSource> is larger then <aTarget>, array elements will
 *      start copying at <nTargetPos> and continue copying until the end
 *      of array <aTarget> is reached. The ACOPY() function doesn't append
 *      subscript positions to the target array, the size of the target
 *      array <aTarget> remains constant.
 *  $EXAMPLES$
 *      LOCAL nCount := 2, nStart := 1, aOne, aTwo
 *      aOne := {"HARBOUR"," is ","POWER"}
 *      aTwo := {"CLIPPER"," was ","POWER"}
 *      ACOPY(aOne, aTwo, nStart, nCount)
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      C
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      ACLONE(),ADEL(),AEVAL(),AFILL(),AINS(),ASORT()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      ACLONE()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Duplicate a  multidimensional array
 *  $SYNTAX$
 *      ACLONE(<aSource>) --> aDuplicate
 *  $ARGUMENTS$
 *      <aSource> Name of the array to be cloned.
 *  $RETURNS$
 *      <aDuplicate> A new array pointer reference complete with nested
 *      array values.
 *  $DESCRIPTION$
 *      This function makes a complete copy of the array expressed as
 *      <aSource> and return a cloned set of array values. This provides
 *      a complete set of arrays values for all dimensions within the
 *      original array <aSource>
 *  $EXAMPLES$
 *      LOCAL aOne, aTwo
 *      aOne := {"Harbour"," is ","POWER"}
 *      aTwo := ACLONE(aOne)       // Result: aTwo is {"Harbour"," is ","POWER"}
 *      aOne[1] := "The Harbour Compiler"
 *      // Result:
 *      // aOne is {"The Harbour Compiler"," is ","POWER"}
 *      // aTwo is {"Harbour"," is ","POWER"}
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *       CA-Cl*pper will return NIL if the parameter is not an array.
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      ACOPY(),ADEL(),AINS(),ASIZE()
 *  $END$
 */

/*  $DOC$
 *  $TEMPLATE$
 *      Function
 *  $NAME$
 *      ASORT()
 *  $CATEGORY$
 *      API
 *  $SUBCATEGORY$
 *      Array
 *  $ONELINER$
 *      Sort an array
 *  $SYNTAX$
 *      ASORT( <aArray>, [<nStart>], [<nCount>], [<bSort>] ) --> aArray
 *  $ARGUMENTS$
 *      <aArray> Array to be sorted.
 *
 *      <nStart> The first element to start the sort from, default is 1.
 *
 *      <nCount> Number of elements starting from <nStart> to sort, default
 *      is all elements.
 *
 *      <bSort> Code block for sorting order, default is ascending order
 *      {| x, y | x < y }. The code block should accept two parameters and
 *      must return .T. if the sort is in order, .F. if not.
 *  $RETURNS$
 *      <aArray> reference to the now sorted <aArray> or NIL if the
 *      passed <aArray> is not an array.
 *  $DESCRIPTION$
 *      ASORT() sort all or part of a given array. If <bSort> is omitted,
 *      the function expect <aArray> to be one dimensional array containing
 *      single data type (one of: Character, Date, Logical, Numeric) and sort
 *      this array in ascending order: Character are sorted by their ASCII
 *      value, Dates are sorted chronologically, Logical put .F. values before
 *      .T., Numeric are sorted by their value.
 *
 *      If <bSort> is specified, it is used to handle the sorting order. With
 *      each time the block is evaluate, two array elements are passed to the
 *      code block, and <bSort> must return a logical value that state if
 *      those elements are in order (.T.) or not (.F.). Using this block you
 *      can sort multidimensional array, descending orders or even (but why
 *      would you want to do that) sort array that contain different data
 *      type.
 *  $EXAMPLES$
 *      // sort numeric values in ascending order
 *      ASORT( { 3, 1, 4, 42, 5, 9 } )     // result: { 1, 3, 4, 5, 9, 42 }
 *
 *      // sort character strings in descending lexical order
 *      aKeys := { "Ctrl", "Alt", "Delete" }
 *      bSort := {| x, y | UPPER( x ) > UPPER( y ) }
 *      ASORT( aKeys,,, bSort )      // result: { "Delete", "Ctrl", "Alt" }
 *
 *      // sort two-dimensional array according to 2nd element of each pair
 *      aPair :=   { {"Sun",8}, {"Mon",1}, {"Tue",57}, {"Wed",-6} }
 *      ASORT( aPair,,, {| x, y | x[2] < y[2] } )
 *      // result: { {"Wed",-6}, {"Mon",1}, {"Sun",8}, {"Tue",57} }
 *  $STATUS$
 *      R
 *  $COMPLIANCE$
 *      C(arrayblock)
 *  $FILES$
 *      Library is vm
 *  $SEEALSO$
 *      ASCAN(),EVAL(),SORT
 *  $END$
 */
