Example #1
0
func ReplaceAllSubmatchFunc(re *regexp.Regexp, b []byte, f func(s []byte) []byte) []byte {
	idxs := re.FindAllSubmatchIndex(b, -1)
	if len(idxs) == 0 {
		return b
	}
	l := len(idxs)
	ret := append([]byte{}, b[:idxs[0][0]]...)
	for i, pair := range idxs {
		// replace internal submatch with result of user supplied function
		ret = append(ret, f(b[pair[2]:pair[3]])...)
		if i+1 < l {
			ret = append(ret, b[pair[1]:idxs[i+1][0]]...)
		}
	}
	ret = append(ret, b[idxs[len(idxs)-1][1]:]...)
	return ret
}
Example #2
0
func builtinString_replace(call FunctionCall) Value {
	checkObjectCoercible(call.This)
	target := []byte(toString(call.This))
	searchValue := call.Argument(0)
	searchObject := searchValue._object()

	// TODO If a capture is -1?
	var search *regexp.Regexp
	global := false
	find := 1
	if searchValue.IsObject() && searchObject.class == "RegExp" {
		regExp := searchObject.regExpValue()
		search = regExp.regularExpression
		if regExp.global {
			find = -1
		}
	} else {
		search = regexp.MustCompile(regexp.QuoteMeta(toString(searchValue)))
	}

	found := search.FindAllSubmatchIndex(target, find)
	if found == nil {
		return toValue_string(string(target)) // !match
	}

	{
		lastIndex := 0
		result := []byte{}

		replaceValue := call.Argument(1)
		if replaceValue.isCallable() {
			target := string(target)
			replace := replaceValue._object()
			for _, match := range found {
				if match[0] != lastIndex {
					result = append(result, target[lastIndex:match[0]]...)
				}
				matchCount := len(match) / 2
				argumentList := make([]Value, matchCount+2)
				for index := 0; index < matchCount; index++ {
					offset := 2 * index
					if match[offset] != -1 {
						argumentList[index] = toValue_string(target[match[offset]:match[offset+1]])
					} else {
						argumentList[index] = UndefinedValue()
					}
				}
				argumentList[matchCount+0] = toValue_int(match[0])
				argumentList[matchCount+1] = toValue_string(target)
				replacement := toString(replace.Call(UndefinedValue(), argumentList))
				result = append(result, []byte(replacement)...)
				lastIndex = match[1]
			}

		} else {
			replace := []byte(toString(replaceValue))
			for _, match := range found {
				result = builtinString_findAndReplaceString(result, lastIndex, match, target, replace)
				lastIndex = match[1]
			}
		}

		if lastIndex != len(target) {
			result = append(result, target[lastIndex:]...)
		}

		if global && searchObject != nil {
			searchObject.put("lastIndex", toValue_int(lastIndex), true)
		}

		return toValue_string(string(result))
	}

	return UndefinedValue()
}