mirror of
https://github.com/golang/go.git
synced 2025-05-07 16:43:03 +00:00
html: use sync.OnceValues instead of var once sync.Once
Simplify populateMaps with sync.OnceValues. Change-Id: Id52e6e1623c621b8d51e11fecbe3f1fab1e74eb4 GitHub-Last-Rev: 3cf736ae299f14ece401d218d68c3c8870e0cf5a GitHub-Pull-Request: golang/go#69946 Reviewed-on: https://go-review.googlesource.com/c/go/+/621255 Reviewed-by: Michael Pratt <mpratt@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Commit-Queue: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
2e9ed44d39
commit
205ab8a3fe
@ -9,22 +9,16 @@ import "sync"
|
|||||||
// All entities that do not end with ';' are 6 or fewer bytes long.
|
// All entities that do not end with ';' are 6 or fewer bytes long.
|
||||||
const longestEntityWithoutSemicolon = 6
|
const longestEntityWithoutSemicolon = 6
|
||||||
|
|
||||||
|
// entityMaps returns entity and entity2.
|
||||||
|
//
|
||||||
// entity is a map from HTML entity names to their values. The semicolon matters:
|
// entity is a map from HTML entity names to their values. The semicolon matters:
|
||||||
// https://html.spec.whatwg.org/multipage/named-characters.html
|
// https://html.spec.whatwg.org/multipage/named-characters.html
|
||||||
// lists both "amp" and "amp;" as two separate entries.
|
// lists both "amp" and "amp;" as two separate entries.
|
||||||
//
|
|
||||||
// Note that the HTML5 list is larger than the HTML4 list at
|
// Note that the HTML5 list is larger than the HTML4 list at
|
||||||
// http://www.w3.org/TR/html4/sgml/entities.html
|
// http://www.w3.org/TR/html4/sgml/entities.html
|
||||||
var entity map[string]rune
|
//
|
||||||
|
// entity2 is a map of HTML entities to two unicode codepoints.
|
||||||
// HTML entities that are two unicode codepoints.
|
var entityMaps = sync.OnceValues(func() (entity map[string]rune, entity2 map[string][2]rune) {
|
||||||
var entity2 map[string][2]rune
|
|
||||||
|
|
||||||
// populateMapsOnce guards calling populateMaps.
|
|
||||||
var populateMapsOnce sync.Once
|
|
||||||
|
|
||||||
// populateMaps populates entity and entity2.
|
|
||||||
func populateMaps() {
|
|
||||||
entity = map[string]rune{
|
entity = map[string]rune{
|
||||||
"AElig;": '\U000000C6',
|
"AElig;": '\U000000C6',
|
||||||
"AMP;": '\U00000026',
|
"AMP;": '\U00000026',
|
||||||
@ -2262,4 +2256,6 @@ func populateMaps() {
|
|||||||
"vsupnE;": {'\u2ACC', '\uFE00'},
|
"vsupnE;": {'\u2ACC', '\uFE00'},
|
||||||
"vsupne;": {'\u228B', '\uFE00'},
|
"vsupne;": {'\u228B', '\uFE00'},
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return entity, entity2
|
||||||
|
})
|
||||||
|
@ -9,11 +9,9 @@ import (
|
|||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
UnescapeString("") // force load of entity maps
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEntityLength(t *testing.T) {
|
func TestEntityLength(t *testing.T) {
|
||||||
|
entity, entity2 := entityMaps()
|
||||||
|
|
||||||
if len(entity) == 0 || len(entity2) == 0 {
|
if len(entity) == 0 || len(entity2) == 0 {
|
||||||
t.Fatal("maps not loaded")
|
t.Fatal("maps not loaded")
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ var replacementTable = [...]rune{
|
|||||||
// unescapeEntity reads an entity like "<" from b[src:] and writes the
|
// unescapeEntity reads an entity like "<" from b[src:] and writes the
|
||||||
// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
|
// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
|
||||||
// Precondition: b[src] == '&' && dst <= src.
|
// Precondition: b[src] == '&' && dst <= src.
|
||||||
func unescapeEntity(b []byte, dst, src int) (dst1, src1 int) {
|
func unescapeEntity(b []byte, dst, src int, entity map[string]rune, entity2 map[string][2]rune) (dst1, src1 int) {
|
||||||
const attribute = false
|
const attribute = false
|
||||||
|
|
||||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
|
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
|
||||||
@ -185,7 +185,6 @@ func EscapeString(s string) string {
|
|||||||
// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
|
// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
|
||||||
// always true.
|
// always true.
|
||||||
func UnescapeString(s string) string {
|
func UnescapeString(s string) string {
|
||||||
populateMapsOnce.Do(populateMaps)
|
|
||||||
i := strings.IndexByte(s, '&')
|
i := strings.IndexByte(s, '&')
|
||||||
|
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
@ -193,7 +192,8 @@ func UnescapeString(s string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b := []byte(s)
|
b := []byte(s)
|
||||||
dst, src := unescapeEntity(b, i, i)
|
entity, entity2 := entityMaps()
|
||||||
|
dst, src := unescapeEntity(b, i, i, entity, entity2)
|
||||||
for len(s[src:]) > 0 {
|
for len(s[src:]) > 0 {
|
||||||
if s[src] == '&' {
|
if s[src] == '&' {
|
||||||
i = 0
|
i = 0
|
||||||
@ -208,7 +208,7 @@ func UnescapeString(s string) string {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
copy(b[dst:], s[src:src+i])
|
copy(b[dst:], s[src:src+i])
|
||||||
}
|
}
|
||||||
dst, src = unescapeEntity(b, dst+i, src+i)
|
dst, src = unescapeEntity(b, dst+i, src+i, entity, entity2)
|
||||||
}
|
}
|
||||||
return string(b[:dst])
|
return string(b[:dst])
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user