| | |
| | |
| | |
| |
|
| | |
| |
|
| | package json |
| |
|
| | import ( |
| | "bytes" |
| | "strings" |
| |
|
| | "encoding/json/jsontext" |
| | ) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | func HTMLEscape(dst *bytes.Buffer, src []byte) { |
| | dst.Grow(len(src)) |
| | dst.Write(appendHTMLEscape(dst.AvailableBuffer(), src)) |
| | } |
| |
|
| | func appendHTMLEscape(dst, src []byte) []byte { |
| | const hex = "0123456789abcdef" |
| | |
| | |
| | start := 0 |
| | for i, c := range src { |
| | if c == '<' || c == '>' || c == '&' { |
| | dst = append(dst, src[start:i]...) |
| | dst = append(dst, '\\', 'u', '0', '0', hex[c>>4], hex[c&0xF]) |
| | start = i + 1 |
| | } |
| | |
| | if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 { |
| | dst = append(dst, src[start:i]...) |
| | dst = append(dst, '\\', 'u', '2', '0', '2', hex[src[i+2]&0xF]) |
| | start = i + len("\u2029") |
| | } |
| | } |
| | return append(dst, src[start:]...) |
| | } |
| |
|
| | |
| | |
| | func Compact(dst *bytes.Buffer, src []byte) error { |
| | dst.Grow(len(src)) |
| | b := dst.AvailableBuffer() |
| | b, err := jsontext.AppendFormat(b, src, |
| | jsontext.AllowDuplicateNames(true), |
| | jsontext.AllowInvalidUTF8(true), |
| | jsontext.PreserveRawStrings(true)) |
| | if err != nil { |
| | return transformSyntacticError(err) |
| | } |
| | dst.Write(b) |
| | return nil |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | const indentGrowthFactor = 2 |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error { |
| | dst.Grow(indentGrowthFactor * len(src)) |
| | b := dst.AvailableBuffer() |
| | b, err := appendIndent(b, src, prefix, indent) |
| | dst.Write(b) |
| | return err |
| | } |
| |
|
| | func appendIndent(dst, src []byte, prefix, indent string) ([]byte, error) { |
| | |
| | dstLen := len(dst) |
| | if len(strings.Trim(prefix, " \t"))+len(strings.Trim(indent, " \t")) > 0 { |
| | |
| | invalidPrefix, invalidIndent := prefix, indent |
| | prefix = strings.Repeat(" ", len(prefix)) |
| | indent = strings.Repeat(" ", len(indent)) |
| | defer func() { |
| | b := dst[dstLen:] |
| | for i := bytes.IndexByte(b, '\n'); i >= 0; i = bytes.IndexByte(b, '\n') { |
| | b = b[i+len("\n"):] |
| | n := len(b) - len(bytes.TrimLeft(b, " ")) |
| | spaces := b[:n] |
| | spaces = spaces[copy(spaces, invalidPrefix):] |
| | for len(spaces) > 0 { |
| | spaces = spaces[copy(spaces, invalidIndent):] |
| | } |
| | b = b[n:] |
| | } |
| | }() |
| | } |
| |
|
| | dst, err := jsontext.AppendFormat(dst, src, |
| | jsontext.AllowDuplicateNames(true), |
| | jsontext.AllowInvalidUTF8(true), |
| | jsontext.PreserveRawStrings(true), |
| | jsontext.Multiline(true), |
| | jsontext.WithIndentPrefix(prefix), |
| | jsontext.WithIndent(indent)) |
| | if err != nil { |
| | return dst[:dstLen], transformSyntacticError(err) |
| | } |
| |
|
| | |
| | if n := len(src) - len(bytes.TrimRight(src, " \n\r\t")); n > 0 { |
| | dst = append(dst, src[len(src)-n:]...) |
| | } |
| | return dst, nil |
| | } |
| |
|