Пример #1
0
        static PhpValue PregReplaceInternal(Context ctx, string pattern, string replacement, IPhpCallable callback, PhpValue subject, int limit, ref long count)
        {
            var regex = new PerlRegex.Regex(pattern);

            // callback
            PerlRegex.MatchEvaluator evaluator = null;
            if (callback != null)
            {
                evaluator = (match) =>
                {
                    var matches_arr = new PhpArray(0);
                    GroupsToPhpArray(match.PcreGroups, false, matches_arr);

                    return(callback
                           .Invoke(ctx, (PhpValue)matches_arr)
                           .ToStringOrThrow(ctx));
                };
            }

            // TODO: subject as a binary string would be corrupted after Replace - https://github.com/peachpiecompiler/peachpie/issues/178

            //
            var subject_array = subject.AsArray();

            if (subject_array == null)
            {
                return(PhpValue.Create(
                           evaluator == null
                        ? regex.Replace(subject.ToStringOrThrow(ctx), replacement, limit, ref count)
                        : regex.Replace(subject.ToStringOrThrow(ctx), evaluator, limit, ref count)));
            }
            else
            {
                var arr = new PhpArray(subject_array.Count);

                var enumerator = subject_array.GetFastEnumerator();
                while (enumerator.MoveNext())
                {
                    var newvalue = evaluator == null
                        ? regex.Replace(enumerator.CurrentValue.ToStringOrThrow(ctx), replacement, limit, ref count)
                        : regex.Replace(enumerator.CurrentValue.ToStringOrThrow(ctx), evaluator, limit, ref count);

                    // TODO: trick on how to quickly update values od enumerated array without hashing:
                    // enumerator.CurrentValue = PhpValue.Create(newvalue);

                    arr[enumerator.CurrentKey] = newvalue;
                }

                return(PhpValue.Create(arr));
            }
        }
Пример #2
0
        ///// <summary>
        ///// Perform a regular expression search and replace.
        ///// </summary>
        //public static PhpValue preg_filter(Context ctx, PhpValue pattern, PhpValue replacement, PhpValue subject, int limit = -1)
        //{
        //    return preg_filter(ctx, pattern, replacement, subject, limit, out _);
        //}

        ///// <summary>
        ///// Perform a regular expression search and replace.
        ///// </summary>
        //public static PhpValue preg_filter(Context ctx, PhpValue pattern, PhpValue replacement, PhpValue subject, int limit, out long count)
        //{
        //    return PregReplaceInternal(ctx, pattern, replacement, subject, limit, out count, filter: true);
        //}

        static PhpValue PregReplaceInternal(Context ctx, string pattern, string replacement, IPhpCallable callback, PhpValue subject, int limit, ref long count, bool filter = false)
        {
            if (!TryParseRegexp(pattern, out var regex))
            {
                return(PhpValue.Null);
            }

            // callback
            PerlRegex.MatchEvaluator evaluator = null;
            if (callback != null)
            {
                evaluator = (match) =>
                {
                    var matches_arr = new PhpArray();
                    GroupsToPhpArray(match.PcreGroups, false, false, matches_arr);

                    return(callback
                           .Invoke(ctx, (PhpValue)matches_arr)
                           .ToStringOrThrow(ctx));
                };
            }

            // TODO: subject as a binary string would be corrupted after Replace - https://github.com/peachpiecompiler/peachpie/issues/178

            //
            if (subject.IsPhpArray(out var subject_array))
            {
                var arr = new PhpArray(subject_array.Count);

                var enumerator = subject_array.GetFastEnumerator();
                while (enumerator.MoveNext())
                {
                    var input    = enumerator.CurrentValue;
                    var oldvalue = input.ToStringOrThrow(ctx);
                    var oldcount = count;

                    PhpValue newvalue = evaluator == null
                        ? regex.Replace(oldvalue, replacement, limit, ref count)
                        : regex.Replace(oldvalue, evaluator, limit, ref count);

                    if (oldcount == count)
                    {
                        // no match
                        if (filter)
                        {
                            continue;
                        }

                        // - quick workaround for https://github.com/peachpiecompiler/peachpie/issues/178
                        // - use the original value if possible (mem perf.)
                        newvalue = (input.IsBinaryString(out var bstring) ? bstring.DeepCopy() : oldvalue);
                    }

                    arr[enumerator.CurrentKey] = newvalue;
                }

                return(arr);
            }
            else
            {
                var oldvalue = subject.ToStringOrThrow(ctx);
                var oldcount = count;

                PhpValue newvalue = evaluator == null
                        ? regex.Replace(oldvalue, replacement, limit, ref count)
                        : regex.Replace(oldvalue, evaluator, limit, ref count);

                if (oldcount == count)
                {
                    // no match
                    if (filter)
                    {
                        return(PhpValue.Null);
                    }

                    // - quick workaround for https://github.com/peachpiecompiler/peachpie/issues/178
                    // - use the original value if possible (mem perf.)
                    newvalue = (subject.IsBinaryString(out var bstring) ? bstring.DeepCopy() : oldvalue);
                }

                //
                return(newvalue);
            }
        }