package quicktemplate

import (
	"io"
	"strings"
)

func writeJSONString(w io.Writer, s string) {
	if len(s) > 24 &&
		strings.IndexByte(s, '"') < 0 &&
		strings.IndexByte(s, '\\') < 0 &&
		strings.IndexByte(s, '\n') < 0 &&
		strings.IndexByte(s, '\r') < 0 &&
		strings.IndexByte(s, '\t') < 0 &&
		strings.IndexByte(s, '\f') < 0 &&
		strings.IndexByte(s, '\b') < 0 &&
		strings.IndexByte(s, '<') < 0 &&
		strings.IndexByte(s, '\'') < 0 &&
		strings.IndexByte(s, 0) < 0 {

		// fast path - nothing to escape
		w.Write(unsafeStrToBytes(s))
		return
	}

	// slow path
	write := w.Write
	b := unsafeStrToBytes(s)
	j := 0
	n := len(b)
	if n > 0 {
		// Hint the compiler to remove bounds checks in the loop below.
		_ = b[n-1]
	}
	for i := 0; i < n; i++ {
		switch b[i] {
		case '"':
			write(b[j:i])
			write(strBackslashQuote)
			j = i + 1
		case '\\':
			write(b[j:i])
			write(strBackslashBackslash)
			j = i + 1
		case '\n':
			write(b[j:i])
			write(strBackslashN)
			j = i + 1
		case '\r':
			write(b[j:i])
			write(strBackslashR)
			j = i + 1
		case '\t':
			write(b[j:i])
			write(strBackslashT)
			j = i + 1
		case '\f':
			write(b[j:i])
			write(strBackslashF)
			j = i + 1
		case '\b':
			write(b[j:i])
			write(strBackslashB)
			j = i + 1
		case '<':
			write(b[j:i])
			write(strBackslashLT)
			j = i + 1
		case '\'':
			write(b[j:i])
			write(strBackslashQ)
			j = i + 1
		case 0:
			write(b[j:i])
			write(strBackslashZero)
			j = i + 1
		}
	}
	write(b[j:])
}

var (
	strBackslashQuote     = []byte(`\"`)
	strBackslashBackslash = []byte(`\\`)
	strBackslashN         = []byte(`\n`)
	strBackslashR         = []byte(`\r`)
	strBackslashT         = []byte(`\t`)
	strBackslashF         = []byte(`\u000c`)
	strBackslashB         = []byte(`\u0008`)
	strBackslashLT        = []byte(`\u003c`)
	strBackslashQ         = []byte(`\u0027`)
	strBackslashZero      = []byte(`\u0000`)
)