string_ascii.go 5.7 KB

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