Exemple #1
0
		/// <summary>
		/// Internal version of <see cref="Chunk"/> with deep-copy option.
		/// </summary>
		internal static PhpArray ChunkInternal(PhpArray array, int size, bool preserveKeys, bool deepCopy)
		{
			if (array == null)
			{
				PhpException.ArgumentNull("array");
				return null;
			}
			if (size <= 0)
			{
				PhpException.InvalidArgument("array", LibResources.GetString("arg:negative_or_zero"));
				return null;
			}

			// nothing to do:
			if (array.Count == 0)
				return new PhpArray();

			// number of chunks:
			int count = (array.Count - 1) / size + 1; // = ceil(Count/size):

			PhpArray chunk;
			PhpArray result = new PhpArray(count, 0);

			IEnumerator<KeyValuePair<IntStringKey, object>> iterator;

			// if deep-copies are required, wrapp iterator by enumerator making deep copies:
			if (deepCopy)
				iterator = PhpVariable.EnumerateDeepCopies(array).GetEnumerator();
			else
				iterator = array.GetEnumerator();

			iterator.MoveNext();

			// all chunks except for the last one:
			for (int i = 0; i < count - 1; i++)
			{
				chunk = new PhpArray(size, 0);

				if (preserveKeys)
				{
					for (int j = 0; j < size; j++, iterator.MoveNext())
						chunk.Add(iterator.Current.Key, iterator.Current.Value);
				}
				else
				{
					for (int j = 0; j < size; j++, iterator.MoveNext())
						chunk.Add(iterator.Current.Value);
				}

				result.Add(chunk);
			}

			// the last chunk:
			chunk = new PhpArray((size <= array.Count) ? size : array.Count, 0);

			if (preserveKeys)
			{
				do { chunk.Add(iterator.Current.Key, iterator.Current.Value); } while (iterator.MoveNext());
			}
			else
			{
				do { chunk.Add(iterator.Current.Value); } while (iterator.MoveNext());
			}

			result.Add(chunk);

			// no deep copy is needed since it has already been done on chunks:
			return result;
		}
Exemple #2
0
		/// <summary>
		/// Compares two instances of <see cref="PhpArray"/> for strict equality.
		/// </summary>
		/// <param name="incomparable">Whether arrays are incomparable 
		/// (no difference is found before both arrays enters an infinite recursion). 
		/// Returns <B>true</B> then.</param>
		/// <include file='Doc/Common.xml' path='docs/method[@name="Compare(x,y)"]/*'/>
		private static bool StrictCompareArrays(PhpArray x, PhpArray y, 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 true;

            //
			object child_x, child_y;
			PhpArray array_x, array_y;
			PhpReference r;
			IEnumerator<KeyValuePair<IntStringKey, object>> iter_x, iter_y;

			// if numbers of elements differs:
			if (x.Count != y.Count) return false;

			// comparing with the same instance:
			if (x == y) return true;

			iter_x = x.GetEnumerator();
			iter_y = y.GetEnumerator();

			// marks arrays as visited (will be always restored to false value before return):
			x.Visited = true;
			y.Visited = true;

			bool result = true;

			try
			{
				// compares corresponding elements (keys first values then):
				while (iter_x.MoveNext())
				{
					iter_y.MoveNext();

					// compares keys:
					if (!iter_x.Current.Key.Equals(iter_y.Current.Key))
					{
						result = false;
						break;
					}

					// dereferences x child if it is a reference:
					child_x = iter_x.Current.Value;
					if ((r = child_x as PhpReference) != null) child_x = r.Value;

					// dereferences y child if it is a reference:
					child_y = iter_y.Current.Value;
					if ((r = child_y as PhpReference) != null) child_y = r.Value;

					// compares values:
					if ((array_x = child_x as PhpArray) != null)
					{
						if ((array_y = child_y as PhpArray) != null)
						{
							// at least one child has not been visited yet => continue with recursion:
							if (!array_x.Visited || !array_y.Visited)
							{
								result = StrictCompareArrays(array_x, array_y, out incomparable);
							}
							else
							{
								incomparable = true;
							}

							// infinity recursion has been detected:
							if (incomparable) break;
						}
						else
						{
							// an array with a non-array comparison:
							result = false;
						}
					}
					else
					{
						// compares unknown item with a non-array:
						result = Operators.StrictEquality(child_x, child_y);
					}

					if (!result) break;
				} // while
			}
			finally
			{
				x.Visited = false;
				y.Visited = false;
			}
			return result;
		}