[Runtime] ArrayBase:GetEnumerator() now enumerates a copy to prevent errors when the original collection gets changed by the code inside the enumerator

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//
USING System.Collections
USING System.Collections.Generic
USING System.Linq
USING System.Diagnostics
USING System.Reflection
USING XSharp
BEGIN NAMESPACE XSharp
	/// Internal type that implements the new TYPED ARRAY type.

	/// This type has methods and properties that normally are never directly called from user code.
	///
    /// <typeparam name="T">Type of the elements inside the array </typeparam>
	PUBLIC CLASS __ArrayBase<T> IMPLEMENTS INamedIndexer, IEnumerable<T> WHERE T IS NEW()
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
		PROTECTED INTERNAL _internalList AS List<T>
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
		PRIVATE _islocked AS LOGIC
		#region constructors
		/// Create an empty array
		CONSTRUCTOR()
			_internalList := List<T>{}
			RETURN

		/// Create an array with a certain capacity.
		CONSTRUCTOR(capacity AS DWORD)
			_internalList := List<T>{ (INT) capacity}
			//_internalList:AddRange(Enumerable.Repeat(DEFAULT(T),(INT) capacity))
			RETURN

		/// Create an array with a certain capacity and specify if it should be filled with default values.
		CONSTRUCTOR(capacity AS DWORD, fill AS LOGIC)
			_internalList := List<T>{ (INT) capacity}
			IF fill
				_internalList:AddRange(Enumerable.Repeat(SELF:DefaultValue,(INT) capacity))
			ENDIF
			RETURN

		/// Create an array and fill it with elements from an existing collection.
		CONSTRUCTOR( collection AS IEnumerable<T>)
			_internalList := List<T>{collection}
			RETURN

		/// Create an array and fill it with elements from an existing .Net array of objects. Note that the objects must be of the right type.
		CONSTRUCTOR( elements AS OBJECT[] )
			SELF()
			IF elements == NULL
				THROW Error{ArgumentNullException{NAMEOF(elements)}}
			ENDIF
			FOREACH element AS OBJECT IN elements
				IF element == NULL
					_internalList:Add(SELF:DefaultValue)
				ELSEIF element IS T
					_internalList:Add( (T) element)
				ELSE
					THROW Error{ArgumentException{"Object array contains element of incorrect type "+element:GetType():FullName}}
				ENDIF
			NEXT
			RETURN

		/// Create an array and fill it with elements from an existing .Net array.
		CONSTRUCTOR( elements AS T[] )
			_internalList := List<T>{elements}
			RETURN
			#endregion

		#region properties
		/// Is the array empty.
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
		PUBLIC PROPERTY IsEmpty AS LOGIC GET _internalList:Count == 0
		/// Length of the array.
		PUBLIC PROPERTY Length AS DWORD GET (DWORD) _internalList:Count
        /// Length of the array as integer.
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        PUBLIC PROPERTY Count AS INT GET _internalList:Count

        /// Returns the default value for array elements when arrays are resized or initialized.
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        PUBLIC VIRTUAL PROPERTY DefaultValue AS T GET T{}
		#endregion

		#region Enumerators
		PUBLIC METHOD IEnumerable<T>.GetEnumerator() AS IEnumerator<T>
            RETURN ((IList<T> ) _internalList:ToArray()):GetEnumerator()

		PUBLIC METHOD IEnumerable.GetEnumerator() AS IEnumerator
			RETURN _internalList:ToArray():GetEnumerator()

			#endregion

		#region Cloning

		INTERNAL METHOD Clone() AS __ArrayBase<T>
			LOCAL aResult AS __ArrayBase<T>
			LOCAL nCount AS DWORD
			nCount := (DWORD) _internalList:Count
			aResult := (__ArrayBase<T>) Activator.CreateInstance(SELF:GetType(), NULL)
			aResult:Resize( _internalList:Count )
		    // warning, nCount-1 below will become MAXDWORD for nCount == 0
			IF nCount == 0
				RETURN aResult
            ENDIF
			FOR VAR i := 0 TO nCount-1
				aResult:_internalList[i] := _internalList[i]
			NEXT
			RETURN aResult

			#endregion

		#region Indexers and TO GET / SET Elements.
	    /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <returns>The element stored at the specified location in the array.</returns>
        PUBLIC METHOD __GetElement(index AS INT) AS T
			RETURN SELF:_internalList[ index ]

	    /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name='e'>New element to store in the array at the position specified</param>
        /// <returns>The new element</returns>
		PUBLIC METHOD __SetElement(e AS T,index AS INT) AS T
			IF SELF:CheckLock()
				_internalList[index]:=e
			ENDIF
			RETURN e

		PRIVATE METHOD __GetProperty(sName AS STRING) AS PropertyInfo
			LOCAL type AS System.Type
			LOCAL oProp AS PropertyInfo
			type := TYPEOF(T)
			oProp := type:GetProperty(sName, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public)
			IF oProp == NULL_OBJECT
				THROW Error{ArgumentException{"Unknown property: "+sName}}
			ENDIF
			RETURN oProp

		PRIVATE METHOD __GetIndexer(lNumeric AS LOGIC) AS PropertyInfo
			LOCAL type AS System.Type
			LOCAL aProps AS PropertyInfo[]
			type := TYPEOF(T)
			aProps := type:GetProperties(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public)
            FOREACH oProp AS PropertyInfo IN aProps
                IF !oProp:Name:ToLower() == "item"
                    LOOP
                ENDIF
                LOCAL pars := oProp:GetIndexParameters() AS ParameterInfo[]
                IF pars:Length > 0
                    LOCAL par := pars[__ARRAYBASE__] AS ParameterInfo
                    SWITCH Type.GetTypeCode(par:ParameterType)
                    CASE TypeCode.Int32
                    CASE TypeCode.Int64
                    CASE TypeCode.UInt32
                    CASE TypeCode.UInt64
                        IF (lNumeric)
                            RETURN oProp
                        ENDIF
                    CASE TypeCode.String
                        IF (!lNumeric)
                            RETURN oProp
                        ENDIF
                    END SWITCH
                ENDIF

            NEXT
			RETURN NULL

		/// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
		/// <returns>The element stored at the indicated location in the collection.</returns>
		PUBLIC PROPERTY SELF[index AS INT] AS T
			GET
				IF  index > _internalList:Count-1
					THROW Error{ArgumentOutOfRangeException{nameof(index)}}
				ENDIF
				RETURN _internalList[index ]
			END GET
			SET
				IF SELF:CheckLock()
					IF index > _internalList:Count-1
						THROW Error{ArgumentOutOfRangeException{nameof(index)}}
					ENDIF
					_internalList[index] := value
				ENDIF
			END SET
		END PROPERTY

        /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
        /// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name="index2"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <returns>The value of the property of the element stored at the indicated location in the array.</returns>
		PUBLIC PROPERTY SELF[index AS INT, index2 AS INT] AS USUAL
			GET
				LOCAL oElement AS T
				IF  index > _internalList:Count-1
					THROW Error{ArgumentOutOfRangeException{nameof(index)}}
                ENDIF
				oElement := _internalList[index ]
                IF oElement IS IIndexedProperties
                    VAR oIndex := (IIndexedProperties) oElement
                    RETURN oIndex[index2]
                ENDIF
				LOCAL oProp    AS PropertyInfo
                oProp    := __GetIndexer(TRUE)
                IF oProp != NULL
                    RETURN oProp:GetValue(oElement, <OBJECT>{index2})
                ENDIF
                THROW Error{ArgumentException{"Indexed property missing for type: "+oElement:GetType():FullName}}
			END GET
			SET
				IF  index > _internalList:Count-1
					THROW Error{ArgumentOutOfRangeException{nameof(index)}}
				ENDIF
				IF SELF:CheckLock()
					LOCAL oElement AS T
				    oElement := _internalList[index ]
                    IF oElement IS IIndexedProperties
                        VAR oIndex := (IIndexedProperties) oElement
                        oIndex[index2] := value
                    ENDIF
					LOCAL oProp    AS PropertyInfo
                    oProp    := __GetIndexer(TRUE)
                    IF oProp != NULL
                        oProp:SetValue(oElement, OOPHelpers.VOConvert(value, oProp:PropertyType), <OBJECT>{index2} )
                        RETURN
                    ENDIF
                    THROW Error{ArgumentException{"Indexed property missing for type: "+oElement:GetType():FullName}}
				ENDIF
			END SET
		END PROPERTY

		/// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name="name"><include file="RTComments.xml" path="Comments/NameBasedIndexParam/*" /></param>
		/// <returns>The value of the property of the element stored at the indicated location in the array.</returns>
		PUBLIC PROPERTY SELF[index AS INT, name AS STRING] AS USUAL
			GET
				LOCAL oElement AS T
				IF  index > _internalList:Count-1
					THROW Error{ArgumentOutOfRangeException{}}
                ENDIF
				oElement := _internalList[index ]
                IF oElement IS IIndexedProperties
                    VAR oIndex := (IIndexedProperties) oElement
                    RETURN oIndex[name]
                ENDIF
				LOCAL oProp    AS PropertyInfo
                oProp    := __GetIndexer(FALSE)
                IF oProp != NULL
                    RETURN oProp:GetValue(oElement, <OBJECT>{name})
                ENDIF
				oProp	 := __GetProperty( name)
				RETURN oProp:GetValue(oElement, NULL)
			END GET
			SET
				IF  index > _internalList:Count-1
					THROW Error{ArgumentOutOfRangeException{}}
				ENDIF
				IF SELF:CheckLock()
					LOCAL oElement AS T
				    oElement := _internalList[index ]
                    IF oElement IS IIndexedProperties
                        VAR oIndex := (IIndexedProperties) oElement
                        oIndex[name] := value
                    ENDIF
					LOCAL oProp    AS PropertyInfo
                    oProp    := __GetIndexer(FALSE)
                    IF oProp != NULL
                        oProp:SetValue(oElement, OOPHelpers.VOConvert(value, oProp:PropertyType), <OBJECT>{name} )
                        RETURN
                    ENDIF
					oProp	 := __GetProperty( name)
					oProp:SetValue(oElement, NULL, value)
				ENDIF
			END SET
		END PROPERTY

		#endregion

		#region Insert and Delete elements
        /// <exclude />
		PUBLIC VIRTUAL METHOD Add(u AS T) AS VOID
			IF SELF:CheckLock()
				_internalList:Add(u)
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC METHOD Delete(position AS INT) AS __ArrayBase<T>
			SELF:RemoveAt(position)
			SELF:Add(SELF:DefaultValue)
			RETURN SELF

        /// <exclude />
		PUBLIC METHOD Insert(index AS INT,u AS T) AS VOID
			IF SELF:CheckLock()
				_internalList:RemoveAt(_internalList:Count - 1)
				_internalList:Insert((INT) index-__ARRAYBASE__ ,u)
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC METHOD Insert(position AS INT) AS __ArrayBase<T>
			SELF:Insert( position, SELF:DefaultValue)
			RETURN SELF

        /// <exclude />
		PUBLIC METHOD RemoveAt(index AS INT) AS VOID
			IF SELF:CheckLock()
				_internalList:RemoveRange(index-__ARRAYBASE__,1 )
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC VIRTUAL METHOD Resize(newSize AS INT) AS VOID
			IF SELF:CheckLock()
				IF newSize == 0
					_internalList:Clear()
				ELSE
					LOCAL count := _internalList:Count AS INT
					IF newSize <= count
						_internalList:RemoveRange(newSize, count - newSize)
					ELSE
						count+=1
						DO WHILE count <= newSize
							_internalList:Add(SELF:DefaultValue)
							count++
						ENDDO
					ENDIF
				ENDIF
			ENDIF
			RETURN

			#endregion
        /// <inheritdoc />
		PUBLIC OVERRIDE METHOD ToString() AS STRING
			RETURN String.Format("[{0}]",_internalList:Count)

		INTERNAL METHOD Sort(startIndex AS INT, count AS INT, comparer AS IComparer<T>) AS VOID
            IF startIndex <= 0
                startIndex := 1
            ENDIF
            IF count < 0
                count := _internalList:Count - startIndex + __ARRAYBASE__
            ENDIF
			_internalList:Sort(startIndex-__ARRAYBASE__ ,count,comparer)
			RETURN

		INTERNAL METHOD Sort(comparer AS IComparer<T>) AS VOID
			_internalList:Sort(comparer)
			RETURN

		INTERNAL METHOD Swap(position AS INT, element AS T) AS T
			LOCAL original := _internalList[position - __ARRAYBASE__] AS T
			_internalList[ position - __ARRAYBASE__]:=element
			RETURN original

		INTERNAL METHOD Swap(position AS INT, element AS OBJECT) AS T
			//try
			VAR elementT := (T) (OBJECT) element
			RETURN Swap( position, elementT)
			//catch
			//	throw ArgumentException{"Parameter is of incorrect type "+element:GetType():FullName,nameof(element)}
			//end try

		INTERNAL METHOD Tail() AS T
			RETURN _internalList:LastOrDefault()

			#region locking
		INTERNAL METHOD Lock(lLocked AS LOGIC) AS LOGIC
			LOCAL wasLocked AS LOGIC
			wasLocked := SELF:_islocked
			SELF:_islocked := lLocked
			RETURN wasLocked
			/// Is the array locked?
		PROPERTY Locked AS LOGIC GET _islocked

		INTERNAL METHOD CheckLock AS LOGIC
			IF SELF:_islocked
				THROW Error{Gencode.EG_PROTECTION}
			ENDIF
			RETURN ! SELF:_islocked

			#endregion

		#region operators
		/// Implicitely convert an array of USUALs to a typed array. Note that the usuals must contain a value of the correct type.
		STATIC OPERATOR IMPLICIT ( a AS ARRAY) AS __ArrayBase<T>
			VAR aResult := __ArrayBase<T>{}
			LOCAL oErr AS Error
			FOREACH VAR u IN a
				LOCAL o := u AS OBJECT
				IF o IS T
					aResult:Add( (T) o)
				ELSE
					LOCAL nArg AS INT
					LOCAL oActType AS System.Type
					oActType := o:GetType()
					nArg := a:_internalList:IndexOf(u)+1
					oErr := Error{Gencode.EG_DATATYPE}
					oErr:Arg := "Array Element : "+nArg:ToString()
					oErr:Description := "Cannot convert array element " +nArg:ToString() + " from type "+oActType:ToString()+" to type "+TYPEOF(T):ToString()
					THROW oErr
				ENDIF
			NEXT
			RETURN aResult

		/// Implicitely convert a typed array to an array of USUALs.
		STATIC OPERATOR IMPLICIT ( a AS __ArrayBase<T> ) AS ARRAY
			VAR aResult := __Array{}
			FOREACH VAR o IN a
				aResult:Add(  o)
			NEXT
			RETURN aResult

        /// Implicitely convert a typed Array to an OBJECT[].
		STATIC OPERATOR IMPLICIT ( a AS __ArrayBase<T> ) AS OBJECT[]
			LOCAL aResult := List<OBJECT>{} AS List<OBJECT>
			FOREACH VAR o IN a
				aResult:Add( o)
			NEXT
			RETURN aResult:ToArray()

    #endregion

	END	CLASS
END NAMESPACE

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//
USING System.Collections
USING System.Collections.Generic
USING System.Linq
USING System.Diagnostics
USING System.Reflection
USING XSharp
BEGIN NAMESPACE XSharp
	/// Internal type that implements the new TYPED ARRAY type.

	/// This type has methods and properties that normally are never directly called from user code.
	///
    /// <typeparam name="T">Type of the elements inside the array </typeparam>
	PUBLIC CLASS __ArrayBase<T> IMPLEMENTS INamedIndexer, IEnumerable<T> WHERE T IS NEW()
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
		PROTECTED INTERNAL _internalList AS List<T>
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
		PRIVATE _islocked AS LOGIC
		#region constructors
		/// Create an empty array
		CONSTRUCTOR()
			_internalList := List<T>{}
			RETURN

		/// Create an array with a certain capacity.
		CONSTRUCTOR(capacity AS DWORD)
			_internalList := List<T>{ (INT) capacity}
			//_internalList:AddRange(Enumerable.Repeat(DEFAULT(T),(INT) capacity))
			RETURN

		/// Create an array with a certain capacity and specify if it should be filled with default values.
		CONSTRUCTOR(capacity AS DWORD, fill AS LOGIC)
			_internalList := List<T>{ (INT) capacity}
			IF fill
				_internalList:AddRange(Enumerable.Repeat(SELF:DefaultValue,(INT) capacity))
			ENDIF
			RETURN

		/// Create an array and fill it with elements from an existing collection.
		CONSTRUCTOR( collection AS IEnumerable<T>)
			_internalList := List<T>{collection}
			RETURN

		/// Create an array and fill it with elements from an existing .Net array of objects. Note that the objects must be of the right type.
		CONSTRUCTOR( elements AS OBJECT[] )
			SELF()
			IF elements == NULL
				THROW Error{ArgumentNullException{NAMEOF(elements)}}
			ENDIF
			FOREACH element AS OBJECT IN elements
				IF element == NULL
					_internalList:Add(SELF:DefaultValue)
				ELSEIF element IS T
					_internalList:Add( (T) element)
				ELSE
					THROW Error{ArgumentException{"Object array contains element of incorrect type "+element:GetType():FullName}}
				ENDIF
			NEXT
			RETURN

		/// Create an array and fill it with elements from an existing .Net array.
		CONSTRUCTOR( elements AS T[] )
			_internalList := List<T>{elements}
			RETURN
			#endregion

		#region properties
		/// Is the array empty.
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
		PUBLIC PROPERTY IsEmpty AS LOGIC GET _internalList:Count == 0
		/// Length of the array.
		PUBLIC PROPERTY Length AS DWORD GET (DWORD) _internalList:Count
        /// Length of the array as integer.
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        PUBLIC PROPERTY Count AS INT GET _internalList:Count

        /// Returns the default value for array elements when arrays are resized or initialized.
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        PUBLIC VIRTUAL PROPERTY DefaultValue AS T GET T{}
		#endregion

		#region Enumerators
		PUBLIC METHOD IEnumerable<T>.GetEnumerator() AS IEnumerator<T>
			RETURN _internalList:GetEnumerator()

		PUBLIC METHOD IEnumerable.GetEnumerator() AS IEnumerator
			RETURN _internalList:GetEnumerator()

			#endregion

		#region Cloning

		INTERNAL METHOD Clone() AS __ArrayBase<T>
			LOCAL aResult AS __ArrayBase<T>
			LOCAL nCount AS DWORD
			nCount := (DWORD) _internalList:Count
			aResult := (__ArrayBase<T>) Activator.CreateInstance(SELF:GetType(), NULL)
			aResult:Resize( _internalList:Count )
		    // warning, nCount-1 below will become MAXDWORD for nCount == 0
			IF nCount == 0
				RETURN aResult
            ENDIF
			FOR VAR i := 0 TO nCount-1
				aResult:_internalList[i] := _internalList[i]
			NEXT
			RETURN aResult

			#endregion

		#region Indexers and TO GET / SET Elements.
	    /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <returns>The element stored at the specified location in the array.</returns>
        PUBLIC METHOD __GetElement(index AS INT) AS T
			RETURN SELF:_internalList[ index ]

	    /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name='e'>New element to store in the array at the position specified</param>
        /// <returns>The new element</returns>
		PUBLIC METHOD __SetElement(e AS T,index AS INT) AS T
			IF SELF:CheckLock()
				_internalList[index]:=e
			ENDIF
			RETURN e

		PRIVATE METHOD __GetProperty(sName AS STRING) AS PropertyInfo
			LOCAL type AS System.Type
			LOCAL oProp AS PropertyInfo
			type := TYPEOF(T)
			oProp := type:GetProperty(sName, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public)
			IF oProp == NULL_OBJECT
				THROW Error{ArgumentException{"Unknown property: "+sName}}
			ENDIF
			RETURN oProp

		PRIVATE METHOD __GetIndexer(lNumeric AS LOGIC) AS PropertyInfo
			LOCAL type AS System.Type
			LOCAL aProps AS PropertyInfo[]
			type := TYPEOF(T)
			aProps := type:GetProperties(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public)
            FOREACH oProp AS PropertyInfo IN aProps
                IF !oProp:Name:ToLower() == "item"
                    LOOP
                ENDIF
                LOCAL pars := oProp:GetIndexParameters() AS ParameterInfo[]
                IF pars:Length > 0
                    LOCAL par := pars[__ARRAYBASE__] AS ParameterInfo
                    SWITCH Type.GetTypeCode(par:ParameterType)
                    CASE TypeCode.Int32
                    CASE TypeCode.Int64
                    CASE TypeCode.UInt32
                    CASE TypeCode.UInt64
                        IF (lNumeric)
                            RETURN oProp
                        ENDIF
                    CASE TypeCode.String
                        IF (!lNumeric)
                            RETURN oProp
                        ENDIF
                    END SWITCH
                ENDIF

            NEXT
			RETURN NULL

		/// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
		/// <returns>The element stored at the indicated location in the collection.</returns>
		PUBLIC PROPERTY SELF[index AS INT] AS T
			GET
				IF  index > _internalList:Count-1
					THROW Error{ArgumentOutOfRangeException{nameof(index)}}
				ENDIF
				RETURN _internalList[index ]
			END GET
			SET
				IF SELF:CheckLock()
					IF index > _internalList:Count-1
						THROW Error{ArgumentOutOfRangeException{nameof(index)}}
					ENDIF
					_internalList[index] := value
				ENDIF
			END SET
		END PROPERTY

        /// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
        /// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name="index2"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <returns>The value of the property of the element stored at the indicated location in the array.</returns>
		PUBLIC PROPERTY SELF[index AS INT, index2 AS INT] AS USUAL
			GET
				LOCAL oElement AS T
				IF  index > _internalList:Count-1
					THROW Error{ArgumentOutOfRangeException{nameof(index)}}
                ENDIF
				oElement := _internalList[index ]
                IF oElement IS IIndexedProperties
                    VAR oIndex := (IIndexedProperties) oElement
                    RETURN oIndex[index2]
                ENDIF
				LOCAL oProp    AS PropertyInfo
                oProp    := __GetIndexer(TRUE)
                IF oProp != NULL
                    RETURN oProp:GetValue(oElement, <OBJECT>{index2})
                ENDIF
                THROW Error{ArgumentException{"Indexed property missing for type: "+oElement:GetType():FullName}}
			END GET
			SET
				IF  index > _internalList:Count-1
					THROW Error{ArgumentOutOfRangeException{nameof(index)}}
				ENDIF
				IF SELF:CheckLock()
					LOCAL oElement AS T
				    oElement := _internalList[index ]
                    IF oElement IS IIndexedProperties
                        VAR oIndex := (IIndexedProperties) oElement
                        oIndex[index2] := value
                    ENDIF
					LOCAL oProp    AS PropertyInfo
                    oProp    := __GetIndexer(TRUE)
                    IF oProp != NULL
                        oProp:SetValue(oElement, OOPHelpers.VOConvert(value, oProp:PropertyType), <OBJECT>{index2} )
                        RETURN
                    ENDIF
                    THROW Error{ArgumentException{"Indexed property missing for type: "+oElement:GetType():FullName}}
				ENDIF
			END SET
		END PROPERTY

		/// <include file="RTComments.xml" path="Comments/ZeroBasedIndexProperty/*" />
		/// <param name="index"><include file="RTComments.xml" path="Comments/ZeroBasedIndexParam/*" /></param>
        /// <param name="name"><include file="RTComments.xml" path="Comments/NameBasedIndexParam/*" /></param>
		/// <returns>The value of the property of the element stored at the indicated location in the array.</returns>
		PUBLIC PROPERTY SELF[index AS INT, name AS STRING] AS USUAL
			GET
				LOCAL oElement AS T
				IF  index > _internalList:Count-1
					THROW Error{ArgumentOutOfRangeException{}}
                ENDIF
				oElement := _internalList[index ]
                IF oElement IS IIndexedProperties
                    VAR oIndex := (IIndexedProperties) oElement
                    RETURN oIndex[name]
                ENDIF
				LOCAL oProp    AS PropertyInfo
                oProp    := __GetIndexer(FALSE)
                IF oProp != NULL
                    RETURN oProp:GetValue(oElement, <OBJECT>{name})
                ENDIF
				oProp	 := __GetProperty( name)
				RETURN oProp:GetValue(oElement, NULL)
			END GET
			SET
				IF  index > _internalList:Count-1
					THROW Error{ArgumentOutOfRangeException{}}
				ENDIF
				IF SELF:CheckLock()
					LOCAL oElement AS T
				    oElement := _internalList[index ]
                    IF oElement IS IIndexedProperties
                        VAR oIndex := (IIndexedProperties) oElement
                        oIndex[name] := value
                    ENDIF
					LOCAL oProp    AS PropertyInfo
                    oProp    := __GetIndexer(FALSE)
                    IF oProp != NULL
                        oProp:SetValue(oElement, OOPHelpers.VOConvert(value, oProp:PropertyType), <OBJECT>{name} )
                        RETURN
                    ENDIF
					oProp	 := __GetProperty( name)
					oProp:SetValue(oElement, NULL, value)
				ENDIF
			END SET
		END PROPERTY

		#endregion

		#region Insert and Delete elements
        /// <exclude />
		PUBLIC VIRTUAL METHOD Add(u AS T) AS VOID
			IF SELF:CheckLock()
				_internalList:Add(u)
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC METHOD Delete(position AS INT) AS __ArrayBase<T>
			SELF:RemoveAt(position)
			SELF:Add(SELF:DefaultValue)
			RETURN SELF

        /// <exclude />
		PUBLIC METHOD Insert(index AS INT,u AS T) AS VOID
			IF SELF:CheckLock()
				_internalList:RemoveAt(_internalList:Count - 1)
				_internalList:Insert((INT) index-__ARRAYBASE__ ,u)
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC METHOD Insert(position AS INT) AS __ArrayBase<T>
			SELF:Insert( position, SELF:DefaultValue)
			RETURN SELF

        /// <exclude />
		PUBLIC METHOD RemoveAt(index AS INT) AS VOID
			IF SELF:CheckLock()
				_internalList:RemoveRange(index-__ARRAYBASE__,1 )
			ENDIF
			RETURN

        /// <exclude />
		PUBLIC VIRTUAL METHOD Resize(newSize AS INT) AS VOID
			IF SELF:CheckLock()
				IF newSize == 0
					_internalList:Clear()
				ELSE
					LOCAL count := _internalList:Count AS INT
					IF newSize <= count
						_internalList:RemoveRange(newSize, count - newSize)
					ELSE
						count+=1
						DO WHILE count <= newSize
							_internalList:Add(SELF:DefaultValue)
							count++
						ENDDO
					ENDIF
				ENDIF
			ENDIF
			RETURN

			#endregion
        /// <inheritdoc />
		PUBLIC OVERRIDE METHOD ToString() AS STRING
			RETURN String.Format("[{0}]",_internalList:Count)

		INTERNAL METHOD Sort(startIndex AS INT, count AS INT, comparer AS IComparer<T>) AS VOID
            IF startIndex <= 0
                startIndex := 1
            ENDIF
            IF count < 0
                count := _internalList:Count - startIndex + __ARRAYBASE__
            ENDIF
			_internalList:Sort(startIndex-__ARRAYBASE__ ,count,comparer)
			RETURN

		INTERNAL METHOD Sort(comparer AS IComparer<T>) AS VOID
			_internalList:Sort(comparer)
			RETURN

		INTERNAL METHOD Swap(position AS INT, element AS T) AS T
			LOCAL original := _internalList[position - __ARRAYBASE__] AS T
			_internalList[ position - __ARRAYBASE__]:=element
			RETURN original

		INTERNAL METHOD Swap(position AS INT, element AS OBJECT) AS T
			//try
			VAR elementT := (T) (OBJECT) element
			RETURN Swap( position, elementT)
			//catch
			//	throw ArgumentException{"Parameter is of incorrect type "+element:GetType():FullName,nameof(element)}
			//end try

		INTERNAL METHOD Tail() AS T
			RETURN _internalList:LastOrDefault()

			#region locking
		INTERNAL METHOD Lock(lLocked AS LOGIC) AS LOGIC
			LOCAL wasLocked AS LOGIC
			wasLocked := SELF:_islocked
			SELF:_islocked := lLocked
			RETURN wasLocked
			/// Is the array locked?
		PROPERTY Locked AS LOGIC GET _islocked

		INTERNAL METHOD CheckLock AS LOGIC
			IF SELF:_islocked
				THROW Error{Gencode.EG_PROTECTION}
			ENDIF
			RETURN ! SELF:_islocked

			#endregion

		#region operators
		/// Implicitely convert an array of USUALs to a typed array. Note that the usuals must contain a value of the correct type.
		STATIC OPERATOR IMPLICIT ( a AS ARRAY) AS __ArrayBase<T>
			VAR aResult := __ArrayBase<T>{}
			LOCAL oErr AS Error
			FOREACH VAR u IN a
				LOCAL o := u AS OBJECT
				IF o IS T
					aResult:Add( (T) o)
				ELSE
					LOCAL nArg AS INT
					LOCAL oActType AS System.Type
					oActType := o:GetType()
					nArg := a:_internalList:IndexOf(u)+1
					oErr := Error{Gencode.EG_DATATYPE}
					oErr:Arg := "Array Element : "+nArg:ToString()
					oErr:Description := "Cannot convert array element " +nArg:ToString() + " from type "+oActType:ToString()+" to type "+TYPEOF(T):ToString()
					THROW oErr
				ENDIF
			NEXT
			RETURN aResult

		/// Implicitely convert a typed array to an array of USUALs.
		STATIC OPERATOR IMPLICIT ( a AS __ArrayBase<T> ) AS ARRAY
			VAR aResult := __Array{}
			FOREACH VAR o IN a
				aResult:Add(  o)
			NEXT
			RETURN aResult

        /// Implicitely convert a typed Array to an OBJECT[].
		STATIC OPERATOR IMPLICIT ( a AS __ArrayBase<T> ) AS OBJECT[]
			LOCAL aResult := List<OBJECT>{} AS List<OBJECT>
			FOREACH VAR o IN a
				aResult:Add( o)
			NEXT
			RETURN aResult:ToArray()

    #endregion

	END	CLASS
END NAMESPACE


codegen/QtX11Extras: updated

codegen/QtX11Extras: updated

Modified:
codegen/QtX11Extras/QX11Info.prg

%%
%% Qt5xHb - Bindings libraries for Harbour/xHarbour and Qt Framework 5
%%
%% Copyright (C) 2018 Marcos Antonio Gambeta <marcosgambeta AT outlook DOT com>
%%

$header

#include "hbclass.ch"

$addRequests

$beginClass

   METHOD delete
   METHOD isPlatformX11
   METHOD appDpiX
   METHOD appDpiY
   METHOD appRootWindow
   METHOD appScreen
   METHOD appTime
   METHOD appUserTime
   METHOD setAppTime
   METHOD setAppUserTime
   METHOD getTimestamp
   METHOD display
   METHOD connection
   METHOD nextStartupId
   METHOD setNextStartupId

$endClass

$destructor

#pragma BEGINDUMP

$includes=5,1,0

$deleteMethod=5,1,0

$prototype=static bool isPlatformX11()
HB_FUNC_STATIC( QX11INFO_ISPLATFORMX11 )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  RBOOL( QX11Info::isPlatformX11 () );
#endif
}

$prototype=static int appDpiX(int screen=-1)
HB_FUNC_STATIC( QX11INFO_APPDPIX )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  RINT( QX11Info::appDpiX ( OPINT(1,-1) ) );
#endif
}

$prototype=static int appDpiY(int screen=-1)
HB_FUNC_STATIC( QX11INFO_APPDPIY )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  RINT( QX11Info::appDpiY ( OPINT(1,-1) ) );
#endif
}

$prototype=static unsigned long appRootWindow(int screen=-1)
HB_FUNC_STATIC( QX11INFO_APPROOTWINDOW )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retnl( QX11Info::appRootWindow ( OPINT(1,-1) ) );
#endif
}

$prototype=static int appScreen()
HB_FUNC_STATIC( QX11INFO_APPSCREEN )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  RINT( QX11Info::appScreen () );
#endif
}

$prototype=static unsigned long appTime()
HB_FUNC_STATIC( QX11INFO_APPTIME )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retnl( QX11Info::appTime () );
#endif
}

$prototype=static unsigned long appUserTime()
HB_FUNC_STATIC( QX11INFO_APPUSERTIME )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retnl( QX11Info::appUserTime () );
#endif
}

$prototype=static void setAppTime(unsigned long time)
HB_FUNC_STATIC( QX11INFO_SETAPPTIME )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  unsigned long par1 = hb_parnl(1);
  QX11Info::setAppTime ( par1 );
  hb_itemReturn( hb_stackSelfItem() );
#endif
}

$prototype=static void setAppUserTime(unsigned long time)
HB_FUNC_STATIC( QX11INFO_SETAPPUSERTIME )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  unsigned long par1 = hb_parnl(1);
  QX11Info::setAppUserTime ( par1 );
  hb_itemReturn( hb_stackSelfItem() );
#endif
}

$prototype=static unsigned long getTimestamp()
HB_FUNC_STATIC( QX11INFO_GETTIMESTAMP )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retnl( QX11Info::getTimestamp () );
#endif
}

$prototype=static Display *display()
HB_FUNC_STATIC( QX11INFO_DISPLAY )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retptr( (Display *) QX11Info::display () );
#endif
}

$prototype=static xcb_connection_t *connection()
HB_FUNC_STATIC( QX11INFO_CONNECTION )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retptr( (xcb_connection_t *) QX11Info::connection () );
#endif
}

$prototype=static QByteArray nextStartupId()
HB_FUNC_STATIC( QX11INFO_NEXTSTARTUPID )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  QByteArray * ptr = new QByteArray( QX11Info::nextStartupId () );
  _qt5xhb_createReturnClass ( ptr, "QBYTEARRAY" );
#endif
}

$prototype=static void setNextStartupId(const QByteArray &id)
HB_FUNC_STATIC( QX11INFO_SETNEXTSTARTUPID )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  QX11Info::setNextStartupId ( *PQBYTEARRAY(1) );
  hb_itemReturn( hb_stackSelfItem() );
#endif
}

$extraMethods

#pragma ENDDUMP

%%
%% Qt5xHb - Bindings libraries for Harbour/xHarbour and Qt Framework 5
%%
%% Copyright (C) 2018 Marcos Antonio Gambeta <marcosgambeta AT outlook DOT com>
%%

$header

#include "hbclass.ch"

#ifndef QT5XHB_NO_REQUESTS
REQUEST QBYTEARRAY
#endif

$beginClass

   METHOD delete
   METHOD isPlatformX11
   METHOD appDpiX
   METHOD appDpiY
   METHOD appRootWindow
   METHOD appScreen
   METHOD appTime
   METHOD appUserTime
   METHOD setAppTime
   METHOD setAppUserTime
   METHOD getTimestamp
   METHOD display
   METHOD connection
   METHOD nextStartupId
   METHOD setNextStartupId

$endClass

$destructor

#pragma BEGINDUMP

$includes=5,1,0

$deleteMethod=5,1,0

$prototype=static bool isPlatformX11()
HB_FUNC_STATIC( QX11INFO_ISPLATFORMX11 )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  RBOOL( QX11Info::isPlatformX11 () );
#endif
}

$prototype=static int appDpiX(int screen=-1)
HB_FUNC_STATIC( QX11INFO_APPDPIX )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  RINT( QX11Info::appDpiX ( OPINT(1,-1) ) );
#endif
}

$prototype=static int appDpiY(int screen=-1)
HB_FUNC_STATIC( QX11INFO_APPDPIY )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  RINT( QX11Info::appDpiY ( OPINT(1,-1) ) );
#endif
}

$prototype=static unsigned long appRootWindow(int screen=-1)
HB_FUNC_STATIC( QX11INFO_APPROOTWINDOW )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retnl( QX11Info::appRootWindow ( OPINT(1,-1) ) );
#endif
}

$prototype=static int appScreen()
HB_FUNC_STATIC( QX11INFO_APPSCREEN )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  RINT( QX11Info::appScreen () );
#endif
}

$prototype=static unsigned long appTime()
HB_FUNC_STATIC( QX11INFO_APPTIME )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retnl( QX11Info::appTime () );
#endif
}

$prototype=static unsigned long appUserTime()
HB_FUNC_STATIC( QX11INFO_APPUSERTIME )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retnl( QX11Info::appUserTime () );
#endif
}

$prototype=static void setAppTime(unsigned long time)
HB_FUNC_STATIC( QX11INFO_SETAPPTIME )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  unsigned long par1 = hb_parnl(1);
  QX11Info::setAppTime ( par1 );
  hb_itemReturn( hb_stackSelfItem() );
#endif
}

$prototype=static void setAppUserTime(unsigned long time)
HB_FUNC_STATIC( QX11INFO_SETAPPUSERTIME )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  unsigned long par1 = hb_parnl(1);
  QX11Info::setAppUserTime ( par1 );
  hb_itemReturn( hb_stackSelfItem() );
#endif
}

$prototype=static unsigned long getTimestamp()
HB_FUNC_STATIC( QX11INFO_GETTIMESTAMP )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retnl( QX11Info::getTimestamp () );
#endif
}

$prototype=static Display *display()
HB_FUNC_STATIC( QX11INFO_DISPLAY )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retptr( (Display *) QX11Info::display () );
#endif
}

$prototype=static xcb_connection_t *connection()
HB_FUNC_STATIC( QX11INFO_CONNECTION )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  hb_retptr( (xcb_connection_t *) QX11Info::connection () );
#endif
}

$prototype=static QByteArray nextStartupId()
HB_FUNC_STATIC( QX11INFO_NEXTSTARTUPID )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  QByteArray * ptr = new QByteArray( QX11Info::nextStartupId () );
  _qt5xhb_createReturnClass ( ptr, "QBYTEARRAY" );
#endif
}

$prototype=static void setNextStartupId(const QByteArray &id)
HB_FUNC_STATIC( QX11INFO_SETNEXTSTARTUPID )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,1,0))
  QX11Info::setNextStartupId ( *PQBYTEARRAY(1) );
  hb_itemReturn( hb_stackSelfItem() );
#endif
}

$extraMethods

#pragma ENDDUMP


Listed methods in class

Listed methods in class

/**
 * An efficient implementation of sets.
 * @package DataStructures
 */
Class Set
  Data oValue
  Data nLen

  Method New( aData ) Constructor
  Method Null()
  Method Size()
  Method Member( xElem )
  Method NotMember( xElem )
  Method Insert( xElem )
  Method Delete( xElem )
EndClass

/**
 * Initializes a set. If the constructor receives an array, maps over it and
 * adds unique elements to the set. Otherwise, initializes an empty set.
 * @author Marcelo Camargo
 * @constructor
 * @param aData :: Array<any>
 * @return Set
 */
Method New( aData ) Class Set
  Local nI

  ::nLen   := 0
  ::oValue := HMNew()

  If ValType( aData ) == "A"
    For nI := 1 To Len( aData )
      If !::oValue:Get( aData[ nI ] )
        ::oValue:Set( aData[ nI ], ++::nLen )
      EndIf
    Next nI
  EndIf
  Return Self

/**
 * Is this the empty set?
 * @author Marcelo Camargo
 * @return Bool
 */
Method Null() Class Set
  Return ::nLen == 0 .Or. ::nLen == Nil

/**
 * The number of elements in the set.
 * @author Marcelo Camargo
 * @return Integer
 */
Method Size() Class Set
  Return ::nLen

/**
 * Is the element in the set?
 * @author Marcelo Camargo
 * @param elem :: any
 * @return Bool
 */
Method Member( xElem ) Class Set
  Return ::oValue:Get( xElem )

/**
 * Is the element not in the set?
 * @author Marcelo Camargo
 * @param elem :: any
 * @return Bool
 */
Method NotMember( xElem ) Class Set
  Return !::oValue:Get( xElem )

/**
 * Inserts an element in the set if it is not already contained there.
 * @author Marcelo Camargo
 * @param xElem :: any
 * @return Set
 */
Method Insert( xElem ) Class Set
  If !::oValue:Get( xElem )
    ::oValue:Set( xElem, ++::nLen )
  EndIf
  Return Self

/**
 * Deletes an element from the set.
 * @author Marcelo Camargo
 * @param xElem : any
 * @return Set
 */
Method Delete( xElem ) Class Set
  If ::oValue:Get( xElem )
    ::oValue:Del( xElem)
  EndIf
  Return Self

/**
 * An efficient implementation of sets.
 * @package DataStructures
 */
Class Set
  Data oValue
  Data nLen

  Method New( aData ) Constructor
  Method Null()
  Method Size()
  Method Member( xElem )
  Method Insert( xElem )
EndClass

/**
 * Initializes a set. If the constructor receives an array, maps over it and
 * adds unique elements to the set. Otherwise, initializes an empty set.
 * @author Marcelo Camargo
 * @constructor
 * @param aData :: Array<any>
 * @return Set
 */
Method New( aData ) Class Set
  Local nI

  ::nLen   := 0
  ::oValue := HMNew()

  If ValType( aData ) == "A"
    For nI := 1 To Len( aData )
      If !::oValue:Get( aData[ nI ] )
        ::oValue:Set( aData[ nI ], ++::nLen )
      EndIf
    Next nI
  EndIf
  Return Self

/**
 * Is this the empty set?
 * @author Marcelo Camargo
 * @return Bool
 */
Method Null() Class Set
  Return ::nLen == 0 .Or. ::nLen == Nil

/**
 * The number of elements in the set.
 * @author Marcelo Camargo
 * @return Integer
 */
Method Size() Class Set
  Return ::nLen

/**
 * Is the element in the set?
 * @author Marcelo Camargo
 * @param elem :: any
 * @return Bool
 */
Method Member( xElem ) Class Set
  Return ::oValue:Get( xElem )

/**
 * Is the element not in the set?
 * @author Marcelo Camargo
 * @param elem :: any
 * @return Bool
 */
Method NotMember( xElem ) Class Set
  Return !::oValue:Get( xElem )

/**
 * Inserts an element in the set if it is not already contained there.
 * @author Marcelo Camargo
 * @param xElem :: any
 * @return Set
 */
Method Insert( xElem ) Class Set
  If !::oValue:Get( xElem )
    ::oValue:Set( xElem, ++::nLen )
  EndIf
  Return Self

/**
 * Deletes an element from the set.
 * @author Marcelo Camargo
 * @param xElem : any
 * @return Set
 */
Method Delete( xElem ) Class Set
  If ::oValue:Get( xElem )
    ::oValue:Del( xElem)
  EndIf
  Return Self