mirror of
https://github.com/robertkrimen/otto
synced 2025-10-12 20:27:30 +08:00

This fixes #68 Some changes over the original patch, removing references to utf8string.String: * (better) This removes a dependency on a non-standard (though solid) package * (better) utf8string.String has mutable parts * (worse) utf8string.String has a smarter consecutive access approach (by remembering where the last access was) * (?) _stringWide allocates a []rune if charAt or charCodeAt access is needed (though it will only do this once for the string object)
113 lines
2.1 KiB
Go
113 lines
2.1 KiB
Go
package otto
|
|
|
|
import (
|
|
"strconv"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
type _stringObject interface {
|
|
Length() int
|
|
At(int) rune
|
|
String() string
|
|
}
|
|
|
|
type _stringASCII string
|
|
|
|
func (str _stringASCII) Length() int {
|
|
return len(str)
|
|
}
|
|
|
|
func (str _stringASCII) At(at int) rune {
|
|
return rune(str[at])
|
|
}
|
|
|
|
func (str _stringASCII) String() string {
|
|
return string(str)
|
|
}
|
|
|
|
type _stringWide struct {
|
|
string string
|
|
length int
|
|
runes []rune
|
|
}
|
|
|
|
func (str _stringWide) Length() int {
|
|
return str.length
|
|
}
|
|
|
|
func (str _stringWide) At(at int) rune {
|
|
if str.runes == nil {
|
|
str.runes = []rune(str.string)
|
|
}
|
|
return str.runes[at]
|
|
}
|
|
|
|
func (str _stringWide) String() string {
|
|
return str.string
|
|
}
|
|
|
|
func _newStringObject(str string) _stringObject {
|
|
for i := 0; i < len(str); i++ {
|
|
if str[i] >= utf8.RuneSelf {
|
|
goto wide
|
|
}
|
|
}
|
|
|
|
return _stringASCII(str)
|
|
|
|
wide:
|
|
return &_stringWide{
|
|
string: str,
|
|
length: utf8.RuneCountInString(str),
|
|
}
|
|
}
|
|
|
|
func stringAt(str _stringObject, index int) rune {
|
|
if 0 <= index && index < str.Length() {
|
|
return str.At(index)
|
|
}
|
|
return utf8.RuneError
|
|
}
|
|
|
|
func (runtime *_runtime) newStringObject(value Value) *_object {
|
|
str := _newStringObject(toString(value))
|
|
|
|
self := runtime.newClassObject("String")
|
|
self.defineProperty("length", toValue_int(str.Length()), 0, false)
|
|
self.objectClass = _classString
|
|
self.value = str
|
|
return self
|
|
}
|
|
|
|
func (self *_object) stringValue() _stringObject {
|
|
if str, ok := self.value.(_stringObject); ok {
|
|
return str
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func stringEnumerate(self *_object, all bool, each func(string) bool) {
|
|
if str := self.stringValue(); str != nil {
|
|
length := str.Length()
|
|
for index := 0; index < length; index++ {
|
|
if !each(strconv.FormatInt(int64(index), 10)) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
objectEnumerate(self, all, each)
|
|
}
|
|
|
|
func stringGetOwnProperty(self *_object, name string) *_property {
|
|
if property := objectGetOwnProperty(self, name); property != nil {
|
|
return property
|
|
}
|
|
// TODO Test a string of length >= +int32 + 1?
|
|
if index := stringToArrayIndex(name); index >= 0 {
|
|
if chr := stringAt(self.stringValue(), int(index)); chr != utf8.RuneError {
|
|
return &_property{toValue_string(string(chr)), 0}
|
|
}
|
|
}
|
|
return nil
|
|
}
|