src.dualinventive.com/go/devsim/vendor/github.com/dop251/goja/string_ascii.go

314 lines
5.7 KiB
Go

package goja
import (
"fmt"
"io"
"math"
"reflect"
"strconv"
"strings"
)
type asciiString string
type asciiRuneReader struct {
s asciiString
pos int
}
func (rr *asciiRuneReader) ReadRune() (r rune, size int, err error) {
if rr.pos < len(rr.s) {
r = rune(rr.s[rr.pos])
size = 1
rr.pos++
} else {
err = io.EOF
}
return
}
func (s asciiString) reader(start int) io.RuneReader {
return &asciiRuneReader{
s: s[start:],
}
}
// ss must be trimmed
func strToInt(ss string) (int64, error) {
if ss == "" {
return 0, nil
}
if ss == "-0" {
return 0, strconv.ErrSyntax
}
if len(ss) > 2 {
switch ss[:2] {
case "0x", "0X":
i, _ := strconv.ParseInt(ss[2:], 16, 64)
return i, nil
case "0b", "0B":
i, _ := strconv.ParseInt(ss[2:], 2, 64)
return i, nil
case "0o", "0O":
i, _ := strconv.ParseInt(ss[2:], 8, 64)
return i, nil
}
}
return strconv.ParseInt(ss, 10, 64)
}
func (s asciiString) _toInt() (int64, error) {
return strToInt(strings.TrimSpace(string(s)))
}
func isRangeErr(err error) bool {
if err, ok := err.(*strconv.NumError); ok {
return err.Err == strconv.ErrRange
}
return false
}
func (s asciiString) _toFloat() (float64, error) {
ss := strings.TrimSpace(string(s))
if ss == "" {
return 0, nil
}
if ss == "-0" {
var f float64
return -f, nil
}
f, err := strconv.ParseFloat(ss, 64)
if isRangeErr(err) {
err = nil
}
return f, err
}
func (s asciiString) ToInteger() int64 {
if s == "" {
return 0
}
if s == "Infinity" || s == "+Infinity" {
return math.MaxInt64
}
if s == "-Infinity" {
return math.MinInt64
}
i, err := s._toInt()
if err != nil {
f, err := s._toFloat()
if err == nil {
return int64(f)
}
}
return i
}
func (s asciiString) ToString() valueString {
return s
}
func (s asciiString) String() string {
return string(s)
}
func (s asciiString) ToFloat() float64 {
if s == "" {
return 0
}
if s == "Infinity" || s == "+Infinity" {
return math.Inf(1)
}
if s == "-Infinity" {
return math.Inf(-1)
}
f, err := s._toFloat()
if err != nil {
i, err := s._toInt()
if err == nil {
return float64(i)
}
f = math.NaN()
}
return f
}
func (s asciiString) ToBoolean() bool {
return s != ""
}
func (s asciiString) ToNumber() Value {
if s == "" {
return intToValue(0)
}
if s == "Infinity" || s == "+Infinity" {
return _positiveInf
}
if s == "-Infinity" {
return _negativeInf
}
if i, err := s._toInt(); err == nil {
return intToValue(i)
}
if f, err := s._toFloat(); err == nil {
return floatToValue(f)
}
return _NaN
}
func (s asciiString) ToObject(r *Runtime) *Object {
return r._newString(s)
}
func (s asciiString) SameAs(other Value) bool {
if otherStr, ok := other.(asciiString); ok {
return s == otherStr
}
return false
}
func (s asciiString) Equals(other Value) bool {
if o, ok := other.(asciiString); ok {
return s == o
}
if o, ok := other.assertInt(); ok {
if o1, e := s._toInt(); e == nil {
return o1 == o
}
return false
}
if o, ok := other.assertFloat(); ok {
return s.ToFloat() == o
}
if o, ok := other.(valueBool); ok {
if o1, e := s._toFloat(); e == nil {
return o1 == o.ToFloat()
}
return false
}
if o, ok := other.(*Object); ok {
return s.Equals(o.self.toPrimitive())
}
return false
}
func (s asciiString) StrictEquals(other Value) bool {
if otherStr, ok := other.(asciiString); ok {
return s == otherStr
}
return false
}
func (s asciiString) assertInt() (int64, bool) {
return 0, false
}
func (s asciiString) assertFloat() (float64, bool) {
return 0, false
}
func (s asciiString) assertString() (valueString, bool) {
return s, true
}
func (s asciiString) baseObject(r *Runtime) *Object {
ss := r.stringSingleton
ss.value = s
ss.setLength()
return ss.val
}
func (s asciiString) charAt(idx int64) rune {
return rune(s[idx])
}
func (s asciiString) length() int64 {
return int64(len(s))
}
func (s asciiString) concat(other valueString) valueString {
switch other := other.(type) {
case asciiString:
b := make([]byte, len(s)+len(other))
copy(b, s)
copy(b[len(s):], other)
return asciiString(b)
//return asciiString(string(s) + string(other))
case unicodeString:
b := make([]uint16, len(s)+len(other))
for i := 0; i < len(s); i++ {
b[i] = uint16(s[i])
}
copy(b[len(s):], other)
return unicodeString(b)
default:
panic(fmt.Errorf("Unknown string type: %T", other))
}
}
func (s asciiString) substring(start, end int64) valueString {
return asciiString(s[start:end])
}
func (s asciiString) compareTo(other valueString) int {
switch other := other.(type) {
case asciiString:
return strings.Compare(string(s), string(other))
case unicodeString:
return strings.Compare(string(s), other.String())
default:
panic(fmt.Errorf("Unknown string type: %T", other))
}
}
func (s asciiString) index(substr valueString, start int64) int64 {
if substr, ok := substr.(asciiString); ok {
p := int64(strings.Index(string(s[start:]), string(substr)))
if p >= 0 {
return p + start
}
}
return -1
}
func (s asciiString) lastIndex(substr valueString, pos int64) int64 {
if substr, ok := substr.(asciiString); ok {
end := pos + int64(len(substr))
var ss string
if end > int64(len(s)) {
ss = string(s)
} else {
ss = string(s[:end])
}
return int64(strings.LastIndex(ss, string(substr)))
}
return -1
}
func (s asciiString) toLower() valueString {
return asciiString(strings.ToLower(string(s)))
}
func (s asciiString) toUpper() valueString {
return asciiString(strings.ToUpper(string(s)))
}
func (s asciiString) toTrimmedUTF8() string {
return strings.TrimSpace(string(s))
}
func (s asciiString) Export() interface{} {
return string(s)
}
func (s asciiString) ExportType() reflect.Type {
return reflectTypeString
}