/// <summary>Initializes global $argv and $argc variables and corresponding $_SERVER entries.</summary> protected void InitializeArgvArgc(string mianscript, params string[] args) { Debug.Assert(args != null); // PHP array with command line arguments // including 0-th argument corresponding to program executable var argv = new PhpArray(1 + args.Length); argv.Add(mianscript ?? "-"); argv.AddRange(args); // command line argc, argv: this.Globals["argv"] = (this.Server["argv"] = argv).DeepCopy(); this.Globals["argc"] = this.Server["argc"] = argv.Count; }
/// <summary> /// Creates array from PHP enumerator. /// </summary> internal static PhpArray Create(IPhpEnumerator phpenumerator) { Debug.Assert(phpenumerator != null); var arr = new PhpArray(); while (phpenumerator.MoveNext()) { var current = phpenumerator.Current; arr.Add(current.Key.ToIntStringKey(), current.Value); } // return(arr); }
/// <summary>Initializes global $argv and $argc variables.</summary> protected void IntializeArgvArgc(params string[] args) { Debug.Assert(args != null); // command line argc, argv: var argv = new PhpArray(args.Length); // adds all arguments to the array (the 0-th argument is not '-' as in PHP but the program file): for (int i = 0; i < args.Length; i++) { argv.Add(i, PhpValue.Create(args[i])); } this.Globals["argv"] = PhpValue.Create(argv); this.Globals["argc"] = PhpValue.Create(args.Length); }
/// <summary> /// Retrieves defined constants. /// </summary> /// <param name="ctx">Current runtime context.</param> /// <param name="categorize">Returns a multi-dimensional array with categories in the keys of the first dimension and constants and their values in the second dimension. </param> /// <returns>Retrives the names and values of all the constants currently defined.</returns> public static PhpArray get_defined_constants(Context ctx, bool categorize = false) { var result = new PhpArray(); if (categorize) { throw new NotImplementedException(); } else { foreach (var c in ctx.GetConstants()) { result.Add(c.Key, c.Value); } } // return result; }
/// <summary> /// Retuns the specified array. /// see http://php.net/manual/en/function.array-filter.php /// </summary> /// <remarks>The caller argument is here just because of the second Filter() method. Phalanger shares the function properties over the overloads.</remarks> public static PhpArray array_filter(PhpArray array) { if (array == null) { //PhpException.ArgumentNull("array"); //return null; throw new ArgumentNullException(nameof(array)); } var result = new PhpArray(); var enumerator = array.GetFastEnumerator(); while (enumerator.MoveNext()) { var entry = enumerator.Current; if (entry.Value.ToBoolean()) { result.Add(entry); } } return result; }
/// <summary> /// Retrieves the current entry and advances array intrinsic enumerator one item forward. /// </summary> /// <param name="array">The array which entry get and which intrinsic enumerator to advance.</param> /// <returns> /// The instance of <see cref="PhpArray"/>(0 => key, 1 => value, "key" => key, "value" => value) /// where key and value are pointed by the enumerator before it is advanced /// or <b>false</b> if the enumerator has been behind the last item of <paramref name="array"/> /// before the call. /// </returns> //[return: CastToFalse, PhpDeepCopy] public static PhpArray each(IPhpEnumerable array) { if (array == null) { //PhpException.ReferenceNull("array"); return null; } if (array.IntrinsicEnumerator.AtEnd) return null; var entry = array.IntrinsicEnumerator.Current; array.IntrinsicEnumerator.MoveNext(); // dereferences result since enumerator doesn't do so: var key = entry.Key; var value = entry.Value; // PhpVariable.Dereference(entry.Value); // creates the resulting array: PhpArray result = new PhpArray(2); result.Add(1, value); result.Add("value", value); result.Add(0, key); result.Add("key", key); // keys and values should be inplace deeply copied: // TODO: result.InplaceCopyOnReturn = true; return result; }
/// <summary> /// Retrieves an array of values contained in a given array. /// </summary> /// <param name="array">An array which values to get.</param> /// <returns>A copy of <paramref name="array"/> with all keys indexed starting from zero.</returns> /// <exception cref="PhpException"><paramref name="array"/> is a <B>null</B> reference.</exception> /// <remarks>Doesn't dereference PHP references.</remarks> //[return: PhpDeepCopy] public static PhpArray array_values(PhpArray array) { if (array == null) { //PhpException.ArgumentNull("array"); //return null; throw new ArgumentNullException(nameof(array)); } // references are not dereferenced: PhpArray result = new PhpArray(array.Count); var enumerator = array.GetFastEnumerator(); while (enumerator.MoveNext()) { result.Add(enumerator.CurrentValue); } // result is inplace deeply copied on return to PHP code: //result.InplaceCopyOnReturn = true; return result; }
/// <summary> /// Converts .NET groups information to PHP array. /// </summary> private static PhpArray GetGroupingArray(int[] groups) { Debug.Assert(groups != null); int length = groups.Length; PhpArray result = new PhpArray(length, 0); for (int i = 0; i < length; i++) if (groups[i] == 0) result.Add(i, CHAR_MAX); else result.Add(i, groups[i]); return result; }
public static PhpArray get_extension_funcs(string extension) { var result = new PhpArray(); foreach (var e in Context.GetRoutinesByExtension(extension)) { result.Add(PhpValue.Create(e)); } // gets NULL (FALSE) if there are no functions return result.Count != 0 ? result : null; }
/// <summary> /// Creates an instance of <see cref="PhpArray"/> filled by given entries. /// </summary> /// <param name="keysValues">Keys and values (alternating) or values only.</param> /// <remarks>If the length of <paramref name="keysValues"/> is odd then its last item is added without a key.</remarks> public static PhpArray Keyed(params object[] keysValues) { PhpArray result = new PhpArray(); int length = keysValues.Length; int remainder = length % 2; for (int i = 0; i < length - remainder; i += 2) result.Add(keysValues[i], keysValues[i + 1]); if (remainder > 0) result.Add(keysValues[length - 1]); return result; }
/// <summary> /// Returns an associative array containing the date information. /// </summary> /// <param name="ctx">Current runtime context.</param> /// <param name="utc">UTC date time.</param> /// <returns>Associative array with date information.</returns> static PhpArray GetDate(Context ctx, System_DateTime utc) { PhpArray result = new PhpArray(1, 10); var zone = PhpTimeZone.GetCurrentTimeZone(ctx); var local = TimeZoneInfo.ConvertTime(utc, zone); result.Add("seconds", local.Second); result.Add("minutes", local.Minute); result.Add("hours", local.Hour); result.Add("mday", local.Day); result.Add("wday", (int)local.DayOfWeek); result.Add("mon", local.Month); result.Add("year", local.Year); result.Add("yday", local.DayOfYear - 1); // PHP: zero based day count result.Add("weekday", local.DayOfWeek.ToString()); result.Add("month", local.ToString("MMMM", DateTimeFormatInfo.InvariantInfo)); result.Add(0, DateTimeUtils.UtcToUnixTimeStamp(utc)); return result; }
/// <summary> /// Retrieves a slice of specified array. /// </summary> /// <param name="array">The array which slice to get.</param> /// <param name="offset">The relativized offset of the first item of the slice.</param> /// <param name="length">The relativized length of the slice.</param> /// <param name="preserveKeys">Whether to preserve integer keys. If <B>false</B>, the integer keys are reset.</param> /// <returns>The slice of <paramref name="array"/>.</returns> /// <remarks> /// See <see cref="PhpMath.AbsolutizeRange"/> for details about <paramref name="offset"/> and <paramref name="length"/>. /// </remarks> public static PhpArray array_slice(PhpArray array, int offset, int length = int.MaxValue, bool preserveKeys = false) { if (array == null) { //PhpException.ArgumentNull("array"); //return null; throw new ArgumentNullException(); } // absolutizes range: PhpMath.AbsolutizeRange(ref offset, ref length, array.Count); var iterator = array.GetFastEnumerator(); // moves iterator to the first item of the slice; // starts either from beginning or from the end (which one is more efficient): if (offset < array.Count - offset) { for (int i = -1; i < offset; i++) if (iterator.MoveNext() == false) break; } else { for (int i = array.Count; i > offset; i--) if (iterator.MovePrevious() == false) break; } // copies the slice: PhpArray result = new PhpArray(length); int ikey = 0; for (int i = 0; i < length; i++) { var entry = iterator.Current; // integer keys are reindexed if preserveKeys is false, string keys are not touched: if (preserveKeys || entry.Key.IsString) { result.Add(entry.Key, entry.Value); } else { result.Add(ikey++, entry.Value); } iterator.MoveNext(); } //result.InplaceCopyOnReturn = true; return result; }
/// <summary> /// Pads array to the specified length with a value. /// If the length is negative adds |length| elements at beginning otherwise adds elements at the end. /// Values with integer keys that are contained in the source array are inserted to the resulting one with new /// integer keys counted from zero (or from |length| if length negative). /// </summary> /// <param name="array">The source array.</param> /// <param name="length">The length of the resulting array.</param> /// <param name="value">The value to add in array.</param> /// <returns>Padded array.</returns> /// <exception cref="PhpException">The <paramref name="array"/> argument is a <B>null</B> reference.</exception> public static PhpArray array_pad(PhpArray array, int length, PhpValue value) { if (array == null) { // PhpException.ArgumentNull("array"); // return null; throw new ArgumentNullException(); } // number of items to add: int remains = Math.Abs(length) - array.Count; // returns unchanged array (or its deep copy if called from PHP): if (remains <= 0) return array; PhpArray result = new PhpArray(array.Count + remains); // prepends items: if (length < 0) { while (remains-- > 0) result.Add(value); } // inserts items from source array // if a key is a string inserts it unchanged otherwise inserts value with max. integer key: var iterator = array.GetFastEnumerator(); while (iterator.MoveNext()) { var key = iterator.CurrentKey; if (key.IsString) result.Add(key, iterator.CurrentValue); else result.Add(iterator.CurrentValue); } // appends items: if (length > 0) { while (remains-- > 0) result.Add(value); } // the result is inplace deeply copied on return to PHP code: //result.InplaceCopyOnReturn = true; return result; }
private static PhpArray/*!*/ GetLevelStatus(BufferedOutput/*!*/ bo, int index) { PhpArray result = new PhpArray(0, 3); Delegate filter; int size; bo.GetLevelInfo(index, out filter, out size); if (filter != null) { result.Add("type", 1); result.Add("name", filter.ToString()); } else { result.Add("type", 0); } result.Add("buffer_size", size); return result; }
public static PhpArray ob_list_handlers(Context ctx) { BufferedOutput bo = ctx.BufferedOutput; PhpArray result = new PhpArray(bo.Level, 0); for (int i = 0; i < bo.Level; i++) { result.Add(bo.GetLevelName(i)); } return result; }
/// <summary> /// Get the status of the current or all output buffers. /// </summary> /// <param name="ctx">Current runtime context.</param> /// <param name="full">Whether to retrieve extended information about all levels of buffering or about the current one.</param> /// <returns>The array of name => value pairs containing information.</returns> public static PhpArray ob_get_status(Context ctx, bool full) { BufferedOutput bo = ctx.BufferedOutput; PhpArray result; if (full) { result = new PhpArray(bo.Level, 0); for (int i = 1; i <= bo.Level; i++) result.Add(i, GetLevelStatus(bo, i)); } else if (bo.Level > 0) { result = GetLevelStatus(bo, bo.Level); result.Add("level", bo.Level); } else { result = new PhpArray(0, 0); } return result; }
/// <summary> /// Extracts part(s) from a specified path. /// </summary> /// <param name="path">The path to be parsed.</param> /// <param name="options">Flags determining the result.</param> /// <returns> /// If <paramref name="options"/> is <see cref="PathInfoOptions.All"/> then returns array /// keyed by <c>"dirname"</c>, <c>"basename"</c>, and <c>"extension"</c>. Otherwise, /// it returns string value containing a single part of the path. /// </returns> public static PhpValue pathinfo(string path, PathInfoOptions options = PathInfoOptions.All) { // collect strings string dirname = null, basename = null, extension = null, filename = null; if ((options & PathInfoOptions.BaseName) != 0 || (options & PathInfoOptions.Extension) != 0 || (options & PathInfoOptions.FileName) != 0) basename = PhpPath.basename(path); if ((options & PathInfoOptions.DirName) != 0) dirname = PhpPath.dirname(path); if ((options & PathInfoOptions.Extension) != 0) { int last_dot = basename.LastIndexOf('.'); if (last_dot >= 0) extension = basename.Substring(last_dot + 1); } if ((options & PathInfoOptions.FileName) != 0) { int last_dot = basename.LastIndexOf('.'); if (last_dot >= 0) filename = basename.Substring(0, last_dot); else filename = basename; } // return requested value or all of them in an associative array if (options == PathInfoOptions.All) { PhpArray result = new PhpArray(0, 4); result.Add("dirname", dirname); result.Add("basename", basename); result.Add("extension", extension); result.Add("filename", filename); return PhpValue.Create(result); } if ((options & PathInfoOptions.DirName) != 0) return PhpValue.Create(dirname); if ((options & PathInfoOptions.BaseName) != 0) return PhpValue.Create(basename); if ((options & PathInfoOptions.Extension) != 0) return PhpValue.Create(extension); if ((options & PathInfoOptions.FileName) != 0) return PhpValue.Create(filename); return PhpValue.Null; }
/// <summary> /// Gets information about the current thread culture. /// </summary> /// <returns>The associative array of number and currency information.</returns> public static PhpArray localeconv(Context ctx) { PhpArray result = new PhpArray(0, 18); NumberFormatInfo number; number = GetCulture(ctx, Category.Numeric).NumberFormat; result.Add("decimal_point", number.NumberDecimalSeparator); result.Add("thousands_sep", number.NumberGroupSeparator); result.Add("grouping", GetGroupingArray(number.CurrencyGroupSizes)); result.Add("positive_sign", number.PositiveSign); result.Add("negative_sign", number.NegativeSign); result.Add("frac_digits", number.CurrencyDecimalDigits); number = GetCulture(ctx, Category.Monetary).NumberFormat; result.Add("currency_symbol", number.CurrencySymbol); result.Add("mon_decimal_point", number.CurrencyDecimalSeparator); result.Add("mon_thousands_sep", number.CurrencyGroupSeparator); result.Add("mon_grouping", GetGroupingArray(number.CurrencyGroupSizes)); // currency patterns: 0 -> $n, 1 -> n$, 2 -> $ n, 3 -> n $ result.Add("p_cs_precedes", number.CurrencyPositivePattern == 0 || number.CurrencyPositivePattern == 2); result.Add("p_sep_by_space", number.CurrencyPositivePattern == 2 || number.CurrencyPositivePattern == 3); result.Add("n_cs_precedes", number.CurrencyNegativePattern == 0 || number.CurrencyNegativePattern == 2); result.Add("n_sep_by_space", number.CurrencyNegativePattern == 2 || number.CurrencyNegativePattern == 3); result.Add("p_sign_posn", 1); result.Add("n_sign_posn", 1); return result; }
/// <summary> /// Filters an array using a specified callback. /// </summary> /// <param name="ctx">Current runtime context.</param> /// <param name="array">The array to be filtered.</param> /// <param name="callback"> /// The callback called on each value in the <paramref name="array"/>. /// If the callback returns value convertible to <B>true</B> the value is copied to the resulting array. /// Otherwise, it is ignored. /// </param> /// <returns>An array of unfiltered items.</returns> //[return: PhpDeepCopy] public static PhpArray array_filter(Context ctx /*, caller*/, PhpArray array, IPhpCallable callback) { if (array == null) { //PhpException.ArgumentNull("array"); //return null; throw new ArgumentNullException(nameof(array)); } if (callback == null) { //PhpException.ArgumentNull("callback"); //return null; throw new ArgumentNullException(nameof(callback)); } var result = new PhpArray(); var args = new PhpValue[1]; var iterator = array.GetFastEnumerator(); while (iterator.MoveNext()) { var entry = iterator.Current; // no deep copying needed because it is done so in callback: args[0] = entry.Value; // adds entry to the resulting array if callback returns true: if (callback.Invoke(ctx, args).ToBoolean()) { result.Add(entry); } } // values should be inplace deeply copied: //result.InplaceCopyOnReturn = true; return result; }
/// <summary> /// Creates an array containing range of doubles from the [low;high] interval with arbitrary step. /// </summary> /// <param name="low">Lower bound of the interval.</param> /// <param name="high">Upper bound of the interval.</param> /// <param name="step">The step. An absolute value is taken if step is less than zero.</param> /// <returns>The array.</returns> /// <exception cref="PhpException">Thrown if the <paramref name="step"/> argument is zero.</exception> private static PhpArray RangeOfDoubles(double low, double high, double step) { if (step == 0) { //PhpException.InvalidArgument("step", LibResources.GetString("arg:zero")); //return null; throw new ArgumentException(); } if (step < 0) step = -step; PhpArray result = new PhpArray(System.Convert.ToInt32(Math.Abs(high - low) / step) + 1); if (high >= low) { for (int i = 0; low <= high; i++, low += step) result.Add(i, low); } else { for (int i = 0; low >= high; i++, low -= step) result.Add(i, low); } return result; }
/// <summary> /// Adds multiple items into an array. /// </summary> /// <param name="array">The array where to add values.</param> /// <param name="vars">The array of values to add.</param> /// <returns>The number of items in array after all items was added.</returns> public static int array_push(PhpArray array, params PhpValue[] vars) { if (array == null) { //PhpException.ReferenceNull("array"); //return 0; throw new ArgumentNullException(); } // adds copies variables (if called by PHP): for (int i = 0; i < vars.Length; i++) { array.Add(vars[i]); } return array.Count; }
/// <summary> /// Creates an instance of <see cref="PhpArray"/> filled by given values. /// </summary> /// <param name="values">Values to be added to the new instance. /// Keys will correspond order of values in the array.</param> public static PhpArray New(params PhpValue[] values) { PhpArray result = new PhpArray(values.Length, 0); foreach (var value in values) result.Add(value); return result; }
/// <summary> /// Creates a new array filled with a specified value. /// </summary> /// <param name="startIndex">The value of the key of the first item in the array.</param> /// <param name="count">The number of items in the array.</param> /// <param name="value">The value copied to all items in the array.</param> /// <returns>The array.</returns> /// <exception cref="PhpException">Thrown if <paramref name="count"/> is not positive.</exception> public static PhpArray array_fill(int startIndex, int count, PhpValue value) { if (count <= 0) { // TODO: PhpException.InvalidArgument("count", LibResources.GetString("arg:negative_or_zero")); return null; } PhpArray result = new PhpArray(count, 0); int last = startIndex + count; for (int i = startIndex; i < last; i++) result.Add(i, value); // makes deep copies of all added items: //result.InplaceCopyOnReturn = true; return result; }
/// <summary> /// Merges one or more arrays. Integer keys are changed to new ones, string keys are preserved. /// Values associated with existing string keys are be overwritten. /// </summary> /// <param name="arrays">Arrays to be merged.</param> /// <returns>The <see cref="PhpArray"/> containing items from all <paramref name="arrays"/>.</returns> //[return: PhpDeepCopy] public static PhpArray array_merge(params PhpArray[] arrays) { // "arrays" argument is PhpArray[] => compiler generates code converting any value to PhpArray. // Note, PHP does reject non-array arguments. if (arrays == null || arrays.Length == 0) { //PhpException.InvalidArgument("arrays", LibResources.GetString("arg:null_or_empty")); //return null; throw new ArgumentException(); } var result = new PhpArray(arrays[0].Count); for (int i = 0; i < arrays.Length; i++) { if (arrays[i] != null) { using (var enumerator = arrays[i].GetFastEnumerator()) while (enumerator.MoveNext()) { if (enumerator.CurrentKey.IsString) result[enumerator.CurrentKey] = enumerator.CurrentValue; else result.Add(enumerator.CurrentValue); } } } // results is inplace deeply copied if returned to PHP code: //result.InplaceCopyOnReturn = true; return result; }
/// <summary> /// Creates an array containing range of long integers from the [low;high] interval with arbitrary step. /// </summary> /// <param name="low">Lower bound of the interval.</param> /// <param name="high">Upper bound of the interval.</param> /// <param name="step">The step. An absolute value is taken if step is zero.</param> /// <returns>The array.</returns> private static PhpArray RangeOfLongInts(long low, long high, long step) { if (step == 0) { //PhpException.InvalidArgument("step", LibResources.GetString("arg:zero")); //return null; throw new ArgumentException(); } if (step < 0) step = -step; PhpArray result = new PhpArray(unchecked((int)(Math.Abs(high - low) / step + 1))); if (high >= low) { for (int i = 0; low <= high; i++, low += step) result.Add(i, low); } else { for (int i = 0; low >= high; i++, low -= step) result.Add(i, low); } return result; }
/// <summary> /// Adds items of "array" to "result" merging those whose string keys are the same. /// </summary> private static bool MergeRecursiveInternal(PhpArray/*!*/ result, PhpArray/*!*/ array, bool deepCopy) { var visited = new HashSet<object>(); // marks arrays that are being visited using (var iterator = array.GetFastEnumerator()) while (iterator.MoveNext()) { var entry = iterator.Current; if (entry.Key.IsString) { if (result.ContainsKey(entry.Key)) { // the result array already contains the item => merging take place var xv = result[entry.Key]; var y = entry.Value.GetValue(); // source item: PhpValue x = xv.GetValue(); // if x is not a reference then we can reuse the ax array for the result // since it has been deeply copied when added to the resulting array: PhpArray item_result = (deepCopy && x.IsArray && !xv.IsAlias) ? x.Array : new PhpArray(); if (x.IsArray && y.IsArray) { var ax = x.Array; var ay = y.Array; if (ax != item_result) ax.AddTo(item_result, deepCopy); if (visited.Add(ax) == false && visited.Add(ay) == false) return false; // merges ay to the item result (may lead to stack overflow, // but only with both arrays recursively referencing themselves - who cares?): bool finite = MergeRecursiveInternal(item_result, ay, deepCopy); visited.Remove(ax); visited.Remove(ay); if (!finite) return false; } else { if (x.IsArray) { if (x.Array != item_result) x.Array.AddTo(item_result, deepCopy); } else { /*if (x != null)*/ item_result.Add(deepCopy ? x.DeepCopy() : x); } if (y.IsArray) y.Array.AddTo(item_result, deepCopy); else /*if (y != null)*/ item_result.Add(deepCopy ? y.DeepCopy() : y); } result[entry.Key] = PhpValue.Create(item_result); } else { // PHP does no dereferencing when items are not merged: result.Add(entry.Key, (deepCopy) ? entry.Value.DeepCopy() : entry.Value); } } else { // PHP does no dereferencing when items are not merged: result.Add((deepCopy) ? entry.Value.DeepCopy() : entry.Value); } } return true; }
/// <summary> /// Creates an array containing range of characters from the [low;high] interval with arbitrary step. /// </summary> /// <param name="low">Lower bound of the interval.</param> /// <param name="high">Upper bound of the interval.</param> /// <param name="step">The step.</param> /// <returns>The array.</returns> /// <exception cref="PhpException">Thrown if the <paramref name="step"/> argument is zero.</exception> private static PhpArray RangeOfChars(char low, char high, int step) { if (step == 0) { //PhpException.InvalidArgument("step", LibResources.GetString("arg:zero")); //step = 1; throw new ArgumentException(); } if (step < 0) step = -step; PhpArray result = new PhpArray(Math.Abs(high - low) / step + 1, 0); if (high >= low) { for (int i = 0; low <= high; i++, low = unchecked((char)(low + step))) result.Add(i, low.ToString()); } else { for (int i = 0; low >= high; i++, low = unchecked((char)(low - step))) result.Add(i, low.ToString()); } return result; }
/// <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; throw new ArgumentNullException(nameof(array)); } if (size <= 0) { //PhpException.InvalidArgument("array", LibResources.GetString("arg:negative_or_zero")); //return null; throw new ArgumentException(nameof(size)); } // 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, PhpValue>> iterator = array.GetEnumerator(); // if deep-copies are required, wrapp iterator by enumerator making deep copies: if (deepCopy) iterator = PhpVariable.EnumerateDeepCopies(iterator); 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; }
public static PhpArray preg_grep(Context ctx, string pattern, PhpArray input, int flags = 0) { if (input == null) { return null; } var result = new PhpArray(input.Count); if (input.Count != 0) { var regex = new PerlRegex.Regex(pattern); var enumerator = input.GetFastEnumerator(); while (enumerator.MoveNext()) { var str = enumerator.CurrentValue.ToStringOrThrow(ctx); var m = regex.Match(str); // move a copy to return array if success and not invert or // not success and invert if (m.Success ^ (flags & PREG_GREP_INVERT) != 0) { result.Add(enumerator.CurrentKey, enumerator.CurrentValue.DeepCopy()); } } } // return result; }
/// <summary> /// Removes duplicate values from an array. /// </summary> /// <param name="ctx">Current runtime context.</param> /// <param name="array">The array which duplicate values to remove.</param> /// <param name="sortFlags">Specifies how the values are compared to be identical.</param> /// <returns>A copy of <paramref name="array"/> without duplicated values.</returns> /// <remarks> /// Values are compared using string comparison method (<see cref="ValueComparer.String"/>). /// </remarks> /// <exception cref="PhpException"><paramref name="array"/> is a <B>null</B> reference.</exception> //[return: PhpDeepCopy] public static PhpArray array_unique(Context ctx, PhpArray array, ComparisonMethod sortFlags = ComparisonMethod.String) { if (array == null) { //PhpException.ArgumentNull("array"); //return null; throw new ArgumentNullException(); } IComparer<PhpValue> comparer; switch (sortFlags) { case ComparisonMethod.Regular: comparer = PhpComparer.Default; break; case ComparisonMethod.Numeric: comparer = PhpNumericComparer.Default; break; case ComparisonMethod.String: comparer = new PhpStringComparer(ctx); break; case ComparisonMethod.LocaleString: //comparer = new PhpLocaleStringComparer(ctx); break; default: //PhpException.ArgumentValueNotSupported("sortFlags", (int)sortFlags); //return null; throw new ArgumentException(nameof(sortFlags)); } var result = new PhpArray(array.Count); var/*!*/identitySet = new HashSet<object>(); // get only unique values - first found using (var enumerator = array.GetFastEnumerator()) while (enumerator.MoveNext()) { if (identitySet.Add(enumerator.CurrentValue.GetValue())) { result.Add(enumerator.Current); } } //result.InplaceCopyOnReturn = true; return result; }
/// <summary> /// Retrieves an array of keys contained in a given array. /// </summary> /// <param name="array">An array which keys to get.</param> /// <returns><see cref="PhpArray"/> of <paramref name="array"/>'s keys. /// Keys in returned array are successive integers starting from zero.</returns> /// <exception cref="PhpException"><paramref name="array"/> is a <B>null</B> reference.</exception> public static PhpArray array_keys(PhpArray array) { if (array == null) { //PhpException.ArgumentNull("array"); //return null; throw new ArgumentNullException(); } // no need to make a deep copy since keys are immutable objects (strings, ints): var result = new PhpArray(array.Count); var enumerator = array.GetFastEnumerator(); while (enumerator.MoveNext()) { result.Add(PhpValue.Create(enumerator.CurrentKey)); } return result; }
/// <summary> /// Returns an array with names of all loaded native extensions. /// </summary> /// <param name="zend_extensions">Only return Zend extensions.</param> public static PhpArray get_loaded_extensions(bool zend_extensions = false) { if (zend_extensions) { throw new NotImplementedException(nameof(zend_extensions)); } var extensions = Context.GetLoadedExtensions(); var result = new PhpArray(extensions.Count); foreach (var e in extensions) { result.Add(PhpValue.Create(e)); } return result; }