Beispiel #1
0
        /// <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;
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        /// <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);
        }
Beispiel #4
0
        /// <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;
        }
Beispiel #5
0
        /// <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;
        }
Beispiel #6
0
        /// <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 =&gt; key, 1 =&gt; value, "key" =&gt; key, "value" =&gt; 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;
        }
Beispiel #7
0
        /// <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;
        }
Beispiel #8
0
        /// <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;
        }
Beispiel #9
0
        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;
        }
Beispiel #10
0
        /// <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;
        }
Beispiel #11
0
        /// <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;
        }
Beispiel #12
0
        /// <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;
        }
Beispiel #13
0
        /// <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;
        }
Beispiel #14
0
        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;
        }
Beispiel #15
0
        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;
        }
Beispiel #16
0
        /// <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;
        }
Beispiel #17
0
        /// <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;
        }
Beispiel #18
0
        /// <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;
        }
Beispiel #19
0
        /// <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;
        }
Beispiel #20
0
        /// <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;
        }
Beispiel #21
0
        /// <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;
        }
Beispiel #22
0
 /// <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;
 }
Beispiel #23
0
        /// <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;
        }
Beispiel #24
0
        /// <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;
        }
Beispiel #25
0
        /// <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;
        }
Beispiel #26
0
        /// <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;
        }
Beispiel #27
0
        /// <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;
        }
Beispiel #28
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;
                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;
        }
Beispiel #29
0
        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;
        }
Beispiel #30
0
        /// <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;
        }
Beispiel #31
0
        /// <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;
        }
Beispiel #32
0
        /// <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;
        }