package parser import ( "bytes" "strconv" "strings" ) // StringBuffer is a string buffer implementation, which is used by the parser // to efficiently accumulate runes from the input and eventually turn these // into a string, either literal or interpreted. type StringBuffer struct { buffer bytes.Buffer } // Reset resets the string buffer, in order to build a new string. func (b *StringBuffer) Reset() *StringBuffer { b.buffer.Reset() return b } // WriteString adds the runes of the input string to the string buffer. func (b *StringBuffer) WriteString(s string) *StringBuffer { for _, r := range s { b.WriteRune(r) } return b } // WriteRune adds a single rune to the string buffer. func (b *StringBuffer) WriteRune(r rune) *StringBuffer { b.buffer.WriteRune(r) return b } // AsLiteralString returns the string buffer as a literal string. // Literal means that no escape sequences are processed. func (b *StringBuffer) AsLiteralString() string { return b.buffer.String() } // AsInterpretedString returns the string in its interpreted form. // Interpreted means that escape sequences are handled in the way that Go would // have, had it been inside double quotes. It translates for example escape // sequences like "\n", "\t", \uXXXX" and "\UXXXXXXXX" into their string // representations. // Since the input might contain invalid escape sequences, this method // also returns an error. When an error is returned, the returned string will // contain the string as far as it could be interpreted. func (b *StringBuffer) AsInterpretedString() (string, error) { var sb strings.Builder tail := b.buffer.String() for len(tail) > 0 { r, _, newtail, err := strconv.UnquoteChar(tail, '"') if err != nil { return sb.String(), err } tail = newtail sb.WriteRune(r) } return sb.String(), nil }