Exemple #1
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);
        }
Exemple #2
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));
            }
        }
Exemple #3
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);

            // TODO: count

            // callback
            PerlRegex.MatchEvaluator evaluator = null;
            if (callback != null)
            {
                evaluator = (match) =>
                {
                    var matches_arr = new PhpArray(0);
                    foreach (PerlRegex.Group g in match.Groups)
                    {
                        matches_arr.Add((PhpValue)g.Value);
                    }

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

            //
            var subject_array = subject.AsArray();

            if (subject_array == null)
            {
                return(PhpValue.Create(
                           evaluator == null
                        ? regex.Replace(subject.ToStringOrThrow(ctx), replacement, limit)
                        : regex.Replace(subject.ToStringOrThrow(ctx), evaluator, limit)));
            }
            else
            {
                var arr        = new PhpArray(subject_array, false);
                var enumerator = arr.GetFastEnumerator();
                while (enumerator.MoveNext())
                {
                    var newvalue = evaluator == null
                        ? regex.Replace(enumerator.CurrentValue.ToStringOrThrow(ctx), replacement, limit)
                        : regex.Replace(enumerator.CurrentValue.ToStringOrThrow(ctx), evaluator, limit);

                    enumerator.CurrentValue = PhpValue.Create(newvalue);
                }

                return(PhpValue.Create(arr));
            }
        }
Exemple #4
0
        public static PhpArray preg_split(string pattern, string subject, int limit = -1, int flags = 0)
        {
            if (limit == 0) // 0 does not make sense, php's behavior is as it is -1
            {
                limit = -1;
            }
            if (limit < -1) // for all other negative values it seems that is as limit == 1
            {
                limit = 1;
            }

            var regex = new PerlRegex.Regex(pattern);

            //if (!regex.IsValid) return null;

            var m = regex.Match(subject);

            bool     offset_capture = (flags & PREG_SPLIT_OFFSET_CAPTURE) != 0;
            PhpArray result         = new PhpArray();
            int      last_index     = 0;

            while (m.Success && (limit == -1 || --limit > 0) && last_index < subject.Length)
            {
                // add part before match
                int length = m.Index - last_index;
                if (length > 0 || (flags & PREG_SPLIT_NO_EMPTY) == 0)
                {
                    result.Add(NewArrayItem(subject.Substring(last_index, length), last_index, offset_capture));
                }

                if (m.Value.Length > 0)
                {
                    if ((flags & PREG_SPLIT_DELIM_CAPTURE) != 0)    // add all captures but not whole pattern match (start at 1)
                    {
                        List <object> lastUnsucessfulGroups = null; // value of groups that was not successful since last succesful one
                        for (int i = 1; i < m.Groups.Count; i++)
                        {
                            Group g = m.Groups[i];
                            if (g.Length > 0 || (flags & PREG_SPLIT_NO_EMPTY) == 0)
                            {
                                // the value to be added into the result:
                                object value = NewArrayItem(g.Value, g.Index, offset_capture);

                                if (g.Success)
                                {
                                    // group {i} was matched:
                                    // if there was some unsuccesfull matches before, add them now:
                                    if (lastUnsucessfulGroups != null && lastUnsucessfulGroups.Count > 0)
                                    {
                                        foreach (var x in lastUnsucessfulGroups)
                                        {
                                            result.Add(x);
                                        }
                                        lastUnsucessfulGroups.Clear();
                                    }
                                    // add the matched group:
                                    result.Add(value);
                                }
                                else
                                {
                                    // The match was unsuccesful, remember all the unsuccesful matches
                                    // and add them only if some succesful match will follow.
                                    // In PHP, unsuccessfully matched groups are trimmed by the end
                                    // (regexp processing stops when other groups cannot be matched):
                                    if (lastUnsucessfulGroups == null)
                                    {
                                        lastUnsucessfulGroups = new List <object>();
                                    }
                                    lastUnsucessfulGroups.Add(value);
                                }
                            }
                        }
                    }

                    last_index = m.Index + m.Length;
                }
                else // regular expression match an empty string => add one character
                {
                    // always not empty
                    result.Add(NewArrayItem(subject.Substring(last_index, 1), last_index, offset_capture));
                    last_index++;
                }

                m = m.NextMatch();
            }

            // add remaining string (might be empty)
            if (last_index < subject.Length || (flags & PREG_SPLIT_NO_EMPTY) == 0)
            {
                result.Add(NewArrayItem(subject.Substring(last_index), last_index, offset_capture));
            }

            return(result);
        }
Exemple #5
0
        /// <summary>
        /// Perform a regular expression match.
        /// </summary>
        static int Match(Context ctx, string pattern, string subject, out PhpArray matches, int flags, long offset, bool matchAll)
        {
            var regex = new PerlRegex.Regex(pattern);
            var m     = regex.Match(subject, (offset < subject.Length) ? (int)offset : subject.Length);

            if ((regex.Options & PerlRegex.RegexOptions.PCRE_ANCHORED) != 0 && m.Success && m.Index != offset)
            {
                matches = PhpArray.NewEmpty();
                return(-1);
            }

            if (m.Success)
            {
                if (!matchAll || (flags & PREG_PATTERN_ORDER) != 0)
                {
                    matches = new PhpArray(m.Groups.Count);
                }
                else
                {
                    matches = new PhpArray();
                }

                if (!matchAll)
                {
                    GroupsToPhpArray(m.PcreGroups, (flags & PREG_OFFSET_CAPTURE) != 0, matches);
                    return(1);
                }

                // store all other matches in PhpArray matches
                if ((flags & PREG_SET_ORDER) != 0) // cannot test PatternOrder, it is 0, SetOrder must be tested
                {
                    return(FillMatchesArrayAllSetOrder(regex, m, ref matches, (flags & PREG_OFFSET_CAPTURE) != 0));
                }
                else
                {
                    return(FillMatchesArrayAllPatternOrder(regex, m, ref matches, (flags & PREG_OFFSET_CAPTURE) != 0));
                }
            }

            // no match has been found
            if (matchAll && (flags & PREG_SET_ORDER) == 0)
            {
                // in that case PHP returns an array filled with empty arrays according to parentheses count
                matches = new PhpArray(m.Groups.Count);
                for (int i = 0; i < regex.GetGroupNumbers().Length; i++)
                {
                    AddGroupNameToResult(regex, matches, i, (ms, groupName) =>
                    {
                        ms[groupName] = (PhpValue) new PhpArray();
                    });

                    matches[i] = (PhpValue) new PhpArray();
                }
            }
            else
            {
                matches = PhpArray.NewEmpty(); // empty array
            }

            return(0);
        }
Exemple #6
0
        public static int preg_match(Context ctx, string pattern, string subject)
        {
            var regex = new PerlRegex.Regex(pattern);

            return(regex.Match(subject).Success ? 1 : 0);
        }