From 394c20fdc5cdf3ae65415218705b6e59b8a7c344 Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Mon, 15 Feb 2016 16:53:44 +0200 Subject: [PATCH] Added AppendHTMLEscape helper function --- bytesconv.go | 31 +++++++++++++++++++++++++++++++ bytesconv_test.go | 15 +++++++++++++++ bytesconv_timing_test.go | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/bytesconv.go b/bytesconv.go index c430a80..6f8931b 100644 --- a/bytesconv.go +++ b/bytesconv.go @@ -12,6 +12,37 @@ import ( "unsafe" ) +// AppendHTMLEscape appends html-escaped s to dst and returns the extended dst. +func AppendHTMLEscape(dst []byte, s string) []byte { + var prev int + var sub string + for i, n := 0, len(s); i < n; i++ { + sub = "" + switch s[i] { + case '<': + sub = "<" + case '>': + sub = ">" + case '"': + sub = """ + case '\'': + sub = "'" + } + if len(sub) > 0 { + dst = append(dst, s[prev:i]...) + dst = append(dst, sub...) + prev = i + 1 + } + } + return append(dst, s[prev:]...) +} + +// AppendHTMLEscapeBytes appends html-escaped s to dst and returns +// the extended dst. +func AppendHTMLEscapeBytes(dst, s []byte) []byte { + return AppendHTMLEscape(dst, unsafeBytesToStr(s)) +} + // AppendIPv4 appends string representation of the given ip v4 to dst // and returns the extended dst. func AppendIPv4(dst []byte, ip net.IP) []byte { diff --git a/bytesconv_test.go b/bytesconv_test.go index 83eb3d8..fde6f26 100644 --- a/bytesconv_test.go +++ b/bytesconv_test.go @@ -9,6 +9,21 @@ import ( "time" ) +func TestAppendHTMLEscape(t *testing.T) { + testAppendHTMLEscape(t, "", "") + testAppendHTMLEscape(t, "<", "<") + testAppendHTMLEscape(t, "a", "a") + testAppendHTMLEscape(t, `><"''`, "><"''") + testAppendHTMLEscape(t, "foaxxx", "fo<b x='ss'>a</b>xxx") +} + +func testAppendHTMLEscape(t *testing.T, s, expectedS string) { + buf := AppendHTMLEscapeBytes(nil, []byte(s)) + if string(buf) != expectedS { + t.Fatalf("unexpected html-escaped string %q. Expecting %q. Original string %q", buf, expectedS, s) + } +} + func TestParseIPv4(t *testing.T) { testParseIPv4(t, "0.0.0.0", true) testParseIPv4(t, "255.255.255.255", true) diff --git a/bytesconv_timing_test.go b/bytesconv_timing_test.go index e233502..bd416d1 100644 --- a/bytesconv_timing_test.go +++ b/bytesconv_timing_test.go @@ -2,10 +2,43 @@ package fasthttp import ( "bufio" + "html" "net" "testing" ) +func BenchmarkAppendHTMLEscape(b *testing.B) { + sOrig := "foobarbazxxxyyyzzz" + sExpected := string(AppendHTMLEscape(nil, sOrig)) + b.RunParallel(func(pb *testing.PB) { + var buf []byte + for pb.Next() { + for i := 0; i < 10; i++ { + buf = AppendHTMLEscape(buf[:0], sOrig) + if string(buf) != sExpected { + b.Fatalf("unexpected escaped string: %s. Expecting %s", buf, sExpected) + } + } + } + }) +} + +func BenchmarkHTMLEscapeString(b *testing.B) { + sOrig := "foobarbazxxxyyyzzz" + sExpected := html.EscapeString(sOrig) + b.RunParallel(func(pb *testing.PB) { + var s string + for pb.Next() { + for i := 0; i < 10; i++ { + s = html.EscapeString(sOrig) + if s != sExpected { + b.Fatalf("unexpected escaped string: %s. Expecting %s", s, sExpected) + } + } + } + }) +} + func BenchmarkParseIPv4(b *testing.B) { ipStr := []byte("123.145.167.189") b.RunParallel(func(pb *testing.PB) {