/// <summary> /// Private mehtod implementing all replace methods. Just one of <paramref name="replacement"/> or <paramref name="callback" /> should be used. /// </summary> /// <param name="context">Current <see cref="ScriptContext"/>. Must not be null.</param> /// <param name="self">Instance of object that called the replace method (replace pattern may contain $this)</param> /// <param name="definedVariables"></param> /// <param name="pattern"></param> /// <param name="replacement"></param> /// <param name="callback"></param> /// <param name="data"></param> /// <param name="limit"></param> /// <param name="count"></param> /// <returns>String or an array.</returns> private static object Replace(ScriptContext/*!*/context, DObject self, Dictionary<string, object> definedVariables, object pattern, object replacement, PhpCallback callback, object data, int limit, ref int count) { // if we have no replacement and no callback, matches are deleted (replaced by an empty string) if (replacement == null && callback == null) replacement = String.Empty; // exactly one of replacement or callback is valid now Debug.Assert(replacement != null ^ callback != null); // get eval info if it has been captured - is needed even if we do not need them later SourceCodeDescriptor descriptor = context.GetCapturedSourceCodeDescriptor(); // PHP's behaviour for undocumented limit range if (limit < -1) limit = 0; PhpArray replacement_array = replacement as PhpArray; string replacement_string = null; if (replacement_array == null && replacement != null) replacement_string = Core.Convert.ObjectToString(replacement); // we should return new array, if there is an array passed as subject, it should remain unchanged: object data_copy = PhpVariable.DeepCopy(data); PhpArray pattern_array = pattern as PhpArray; if (pattern_array == null) { // string pattern // string replacement if (replacement_array != null) { // string pattern and array replacement not allowed: PhpException.InvalidArgument("replacement", LibResources.GetString("replacement_array_pattern_not")); return null; } // pattern should be treated as string and therefore replacement too: return SimpleReplace(self, definedVariables, pattern, replacement_string, callback, data_copy, limit, descriptor, ref count); } else if (replacement_array == null) { // array pattern // string replacement using (var pattern_enumerator = pattern_array.GetFastEnumerator()) while (pattern_enumerator.MoveNext()) { data_copy = SimpleReplace(self, definedVariables, pattern_enumerator.CurrentValue, replacement_string, callback, data_copy, limit, descriptor, ref count); } } else //if (replacement_array != null) { // array pattern // array replacement var replacement_enumerator = replacement_array.GetFastEnumerator(); bool replacement_valid = true; using (var pattern_enumerator = pattern_array.GetFastEnumerator()) while (pattern_enumerator.MoveNext()) { // replacements are in array, move to next item and take it if possible, in other case take empty string: if (replacement_valid && replacement_enumerator.MoveNext()) { replacement_string = Core.Convert.ObjectToString(replacement_enumerator.CurrentValue); } else { replacement_string = string.Empty; replacement_valid = false; // end of replacement_enumerator, do not call MoveNext again! } data_copy = SimpleReplace(self, definedVariables, pattern_enumerator.CurrentValue, replacement_string, callback, data_copy, limit, descriptor, ref count); } } // return resulting array or string assigned to data return data_copy; }