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); }
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)); } }
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)); } }
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); }
/// <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); }
public static int preg_match(Context ctx, string pattern, string subject) { var regex = new PerlRegex.Regex(pattern); return(regex.Match(subject).Success ? 1 : 0); }