From 361d848e26c6fcb36d0a3ee62442504306752a2a Mon Sep 17 00:00:00 2001 From: Daniel Richter Date: Mon, 11 Dec 2023 17:53:45 -0800 Subject: [PATCH 1/2] Add benchmark for valid identifier check --- contest_test.go | 18 ++++++++++++++++++ context.go | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 contest_test.go diff --git a/contest_test.go b/contest_test.go new file mode 100644 index 0000000..3f1a10c --- /dev/null +++ b/contest_test.go @@ -0,0 +1,18 @@ +package pongo2 + +import "testing" + +func BenchmarkCheckForValidIdentifiers(b *testing.B) { + input := `valid_key` + + b.Run("regex", func(b *testing.B) { + for i := 0; i < b.N; i++ { + isValidIdentifierRegex(input) + } + }) + b.Run("char_check", func(b *testing.B) { + for i := 0; i < b.N; i++ { + isValidIdentifierCharCheck(input) + } + }) +} diff --git a/context.go b/context.go index 525ac3a..aa40861 100644 --- a/context.go +++ b/context.go @@ -40,6 +40,26 @@ func (c Context) checkForValidIdentifiers() *Error { return nil } +func isValidIdentifierRegex(s string) bool { + return reIdentifiers.MatchString(s) +} + +func isValidIdentifierCharCheck(s string) bool { + for i := range s { + if !isValidIdentifierChar(s[i]) { + return false + } + } + return true +} + +func isValidIdentifierChar(c byte) bool { + return (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '_' +} + // Update updates this context with the key/value-pairs from another context. func (c Context) Update(other Context) Context { for k, v := range other { From c0cb743a6c1222e980e961f1dcff71cc7eb9da14 Mon Sep 17 00:00:00 2001 From: Daniel Richter Date: Mon, 11 Dec 2023 17:56:32 -0800 Subject: [PATCH 2/2] Switch valid identifier check to faster alternative --- contest_test.go | 18 ------------------ context.go | 11 ++--------- 2 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 contest_test.go diff --git a/contest_test.go b/contest_test.go deleted file mode 100644 index 3f1a10c..0000000 --- a/contest_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package pongo2 - -import "testing" - -func BenchmarkCheckForValidIdentifiers(b *testing.B) { - input := `valid_key` - - b.Run("regex", func(b *testing.B) { - for i := 0; i < b.N; i++ { - isValidIdentifierRegex(input) - } - }) - b.Run("char_check", func(b *testing.B) { - for i := 0; i < b.N; i++ { - isValidIdentifierCharCheck(input) - } - }) -} diff --git a/context.go b/context.go index aa40861..3ebf18f 100644 --- a/context.go +++ b/context.go @@ -3,11 +3,8 @@ package pongo2 import ( "errors" "fmt" - "regexp" ) -var reIdentifiers = regexp.MustCompile("^[a-zA-Z0-9_]+$") - var autoescape = true func SetAutoescape(newValue bool) { @@ -30,7 +27,7 @@ type Context map[string]any func (c Context) checkForValidIdentifiers() *Error { for k, v := range c { - if !reIdentifiers.MatchString(k) { + if !isValidIdentifier(k) { return &Error{ Sender: "checkForValidIdentifiers", OrigError: fmt.Errorf("context-key '%s' (value: '%+v') is not a valid identifier", k, v), @@ -40,11 +37,7 @@ func (c Context) checkForValidIdentifiers() *Error { return nil } -func isValidIdentifierRegex(s string) bool { - return reIdentifiers.MatchString(s) -} - -func isValidIdentifierCharCheck(s string) bool { +func isValidIdentifier(s string) bool { for i := range s { if !isValidIdentifierChar(s[i]) { return false