string_ascii.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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.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 isRangeErr(err) {
  111. err = nil
  112. }
  113. return f, err
  114. }
  115. func (s asciiString) ToInteger() int64 {
  116. if s == "" {
  117. return 0
  118. }
  119. if s == "Infinity" || s == "+Infinity" {
  120. return math.MaxInt64
  121. }
  122. if s == "-Infinity" {
  123. return math.MinInt64
  124. }
  125. i, err := s._toInt()
  126. if err != nil {
  127. f, err := s._toFloat()
  128. if err == nil {
  129. return int64(f)
  130. }
  131. }
  132. return i
  133. }
  134. func (s asciiString) toString() String {
  135. return s
  136. }
  137. func (s asciiString) ToString() Value {
  138. return s
  139. }
  140. func (s asciiString) String() string {
  141. return string(s)
  142. }
  143. func (s asciiString) ToFloat() float64 {
  144. if s == "" {
  145. return 0
  146. }
  147. if s == "Infinity" || s == "+Infinity" {
  148. return math.Inf(1)
  149. }
  150. if s == "-Infinity" {
  151. return math.Inf(-1)
  152. }
  153. f, err := s._toFloat()
  154. if err != nil {
  155. i, err := s._toInt()
  156. if err == nil {
  157. return float64(i)
  158. }
  159. f = math.NaN()
  160. }
  161. return f
  162. }
  163. func (s asciiString) ToBoolean() bool {
  164. return s != ""
  165. }
  166. func (s asciiString) ToNumber() Value {
  167. if s == "" {
  168. return intToValue(0)
  169. }
  170. if s == "Infinity" || s == "+Infinity" {
  171. return _positiveInf
  172. }
  173. if s == "-Infinity" {
  174. return _negativeInf
  175. }
  176. if i, err := s._toInt(); err == nil {
  177. return intToValue(i)
  178. }
  179. if f, err := s._toFloat(); err == nil {
  180. return floatToValue(f)
  181. }
  182. return _NaN
  183. }
  184. func (s asciiString) ToObject(r *Runtime) *Object {
  185. return r._newString(s, r.getStringPrototype())
  186. }
  187. func (s asciiString) SameAs(other Value) bool {
  188. return s.StrictEquals(other)
  189. }
  190. func (s asciiString) Equals(other Value) bool {
  191. if s.StrictEquals(other) {
  192. return true
  193. }
  194. if o, ok := other.(valueInt); ok {
  195. if o1, e := s._toInt(); e == nil {
  196. return o1 == int64(o)
  197. }
  198. return false
  199. }
  200. if o, ok := other.(valueFloat); ok {
  201. return s.ToFloat() == float64(o)
  202. }
  203. if o, ok := other.(valueBool); ok {
  204. if o1, e := s._toFloat(); e == nil {
  205. return o1 == o.ToFloat()
  206. }
  207. return false
  208. }
  209. if o, ok := other.(*Object); ok {
  210. return s.Equals(o.toPrimitive())
  211. }
  212. return false
  213. }
  214. func (s asciiString) StrictEquals(other Value) bool {
  215. if otherStr, ok := other.(asciiString); ok {
  216. return s == otherStr
  217. }
  218. if otherStr, ok := other.(*importedString); ok {
  219. if otherStr.u == nil {
  220. return string(s) == otherStr.s
  221. }
  222. }
  223. return false
  224. }
  225. func (s asciiString) baseObject(r *Runtime) *Object {
  226. ss := r.getStringSingleton()
  227. ss.value = s
  228. ss.setLength()
  229. return ss.val
  230. }
  231. func (s asciiString) hash(hash *maphash.Hash) uint64 {
  232. _, _ = hash.WriteString(string(s))
  233. h := hash.Sum64()
  234. hash.Reset()
  235. return h
  236. }
  237. func (s asciiString) CharAt(idx int) uint16 {
  238. return uint16(s[idx])
  239. }
  240. func (s asciiString) Length() int {
  241. return len(s)
  242. }
  243. func (s asciiString) Concat(other String) String {
  244. a, u := devirtualizeString(other)
  245. if u != nil {
  246. b := make([]uint16, len(s)+len(u))
  247. b[0] = unistring.BOM
  248. for i := 0; i < len(s); i++ {
  249. b[i+1] = uint16(s[i])
  250. }
  251. copy(b[len(s)+1:], u[1:])
  252. return unicodeString(b)
  253. }
  254. return s + a
  255. }
  256. func (s asciiString) Substring(start, end int) String {
  257. return s[start:end]
  258. }
  259. func (s asciiString) CompareTo(other String) int {
  260. switch other := other.(type) {
  261. case asciiString:
  262. return strings.Compare(string(s), string(other))
  263. case unicodeString:
  264. return strings.Compare(string(s), other.String())
  265. case *importedString:
  266. return strings.Compare(string(s), other.s)
  267. default:
  268. panic(newTypeError("Internal bug: unknown string type: %T", other))
  269. }
  270. }
  271. func (s asciiString) index(substr String, start int) int {
  272. a, u := devirtualizeString(substr)
  273. if u == nil {
  274. if start > len(s) {
  275. return -1
  276. }
  277. p := strings.Index(string(s[start:]), string(a))
  278. if p >= 0 {
  279. return p + start
  280. }
  281. }
  282. return -1
  283. }
  284. func (s asciiString) lastIndex(substr String, pos int) int {
  285. a, u := devirtualizeString(substr)
  286. if u == nil {
  287. end := pos + len(a)
  288. var ss string
  289. if end > len(s) {
  290. ss = string(s)
  291. } else {
  292. ss = string(s[:end])
  293. }
  294. return strings.LastIndex(ss, string(a))
  295. }
  296. return -1
  297. }
  298. func (s asciiString) toLower() String {
  299. return asciiString(strings.ToLower(string(s)))
  300. }
  301. func (s asciiString) toUpper() String {
  302. return asciiString(strings.ToUpper(string(s)))
  303. }
  304. func (s asciiString) toTrimmedUTF8() string {
  305. return strings.TrimSpace(string(s))
  306. }
  307. func (s asciiString) string() unistring.String {
  308. return unistring.String(s)
  309. }
  310. func (s asciiString) Export() interface{} {
  311. return string(s)
  312. }
  313. func (s asciiString) ExportType() reflect.Type {
  314. return reflectTypeString
  315. }