forked from mirror/go-json
Add indent test
This commit is contained in:
parent
1657b0e50e
commit
d42d09f9f9
|
@ -1838,7 +1838,7 @@ func TestCoverArray(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
for _, indent := range []bool{false} {
|
for _, indent := range []bool{true, false} {
|
||||||
for _, htmlEscape := range []bool{true, false} {
|
for _, htmlEscape := range []bool{true, false} {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := json.NewEncoder(&buf)
|
enc := json.NewEncoder(&buf)
|
||||||
|
|
|
@ -1774,11 +1774,11 @@ func TestCoverBool(t *testing.T) {
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
}
|
}
|
||||||
if err := enc.Encode(test.data); err != nil {
|
if err := enc.Encode(test.data); err != nil {
|
||||||
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
|
||||||
}
|
}
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
if buf.String() != stdresult {
|
if buf.String() != stdresult {
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1765,7 +1765,7 @@ func TestCoverInt(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
for _, indent := range []bool{false} {
|
for _, indent := range []bool{true, false} {
|
||||||
for _, htmlEscape := range []bool{true, false} {
|
for _, htmlEscape := range []bool{true, false} {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := json.NewEncoder(&buf)
|
enc := json.NewEncoder(&buf)
|
||||||
|
|
|
@ -1838,7 +1838,7 @@ func TestCoverMap(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
for _, indent := range []bool{false} {
|
for _, indent := range []bool{true, false} {
|
||||||
for _, htmlEscape := range []bool{true, false} {
|
for _, htmlEscape := range []bool{true, false} {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := json.NewEncoder(&buf)
|
enc := json.NewEncoder(&buf)
|
||||||
|
|
|
@ -3525,7 +3525,7 @@ func TestCoverMarshalJSON(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
for _, indent := range []bool{false} {
|
for _, indent := range []bool{true, false} {
|
||||||
for _, htmlEscape := range []bool{true, false} {
|
for _, htmlEscape := range []bool{true, false} {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := json.NewEncoder(&buf)
|
enc := json.NewEncoder(&buf)
|
||||||
|
|
|
@ -3525,7 +3525,7 @@ func TestCoverMarshalText(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
for _, indent := range []bool{false} {
|
for _, indent := range []bool{true, false} {
|
||||||
for _, htmlEscape := range []bool{true, false} {
|
for _, htmlEscape := range []bool{true, false} {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := json.NewEncoder(&buf)
|
enc := json.NewEncoder(&buf)
|
||||||
|
|
|
@ -1838,7 +1838,7 @@ func TestCoverSlice(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
for _, indent := range []bool{false} {
|
for _, indent := range []bool{true, false} {
|
||||||
for _, htmlEscape := range []bool{true, false} {
|
for _, htmlEscape := range []bool{true, false} {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := json.NewEncoder(&buf)
|
enc := json.NewEncoder(&buf)
|
||||||
|
|
|
@ -1793,11 +1793,11 @@ func TestCoverString(t *testing.T) {
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
}
|
}
|
||||||
if err := enc.Encode(test.data); err != nil {
|
if err := enc.Encode(test.data); err != nil {
|
||||||
t.Fatalf("%s(htmlEscape:%T): %v: %s", test.name, htmlEscape, test.data, err)
|
t.Fatalf("%s(htmlEscape:%v,indent:%v): %v: %s", test.name, htmlEscape, indent, test.data, err)
|
||||||
}
|
}
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
if buf.String() != stdresult {
|
if buf.String() != stdresult {
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1774,11 +1774,11 @@ func TestCoverUint16(t *testing.T) {
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
}
|
}
|
||||||
if err := enc.Encode(test.data); err != nil {
|
if err := enc.Encode(test.data); err != nil {
|
||||||
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
|
||||||
}
|
}
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
if buf.String() != stdresult {
|
if buf.String() != stdresult {
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
36
encode.go
36
encode.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
@ -385,6 +386,33 @@ func encodeMarshalJSON(b []byte, v interface{}) ([]byte, error) {
|
||||||
return buf.Bytes(), nil
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeMarshalJSONIndent(ctx *encodeRuntimeContext, b []byte, v interface{}, indent int) ([]byte, error) {
|
||||||
|
bb, err := v.(Marshaler).MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
return nil, &MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||||
|
}
|
||||||
|
if len(bb) == 0 {
|
||||||
|
return nil, errUnexpectedEndOfJSON(
|
||||||
|
fmt.Sprintf("error calling MarshalJSON for type %s", reflect.TypeOf(v)),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var compactBuf bytes.Buffer
|
||||||
|
if err := compact(&compactBuf, bb, false); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var indentBuf bytes.Buffer
|
||||||
|
if err := encodeWithIndent(
|
||||||
|
&indentBuf,
|
||||||
|
compactBuf.Bytes(),
|
||||||
|
string(ctx.prefix)+strings.Repeat(string(ctx.indentStr), ctx.baseIndent+indent),
|
||||||
|
string(ctx.indentStr),
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return append(b, indentBuf.Bytes()...), nil
|
||||||
|
}
|
||||||
|
|
||||||
func encodeMarshalText(b []byte, v interface{}) ([]byte, error) {
|
func encodeMarshalText(b []byte, v interface{}) ([]byte, error) {
|
||||||
bytes, err := v.(encoding.TextMarshaler).MarshalText()
|
bytes, err := v.(encoding.TextMarshaler).MarshalText()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -392,3 +420,11 @@ func encodeMarshalText(b []byte, v interface{}) ([]byte, error) {
|
||||||
}
|
}
|
||||||
return encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))), nil
|
return encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeMarshalTextIndent(b []byte, v interface{}) ([]byte, error) {
|
||||||
|
bytes, err := v.(encoding.TextMarshaler).MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
return nil, &MarshalerError{Type: reflect.TypeOf(v), Err: err}
|
||||||
|
}
|
||||||
|
return encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))), nil
|
||||||
|
}
|
||||||
|
|
|
@ -1327,6 +1327,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
||||||
}
|
}
|
||||||
if field.Anonymous {
|
if field.Anonymous {
|
||||||
valueCode.anonymousHead = true
|
valueCode.anonymousHead = true
|
||||||
|
valueCode.decIndent()
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf(`"%s":`, tag.key)
|
key := fmt.Sprintf(`"%s":`, tag.key)
|
||||||
escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key)))
|
escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key)))
|
||||||
|
|
|
@ -178,6 +178,18 @@ func (c *opcode) decOpcodeIndex() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *opcode) decIndent() {
|
||||||
|
for code := c; code.op != opEnd; {
|
||||||
|
code.indent--
|
||||||
|
switch code.op.codeType() {
|
||||||
|
case codeArrayElem, codeSliceElem, codeMapKey:
|
||||||
|
code = code.end
|
||||||
|
default:
|
||||||
|
code = code.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *opcode) dumpHead(code *opcode) string {
|
func (c *opcode) dumpHead(code *opcode) string {
|
||||||
var length uintptr
|
var length uintptr
|
||||||
if code.op.codeType() == codeArrayHead {
|
if code.op.codeType() == codeArrayHead {
|
||||||
|
@ -412,6 +424,7 @@ func newArrayElemCode(ctx *encodeCompileContext, head *opcode, length int, size
|
||||||
elemIdx: head.elemIdx,
|
elemIdx: head.elemIdx,
|
||||||
headIdx: head.headIdx,
|
headIdx: head.headIdx,
|
||||||
length: uintptr(length),
|
length: uintptr(length),
|
||||||
|
indent: ctx.indent,
|
||||||
size: size,
|
size: size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
encode_vm.go
18
encode_vm.go
|
@ -240,7 +240,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
||||||
case opSliceHead:
|
case opSliceHead:
|
||||||
p := load(ctxptr, code.idx)
|
p := load(ctxptr, code.idx)
|
||||||
slice := ptrToSlice(p)
|
slice := ptrToSlice(p)
|
||||||
if p == 0 || uintptr(slice.data) == 0 {
|
if p == 0 || slice.data == nil {
|
||||||
b = encodeNull(b)
|
b = encodeNull(b)
|
||||||
b = encodeComma(b)
|
b = encodeComma(b)
|
||||||
code = code.end.next
|
code = code.end.next
|
||||||
|
@ -1723,7 +1723,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
||||||
fallthrough
|
fallthrough
|
||||||
case opStructFieldHeadBoolPtr:
|
case opStructFieldHeadBoolPtr:
|
||||||
p := load(ctxptr, code.idx)
|
p := load(ctxptr, code.idx)
|
||||||
if p == 0 {
|
if p == 0 && code.indirect {
|
||||||
if !code.anonymousHead {
|
if !code.anonymousHead {
|
||||||
b = encodeNull(b)
|
b = encodeNull(b)
|
||||||
b = encodeComma(b)
|
b = encodeComma(b)
|
||||||
|
@ -1759,7 +1759,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
||||||
fallthrough
|
fallthrough
|
||||||
case opStructFieldHeadOmitEmptyBoolPtr:
|
case opStructFieldHeadOmitEmptyBoolPtr:
|
||||||
p := load(ctxptr, code.idx)
|
p := load(ctxptr, code.idx)
|
||||||
if p == 0 {
|
if p == 0 && code.indirect {
|
||||||
if !code.anonymousHead {
|
if !code.anonymousHead {
|
||||||
b = encodeNull(b)
|
b = encodeNull(b)
|
||||||
b = encodeComma(b)
|
b = encodeComma(b)
|
||||||
|
@ -1793,7 +1793,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
||||||
fallthrough
|
fallthrough
|
||||||
case opStructFieldHeadStringTagBoolPtr:
|
case opStructFieldHeadStringTagBoolPtr:
|
||||||
p := load(ctxptr, code.idx)
|
p := load(ctxptr, code.idx)
|
||||||
if p == 0 {
|
if p == 0 && code.indirect {
|
||||||
if !code.anonymousHead {
|
if !code.anonymousHead {
|
||||||
b = encodeNull(b)
|
b = encodeNull(b)
|
||||||
b = encodeComma(b)
|
b = encodeComma(b)
|
||||||
|
@ -3349,15 +3349,15 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
||||||
}
|
}
|
||||||
case opStructFieldSlice, opStructFieldStringTagSlice:
|
case opStructFieldSlice, opStructFieldStringTagSlice:
|
||||||
b = append(b, code.key...)
|
b = append(b, code.key...)
|
||||||
ptr := load(ctxptr, code.headIdx)
|
p := load(ctxptr, code.headIdx)
|
||||||
p := ptr + code.offset
|
p += code.offset
|
||||||
code = code.next
|
code = code.next
|
||||||
store(ctxptr, code.idx, p)
|
store(ctxptr, code.idx, p)
|
||||||
case opStructFieldOmitEmptySlice:
|
case opStructFieldOmitEmptySlice:
|
||||||
ptr := load(ctxptr, code.headIdx)
|
p := load(ctxptr, code.headIdx)
|
||||||
p := ptr + code.offset
|
p += code.offset
|
||||||
slice := ptrToSlice(p)
|
slice := ptrToSlice(p)
|
||||||
if p == 0 || uintptr(slice.data) == 0 {
|
if p == 0 || slice.data == nil {
|
||||||
code = code.nextField
|
code = code.nextField
|
||||||
} else {
|
} else {
|
||||||
b = append(b, code.key...)
|
b = append(b, code.key...)
|
||||||
|
|
|
@ -1665,7 +1665,7 @@ func encodeRunEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, o
|
||||||
fallthrough
|
fallthrough
|
||||||
case opStructFieldHeadBoolPtr:
|
case opStructFieldHeadBoolPtr:
|
||||||
p := load(ctxptr, code.idx)
|
p := load(ctxptr, code.idx)
|
||||||
if p == 0 {
|
if p == 0 && code.indirect {
|
||||||
if !code.anonymousHead {
|
if !code.anonymousHead {
|
||||||
b = encodeNull(b)
|
b = encodeNull(b)
|
||||||
b = encodeComma(b)
|
b = encodeComma(b)
|
||||||
|
@ -1701,7 +1701,7 @@ func encodeRunEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, o
|
||||||
fallthrough
|
fallthrough
|
||||||
case opStructFieldHeadOmitEmptyBoolPtr:
|
case opStructFieldHeadOmitEmptyBoolPtr:
|
||||||
p := load(ctxptr, code.idx)
|
p := load(ctxptr, code.idx)
|
||||||
if p == 0 {
|
if p == 0 && code.indirect {
|
||||||
if !code.anonymousHead {
|
if !code.anonymousHead {
|
||||||
b = encodeNull(b)
|
b = encodeNull(b)
|
||||||
b = encodeComma(b)
|
b = encodeComma(b)
|
||||||
|
@ -1735,7 +1735,7 @@ func encodeRunEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, o
|
||||||
fallthrough
|
fallthrough
|
||||||
case opStructFieldHeadStringTagBoolPtr:
|
case opStructFieldHeadStringTagBoolPtr:
|
||||||
p := load(ctxptr, code.idx)
|
p := load(ctxptr, code.idx)
|
||||||
if p == 0 {
|
if p == 0 && code.indirect {
|
||||||
if !code.anonymousHead {
|
if !code.anonymousHead {
|
||||||
b = encodeNull(b)
|
b = encodeNull(b)
|
||||||
b = encodeComma(b)
|
b = encodeComma(b)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
3963
encode_vm_indent.go
3963
encode_vm_indent.go
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue