string_ascii.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. package goja
  2. import (
  3. "fmt"
  4. "hash/maphash"
  5. "io"
  6. "math"
  7. "reflect"
  8. "strconv"
  9. "strings"
  10. "github.com/dop251/goja/unistring"
  11. )
  12. type asciiString string
  13. type asciiRuneReader struct {
  14. s asciiString
  15. pos int
  16. }
  17. func (rr *asciiRuneReader) ReadRune() (r rune, size int, err error) {
  18. if rr.pos < len(rr.s) {
  19. r = rune(rr.s[rr.pos])
  20. size = 1
  21. rr.pos++
  22. } else {
  23. err = io.EOF
  24. }
  25. return
  26. }
  27. func (s asciiString) reader(start int) io.RuneReader {
  28. return &asciiRuneReader{
  29. s: s[start:],
  30. }
  31. }
  32. func (s asciiString) utf16Reader(start int) io.RuneReader {
  33. return s.reader(start)
  34. }
  35. func (s asciiString) utf16Runes() []rune {
  36. runes := make([]rune, len(s))
  37. for i := 0; i < len(s); i++ {
  38. runes[i] = rune(s[i])
  39. }
  40. return runes
  41. }
  42. // ss must be trimmed
  43. func stringToInt(ss string) (int64, error) {
  44. if ss == "" {
  45. return 0, nil
  46. }
  47. if ss == "-0" {
  48. return 0, strconv.ErrSyntax
  49. }
  50. if len(ss) > 2 {
  51. switch ss[:2] {
  52. case "0x", "0X":
  53. return strconv.ParseInt(ss[2:], 16, 64)
  54. case "0b", "0B":
  55. return strconv.ParseInt(ss[2:], 2, 64)
  56. case "0o", "0O":
  57. return strconv.ParseInt(ss[2:], 8, 64)
  58. }
  59. }
  60. return strconv.ParseInt(ss, 10, 64)
  61. }
  62. func (s asciiString) _toInt() (int64, error) {
  63. return stringToInt(strings.TrimSpace(string(s)))
  64. }
  65. func isRangeErr(err error) bool {
  66. if err, ok := err.(*strconv.NumError); ok {
  67. return err.Err == strconv.ErrRange
  68. }
  69. return false
  70. }
  71. func (s asciiString) _toFloat() (float64, error) {
  72. ss := strings.TrimSpace(string(s))
  73. if ss == "" {
  74. return 0, nil
  75. }
  76. if ss == "-0" {
  77. var f float64
  78. return -f, nil
  79. }
  80. f, err := strconv.ParseFloat(ss, 64)
  81. if isRangeErr(err) {
  82. err = nil
  83. }
  84. return f, err
  85. }
  86. func (s asciiString) ToInteger() int64 {
  87. if s == "" {
  88. return 0
  89. }
  90. if s == "Infinity" || s == "+Infinity" {
  91. return math.MaxInt64
  92. }
  93. if s == "-Infinity" {
  94. return math.MinInt64
  95. }
  96. i, err := s._toInt()
  97. if err != nil {
  98. f, err := s._toFloat()
  99. if err == nil {
  100. return int64(f)
  101. }
  102. }
  103. return i
  104. }
  105. func (s asciiString) toString() valueString {
  106. return s
  107. }
  108. func (s asciiString) ToString() Value {
  109. return s
  110. }
  111. func (s asciiString) String() string {
  112. return string(s)
  113. }
  114. func (s asciiString) ToFloat() float64 {
  115. if s == "" {
  116. return 0
  117. }
  118. if s == "Infinity" || s == "+Infinity" {
  119. return math.Inf(1)
  120. }
  121. if s == "-Infinity" {
  122. return math.Inf(-1)
  123. }
  124. f, err := s._toFloat()
  125. if err != nil {
  126. i, err := s._toInt()
  127. if err == nil {
  128. return float64(i)
  129. }
  130. f = math.NaN()
  131. }
  132. return f
  133. }
  134. func (s asciiString) ToBoolean() bool {
  135. return s != ""
  136. }
  137. func (s asciiString) ToNumber() Value {
  138. if s == "" {
  139. return intToValue(0)
  140. }
  141. if s == "Infinity" || s == "+Infinity" {
  142. return _positiveInf
  143. }
  144. if s == "-Infinity" {
  145. return _negativeInf
  146. }
  147. if i, err := s._toInt(); err == nil {
  148. return intToValue(i)
  149. }
  150. if f, err := s._toFloat(); err == nil {
  151. return floatToValue(f)
  152. }
  153. return _NaN
  154. }
  155. func (s asciiString) ToObject(r *Runtime) *Object {
  156. return r._newString(s, r.global.StringPrototype)
  157. }
  158. func (s asciiString) SameAs(other Value) bool {
  159. if otherStr, ok := other.(asciiString); ok {
  160. return s == otherStr
  161. }
  162. return false
  163. }
  164. func (s asciiString) Equals(other Value) bool {
  165. if o, ok := other.(asciiString); ok {
  166. return s == o
  167. }
  168. if o, ok := other.(valueInt); ok {
  169. if o1, e := s._toInt(); e == nil {
  170. return o1 == int64(o)
  171. }
  172. return false
  173. }
  174. if o, ok := other.(valueFloat); ok {
  175. return s.ToFloat() == float64(o)
  176. }
  177. if o, ok := other.(valueBool); ok {
  178. if o1, e := s._toFloat(); e == nil {
  179. return o1 == o.ToFloat()
  180. }
  181. return false
  182. }
  183. if o, ok := other.(*Object); ok {
  184. return s.Equals(o.toPrimitive())
  185. }
  186. return false
  187. }
  188. func (s asciiString) StrictEquals(other Value) bool {
  189. if otherStr, ok := other.(asciiString); ok {
  190. return s == otherStr
  191. }
  192. return false
  193. }
  194. func (s asciiString) baseObject(r *Runtime) *Object {
  195. ss := r.stringSingleton
  196. ss.value = s
  197. ss.setLength()
  198. return ss.val
  199. }
  200. func (s asciiString) hash(hash *maphash.Hash) uint64 {
  201. _, _ = hash.WriteString(string(s))
  202. h := hash.Sum64()
  203. hash.Reset()
  204. return h
  205. }
  206. func (s asciiString) charAt(idx int) rune {
  207. return rune(s[idx])
  208. }
  209. func (s asciiString) length() int {
  210. return len(s)
  211. }
  212. func (s asciiString) concat(other valueString) valueString {
  213. switch other := other.(type) {
  214. case asciiString:
  215. b := make([]byte, len(s)+len(other))
  216. copy(b, s)
  217. copy(b[len(s):], other)
  218. return asciiString(b)
  219. case unicodeString:
  220. b := make([]uint16, len(s)+len(other))
  221. b[0] = unistring.BOM
  222. for i := 0; i < len(s); i++ {
  223. b[i+1] = uint16(s[i])
  224. }
  225. copy(b[len(s)+1:], other[1:])
  226. return unicodeString(b)
  227. default:
  228. panic(fmt.Errorf("unknown string type: %T", other))
  229. }
  230. }
  231. func (s asciiString) substring(start, end int) valueString {
  232. return s[start:end]
  233. }
  234. func (s asciiString) compareTo(other valueString) int {
  235. switch other := other.(type) {
  236. case asciiString:
  237. return strings.Compare(string(s), string(other))
  238. case unicodeString:
  239. return strings.Compare(string(s), other.String())
  240. default:
  241. panic(fmt.Errorf("unknown string type: %T", other))
  242. }
  243. }
  244. func (s asciiString) index(substr valueString, start int) int {
  245. if substr, ok := substr.(asciiString); ok {
  246. p := strings.Index(string(s[start:]), string(substr))
  247. if p >= 0 {
  248. return p + start
  249. }
  250. }
  251. return -1
  252. }
  253. func (s asciiString) lastIndex(substr valueString, pos int) int {
  254. if substr, ok := substr.(asciiString); ok {
  255. end := pos + len(substr)
  256. var ss string
  257. if end > len(s) {
  258. ss = string(s)
  259. } else {
  260. ss = string(s[:end])
  261. }
  262. return strings.LastIndex(ss, string(substr))
  263. }
  264. return -1
  265. }
  266. func (s asciiString) toLower() valueString {
  267. return asciiString(strings.ToLower(string(s)))
  268. }
  269. func (s asciiString) toUpper() valueString {
  270. return asciiString(strings.ToUpper(string(s)))
  271. }
  272. func (s asciiString) toTrimmedUTF8() string {
  273. return strings.TrimSpace(string(s))
  274. }
  275. func (s asciiString) string() unistring.String {
  276. return unistring.String(s)
  277. }
  278. func (s asciiString) Export() interface{} {
  279. return string(s)
  280. }
  281. func (s asciiString) ExportType() reflect.Type {
  282. return reflectTypeString
  283. }