mirror of
https://github.com/golang/go
synced 2024-11-22 00:54:43 -07:00
strconv: add QuoteRune, which is analogous to Quote, but for runes rather than strings.
R=golang-dev, rsc CC=golang-dev https://golang.org/cl/4556059
This commit is contained in:
parent
feb9a146f9
commit
c4918db8b9
@ -14,17 +14,14 @@ import (
|
|||||||
|
|
||||||
const lowerhex = "0123456789abcdef"
|
const lowerhex = "0123456789abcdef"
|
||||||
|
|
||||||
// Quote returns a double-quoted Go string literal
|
func quoteWith(s string, quote byte) string {
|
||||||
// representing s. The returned string s uses Go escape
|
|
||||||
// sequences (\t, \n, \xFF, \u0100) for control characters
|
|
||||||
// and non-ASCII characters.
|
|
||||||
func Quote(s string) string {
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
buf.WriteByte('"')
|
buf.WriteByte(quote)
|
||||||
for ; len(s) > 0; s = s[1:] {
|
for ; len(s) > 0; s = s[1:] {
|
||||||
switch c := s[0]; {
|
switch c := s[0]; {
|
||||||
case c == '"':
|
case c == quote:
|
||||||
buf.WriteString(`\"`)
|
buf.WriteByte('\\')
|
||||||
|
buf.WriteByte(quote)
|
||||||
case c == '\\':
|
case c == '\\':
|
||||||
buf.WriteString(`\\`)
|
buf.WriteString(`\\`)
|
||||||
case ' ' <= c && c <= '~':
|
case ' ' <= c && c <= '~':
|
||||||
@ -69,8 +66,26 @@ func Quote(s string) string {
|
|||||||
buf.WriteByte(lowerhex[c&0xF])
|
buf.WriteByte(lowerhex[c&0xF])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf.WriteByte('"')
|
buf.WriteByte(quote)
|
||||||
return buf.String()
|
return buf.String()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quote returns a double-quoted Go string literal
|
||||||
|
// representing s. The returned string uses Go escape
|
||||||
|
// sequences (\t, \n, \xFF, \u0100) for control characters
|
||||||
|
// and non-ASCII characters.
|
||||||
|
func Quote(s string) string {
|
||||||
|
return quoteWith(s, '"')
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuoteRune returns a single-quoted Go character literal
|
||||||
|
// representing the rune. The returned string uses Go escape
|
||||||
|
// sequences (\t, \n, \xFF, \u0100) for control characters
|
||||||
|
// and non-ASCII characters.
|
||||||
|
func QuoteRune(rune int) string {
|
||||||
|
// TODO: avoid the allocation here.
|
||||||
|
return quoteWith(string(rune), '\'')
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanBackquote returns whether the string s would be
|
// CanBackquote returns whether the string s would be
|
||||||
|
@ -25,14 +25,37 @@ var quotetests = []quoteTest{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestQuote(t *testing.T) {
|
func TestQuote(t *testing.T) {
|
||||||
for i := 0; i < len(quotetests); i++ {
|
for _, tt := range quotetests {
|
||||||
tt := quotetests[i]
|
|
||||||
if out := Quote(tt.in); out != tt.out {
|
if out := Quote(tt.in); out != tt.out {
|
||||||
t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
|
t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type quoteRuneTest struct {
|
||||||
|
in int
|
||||||
|
out string
|
||||||
|
}
|
||||||
|
|
||||||
|
var quoterunetests = []quoteRuneTest{
|
||||||
|
{'a', `'a'`},
|
||||||
|
{'\a', `'\a'`},
|
||||||
|
{'\\', `'\\'`},
|
||||||
|
{0xFF, `'\u00ff'`},
|
||||||
|
{0x263a, `'\u263a'`},
|
||||||
|
{0x0010ffff, `'\U0010ffff'`},
|
||||||
|
{0x0010ffff + 1, `'\ufffd'`},
|
||||||
|
{0x04, `'\x04'`},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQuoteRune(t *testing.T) {
|
||||||
|
for _, tt := range quoterunetests {
|
||||||
|
if out := QuoteRune(tt.in); out != tt.out {
|
||||||
|
t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type canBackquoteTest struct {
|
type canBackquoteTest struct {
|
||||||
in string
|
in string
|
||||||
out bool
|
out bool
|
||||||
@ -80,8 +103,7 @@ var canbackquotetests = []canBackquoteTest{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCanBackquote(t *testing.T) {
|
func TestCanBackquote(t *testing.T) {
|
||||||
for i := 0; i < len(canbackquotetests); i++ {
|
for _, tt := range canbackquotetests {
|
||||||
tt := canbackquotetests[i]
|
|
||||||
if out := CanBackquote(tt.in); out != tt.out {
|
if out := CanBackquote(tt.in); out != tt.out {
|
||||||
t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out)
|
t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out)
|
||||||
}
|
}
|
||||||
@ -146,23 +168,20 @@ var misquoted = []string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUnquote(t *testing.T) {
|
func TestUnquote(t *testing.T) {
|
||||||
for i := 0; i < len(unquotetests); i++ {
|
for _, tt := range unquotetests {
|
||||||
tt := unquotetests[i]
|
|
||||||
if out, err := Unquote(tt.in); err != nil && out != tt.out {
|
if out, err := Unquote(tt.in); err != nil && out != tt.out {
|
||||||
t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
|
t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the quote tests too, backward
|
// run the quote tests too, backward
|
||||||
for i := 0; i < len(quotetests); i++ {
|
for _, tt := range quotetests {
|
||||||
tt := quotetests[i]
|
|
||||||
if in, err := Unquote(tt.out); in != tt.in {
|
if in, err := Unquote(tt.out); in != tt.in {
|
||||||
t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in)
|
t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(misquoted); i++ {
|
for _, s := range misquoted {
|
||||||
s := misquoted[i]
|
|
||||||
if out, err := Unquote(s); out != "" || err != os.EINVAL {
|
if out, err := Unquote(s); out != "" || err != os.EINVAL {
|
||||||
t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", os.EINVAL)
|
t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", os.EINVAL)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user