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)); } }
///// <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); } }