func()

in json/visitor.go [205:285]


func (vs *Visitor) OnString(s string) error {
	if err := vs.tryElemNext(); err != nil {
		return err
	}

	escapeSet := vs.escapeSet

	vs.writeByte('"')
	start := 0
	for i := 0; i < len(s); {
		if b := s[i]; b < utf8.RuneSelf {
			if !escapeSet[b] {
				i++
				continue
			}

			if start < i {
				vs.writeString(s[start:i])
			}
			switch b {
			case '\\', '"':
				vs.scratch[0], vs.scratch[1] = '\\', b
				vs.w.write(vs.scratch[:2])
			case '\n':
				vs.scratch[0], vs.scratch[1] = '\\', 'n'
				vs.w.write(vs.scratch[:2])
			case '\r':
				vs.scratch[0], vs.scratch[1] = '\\', 'r'
				vs.w.write(vs.scratch[:2])
			case '\t':
				vs.scratch[0], vs.scratch[1] = '\\', 't'
				vs.w.write(vs.scratch[:2])
			default:
				// This vsodes bytes < 0x20 except for \n and \r,
				// as well as <, > and &. The latter are escaped because they
				// can lead to security holes when user-controlled strings
				// are rendered into JSON and served to some browsers.
				vs.scratch[0], vs.scratch[1], vs.scratch[2], vs.scratch[3] = '\\', 'u', '0', '0'
				vs.scratch[4] = hex[b>>4]
				vs.scratch[5] = hex[b&0xF]
				vs.w.write(vs.scratch[:6])
			}
			i++
			start = i
			continue
		}
		c, size := utf8.DecodeRuneInString(s[i:])
		if c == utf8.RuneError && size == 1 {
			if start < i {
				vs.writeString(s[start:i])
			}
			vs.w.write(invalidCharSym)
			i += size
			start = i
			continue
		}
		// U+2028 is LINE SEPARATOR.
		// U+2029 is PARAGRAPH SEPARATOR.
		// They are both technically valid characters in JSON strings,
		// but don't work in JSONP, which has to be evaluated as JavaScript,
		// and can lead to security holes there. It is valid JSON to
		// escape them, so we do so unconditionally.
		// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
		if c == '\u2028' || c == '\u2029' {
			if start < i {
				vs.writeString(s[start:i])
			}
			vs.writeString(`\u202`)
			vs.writeByte(hex[c&0xF])
			i += size
			start = i
			continue
		}
		i += size
	}
	if start < len(s) {
		vs.writeString(s[start:])
	}
	vs.writeByte('"')
	return nil
}