string_ascii.go 6.6 KB

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