package parsekit 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 }