diff options
Diffstat (limited to 'Godeps/_workspace/src/github.com/obscuren/otto/builtin_string.go')
-rw-r--r-- | Godeps/_workspace/src/github.com/obscuren/otto/builtin_string.go | 504 |
1 files changed, 0 insertions, 504 deletions
diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_string.go b/Godeps/_workspace/src/github.com/obscuren/otto/builtin_string.go deleted file mode 100644 index e2c6a620c..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_string.go +++ /dev/null @@ -1,504 +0,0 @@ -package otto - -import ( - "bytes" - "regexp" - "strconv" - "strings" - "unicode/utf8" -) - -// String - -func stringValueFromStringArgumentList(argumentList []Value) Value { - if len(argumentList) > 0 { - return toValue_string(toString(argumentList[0])) - } - return toValue_string("") -} - -func builtinString(call FunctionCall) Value { - return stringValueFromStringArgumentList(call.ArgumentList) -} - -func builtinNewString(self *_object, _ Value, argumentList []Value) Value { - return toValue_object(self.runtime.newString(stringValueFromStringArgumentList(argumentList))) -} - -func builtinString_toString(call FunctionCall) Value { - return call.thisClassObject("String").primitiveValue() -} -func builtinString_valueOf(call FunctionCall) Value { - return call.thisClassObject("String").primitiveValue() -} - -func builtinString_fromCharCode(call FunctionCall) Value { - chrList := make([]uint16, len(call.ArgumentList)) - for index, value := range call.ArgumentList { - chrList[index] = toUint16(value) - } - return toValue_string16(chrList) -} - -func builtinString_charAt(call FunctionCall) Value { - checkObjectCoercible(call.This) - idx := int(toInteger(call.Argument(0)).value) - chr := stringAt(call.This._object().stringValue(), idx) - if chr == utf8.RuneError { - return toValue_string("") - } - return toValue_string(string(chr)) -} - -func builtinString_charCodeAt(call FunctionCall) Value { - checkObjectCoercible(call.This) - idx := int(toInteger(call.Argument(0)).value) - chr := stringAt(call.This._object().stringValue(), idx) - if chr == utf8.RuneError { - return NaNValue() - } - return toValue_uint16(uint16(chr)) -} - -func builtinString_concat(call FunctionCall) Value { - checkObjectCoercible(call.This) - var value bytes.Buffer - value.WriteString(toString(call.This)) - for _, item := range call.ArgumentList { - value.WriteString(toString(item)) - } - return toValue_string(value.String()) -} - -func builtinString_indexOf(call FunctionCall) Value { - checkObjectCoercible(call.This) - value := toString(call.This) - target := toString(call.Argument(0)) - if 2 > len(call.ArgumentList) { - return toValue_int(strings.Index(value, target)) - } - start := toIntegerFloat(call.Argument(1)) - if 0 > start { - start = 0 - } else if start >= float64(len(value)) { - if target == "" { - return toValue_int(len(value)) - } - return toValue_int(-1) - } - index := strings.Index(value[int(start):], target) - if index >= 0 { - index += int(start) - } - return toValue_int(index) -} - -func builtinString_lastIndexOf(call FunctionCall) Value { - checkObjectCoercible(call.This) - value := toString(call.This) - target := toString(call.Argument(0)) - if 2 > len(call.ArgumentList) || call.ArgumentList[1].IsUndefined() { - return toValue_int(strings.LastIndex(value, target)) - } - length := len(value) - if length == 0 { - return toValue_int(strings.LastIndex(value, target)) - } - start := toInteger(call.ArgumentList[1]) - if !start.valid() { - // startNumber is infinity, so start is the end of string (start = length) - return toValue_int(strings.LastIndex(value, target)) - } - if 0 > start.value { - start.value = 0 - } - end := int(start.value) + len(target) - if end > length { - end = length - } - return toValue_int(strings.LastIndex(value[:end], target)) -} - -func builtinString_match(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := toString(call.This) - matcherValue := call.Argument(0) - matcher := matcherValue._object() - if !matcherValue.IsObject() || matcher.class != "RegExp" { - matcher = call.runtime.newRegExp(matcherValue, UndefinedValue()) - } - global := toBoolean(matcher.get("global")) - if !global { - match, result := execRegExp(matcher, target) - if !match { - return NullValue() - } - return toValue_object(execResultToArray(call.runtime, target, result)) - } - - { - result := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1) - matchCount := len(result) - if result == nil { - matcher.put("lastIndex", toValue_int(0), true) - return UndefinedValue() // !match - } - matchCount = len(result) - valueArray := make([]Value, matchCount) - for index := 0; index < matchCount; index++ { - valueArray[index] = toValue_string(target[result[index][0]:result[index][1]]) - } - matcher.put("lastIndex", toValue_int(result[matchCount-1][1]), true) - return toValue_object(call.runtime.newArrayOf(valueArray)) - } -} - -var builtinString_replace_Regexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])") - -func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) (output []byte) { - matchCount := len(match) / 2 - output = input - if match[0] != lastIndex { - output = append(output, target[lastIndex:match[0]]...) - } - replacement := builtinString_replace_Regexp.ReplaceAllFunc(replaceValue, func(part []byte) []byte { - // TODO Check if match[0] or match[1] can be -1 in this scenario - switch part[1] { - case '$': - return []byte{'$'} - case '&': - return target[match[0]:match[1]] - case '`': - return target[:match[0]] - case '\'': - return target[match[1]:len(target)] - } - matchNumberParse, error := strconv.ParseInt(string(part[1:]), 10, 64) - matchNumber := int(matchNumberParse) - if error != nil || matchNumber >= matchCount { - return []byte{} - } - offset := 2 * matchNumber - if match[offset] != -1 { - return target[match[offset]:match[offset+1]] - } - return []byte{} // The empty string - }) - output = append(output, replacement...) - return output -} - -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() -} - -func builtinString_search(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := toString(call.This) - searchValue := call.Argument(0) - search := searchValue._object() - if !searchValue.IsObject() || search.class != "RegExp" { - search = call.runtime.newRegExp(searchValue, UndefinedValue()) - } - result := search.regExpValue().regularExpression.FindStringIndex(target) - if result == nil { - return toValue_int(-1) - } - return toValue_int(result[0]) -} - -func stringSplitMatch(target string, targetLength int64, index uint, search string, searchLength int64) (bool, uint) { - if int64(index)+searchLength > searchLength { - return false, 0 - } - found := strings.Index(target[index:], search) - if 0 > found { - return false, 0 - } - return true, uint(found) -} - -func builtinString_split(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := toString(call.This) - - separatorValue := call.Argument(0) - limitValue := call.Argument(1) - limit := -1 - if limitValue.IsDefined() { - limit = int(toUint32(limitValue)) - } - - if limit == 0 { - return toValue_object(call.runtime.newArray(0)) - } - - if separatorValue.IsUndefined() { - return toValue_object(call.runtime.newArrayOf([]Value{toValue_string(target)})) - } - - if separatorValue.isRegExp() { - targetLength := len(target) - search := separatorValue._object().regExpValue().regularExpression - valueArray := []Value{} - result := search.FindAllStringSubmatchIndex(target, -1) - lastIndex := 0 - found := 0 - - for _, match := range result { - if match[0] == match[1] { - // FIXME Ugh, this is a hack - if match[0] == 0 || match[0] == targetLength { - continue - } - } - - if lastIndex != match[0] { - valueArray = append(valueArray, toValue_string(target[lastIndex:match[0]])) - found++ - } else if lastIndex == match[0] { - if lastIndex != -1 { - valueArray = append(valueArray, toValue_string("")) - found++ - } - } - - lastIndex = match[1] - if found == limit { - goto RETURN - } - - captureCount := len(match) / 2 - for index := 1; index < captureCount; index++ { - offset := index * 2 - value := UndefinedValue() - if match[offset] != -1 { - value = toValue_string(target[match[offset]:match[offset+1]]) - } - valueArray = append(valueArray, value) - found++ - if found == limit { - goto RETURN - } - } - } - - if found != limit { - if lastIndex != targetLength { - valueArray = append(valueArray, toValue_string(target[lastIndex:targetLength])) - } else { - valueArray = append(valueArray, toValue_string("")) - } - } - - RETURN: - return toValue_object(call.runtime.newArrayOf(valueArray)) - - } else { - separator := toString(separatorValue) - - splitLimit := limit - excess := false - if limit > 0 { - splitLimit = limit + 1 - excess = true - } - - split := strings.SplitN(target, separator, splitLimit) - - if excess && len(split) > limit { - split = split[:limit] - } - - valueArray := make([]Value, len(split)) - for index, value := range split { - valueArray[index] = toValue_string(value) - } - - return toValue_object(call.runtime.newArrayOf(valueArray)) - } - - return UndefinedValue() -} - -func builtinString_slice(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := toString(call.This) - - length := int64(len(target)) - start, end := rangeStartEnd(call.ArgumentList, length, false) - if end-start <= 0 { - return toValue_string("") - } - return toValue_string(target[start:end]) -} - -func builtinString_substring(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := toString(call.This) - - length := int64(len(target)) - start, end := rangeStartEnd(call.ArgumentList, length, true) - if start > end { - start, end = end, start - } - return toValue_string(target[start:end]) -} - -func builtinString_substr(call FunctionCall) Value { - target := toString(call.This) - - size := int64(len(target)) - start, length := rangeStartLength(call.ArgumentList, size) - - if start >= size { - return toValue_string("") - } - - if length <= 0 { - return toValue_string("") - } - - if start+length >= size { - // Cap length to be to the end of the string - // start = 3, length = 5, size = 4 [0, 1, 2, 3] - // 4 - 3 = 1 - // target[3:4] - length = size - start - } - - return toValue_string(target[start : start+length]) -} - -func builtinString_toLowerCase(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue_string(strings.ToLower(toString(call.This))) -} - -func builtinString_toUpperCase(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue_string(strings.ToUpper(toString(call.This))) -} - -// 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters -const builtinString_trim_whitespace = "\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF" - -func builtinString_trim(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue(strings.Trim(toString(call.This), - builtinString_trim_whitespace)) -} - -// Mozilla extension, not ECMAScript 5 -func builtinString_trimLeft(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue(strings.TrimLeft(toString(call.This), - builtinString_trim_whitespace)) -} - -// Mozilla extension, not ECMAScript 5 -func builtinString_trimRight(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue(strings.TrimRight(toString(call.This), - builtinString_trim_whitespace)) -} - -func builtinString_localeCompare(call FunctionCall) Value { - checkObjectCoercible(call.This) - this := toString(call.This) - that := toString(call.Argument(0)) - if this < that { - return toValue_int(-1) - } else if this == that { - return toValue_int(0) - } - return toValue_int(1) -} - -/* -An alternate version of String.trim -func builtinString_trim(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue_string(strings.TrimFunc(toString(call.This), isWhiteSpaceOrLineTerminator)) -} -*/ - -func builtinString_toLocaleLowerCase(call FunctionCall) Value { - return builtinString_toLowerCase(call) -} - -func builtinString_toLocaleUpperCase(call FunctionCall) Value { - return builtinString_toUpperCase(call) -} |