From a0e805e4fc334d971173d0c76f4b8624b5df07b9 Mon Sep 17 00:00:00 2001 From: Peijun Ma Date: Fri, 11 Oct 2024 14:12:19 -0400 Subject: [PATCH] Revert "go api: reduce allocations in deck decompression" This commit has caused some card text to be displayed wrongly in the deck view endpoint. This reverts commit caf7d314bbfa4a9b9deb1b5efe1aca1293089ed0. --- backend/api/deck.go | 85 +++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 50 deletions(-) diff --git a/backend/api/deck.go b/backend/api/deck.go index 7fd5e83..fed8641 100644 --- a/backend/api/deck.go +++ b/backend/api/deck.go @@ -1,10 +1,10 @@ package api import ( + "encoding/json" "errors" "fmt" "regexp" - "strconv" "strings" "github.com/gin-gonic/gin" @@ -13,19 +13,6 @@ import ( const WILDCARDS = "0123456789abcdefghijklmnopqrstvwxyzABCDEFGHIJKLMNOPQRSTVWXYZ_`[]/^%?@><=-+*:;,.()#$!'{}~" -var compressionWildcardRegex []*regexp.Regexp - -func init() { - escapeRegex := regexp.MustCompile(`[-\/\\^$*+?.()|[\]{}]`) - - compressionWildcardRegex = make([]*regexp.Regexp, 0, len(WILDCARDS)) - for i := range WILDCARDS { - wildCard := fmt.Sprintf("&%c", WILDCARDS[i]) - escaped := escapeRegex.ReplaceAllString(wildCard, "\\$&") - compressionWildcardRegex = append(compressionWildcardRegex, regexp.MustCompile(escaped)) - } -} - func (a *API) getDeckHandler(c *gin.Context) { name := c.Param("name") name = strings.ToLower(name) @@ -73,6 +60,11 @@ func (a *API) getDeckHandler(c *gin.Context) { c.Data(200, "text/plain", []byte(result.String())) } +func escapeRegexp(s string) string { + r := regexp.MustCompile(`[-\/\\^$*+?.()|[\]{}]`) + return r.ReplaceAllString(s, "\\$&") +} + func decompress(s string) (string, error) { parts := strings.Split(s, "||") if len(parts) < 2 { @@ -84,58 +76,51 @@ func decompress(s string) (string, error) { for i := len(compressionDict) - 1; i >= 0; i-- { word := compressionDict[i] - text = compressionWildcardRegex[i].ReplaceAllString(text, word) + wildCard := fmt.Sprintf("&%c", WILDCARDS[i]) + r, err := regexp.Compile(escapeRegexp(wildCard)) + if err != nil { + return "", err + } + text = r.ReplaceAllString(text, word) } return text, nil } func parseCommaDelimitedIntegerArray(s string) ([]int, error) { if s == "-" { - return nil, nil + return make([]int, 0), nil } - - currIndex := 0 - result := make([]int, 0, strings.Count(s, ",")+1) - for currIndex < len(s) { - nextIndex := currIndex + strings.Index(s[currIndex:], ",") - if nextIndex < currIndex { - nextIndex = len(s) - } - - resultVal, err := strconv.ParseInt(s[currIndex:nextIndex], 10, 64) - if err != nil { - return nil, err - } - - currIndex = nextIndex + 1 - result = append(result, int(resultVal)) - } - return result, nil + //nolint:prealloc + var result []int + err := json.Unmarshal([]byte(fmt.Sprintf("[%s]", s)), &result) + return result, err } -func splitDoubleSemicolonArray(s string) []string { +func splitSemicolonDelimited2DArray(s string) [][]string { if s == "-" { - return nil + return make([][]string, 0) } - return strings.Split(s, ";;") -} - -func parseCards(cardSections []string) []string { - result := make([]string, 0, len(cardSections)) - for _, cardSection := range cardSections { - result = append(result, parseCard(cardSection)) + //nolint:prealloc + var result [][]string + split := strings.Split(s, ";;") + for _, element := range split { + result = append(result, strings.Split(element, ";")) } return result } -func parseCard(cardSection string) string { - sectionEnd := strings.Index(cardSection, ";") - if sectionEnd == -1 { - return cardSection +func parseCards(cards [][]string) []string { + //nolint:prealloc + var result []string + for _, card := range cards { + result = append(result, parseCard(card)) } + return result +} - return cardSection[:sectionEnd] +func parseCard(c []string) string { + return c[0] } func decompressDeck(deck string) (map[string]int, error) { @@ -149,9 +134,9 @@ func decompressDeck(deck string) (map[string]int, error) { if err != nil { return nil, err } - cards := parseCards(splitDoubleSemicolonArray(parts[1])) + cards := parseCards(splitSemicolonDelimited2DArray(parts[1])) - deckDict := make(map[string]int, len(cards)) + deckDict := make(map[string]int) for _, idx := range d { if idx < 0 || idx >= len(cards) { return nil, errors.New("card index out of bounds")