diff --git a/internal/encoder/vm_escaped_indent/util.go b/internal/encoder/vm_escaped_indent/util.go index e238cf6..eba9a48 100644 --- a/internal/encoder/vm_escaped_indent/util.go +++ b/internal/encoder/vm_escaped_indent/util.go @@ -75,3 +75,19 @@ func appendNull(b []byte) []byte { func appendComma(b []byte) []byte { return append(b, ',', '\n') } + +func appendStructEndSkipLast(ctx *encoder.RuntimeContext, b []byte, code *encoder.Opcode) []byte { + last := len(b) - 1 + if b[last-1] == '{' { + b[last] = '}' + } else { + if b[last] == '\n' { + // to remove ',' and '\n' characters + b = b[:len(b)-2] + } + b = append(b, '\n') + b = appendIndent(ctx, b, code.Indent-1) + b = append(b, '}') + } + return appendComma(b) +} diff --git a/internal/encoder/vm_escaped_indent/vm.go b/internal/encoder/vm_escaped_indent/vm.go index f1a1915..f5fc20d 100644 --- a/internal/encoder/vm_escaped_indent/vm.go +++ b/internal/encoder/vm_escaped_indent/vm.go @@ -761,6 +761,46 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntString: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyIntString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v == 0 { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendInt(b, u64, code) + b = append(b, '"') + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -875,6 +915,43 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendInt(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadUint: if code.Indirect { p := load(ctxptr, code.Idx) @@ -981,6 +1058,46 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintString: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyUintString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v == 0 { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendUint(b, u64, code) + b = append(b, '"') + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1095,6 +1212,43 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendUint(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadFloat32: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1200,6 +1354,45 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32String: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + v := ptrToFloat32(p + code.Offset) + if v == 0 { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1314,6 +1507,43 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadFloat64: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1430,6 +1660,48 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64String: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + v := ptrToFloat64(p + code.Offset) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + if v == 0 { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1556,6 +1828,47 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadString: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1661,6 +1974,44 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, string(appendString([]byte{}, v))) b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringString: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyStringString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + v := ptrToString(p + code.Offset) + if v == "" { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ') + b = appendString(b, string(appendString([]byte{}, v))) + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1773,6 +2124,43 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadBool: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1878,6 +2266,45 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolString: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + v := ptrToBool(p + code.Offset) + if v { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendComma(b) + code = code.Next + } else { + code = code.NextField + } case encoder.OpStructPtrHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1992,6 +2419,43 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadBytes: if code.Indirect { p := load(ctxptr, code.Idx) @@ -2252,6 +2716,48 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(bb, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberString: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + v := ptrToNumber(p + code.Offset) + if v == "" { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, v) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendComma(bb) + code = code.Next + } case encoder.OpStructPtrHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -2376,6 +2882,46 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendComma(bb) + } + code = code.Next case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: if code.Indirect { p := load(ctxptr, code.Idx) @@ -3117,6 +3663,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyIntString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendInt(b, u64, code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldIntPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3156,6 +3715,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyIntPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendInt(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldUint: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3185,6 +3756,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyUintString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendUint(b, u64, code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldUintPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3224,6 +3808,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyUintPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendUint(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat32: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3252,6 +3848,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat32(p + code.Offset) + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat32Ptr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3291,6 +3899,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat64: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3330,6 +3950,21 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat64(p + code.Offset) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat64Ptr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3381,6 +4016,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldString: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3409,6 +4060,17 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, string(appendString([]byte{}, s))) b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyStringString: + p := load(ctxptr, code.HeadIdx) + v := ptrToString(p + code.Offset) + if v != "" { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ') + b = appendString(b, string(appendString([]byte{}, v))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldStringPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3446,6 +4108,17 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyStringPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ') + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBool: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3474,6 +4147,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyBoolString: + p := load(ctxptr, code.HeadIdx) + v := ptrToBool(p + code.Offset) + if v { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBoolPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3513,6 +4198,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyBoolPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBytes: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3594,6 +4291,21 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(bb, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyNumberString: + p := load(ctxptr, code.HeadIdx) + v := ptrToNumber(p + code.Offset) + if v != "" { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, v) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendComma(bb) + } + code = code.Next case encoder.OpStructFieldNumberPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3643,6 +4355,21 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyNumberPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendComma(bb) + } + code = code.Next case encoder.OpStructFieldMarshalJSON: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -3969,19 +4696,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendInt(b, u64, code) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndIntString: @@ -3993,6 +4708,21 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyIntString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendInt(b, u64, code) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndIntPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4016,19 +4746,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendInt(b, ptrToUint64(p), code) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndIntPtrString: @@ -4046,6 +4764,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyIntPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendInt(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndUint: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4065,19 +4797,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendUint(b, u64, code) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndUintString: @@ -4089,6 +4809,21 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyUintString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendUint(b, u64, code) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndUintPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4112,19 +4847,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendUint(b, ptrToUint64(p), code) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndUintPtrString: @@ -4142,6 +4865,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyUintPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendUint(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndFloat32: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4160,19 +4897,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat32(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndFloat32String: @@ -4184,6 +4909,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyFloat32String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat32(p + code.Offset) + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndFloat32Ptr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4207,19 +4946,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat32(b, ptrToFloat32(p)) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndFloat32PtrString: @@ -4237,6 +4964,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyFloat32PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndFloat64: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4262,19 +5003,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat64(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndFloat64String: @@ -4290,6 +5019,23 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyFloat64String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat64(p + code.Offset) + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(b, v) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndFloat64Ptr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4321,19 +5067,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat64(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndFloat64PtrString: @@ -4355,6 +5089,24 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyFloat64PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(b, v) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndString: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4373,19 +5125,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndStringString: @@ -4397,6 +5137,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, string(appendString([]byte{}, s))) b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyStringString: + p := load(ctxptr, code.HeadIdx) + v := ptrToString(p + code.Offset) + if v != "" { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ') + b = appendString(b, string(appendString([]byte{}, v))) + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndStringPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4420,19 +5173,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, ptrToString(p)) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndStringPtrString: @@ -4448,6 +5189,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyStringPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ') + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndBool: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4466,19 +5220,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendBool(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndBoolString: @@ -4490,6 +5232,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyBoolString: + p := load(ctxptr, code.HeadIdx) + v := ptrToBool(p + code.Offset) + if v { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndBoolPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4513,19 +5269,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendBool(b, ptrToBool(p)) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndBoolPtrString: @@ -4543,6 +5287,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndBytes: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4561,19 +5319,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendByteSlice(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndBytesPtr: @@ -4599,19 +5345,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendByteSlice(b, ptrToBytes(p)) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndNumber: @@ -4638,19 +5372,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, bb, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndNumberString: @@ -4666,6 +5388,23 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(bb, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyNumberString: + p := load(ctxptr, code.HeadIdx) + v := ptrToNumber(p + code.Offset) + if v != "" { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, v) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendStructEnd(ctx, bb, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndNumberPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.EscapedKey...) @@ -4696,19 +5435,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, bb, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndNumberPtrString: @@ -4729,6 +5456,23 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.EscapedKey...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendStructEnd(ctx, bb, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpEnd: goto END } diff --git a/internal/encoder/vm_indent/util.go b/internal/encoder/vm_indent/util.go index e678217..d9d74c6 100644 --- a/internal/encoder/vm_indent/util.go +++ b/internal/encoder/vm_indent/util.go @@ -75,3 +75,19 @@ func appendNull(b []byte) []byte { func appendComma(b []byte) []byte { return append(b, ',', '\n') } + +func appendStructEndSkipLast(ctx *encoder.RuntimeContext, b []byte, code *encoder.Opcode) []byte { + last := len(b) - 1 + if b[last-1] == '{' { + b[last] = '}' + } else { + if b[last] == '\n' { + // to remove ',' and '\n' characters + b = b[:len(b)-2] + } + b = append(b, '\n') + b = appendIndent(ctx, b, code.Indent-1) + b = append(b, '}') + } + return appendComma(b) +} diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index 4aa83df..a288c2a 100644 --- a/internal/encoder/vm_indent/vm.go +++ b/internal/encoder/vm_indent/vm.go @@ -761,6 +761,46 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntString: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyIntString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v == 0 { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendInt(b, u64, code) + b = append(b, '"') + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadIntPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -875,6 +915,43 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyIntPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendInt(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadUint: if code.Indirect { p := load(ctxptr, code.Idx) @@ -981,6 +1058,46 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintString: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyUintString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v == 0 { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendUint(b, u64, code) + b = append(b, '"') + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadUintPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1095,6 +1212,43 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyUintPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendUint(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadFloat32: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1200,6 +1354,45 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32String: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32String: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + v := ptrToFloat32(p + code.Offset) + if v == 0 { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadFloat32Ptr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1314,6 +1507,43 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat32PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadFloat64: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1430,6 +1660,48 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64String: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64String: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + v := ptrToFloat64(p + code.Offset) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + if v == 0 { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadFloat64Ptr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1556,6 +1828,47 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyFloat64PtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadString: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1661,6 +1974,44 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, string(appendString([]byte{}, v))) b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringString: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyStringString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + v := ptrToString(p + code.Offset) + if v == "" { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ') + b = appendString(b, string(appendString([]byte{}, v))) + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1773,6 +2124,43 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyStringPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadBool: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1878,6 +2266,45 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolString: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyBoolString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + v := ptrToBool(p + code.Offset) + if v { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendComma(b) + code = code.Next + } else { + code = code.NextField + } case encoder.OpStructPtrHeadBoolPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1992,6 +2419,43 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyBoolPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadBytes: if code.Indirect { p := load(ctxptr, code.Idx) @@ -2252,6 +2716,48 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(bb, '"') b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberString: + if code.Indirect { + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + } + fallthrough + case encoder.OpStructHeadOmitEmptyNumberString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + v := ptrToNumber(p + code.Offset) + if v == "" { + code = code.NextField + } else { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, v) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendComma(bb) + code = code.Next + } case encoder.OpStructPtrHeadNumberPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -2376,6 +2882,46 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructPtrHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum)) + fallthrough + case encoder.OpStructHeadOmitEmptyNumberPtrString: + p := load(ctxptr, code.Idx) + if p == 0 && code.Indirect { + if !code.AnonymousHead { + b = appendNull(b) + b = appendComma(b) + } + code = code.End.Next + break + } + if !code.AnonymousHead { + b = append(b, '{', '\n') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = appendIndent(ctx, b, code.Indent+1) + b = append(b, code.Key...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendComma(bb) + } + code = code.Next case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice: if code.Indirect { p := load(ctxptr, code.Idx) @@ -3117,6 +3663,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyIntString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendInt(b, u64, code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldIntPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3156,6 +3715,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyIntPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendInt(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldUint: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3185,6 +3756,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyUintString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendUint(b, u64, code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldUintPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3224,6 +3808,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyUintPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendUint(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat32: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3252,6 +3848,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat32(p + code.Offset) + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat32Ptr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3291,6 +3899,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyFloat32PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat64: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3330,6 +3950,21 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat64(p + code.Offset) + if v != 0 { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat64Ptr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3381,6 +4016,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyFloat64PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldString: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3409,6 +4060,17 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, string(appendString([]byte{}, s))) b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyStringString: + p := load(ctxptr, code.HeadIdx) + v := ptrToString(p + code.Offset) + if v != "" { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ') + b = appendString(b, string(appendString([]byte{}, v))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldStringPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3446,6 +4108,17 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyStringPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ') + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBool: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3474,6 +4147,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyBoolString: + p := load(ctxptr, code.HeadIdx) + v := ptrToBool(p + code.Offset) + if v { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBoolPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3513,6 +4198,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyBoolPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBytes: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3594,6 +4291,21 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(bb, '"') b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyNumberString: + p := load(ctxptr, code.HeadIdx) + v := ptrToNumber(p + code.Offset) + if v != "" { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, v) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendComma(bb) + } + code = code.Next case encoder.OpStructFieldNumberPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3643,6 +4355,21 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendComma(b) code = code.Next + case encoder.OpStructFieldOmitEmptyNumberPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendComma(bb) + } + code = code.Next case encoder.OpStructFieldMarshalJSON: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -3969,19 +4696,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendInt(b, u64, code) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndIntString: @@ -3993,6 +4708,21 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyIntString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendInt(b, u64, code) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndIntPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4016,19 +4746,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendInt(b, ptrToUint64(p), code) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndIntPtrString: @@ -4046,6 +4764,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyIntPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendInt(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndUint: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4065,19 +4797,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendUint(b, u64, code) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndUintString: @@ -4089,6 +4809,21 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyUintString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendUint(b, u64, code) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndUintPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4112,19 +4847,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendUint(b, ptrToUint64(p), code) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndUintPtrString: @@ -4142,6 +4865,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyUintPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendUint(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndFloat32: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4160,19 +4897,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat32(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndFloat32String: @@ -4184,6 +4909,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyFloat32String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat32(p + code.Offset) + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndFloat32Ptr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4207,19 +4946,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat32(b, ptrToFloat32(p)) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndFloat32PtrString: @@ -4237,6 +4964,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyFloat32PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndFloat64: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4262,19 +5003,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat64(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndFloat64String: @@ -4290,6 +5019,23 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyFloat64String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat64(p + code.Offset) + if v != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(b, v) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndFloat64Ptr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4321,19 +5067,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat64(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndFloat64PtrString: @@ -4355,6 +5089,24 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyFloat64PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = appendFloat64(b, v) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndString: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4373,19 +5125,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndStringString: @@ -4397,6 +5137,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, string(appendString([]byte{}, s))) b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyStringString: + p := load(ctxptr, code.HeadIdx) + v := ptrToString(p + code.Offset) + if v != "" { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ') + b = appendString(b, string(appendString([]byte{}, v))) + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndStringPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4420,19 +5173,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, ptrToString(p)) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndStringPtrString: @@ -4448,6 +5189,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyStringPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ') + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndBool: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4466,19 +5220,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendBool(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndBoolString: @@ -4490,6 +5232,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyBoolString: + p := load(ctxptr, code.HeadIdx) + v := ptrToBool(p + code.Offset) + if v { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndBoolPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4513,19 +5269,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendBool(b, ptrToBool(p)) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndBoolPtrString: @@ -4543,6 +5287,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendStructEnd(ctx, b, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndBytes: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4561,19 +5319,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendByteSlice(b, v) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndBytesPtr: @@ -4599,19 +5345,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendByteSlice(b, ptrToBytes(p)) b = appendStructEnd(ctx, b, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndNumber: @@ -4638,19 +5372,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, bb, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndNumberString: @@ -4666,6 +5388,23 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(bb, '"') b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyNumberString: + p := load(ctxptr, code.HeadIdx) + v := ptrToNumber(p + code.Offset) + if v != "" { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, v) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendStructEnd(ctx, bb, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpStructEndNumberPtr: b = appendIndent(ctx, b, code.Indent) b = append(b, code.Key...) @@ -4696,19 +5435,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, bb, code.Indent-1) } else { - last := len(b) - 1 - if b[last-1] == '{' { - b[last] = '}' - } else { - if b[last] == '\n' { - // to remove ',' and '\n' characters - b = b[:len(b)-2] - } - b = append(b, '\n') - b = appendIndent(ctx, b, code.Indent-1) - b = append(b, '}') - } - b = appendComma(b) + b = appendStructEndSkipLast(ctx, b, code) } code = code.Next case encoder.OpStructEndNumberPtrString: @@ -4729,6 +5456,23 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = appendIndent(ctx, b, code.Indent) + b = append(b, code.Key...) + b = append(b, ' ', '"') + bb, err := appendNumber(b, ptrToNumber(p)) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendStructEnd(ctx, bb, code.Indent-1) + } else { + b = appendStructEndSkipLast(ctx, b, code) + } + code = code.Next case encoder.OpEnd: goto END }