gofront 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/package.json +5 -4
- package/src/backend/js/expressions.js +849 -371
- package/src/backend/js/index.js +241 -147
- package/src/backend/js/natives.js +383 -0
- package/src/backend/js/runtime.js +512 -2547
- package/src/backend/js/statements.js +506 -103
- package/src/backend/js/stdlib/index.js +45 -93
- package/src/backend/js/templ.js +32 -45
- package/src/backend/js/type-info.js +177 -13
- package/src/backend/shared/fixed-float.js +20 -0
- package/src/backend/shared/fmt-types.js +63 -171
- package/src/backend/shared/host-unicode.js +36 -0
- package/src/backend/wasm/boundary.js +490 -965
- package/src/backend/wasm/emit-builtins.js +643 -256
- package/src/backend/wasm/emit-exprs.js +124 -57
- package/src/backend/wasm/emit-maps.js +17 -367
- package/src/backend/wasm/emit-stmts.js +325 -75
- package/src/backend/wasm/emit.js +104 -13
- package/src/backend/wasm/globals.js +47 -8
- package/src/backend/wasm/glue.js +2 -4
- package/src/backend/wasm/index.js +36 -530
- package/src/backend/wasm/method-expr.js +12 -1
- package/src/backend/wasm/module-emitter.js +92 -717
- package/src/backend/wasm/monomorph.js +103 -6
- package/src/backend/wasm/natives.js +596 -0
- package/src/backend/wasm/prescan.js +5 -153
- package/src/backend/wasm/prune-funcs.js +89 -0
- package/src/backend/wasm/stdlib/index.js +2 -32
- package/src/backend/wasm/types.js +68 -20
- package/src/backend/wasm/variadic.js +3 -3
- package/src/cli/cli-core.js +5 -1
- package/src/cli/test-runner.js +115 -342
- package/src/compiler.js +108 -130
- package/src/lexer/lexer.js +105 -11
- package/src/lexer/templ-lexer.js +61 -18
- package/src/lexer/tokens.js +1 -0
- package/src/link/stdlib.js +354 -132
- package/src/link/type-names.js +148 -0
- package/src/link/wasm.js +30 -6
- package/src/lower/bounds.js +153 -0
- package/src/lower/captures.js +92 -33
- package/src/lower/embedding.js +32 -3
- package/src/lower/errors-as.js +196 -0
- package/src/lower/fmt-formatters.js +905 -0
- package/src/lower/functions.js +2 -0
- package/src/lower/gen-types.js +274 -0
- package/src/lower/index.js +7 -1
- package/src/lower/json-codecs.js +228 -247
- package/src/lower/ownership.js +25 -7
- package/src/lower/reachability.js +69 -51
- package/src/lower/walk.js +12 -0
- package/src/parser/declarations.js +28 -5
- package/src/parser/expressions.js +86 -16
- package/src/parser/statements.js +1 -0
- package/src/parser/templ.js +44 -5
- package/src/parser/types.js +1 -0
- package/src/resolver.js +1 -2
- package/src/typechecker/assignability.js +124 -11
- package/src/typechecker/const-fold.js +70 -27
- package/src/typechecker/constants.js +32 -6
- package/src/typechecker/expressions.js +326 -98
- package/src/typechecker/index.js +208 -33
- package/src/typechecker/init-order.js +136 -40
- package/src/typechecker/operand-text.js +40 -0
- package/src/typechecker/resolve.js +192 -36
- package/src/typechecker/statements.js +122 -11
- package/src/typechecker/stdlib/excluded.js +9 -5
- package/src/typechecker/stdlib/index.js +25 -9
- package/src/typechecker/termination.js +10 -1
- package/src/typechecker/types.js +203 -573
- package/stdlib/bytes/buffer.go +479 -0
- package/stdlib/bytes/bytes.go +1010 -0
- package/stdlib/bytes/reader.go +161 -0
- package/stdlib/context/context.go +115 -0
- package/stdlib/crypto/rand/rand.go +34 -0
- package/stdlib/crypto/sha256/sha256.go +249 -0
- package/stdlib/encoding/base64/base64.go +331 -0
- package/stdlib/encoding/binary/binary.go +332 -0
- package/stdlib/encoding/hex/hex.go +140 -0
- package/stdlib/encoding/json/json.go +62 -0
- package/stdlib/errors/errors.go +174 -0
- package/stdlib/fmt/errors.go +110 -0
- package/stdlib/fmt/format.go +732 -0
- package/stdlib/fmt/print.go +1232 -0
- package/stdlib/gom/gom.go +293 -0
- package/stdlib/html/html.go +251 -0
- package/stdlib/internal/fmtrt/fmtrt.go +163 -0
- package/stdlib/internal/jsonrt/dec.go +171 -38
- package/stdlib/internal/jsonrt/enc.go +186 -36
- package/stdlib/internal/jsonrt/scanner.go +17 -8
- package/stdlib/io/io.go +157 -1
- package/stdlib/maps/maps.go +131 -0
- package/stdlib/math/bits/bits.go +507 -0
- package/stdlib/math/extra.go +16 -14
- package/stdlib/math/math.go +439 -0
- package/stdlib/math/rand/rand.go +297 -0
- package/stdlib/os/os.go +93 -0
- package/stdlib/path/filepath/filepath.go +47 -0
- package/stdlib/path/path.go +394 -0
- package/stdlib/regexp/regexp.go +231 -0
- package/stdlib/slices/slices.go +526 -0
- package/stdlib/slices/sort.go +209 -0
- package/stdlib/slices/zsort_cmp.go +480 -0
- package/stdlib/slices/zsort_ordered.go +482 -0
- package/stdlib/sort/sort.go +391 -452
- package/stdlib/sort/zsort_func.go +480 -0
- package/stdlib/sort/zsort_iface.go +480 -0
- package/stdlib/strconv/float.go +1699 -0
- package/stdlib/strconv/isprint.go +752 -0
- package/stdlib/strconv/quote.go +235 -50
- package/stdlib/strconv/strconv.go +616 -0
- package/stdlib/strings/builder.go +95 -0
- package/stdlib/strings/reader.go +163 -0
- package/stdlib/strings/replacer.go +102 -0
- package/stdlib/strings/strings.go +807 -0
- package/stdlib/sync/sync.go +268 -0
- package/stdlib/testing/async_js.go +61 -0
- package/stdlib/testing/benchmark.go +297 -0
- package/stdlib/testing/testing.go +523 -0
- package/stdlib/time/duration.go +233 -0
- package/stdlib/time/format.go +745 -0
- package/stdlib/time/parse.go +790 -0
- package/stdlib/time/sleep_js.go +63 -0
- package/stdlib/time/time.go +834 -0
- package/stdlib/unicode/unicode.go +141 -3
- package/stdlib/unicode/utf8/utf8.go +464 -0
- package/src/backend/js/fmt-runtime.js +0 -573
- package/src/backend/js/stdlib/base64.js +0 -12
- package/src/backend/js/stdlib/binary.js +0 -102
- package/src/backend/js/stdlib/bits.js +0 -119
- package/src/backend/js/stdlib/builder.js +0 -98
- package/src/backend/js/stdlib/bytes.js +0 -368
- package/src/backend/js/stdlib/errors.js +0 -45
- package/src/backend/js/stdlib/fmt.js +0 -517
- package/src/backend/js/stdlib/gom.js +0 -155
- package/src/backend/js/stdlib/hex.js +0 -17
- package/src/backend/js/stdlib/html.js +0 -20
- package/src/backend/js/stdlib/io.js +0 -137
- package/src/backend/js/stdlib/json.js +0 -1167
- package/src/backend/js/stdlib/maps.js +0 -37
- package/src/backend/js/stdlib/math.js +0 -85
- package/src/backend/js/stdlib/os.js +0 -13
- package/src/backend/js/stdlib/path.js +0 -48
- package/src/backend/js/stdlib/rand.js +0 -32
- package/src/backend/js/stdlib/regexp.js +0 -54
- package/src/backend/js/stdlib/sha256.js +0 -12
- package/src/backend/js/stdlib/shared.js +0 -17
- package/src/backend/js/stdlib/simd.js +0 -34
- package/src/backend/js/stdlib/slices.js +0 -107
- package/src/backend/js/stdlib/sort.js +0 -30
- package/src/backend/js/stdlib/strconv.js +0 -79
- package/src/backend/js/stdlib/strings.js +0 -301
- package/src/backend/js/stdlib/sync.js +0 -13
- package/src/backend/js/stdlib/testing.js +0 -41
- package/src/backend/js/stdlib/time.js +0 -152
- package/src/backend/js/stdlib/unicode.js +0 -25
- package/src/backend/js/stdlib/utf8.js +0 -26
- package/src/backend/wasm/stdlib/bytes.js +0 -6716
- package/src/backend/wasm/stdlib/core.js +0 -10278
- package/src/backend/wasm/stdlib/io.js +0 -3578
- package/src/backend/wasm/stdlib/packages.js +0 -2402
- package/src/backend/wasm/stdlib/pure.js +0 -720
- package/src/backend/wasm/stdlib/time.js +0 -2229
- package/src/typechecker/stdlib/core.js +0 -1079
- package/src/typechecker/stdlib/extended.js +0 -1210
- package/stdlib/bytes/iter.go +0 -192
- package/stdlib/bytes/search.go +0 -240
- package/stdlib/bytes/split.go +0 -218
- package/stdlib/errors/overlay.go +0 -12
- package/stdlib/maps/iter.go +0 -65
- package/stdlib/slices/extra.go +0 -73
- package/stdlib/slices/iter.go +0 -113
- package/stdlib/strings/extra.go +0 -35
- package/stdlib/strings/iter.go +0 -122
- package/stdlib/sync/extra.go +0 -105
- package/stdlib/unicode/utf8/bytes.go +0 -239
|
@@ -13,6 +13,144 @@ const (
|
|
|
13
13
|
Version = "15.0.0"
|
|
14
14
|
)
|
|
15
15
|
|
|
16
|
+
// Classes of unicode_is, the host's answer for runes above ASCII.
|
|
17
|
+
const (
|
|
18
|
+
classLetter = iota
|
|
19
|
+
classDigit
|
|
20
|
+
classSpace
|
|
21
|
+
classUpper
|
|
22
|
+
classLower
|
|
23
|
+
classPunct
|
|
24
|
+
classControl
|
|
25
|
+
classPrint
|
|
26
|
+
classGraphic
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
// hostIs reports whether the host's Unicode tables place r in the class.
|
|
30
|
+
//
|
|
31
|
+
//gofront:intrinsic unicode_is
|
|
32
|
+
func hostIs(r rune, class int) bool
|
|
33
|
+
|
|
34
|
+
// hostToUpper is the host's upper case mapping of r; a letter whose upper
|
|
35
|
+
// case spans several code points stays as it is.
|
|
36
|
+
//
|
|
37
|
+
//gofront:intrinsic unicode_to_upper
|
|
38
|
+
func hostToUpper(r rune) rune
|
|
39
|
+
|
|
40
|
+
// hostToLower is the host's lower case mapping of r.
|
|
41
|
+
//
|
|
42
|
+
//gofront:intrinsic unicode_to_lower
|
|
43
|
+
func hostToLower(r rune) rune
|
|
44
|
+
|
|
45
|
+
func isValid(r rune) bool { return r >= 0 && r <= MaxRune }
|
|
46
|
+
|
|
47
|
+
// IsLetter reports whether the rune is a letter (category L).
|
|
48
|
+
func IsLetter(r rune) bool {
|
|
49
|
+
if r < 0x80 {
|
|
50
|
+
return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z'
|
|
51
|
+
}
|
|
52
|
+
return isValid(r) && hostIs(r, classLetter)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// IsDigit reports whether the rune is a decimal digit.
|
|
56
|
+
func IsDigit(r rune) bool {
|
|
57
|
+
if r < 0x80 {
|
|
58
|
+
return '0' <= r && r <= '9'
|
|
59
|
+
}
|
|
60
|
+
return isValid(r) && hostIs(r, classDigit)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// IsSpace reports whether the rune is a space character as defined by
|
|
64
|
+
// Unicode's White Space property.
|
|
65
|
+
func IsSpace(r rune) bool {
|
|
66
|
+
if r < 0x80 {
|
|
67
|
+
return r == ' ' || '\t' <= r && r <= '\r'
|
|
68
|
+
}
|
|
69
|
+
return isValid(r) && hostIs(r, classSpace)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// IsUpper reports whether the rune is an upper case letter.
|
|
73
|
+
func IsUpper(r rune) bool {
|
|
74
|
+
if r < 0x80 {
|
|
75
|
+
return 'A' <= r && r <= 'Z'
|
|
76
|
+
}
|
|
77
|
+
return isValid(r) && hostIs(r, classUpper)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// IsLower reports whether the rune is a lower case letter.
|
|
81
|
+
func IsLower(r rune) bool {
|
|
82
|
+
if r < 0x80 {
|
|
83
|
+
return 'a' <= r && r <= 'z'
|
|
84
|
+
}
|
|
85
|
+
return isValid(r) && hostIs(r, classLower)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// IsPunct reports whether the rune is a Unicode punctuation character
|
|
89
|
+
// (category P).
|
|
90
|
+
func IsPunct(r rune) bool {
|
|
91
|
+
if r < 0x80 {
|
|
92
|
+
switch r {
|
|
93
|
+
case '!', '"', '#', '%', '&', '\'', '(', ')', '*', ',', '-', '.', '/',
|
|
94
|
+
':', ';', '?', '@', '[', '\\', ']', '_', '{', '}':
|
|
95
|
+
return true
|
|
96
|
+
}
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
return isValid(r) && hostIs(r, classPunct)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// IsControl reports whether the rune is a control character.
|
|
103
|
+
func IsControl(r rune) bool {
|
|
104
|
+
if r < 0x80 {
|
|
105
|
+
return r >= 0 && r < ' ' || r == 0x7F
|
|
106
|
+
}
|
|
107
|
+
return isValid(r) && hostIs(r, classControl)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// IsPrint reports whether the rune is printable.
|
|
111
|
+
func IsPrint(r rune) bool {
|
|
112
|
+
if r < 0x80 {
|
|
113
|
+
return ' ' <= r && r <= '~'
|
|
114
|
+
}
|
|
115
|
+
return isValid(r) && !IsSpace(r) && hostIs(r, classPrint)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// IsGraphic reports whether the rune is a graphic character.
|
|
119
|
+
func IsGraphic(r rune) bool {
|
|
120
|
+
if r < 0x80 {
|
|
121
|
+
return ' ' <= r && r <= '~'
|
|
122
|
+
}
|
|
123
|
+
return isValid(r) && hostIs(r, classGraphic)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ToUpper maps the rune to upper case.
|
|
127
|
+
func ToUpper(r rune) rune {
|
|
128
|
+
if r < 0x80 {
|
|
129
|
+
if 'a' <= r && r <= 'z' {
|
|
130
|
+
return r - ('a' - 'A')
|
|
131
|
+
}
|
|
132
|
+
return r
|
|
133
|
+
}
|
|
134
|
+
if !isValid(r) {
|
|
135
|
+
return r
|
|
136
|
+
}
|
|
137
|
+
return hostToUpper(r)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ToLower maps the rune to lower case.
|
|
141
|
+
func ToLower(r rune) rune {
|
|
142
|
+
if r < 0x80 {
|
|
143
|
+
if 'A' <= r && r <= 'Z' {
|
|
144
|
+
return r + ('a' - 'A')
|
|
145
|
+
}
|
|
146
|
+
return r
|
|
147
|
+
}
|
|
148
|
+
if !isValid(r) {
|
|
149
|
+
return r
|
|
150
|
+
}
|
|
151
|
+
return hostToLower(r)
|
|
152
|
+
}
|
|
153
|
+
|
|
16
154
|
// ToTitle maps the rune to title case.
|
|
17
155
|
func ToTitle(r rune) rune {
|
|
18
156
|
if r <= MaxASCII {
|
|
@@ -34,7 +172,7 @@ func ToTitle(r rune) rune {
|
|
|
34
172
|
if 0x10D0 <= r && r <= 0x10FF {
|
|
35
173
|
return r
|
|
36
174
|
}
|
|
37
|
-
return
|
|
175
|
+
return ToUpper(r)
|
|
38
176
|
}
|
|
39
177
|
|
|
40
178
|
type foldPair struct {
|
|
@@ -105,8 +243,8 @@ func SimpleFold(r rune) rune {
|
|
|
105
243
|
if lo < len(caseOrbit) && rune(caseOrbit[lo].From) == r {
|
|
106
244
|
return rune(caseOrbit[lo].To)
|
|
107
245
|
}
|
|
108
|
-
if l :=
|
|
246
|
+
if l := ToLower(r); l != r {
|
|
109
247
|
return l
|
|
110
248
|
}
|
|
111
|
-
return
|
|
249
|
+
return ToUpper(r)
|
|
112
250
|
}
|
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
// Copyright 2009 The Go Authors. All rights reserved.
|
|
6
|
+
// Use of this source code is governed by a BSD-style
|
|
7
|
+
// license that can be found in the LICENSE file.
|
|
8
|
+
|
|
9
|
+
// Package utf8 implements functions and constants to support text encoded in
|
|
10
|
+
// UTF-8. It includes functions to translate between runes and UTF-8 byte sequences.
|
|
11
|
+
// See https://en.wikipedia.org/wiki/UTF-8
|
|
12
|
+
package utf8
|
|
13
|
+
|
|
14
|
+
// The conditions RuneError==unicode.ReplacementChar and
|
|
15
|
+
// MaxRune==unicode.MaxRune are verified in the tests.
|
|
16
|
+
// Defining them locally avoids this package depending on package unicode.
|
|
17
|
+
|
|
18
|
+
// Numbers fundamental to the encoding.
|
|
19
|
+
const (
|
|
20
|
+
RuneError = '\uFFFD' // the "error" Rune or "Unicode replacement character"
|
|
21
|
+
RuneSelf = 0x80 // characters below RuneSelf are represented as themselves in a single byte.
|
|
22
|
+
MaxRune = '\U0010FFFF' // Maximum valid Unicode code point.
|
|
23
|
+
UTFMax = 4 // maximum number of bytes of a UTF-8 encoded Unicode character.
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
// Code points in the surrogate range are not valid for UTF-8.
|
|
27
|
+
const (
|
|
28
|
+
surrogateMin = 0xD800
|
|
29
|
+
surrogateMax = 0xDFFF
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
const (
|
|
33
|
+
t1 = 0b00000000
|
|
34
|
+
tx = 0b10000000
|
|
35
|
+
t2 = 0b11000000
|
|
36
|
+
t3 = 0b11100000
|
|
37
|
+
t4 = 0b11110000
|
|
38
|
+
t5 = 0b11111000
|
|
39
|
+
|
|
40
|
+
maskx = 0b00111111
|
|
41
|
+
mask2 = 0b00011111
|
|
42
|
+
mask3 = 0b00001111
|
|
43
|
+
mask4 = 0b00000111
|
|
44
|
+
|
|
45
|
+
rune1Max = 1<<7 - 1
|
|
46
|
+
rune2Max = 1<<11 - 1
|
|
47
|
+
rune3Max = 1<<16 - 1
|
|
48
|
+
|
|
49
|
+
// The default lowest and highest continuation byte.
|
|
50
|
+
locb = 0b10000000
|
|
51
|
+
hicb = 0b10111111
|
|
52
|
+
|
|
53
|
+
// These names of these constants are chosen to give nice alignment in the
|
|
54
|
+
// table below. The first nibble is an index into acceptRanges or F for
|
|
55
|
+
// special one-byte cases. The second nibble is the Rune length or the
|
|
56
|
+
// Status for the special one-byte case.
|
|
57
|
+
xx = 0xF1 // invalid: size 1
|
|
58
|
+
as = 0xF0 // ASCII: size 1
|
|
59
|
+
s1 = 0x02 // accept 0, size 2
|
|
60
|
+
s2 = 0x13 // accept 1, size 3
|
|
61
|
+
s3 = 0x03 // accept 0, size 3
|
|
62
|
+
s4 = 0x23 // accept 2, size 3
|
|
63
|
+
s5 = 0x34 // accept 3, size 4
|
|
64
|
+
s6 = 0x04 // accept 0, size 4
|
|
65
|
+
s7 = 0x44 // accept 4, size 4
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
const (
|
|
69
|
+
runeErrorByte0 = t3 | (RuneError >> 12)
|
|
70
|
+
runeErrorByte1 = tx | (RuneError>>6)&maskx
|
|
71
|
+
runeErrorByte2 = tx | RuneError&maskx
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
// first is information about the first byte in a UTF-8 sequence.
|
|
75
|
+
var first = [256]uint8{
|
|
76
|
+
// 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
77
|
+
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F
|
|
78
|
+
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F
|
|
79
|
+
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F
|
|
80
|
+
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F
|
|
81
|
+
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F
|
|
82
|
+
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F
|
|
83
|
+
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F
|
|
84
|
+
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F
|
|
85
|
+
// 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
86
|
+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F
|
|
87
|
+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F
|
|
88
|
+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF
|
|
89
|
+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF
|
|
90
|
+
xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF
|
|
91
|
+
s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF
|
|
92
|
+
s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF
|
|
93
|
+
s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// acceptRange gives the range of valid values for the second byte in a UTF-8
|
|
97
|
+
// sequence.
|
|
98
|
+
type acceptRange struct {
|
|
99
|
+
lo uint8 // lowest value for second byte.
|
|
100
|
+
hi uint8 // highest value for second byte.
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// acceptRanges has size 16 to avoid bounds checks in the code that uses it.
|
|
104
|
+
var acceptRanges = [16]acceptRange{
|
|
105
|
+
0: {locb, hicb},
|
|
106
|
+
1: {0xA0, hicb},
|
|
107
|
+
2: {locb, 0x9F},
|
|
108
|
+
3: {0x90, hicb},
|
|
109
|
+
4: {locb, 0x8F},
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// GoFront strings are JavaScript strings, indexed by UTF-16 code unit. The
|
|
113
|
+
// *InString functions therefore decode code points and report widths in
|
|
114
|
+
// code units, so that "s = s[size:]" walks a string as in Go; only for
|
|
115
|
+
// ASCII text do the widths equal Go's byte counts.
|
|
116
|
+
|
|
117
|
+
func isHigh(c rune) bool { return c >= 0xD800 && c <= 0xDBFF }
|
|
118
|
+
func isLow(c rune) bool { return c >= 0xDC00 && c <= 0xDFFF }
|
|
119
|
+
|
|
120
|
+
// FullRune reports whether the bytes in p begin with a full UTF-8 encoding of a rune.
|
|
121
|
+
// An invalid encoding is considered a full Rune since it will convert as a width-1 error rune.
|
|
122
|
+
func FullRune(p []byte) bool {
|
|
123
|
+
n := len(p)
|
|
124
|
+
if n == 0 {
|
|
125
|
+
return false
|
|
126
|
+
}
|
|
127
|
+
x := first[p[0]]
|
|
128
|
+
if n >= int(x&7) {
|
|
129
|
+
return true // ASCII, invalid or valid.
|
|
130
|
+
}
|
|
131
|
+
// Must be short or invalid.
|
|
132
|
+
accept := acceptRanges[x>>4]
|
|
133
|
+
if n > 1 && (p[1] < accept.lo || accept.hi < p[1]) {
|
|
134
|
+
return true
|
|
135
|
+
} else if n > 2 && (p[2] < locb || hicb < p[2]) {
|
|
136
|
+
return true
|
|
137
|
+
}
|
|
138
|
+
return false
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// FullRuneInString is like FullRune but its input is a string.
|
|
142
|
+
func FullRuneInString(s string) bool {
|
|
143
|
+
return len(s) > 1 || (len(s) == 1 && !isHigh(rune(s[0])))
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and
|
|
147
|
+
// its width in bytes. If p is empty it returns ([RuneError], 0). Otherwise, if
|
|
148
|
+
// the encoding is invalid, it returns (RuneError, 1). Both are impossible
|
|
149
|
+
// results for correct, non-empty UTF-8.
|
|
150
|
+
//
|
|
151
|
+
// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
|
|
152
|
+
// out of range, or is not the shortest possible UTF-8 encoding for the
|
|
153
|
+
// value. No other validation is performed.
|
|
154
|
+
func DecodeRune(p []byte) (r rune, size int) {
|
|
155
|
+
// Inlineable fast path for ASCII characters; see #48195.
|
|
156
|
+
// This implementation is weird but effective at rendering the
|
|
157
|
+
// function inlineable.
|
|
158
|
+
for _, b := range p {
|
|
159
|
+
if b < RuneSelf {
|
|
160
|
+
return rune(b), 1
|
|
161
|
+
}
|
|
162
|
+
break
|
|
163
|
+
}
|
|
164
|
+
r, size = decodeRuneSlow(p)
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
func decodeRuneSlow(p []byte) (r rune, size int) {
|
|
169
|
+
n := len(p)
|
|
170
|
+
if n < 1 {
|
|
171
|
+
return RuneError, 0
|
|
172
|
+
}
|
|
173
|
+
p0 := p[0]
|
|
174
|
+
x := first[p0]
|
|
175
|
+
if x >= as {
|
|
176
|
+
// The following code simulates an additional check for x == xx and
|
|
177
|
+
// handling the ASCII and invalid cases accordingly. This mask-and-or
|
|
178
|
+
// approach prevents an additional branch.
|
|
179
|
+
mask := rune(x) << 31 >> 31 // Create 0x0000 or 0xFFFF.
|
|
180
|
+
return rune(p[0])&^mask | RuneError&mask, 1
|
|
181
|
+
}
|
|
182
|
+
sz := int(x & 7)
|
|
183
|
+
accept := acceptRanges[x>>4]
|
|
184
|
+
if n < sz {
|
|
185
|
+
return RuneError, 1
|
|
186
|
+
}
|
|
187
|
+
b1 := p[1]
|
|
188
|
+
if b1 < accept.lo || accept.hi < b1 {
|
|
189
|
+
return RuneError, 1
|
|
190
|
+
}
|
|
191
|
+
if sz <= 2 { // <= instead of == to help the compiler eliminate some bounds checks
|
|
192
|
+
return rune(p0&mask2)<<6 | rune(b1&maskx), 2
|
|
193
|
+
}
|
|
194
|
+
b2 := p[2]
|
|
195
|
+
if b2 < locb || hicb < b2 {
|
|
196
|
+
return RuneError, 1
|
|
197
|
+
}
|
|
198
|
+
if sz <= 3 {
|
|
199
|
+
return rune(p0&mask3)<<12 | rune(b1&maskx)<<6 | rune(b2&maskx), 3
|
|
200
|
+
}
|
|
201
|
+
b3 := p[3]
|
|
202
|
+
if b3 < locb || hicb < b3 {
|
|
203
|
+
return RuneError, 1
|
|
204
|
+
}
|
|
205
|
+
return rune(p0&mask4)<<18 | rune(b1&maskx)<<12 | rune(b2&maskx)<<6 | rune(b3&maskx), 4
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// DecodeRuneInString is like [DecodeRune] but its input is a string. If s is
|
|
209
|
+
// empty it returns ([RuneError], 0). Otherwise, if the encoding is invalid, it
|
|
210
|
+
// returns (RuneError, 1). Both are impossible results for correct, non-empty
|
|
211
|
+
// UTF-8.
|
|
212
|
+
//
|
|
213
|
+
// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
|
|
214
|
+
// out of range, or is not the shortest possible UTF-8 encoding for the
|
|
215
|
+
// value. No other validation is performed.
|
|
216
|
+
func DecodeRuneInString(s string) (r rune, size int) {
|
|
217
|
+
if len(s) == 0 {
|
|
218
|
+
return RuneError, 0
|
|
219
|
+
}
|
|
220
|
+
c := rune(s[0])
|
|
221
|
+
if isHigh(c) && len(s) > 1 && isLow(rune(s[1])) {
|
|
222
|
+
return (c-0xD800)<<10 + (rune(s[1]) - 0xDC00) + 0x10000, 2
|
|
223
|
+
}
|
|
224
|
+
if isHigh(c) || isLow(c) {
|
|
225
|
+
return RuneError, 1
|
|
226
|
+
}
|
|
227
|
+
return c, 1
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// DecodeLastRune unpacks the last UTF-8 encoding in p and returns the rune and
|
|
231
|
+
// its width in bytes. If p is empty it returns ([RuneError], 0). Otherwise, if
|
|
232
|
+
// the encoding is invalid, it returns (RuneError, 1). Both are impossible
|
|
233
|
+
// results for correct, non-empty UTF-8.
|
|
234
|
+
//
|
|
235
|
+
// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
|
|
236
|
+
// out of range, or is not the shortest possible UTF-8 encoding for the
|
|
237
|
+
// value. No other validation is performed.
|
|
238
|
+
func DecodeLastRune(p []byte) (r rune, size int) {
|
|
239
|
+
end := len(p)
|
|
240
|
+
if end == 0 {
|
|
241
|
+
return RuneError, 0
|
|
242
|
+
}
|
|
243
|
+
start := end - 1
|
|
244
|
+
r = rune(p[start])
|
|
245
|
+
if r < RuneSelf {
|
|
246
|
+
return r, 1
|
|
247
|
+
}
|
|
248
|
+
// guard against O(n^2) behavior when traversing
|
|
249
|
+
// backwards through strings with long sequences of
|
|
250
|
+
// invalid UTF-8.
|
|
251
|
+
lim := end - UTFMax
|
|
252
|
+
if lim < 0 {
|
|
253
|
+
lim = 0
|
|
254
|
+
}
|
|
255
|
+
for start--; start >= lim; start-- {
|
|
256
|
+
if RuneStart(p[start]) {
|
|
257
|
+
break
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if start < 0 {
|
|
261
|
+
start = 0
|
|
262
|
+
}
|
|
263
|
+
r, size = DecodeRune(p[start:end])
|
|
264
|
+
if start+size != end {
|
|
265
|
+
return RuneError, 1
|
|
266
|
+
}
|
|
267
|
+
return r, size
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// DecodeLastRuneInString is like [DecodeLastRune] but its input is a string. If
|
|
271
|
+
// s is empty it returns ([RuneError], 0). Otherwise, if the encoding is invalid,
|
|
272
|
+
// it returns (RuneError, 1). Both are impossible results for correct,
|
|
273
|
+
// non-empty UTF-8.
|
|
274
|
+
//
|
|
275
|
+
// An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
|
|
276
|
+
// out of range, or is not the shortest possible UTF-8 encoding for the
|
|
277
|
+
// value. No other validation is performed.
|
|
278
|
+
func DecodeLastRuneInString(s string) (r rune, size int) {
|
|
279
|
+
end := len(s)
|
|
280
|
+
if end == 0 {
|
|
281
|
+
return RuneError, 0
|
|
282
|
+
}
|
|
283
|
+
c := rune(s[end-1])
|
|
284
|
+
if isLow(c) && end > 1 && isHigh(rune(s[end-2])) {
|
|
285
|
+
return (rune(s[end-2])-0xD800)<<10 + (c - 0xDC00) + 0x10000, 2
|
|
286
|
+
}
|
|
287
|
+
if isHigh(c) || isLow(c) {
|
|
288
|
+
return RuneError, 1
|
|
289
|
+
}
|
|
290
|
+
return c, 1
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// RuneLen returns the number of bytes in the UTF-8 encoding of the rune.
|
|
294
|
+
// It returns -1 if the rune is not a valid value to encode in UTF-8.
|
|
295
|
+
func RuneLen(r rune) int {
|
|
296
|
+
switch {
|
|
297
|
+
case r < 0:
|
|
298
|
+
return -1
|
|
299
|
+
case r <= rune1Max:
|
|
300
|
+
return 1
|
|
301
|
+
case r <= rune2Max:
|
|
302
|
+
return 2
|
|
303
|
+
case surrogateMin <= r && r <= surrogateMax:
|
|
304
|
+
return -1
|
|
305
|
+
case r <= rune3Max:
|
|
306
|
+
return 3
|
|
307
|
+
case r <= MaxRune:
|
|
308
|
+
return 4
|
|
309
|
+
}
|
|
310
|
+
return -1
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// EncodeRune writes into p (which must be large enough) the UTF-8 encoding of the rune.
|
|
314
|
+
// If the rune is out of range, it writes the encoding of [RuneError].
|
|
315
|
+
// It returns the number of bytes written.
|
|
316
|
+
func EncodeRune(p []byte, r rune) int {
|
|
317
|
+
// This function is inlineable for fast handling of ASCII.
|
|
318
|
+
if uint32(r) <= rune1Max {
|
|
319
|
+
p[0] = byte(r)
|
|
320
|
+
return 1
|
|
321
|
+
}
|
|
322
|
+
return encodeRuneNonASCII(p, r)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
func encodeRuneNonASCII(p []byte, r rune) int {
|
|
326
|
+
// Negative values are erroneous. Making it unsigned addresses the problem.
|
|
327
|
+
switch i := uint32(r); {
|
|
328
|
+
case i <= rune2Max:
|
|
329
|
+
_ = p[1] // eliminate bounds checks
|
|
330
|
+
p[0] = t2 | byte(r>>6)
|
|
331
|
+
p[1] = tx | byte(r)&maskx
|
|
332
|
+
return 2
|
|
333
|
+
case i < surrogateMin, surrogateMax < i && i <= rune3Max:
|
|
334
|
+
_ = p[2] // eliminate bounds checks
|
|
335
|
+
p[0] = t3 | byte(r>>12)
|
|
336
|
+
p[1] = tx | byte(r>>6)&maskx
|
|
337
|
+
p[2] = tx | byte(r)&maskx
|
|
338
|
+
return 3
|
|
339
|
+
case i > rune3Max && i <= MaxRune:
|
|
340
|
+
_ = p[3] // eliminate bounds checks
|
|
341
|
+
p[0] = t4 | byte(r>>18)
|
|
342
|
+
p[1] = tx | byte(r>>12)&maskx
|
|
343
|
+
p[2] = tx | byte(r>>6)&maskx
|
|
344
|
+
p[3] = tx | byte(r)&maskx
|
|
345
|
+
return 4
|
|
346
|
+
default:
|
|
347
|
+
_ = p[2] // eliminate bounds checks
|
|
348
|
+
p[0] = runeErrorByte0
|
|
349
|
+
p[1] = runeErrorByte1
|
|
350
|
+
p[2] = runeErrorByte2
|
|
351
|
+
return 3
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// AppendRune appends the UTF-8 encoding of r to the end of p and
|
|
356
|
+
// returns the extended buffer. If the rune is out of range,
|
|
357
|
+
// it appends the encoding of [RuneError].
|
|
358
|
+
func AppendRune(p []byte, r rune) []byte {
|
|
359
|
+
// This function is inlineable for fast handling of ASCII.
|
|
360
|
+
if uint32(r) <= rune1Max {
|
|
361
|
+
return append(p, byte(r))
|
|
362
|
+
}
|
|
363
|
+
return appendRuneNonASCII(p, r)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
func appendRuneNonASCII(p []byte, r rune) []byte {
|
|
367
|
+
// Negative values are erroneous. Making it unsigned addresses the problem.
|
|
368
|
+
switch i := uint32(r); {
|
|
369
|
+
case i <= rune2Max:
|
|
370
|
+
return append(p, t2|byte(r>>6), tx|byte(r)&maskx)
|
|
371
|
+
case i < surrogateMin, surrogateMax < i && i <= rune3Max:
|
|
372
|
+
return append(p, t3|byte(r>>12), tx|byte(r>>6)&maskx, tx|byte(r)&maskx)
|
|
373
|
+
case i > rune3Max && i <= MaxRune:
|
|
374
|
+
return append(p, t4|byte(r>>18), tx|byte(r>>12)&maskx, tx|byte(r>>6)&maskx, tx|byte(r)&maskx)
|
|
375
|
+
default:
|
|
376
|
+
return append(p, runeErrorByte0, runeErrorByte1, runeErrorByte2)
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// RuneCount returns the number of runes in p. Erroneous and short
|
|
381
|
+
// encodings are treated as single runes of width 1 byte.
|
|
382
|
+
func RuneCount(p []byte) int {
|
|
383
|
+
n := 0
|
|
384
|
+
for i := 0; i < len(p); n++ {
|
|
385
|
+
if p[i] < RuneSelf {
|
|
386
|
+
i++
|
|
387
|
+
continue
|
|
388
|
+
}
|
|
389
|
+
_, size := DecodeRune(p[i:])
|
|
390
|
+
i += size
|
|
391
|
+
}
|
|
392
|
+
return n
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// RuneCountInString is like [RuneCount] but its input is a string.
|
|
396
|
+
//
|
|
397
|
+
//gofront:native utf8.RuneCountInString
|
|
398
|
+
func RuneCountInString(s string) (n int) {
|
|
399
|
+
return len([]rune(s))
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// RuneStart reports whether the byte could be the first byte of an encoded,
|
|
403
|
+
// possibly invalid rune. Second and subsequent bytes always have the top two
|
|
404
|
+
// bits set to 10.
|
|
405
|
+
func RuneStart(b byte) bool { return b&0xC0 != 0x80 }
|
|
406
|
+
|
|
407
|
+
// Valid reports whether p consists entirely of valid UTF-8-encoded runes.
|
|
408
|
+
func Valid(p []byte) bool {
|
|
409
|
+
for len(p) > 0 {
|
|
410
|
+
p0 := p[0]
|
|
411
|
+
if p0 < RuneSelf {
|
|
412
|
+
p = p[1:]
|
|
413
|
+
continue
|
|
414
|
+
}
|
|
415
|
+
x := first[p0]
|
|
416
|
+
size := int(x & 7)
|
|
417
|
+
accept := acceptRanges[x>>4]
|
|
418
|
+
switch size {
|
|
419
|
+
case 2:
|
|
420
|
+
if len(p) < 2 || p[1] < accept.lo || accept.hi < p[1] {
|
|
421
|
+
return false
|
|
422
|
+
}
|
|
423
|
+
p = p[2:]
|
|
424
|
+
case 3:
|
|
425
|
+
if len(p) < 3 || p[1] < accept.lo || accept.hi < p[1] || p[2] < locb || hicb < p[2] {
|
|
426
|
+
return false
|
|
427
|
+
}
|
|
428
|
+
p = p[3:]
|
|
429
|
+
case 4:
|
|
430
|
+
if len(p) < 4 || p[1] < accept.lo || accept.hi < p[1] || p[2] < locb || hicb < p[2] || p[3] < locb || hicb < p[3] {
|
|
431
|
+
return false
|
|
432
|
+
}
|
|
433
|
+
p = p[4:]
|
|
434
|
+
default:
|
|
435
|
+
return false // illegal starter byte
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return true
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// ValidString reports whether s consists entirely of valid UTF-8-encoded runes.
|
|
442
|
+
func ValidString(s string) bool {
|
|
443
|
+
for i := 0; i < len(s); i++ {
|
|
444
|
+
c := rune(s[i])
|
|
445
|
+
if isHigh(c) && i+1 < len(s) && isLow(rune(s[i+1])) {
|
|
446
|
+
i++
|
|
447
|
+
} else if isHigh(c) || isLow(c) {
|
|
448
|
+
return false
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return true
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// ValidRune reports whether r can be legally encoded as UTF-8.
|
|
455
|
+
// Code points that are out of range or a surrogate half are illegal.
|
|
456
|
+
func ValidRune(r rune) bool {
|
|
457
|
+
switch {
|
|
458
|
+
case 0 <= r && r < surrogateMin:
|
|
459
|
+
return true
|
|
460
|
+
case surrogateMax < r && r <= MaxRune:
|
|
461
|
+
return true
|
|
462
|
+
}
|
|
463
|
+
return false
|
|
464
|
+
}
|