2020-08-14 10:01:03 +03:00
|
|
|
package json
|
|
|
|
|
|
|
|
import "bytes"
|
|
|
|
|
|
|
|
func encodeWithIndent(dst *bytes.Buffer, src []byte, prefix, indentStr string) error {
|
|
|
|
length := int64(len(src))
|
|
|
|
indentNum := 0
|
|
|
|
indentBytes := []byte(indentStr)
|
|
|
|
for cursor := int64(0); cursor < length; cursor++ {
|
|
|
|
c := src[cursor]
|
|
|
|
switch c {
|
|
|
|
case ' ', '\t', '\n', '\r':
|
|
|
|
continue
|
|
|
|
case '"':
|
|
|
|
if err := dst.WriteByte(c); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for {
|
|
|
|
cursor++
|
|
|
|
if err := dst.WriteByte(src[cursor]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
switch src[cursor] {
|
|
|
|
case '\\':
|
|
|
|
cursor++
|
|
|
|
if err := dst.WriteByte(src[cursor]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case '"':
|
|
|
|
goto LOOP_END
|
|
|
|
case nul:
|
2021-02-01 16:31:39 +03:00
|
|
|
return errUnexpectedEndOfJSON("string", length)
|
2020-08-14 10:01:03 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case '{':
|
|
|
|
if cursor+1 < length && src[cursor+1] == '}' {
|
|
|
|
if _, err := dst.Write([]byte{'{', '}'}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
cursor++
|
|
|
|
} else {
|
|
|
|
indentNum++
|
|
|
|
b := []byte{c, '\n'}
|
|
|
|
b = append(b, prefix...)
|
|
|
|
b = append(b, bytes.Repeat(indentBytes, indentNum)...)
|
|
|
|
if _, err := dst.Write(b); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case '}':
|
|
|
|
indentNum--
|
|
|
|
if indentNum < 0 {
|
|
|
|
return errInvalidCharacter('}', "}", cursor)
|
|
|
|
}
|
2020-08-27 15:01:53 +03:00
|
|
|
b := []byte{'\n'}
|
2020-08-14 10:01:03 +03:00
|
|
|
b = append(b, prefix...)
|
|
|
|
b = append(b, bytes.Repeat(indentBytes, indentNum)...)
|
2020-08-27 15:01:53 +03:00
|
|
|
b = append(b, c)
|
2020-08-14 10:01:03 +03:00
|
|
|
if _, err := dst.Write(b); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case '[':
|
|
|
|
if cursor+1 < length && src[cursor+1] == ']' {
|
|
|
|
if _, err := dst.Write([]byte{'[', ']'}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
cursor++
|
|
|
|
} else {
|
|
|
|
indentNum++
|
|
|
|
b := []byte{c, '\n'}
|
|
|
|
b = append(b, prefix...)
|
|
|
|
b = append(b, bytes.Repeat(indentBytes, indentNum)...)
|
|
|
|
if _, err := dst.Write(b); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case ']':
|
|
|
|
indentNum--
|
|
|
|
if indentNum < 0 {
|
|
|
|
return errInvalidCharacter(']', "]", cursor)
|
|
|
|
}
|
2020-08-27 15:01:53 +03:00
|
|
|
b := []byte{'\n'}
|
2020-08-14 10:01:03 +03:00
|
|
|
b = append(b, prefix...)
|
|
|
|
b = append(b, bytes.Repeat(indentBytes, indentNum)...)
|
2020-08-27 15:01:53 +03:00
|
|
|
b = append(b, c)
|
2020-08-14 10:01:03 +03:00
|
|
|
if _, err := dst.Write(b); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case ':':
|
|
|
|
if _, err := dst.Write([]byte{':', ' '}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case ',':
|
|
|
|
b := []byte{',', '\n'}
|
|
|
|
b = append(b, prefix...)
|
|
|
|
b = append(b, bytes.Repeat(indentBytes, indentNum)...)
|
|
|
|
if _, err := dst.Write(b); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if err := dst.WriteByte(c); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LOOP_END:
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|