/// <summary> /// Fast creation of an empty array /// by referencing internal structure of empty singleton. /// </summary> public static PhpArray NewEmpty() => Empty.DeepCopy();
/// <summary> /// Makes new array containing union of two arrays. /// </summary> public static PhpArray Union(PhpArray x, PhpArray y) => (PhpArray)x.DeepCopy().Unite(y);
/// <summary> /// Compares two instances of <see cref="PhpArray"/>. /// </summary> /// <param name="x">First operand. Cannot be <c>null</c>.</param> /// <param name="y">Second operand. Cannot be <c>null</c>.</param> /// <param name="comparer">The comparer.</param> /// <param name="incomparable">Whether arrays are incomparable /// (no difference is found before both arrays enters an infinite recursion). /// Returns zero then.</param> public static int CompareArrays(PhpArray x, PhpArray y, IComparer <PhpValue> comparer, out bool incomparable) { Debug.Assert(x != null && y != null); incomparable = false; // if both operands point to the same internal dictionary: if (object.ReferenceEquals(x.table, y.table)) { return(0); } // PhpArray array_x, array_y; PhpArray sorted_x, sorted_y; // if numbers of elements differs: int result = x.Count - y.Count; if (result != 0) { return(result); } // comparing with the same instance: if (x == y) { return(0); } // marks arrays as visited (will be always restored to false value before return): x.Visited = true; y.Visited = true; // it will be more effective to implement OrderedHashtable.ToOrderedList method and use it here (in future version): sorted_x = x.DeepCopy(); sorted_x.Sort(KeyComparer.ArrayKeys); sorted_y = y.DeepCopy(); sorted_y.Sort(KeyComparer.ArrayKeys); var iter_x = sorted_x.GetFastEnumerator(); var iter_y = sorted_y.GetFastEnumerator(); result = 0; try { // compares corresponding elements (keys first values then): while (iter_x.MoveNext()) { iter_y.MoveNext(); // compares keys: result = iter_x.CurrentKey.CompareTo(iter_y.CurrentKey); if (result != 0) { break; } // dereferences childs if they are references: var child_x = iter_x.CurrentValue.GetValue(); var child_y = iter_y.CurrentValue.GetValue(); // compares values: if ((array_x = child_x.ArrayOrNull()) != null) { if ((array_y = child_y.ArrayOrNull()) != null) { // at least one child has not been visited yet => continue with recursion: if (!array_x.Visited || !array_y.Visited) { result = CompareArrays(array_x, array_y, comparer, out incomparable); } else { incomparable = true; } // infinity recursion has been detected: if (incomparable) { break; } } else { // compares an array with a non-array: array_x.Compare(child_y, comparer); } } else { // compares unknown item with a non-array: result = -comparer.Compare(child_y, child_x); } if (result != 0) { break; } } // while } finally { x.Visited = false; y.Visited = false; } return(result); }
/// <remarks>Performs deep copy of array, return array with replacements.</remarks> internal static PhpArray ArrayReplaceImpl(PhpArray array, PhpArray[] arrays, bool recursive) { PhpArray result = array.DeepCopy(); if (arrays != null) { for (int i = 0; i < arrays.Length; i++) { ArrayReplaceImpl(result, arrays[i], recursive); } } //// if called by PHP language then all items in the result should be in place deeply copied: //result.InplaceCopyOnReturn = true; return result; }