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 _, indent := range []bool{false} {
|
||||
for _, indent := range []bool{true, false} {
|
||||
for _, htmlEscape := range []bool{true, false} {
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
|
|
|
@ -1774,11 +1774,11 @@ func TestCoverBool(t *testing.T) {
|
|||
enc.SetIndent("", " ")
|
||||
}
|
||||
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)
|
||||
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 _, indent := range []bool{false} {
|
||||
for _, indent := range []bool{true, false} {
|
||||
for _, htmlEscape := range []bool{true, false} {
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
|
|
|
@ -1838,7 +1838,7 @@ func TestCoverMap(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
for _, indent := range []bool{false} {
|
||||
for _, indent := range []bool{true, false} {
|
||||
for _, htmlEscape := range []bool{true, false} {
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
|
|
|
@ -3525,7 +3525,7 @@ func TestCoverMarshalJSON(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
for _, indent := range []bool{false} {
|
||||
for _, indent := range []bool{true, false} {
|
||||
for _, htmlEscape := range []bool{true, false} {
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
|
|
|
@ -3525,7 +3525,7 @@ func TestCoverMarshalText(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
for _, indent := range []bool{false} {
|
||||
for _, indent := range []bool{true, false} {
|
||||
for _, htmlEscape := range []bool{true, false} {
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
|
|
|
@ -1838,7 +1838,7 @@ func TestCoverSlice(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
for _, indent := range []bool{false} {
|
||||
for _, indent := range []bool{true, false} {
|
||||
for _, htmlEscape := range []bool{true, false} {
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
|
|
|
@ -1793,11 +1793,11 @@ func TestCoverString(t *testing.T) {
|
|||
enc.SetIndent("", " ")
|
||||
}
|
||||
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)
|
||||
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("", " ")
|
||||
}
|
||||
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)
|
||||
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"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
@ -385,6 +386,33 @@ func encodeMarshalJSON(b []byte, v interface{}) ([]byte, error) {
|
|||
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) {
|
||||
bytes, err := v.(encoding.TextMarshaler).MarshalText()
|
||||
if err != nil {
|
||||
|
@ -392,3 +420,11 @@ func encodeMarshalText(b []byte, v interface{}) ([]byte, error) {
|
|||
}
|
||||
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 {
|
||||
valueCode.anonymousHead = true
|
||||
valueCode.decIndent()
|
||||
}
|
||||
key := fmt.Sprintf(`"%s":`, 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 {
|
||||
var length uintptr
|
||||
if code.op.codeType() == codeArrayHead {
|
||||
|
@ -412,6 +424,7 @@ func newArrayElemCode(ctx *encodeCompileContext, head *opcode, length int, size
|
|||
elemIdx: head.elemIdx,
|
||||
headIdx: head.headIdx,
|
||||
length: uintptr(length),
|
||||
indent: ctx.indent,
|
||||
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:
|
||||
p := load(ctxptr, code.idx)
|
||||
slice := ptrToSlice(p)
|
||||
if p == 0 || uintptr(slice.data) == 0 {
|
||||
if p == 0 || slice.data == nil {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
code = code.end.next
|
||||
|
@ -1723,7 +1723,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
fallthrough
|
||||
case opStructFieldHeadBoolPtr:
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 {
|
||||
if p == 0 && code.indirect {
|
||||
if !code.anonymousHead {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
|
@ -1759,7 +1759,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
fallthrough
|
||||
case opStructFieldHeadOmitEmptyBoolPtr:
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 {
|
||||
if p == 0 && code.indirect {
|
||||
if !code.anonymousHead {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
|
@ -1793,7 +1793,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
fallthrough
|
||||
case opStructFieldHeadStringTagBoolPtr:
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 {
|
||||
if p == 0 && code.indirect {
|
||||
if !code.anonymousHead {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
|
@ -3349,15 +3349,15 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
|
|||
}
|
||||
case opStructFieldSlice, opStructFieldStringTagSlice:
|
||||
b = append(b, code.key...)
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
p := load(ctxptr, code.headIdx)
|
||||
p += code.offset
|
||||
code = code.next
|
||||
store(ctxptr, code.idx, p)
|
||||
case opStructFieldOmitEmptySlice:
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
p := load(ctxptr, code.headIdx)
|
||||
p += code.offset
|
||||
slice := ptrToSlice(p)
|
||||
if p == 0 || uintptr(slice.data) == 0 {
|
||||
if p == 0 || slice.data == nil {
|
||||
code = code.nextField
|
||||
} else {
|
||||
b = append(b, code.key...)
|
||||
|
|
|
@ -1665,7 +1665,7 @@ func encodeRunEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, o
|
|||
fallthrough
|
||||
case opStructFieldHeadBoolPtr:
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 {
|
||||
if p == 0 && code.indirect {
|
||||
if !code.anonymousHead {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
|
@ -1701,7 +1701,7 @@ func encodeRunEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, o
|
|||
fallthrough
|
||||
case opStructFieldHeadOmitEmptyBoolPtr:
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 {
|
||||
if p == 0 && code.indirect {
|
||||
if !code.anonymousHead {
|
||||
b = encodeNull(b)
|
||||
b = encodeComma(b)
|
||||
|
@ -1735,7 +1735,7 @@ func encodeRunEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, o
|
|||
fallthrough
|
||||
case opStructFieldHeadStringTagBoolPtr:
|
||||
p := load(ctxptr, code.idx)
|
||||
if p == 0 {
|
||||
if p == 0 && code.indirect {
|
||||
if !code.anonymousHead {
|
||||
b = encodeNull(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