diff --git a/internal/encoder/vm/util.go b/internal/encoder/vm/util.go index 954b0d0..713655e 100644 --- a/internal/encoder/vm/util.go +++ b/internal/encoder/vm/util.go @@ -79,3 +79,12 @@ func appendComma(b []byte) []byte { func appendStructEnd(b []byte) []byte { return append(b, '}', ',') } + +func appendStructEndSkipLast(b []byte) []byte { + last := len(b) - 1 + if b[last] == ',' { + b[last] = '}' + return appendComma(b) + } + return appendStructEnd(b) +} diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index 55c7a8f..9039bee 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -729,6 +729,45 @@ 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, '{') + } + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v == 0 { + code = code.NextField + } else { + 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 { @@ -837,6 +876,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -938,6 +1013,45 @@ 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, '{') + } + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v == 0 { + code = code.NextField + } else { + 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 { @@ -1046,6 +1160,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -1146,6 +1296,44 @@ 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, '{') + } + v := ptrToFloat32(p + code.Offset) + if v == 0 { + code = code.NextField + } else { + 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 { @@ -1254,6 +1442,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -1365,6 +1589,47 @@ 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, '{') + } + v := ptrToFloat64(p + code.Offset) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + 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 { @@ -1485,6 +1750,46 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -1584,6 +1889,42 @@ 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.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, '{') + } + v := ptrToString(p + code.Offset) + if v == "" { + code = code.NextField + } else { + b = append(b, code.Key...) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1690,6 +2031,40 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = append(b, code.Key...) + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadBool: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1790,6 +2165,44 @@ 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, '{') + } + v := ptrToBool(p + code.Offset) + if v { + 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 { @@ -1898,6 +2311,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -2144,6 +2593,47 @@ 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, '{') + } + v := ptrToNumber(p + code.Offset) + if v == "" { + code = code.NextField + } else { + 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 { @@ -2262,6 +2752,45 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -2960,6 +3489,18 @@ 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 = 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 = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -2993,6 +3534,17 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3017,6 +3569,18 @@ 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 = 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 = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3050,6 +3614,17 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3073,6 +3648,17 @@ 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 = append(b, code.Key...) + b = append(b, '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat32Ptr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3106,6 +3692,17 @@ 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 = append(b, code.Key...) + b = append(b, '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat64: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3140,6 +3737,20 @@ 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 = append(b, code.Key...) + b = append(b, '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat64Ptr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3187,6 +3798,21 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3209,6 +3835,15 @@ 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 = append(b, code.Key...) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldStringPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3240,6 +3875,15 @@ 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 = append(b, code.Key...) + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBool: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3263,6 +3907,17 @@ 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 = append(b, code.Key...) + b = append(b, '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBoolPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3296,6 +3951,17 @@ 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 = append(b, code.Key...) + b = append(b, '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBytes: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3363,6 +4029,20 @@ 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 = 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 = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3406,6 +4086,20 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3666,13 +4360,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendInt(b, u64, code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndIntString: @@ -3683,6 +4371,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyIntString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendInt(b, u64, code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndIntPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3702,13 +4404,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendInt(b, ptrToUint64(p), code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndIntPtrString: @@ -3724,6 +4420,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyIntPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendInt(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndUint: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3739,13 +4448,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendUint(b, u64, code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndUintString: @@ -3756,6 +4459,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyUintString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendUint(b, u64, code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndUintPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3775,13 +4492,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendUint(b, ptrToUint64(p), code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndUintPtrString: @@ -3797,6 +4508,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyUintPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendUint(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat32: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3811,13 +4535,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat32(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat32String: @@ -3828,6 +4546,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat32String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat32(p + code.Offset) + if v != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat32Ptr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3847,13 +4578,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat32(b, ptrToFloat32(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat32PtrString: @@ -3869,6 +4594,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat32PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat64: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3890,13 +4628,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat64(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat64String: @@ -3911,6 +4643,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat64String: + 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 = append(b, code.Key...) + b = append(b, '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat64Ptr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3940,13 +4688,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat64(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat64PtrString: @@ -3966,6 +4708,23 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat64PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndString: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3980,13 +4739,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndStringString: @@ -3996,6 +4749,17 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, string(appendString([]byte{}, s))) b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyStringString: + p := load(ctxptr, code.HeadIdx) + v := ptrToString(p + code.Offset) + if v != "" { + b = append(b, code.Key...) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndStringPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -4015,13 +4779,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, ptrToString(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndStringPtrString: @@ -4036,6 +4794,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyStringPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + v := ptrToString(p) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndBool: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -4050,13 +4820,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendBool(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndBoolString: @@ -4067,6 +4831,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyBoolString: + p := load(ctxptr, code.HeadIdx) + v := ptrToBool(p + code.Offset) + if v { + b = append(b, code.Key...) + b = append(b, '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndBoolPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -4086,13 +4863,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendBool(b, ptrToBool(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndBoolPtrString: @@ -4108,6 +4879,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndBytes: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -4122,13 +4906,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendByteSlice(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndBytesPtr: @@ -4150,13 +4928,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendByteSlice(b, ptrToBytes(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndNumber: @@ -4179,13 +4951,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(bb) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndNumberString: @@ -4199,6 +4965,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(bb, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyNumberString: + p := load(ctxptr, code.HeadIdx) + v := ptrToNumber(p + code.Offset) + if v != "" { + b = append(b, code.Key...) + b = append(b, '"') + bb, err := appendNumber(b, v) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendStructEnd(bb) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndNumberPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -4225,13 +5007,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(bb) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndNumberPtrString: @@ -4250,6 +5026,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + 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(bb) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpEnd: goto END } diff --git a/internal/encoder/vm_debug/util.go b/internal/encoder/vm_debug/util.go index 56e47fd..5fc11d6 100644 --- a/internal/encoder/vm_debug/util.go +++ b/internal/encoder/vm_debug/util.go @@ -79,3 +79,12 @@ func appendComma(b []byte) []byte { func appendStructEnd(b []byte) []byte { return append(b, '}', ',') } + +func appendStructEndSkipLast(b []byte) []byte { + last := len(b) - 1 + if b[last] == ',' { + b[last] = '}' + return appendComma(b) + } + return appendStructEnd(b) +} diff --git a/internal/encoder/vm_debug/vm.go b/internal/encoder/vm_debug/vm.go index 31490c4..d1a2094 100644 --- a/internal/encoder/vm_debug/vm.go +++ b/internal/encoder/vm_debug/vm.go @@ -742,6 +742,45 @@ 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, '{') + } + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v == 0 { + code = code.NextField + } else { + 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 { @@ -850,6 +889,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -951,6 +1026,45 @@ 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, '{') + } + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v == 0 { + code = code.NextField + } else { + 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 { @@ -1059,6 +1173,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -1159,6 +1309,44 @@ 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, '{') + } + v := ptrToFloat32(p + code.Offset) + if v == 0 { + code = code.NextField + } else { + 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 { @@ -1267,6 +1455,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -1378,6 +1602,47 @@ 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, '{') + } + v := ptrToFloat64(p + code.Offset) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + 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 { @@ -1498,6 +1763,46 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -1597,6 +1902,42 @@ 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.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, '{') + } + v := ptrToString(p + code.Offset) + if v == "" { + code = code.NextField + } else { + b = append(b, code.Key...) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1703,6 +2044,40 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = append(b, code.Key...) + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadBool: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1803,6 +2178,44 @@ 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, '{') + } + v := ptrToBool(p + code.Offset) + if v { + 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 { @@ -1911,6 +2324,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -2157,6 +2606,47 @@ 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, '{') + } + v := ptrToNumber(p + code.Offset) + if v == "" { + code = code.NextField + } else { + 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 { @@ -2275,6 +2765,45 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -2973,6 +3502,18 @@ 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 = 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 = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3006,6 +3547,17 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3030,6 +3582,18 @@ 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 = 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 = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3063,6 +3627,17 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3086,6 +3661,17 @@ 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 = append(b, code.Key...) + b = append(b, '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat32Ptr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3119,6 +3705,17 @@ 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 = append(b, code.Key...) + b = append(b, '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat64: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3153,6 +3750,20 @@ 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 = append(b, code.Key...) + b = append(b, '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat64Ptr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3200,6 +3811,21 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3222,6 +3848,15 @@ 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 = append(b, code.Key...) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldStringPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3253,6 +3888,15 @@ 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 = append(b, code.Key...) + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBool: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3276,6 +3920,17 @@ 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 = append(b, code.Key...) + b = append(b, '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBoolPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3309,6 +3964,17 @@ 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 = append(b, code.Key...) + b = append(b, '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBytes: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3376,6 +4042,20 @@ 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 = 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 = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3419,6 +4099,20 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3679,13 +4373,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendInt(b, u64, code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndIntString: @@ -3696,6 +4384,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyIntString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendInt(b, u64, code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndIntPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3715,13 +4417,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendInt(b, ptrToUint64(p), code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndIntPtrString: @@ -3737,6 +4433,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyIntPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendInt(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndUint: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3752,13 +4461,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendUint(b, u64, code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndUintString: @@ -3769,6 +4472,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyUintString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendUint(b, u64, code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndUintPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3788,13 +4505,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendUint(b, ptrToUint64(p), code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndUintPtrString: @@ -3810,6 +4521,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyUintPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendUint(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat32: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3824,13 +4548,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat32(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat32String: @@ -3841,6 +4559,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat32String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat32(p + code.Offset) + if v != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat32Ptr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3860,13 +4591,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat32(b, ptrToFloat32(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat32PtrString: @@ -3882,6 +4607,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat32PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat64: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3903,13 +4641,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat64(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat64String: @@ -3924,6 +4656,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat64String: + 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 = append(b, code.Key...) + b = append(b, '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat64Ptr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -3953,13 +4701,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat64(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat64PtrString: @@ -3979,6 +4721,23 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat64PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndString: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -3993,13 +4752,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndStringString: @@ -4009,6 +4762,17 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, string(appendString([]byte{}, s))) b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyStringString: + p := load(ctxptr, code.HeadIdx) + v := ptrToString(p + code.Offset) + if v != "" { + b = append(b, code.Key...) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndStringPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -4028,13 +4792,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, ptrToString(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndStringPtrString: @@ -4049,6 +4807,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyStringPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + v := ptrToString(p) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndBool: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -4063,13 +4833,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendBool(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndBoolString: @@ -4080,6 +4844,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyBoolString: + p := load(ctxptr, code.HeadIdx) + v := ptrToBool(p + code.Offset) + if v { + b = append(b, code.Key...) + b = append(b, '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndBoolPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -4099,13 +4876,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendBool(b, ptrToBool(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndBoolPtrString: @@ -4121,6 +4892,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.Key...) + b = append(b, '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndBytes: p := load(ctxptr, code.HeadIdx) b = append(b, code.Key...) @@ -4135,13 +4919,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendByteSlice(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndBytesPtr: @@ -4163,13 +4941,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendByteSlice(b, ptrToBytes(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndNumber: @@ -4192,13 +4964,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(bb) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndNumberString: @@ -4212,6 +4978,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(bb, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyNumberString: + p := load(ctxptr, code.HeadIdx) + v := ptrToNumber(p + code.Offset) + if v != "" { + b = append(b, code.Key...) + b = append(b, '"') + bb, err := appendNumber(b, v) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendStructEnd(bb) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndNumberPtr: b = append(b, code.Key...) p := load(ctxptr, code.HeadIdx) @@ -4238,13 +5020,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(bb) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndNumberPtrString: @@ -4263,6 +5039,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + 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(bb) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpEnd: goto END } diff --git a/internal/encoder/vm_escaped/util.go b/internal/encoder/vm_escaped/util.go index 3628780..c7a335a 100644 --- a/internal/encoder/vm_escaped/util.go +++ b/internal/encoder/vm_escaped/util.go @@ -79,3 +79,12 @@ func appendComma(b []byte) []byte { func appendStructEnd(b []byte) []byte { return append(b, '}', ',') } + +func appendStructEndSkipLast(b []byte) []byte { + last := len(b) - 1 + if b[last] == ',' { + b[last] = '}' + return appendComma(b) + } + return appendStructEnd(b) +} diff --git a/internal/encoder/vm_escaped/vm.go b/internal/encoder/vm_escaped/vm.go index 65458df..4861fea 100644 --- a/internal/encoder/vm_escaped/vm.go +++ b/internal/encoder/vm_escaped/vm.go @@ -729,6 +729,45 @@ 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, '{') + } + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v == 0 { + code = code.NextField + } else { + 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 { @@ -837,6 +876,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -938,6 +1013,45 @@ 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, '{') + } + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v == 0 { + code = code.NextField + } else { + 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 { @@ -1046,6 +1160,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -1146,6 +1296,44 @@ 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, '{') + } + v := ptrToFloat32(p + code.Offset) + if v == 0 { + code = code.NextField + } else { + 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 { @@ -1254,6 +1442,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -1365,6 +1589,47 @@ 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, '{') + } + v := ptrToFloat64(p + code.Offset) + if v == 0 { + code = code.NextField + } else { + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + 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 { @@ -1485,6 +1750,46 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -1584,6 +1889,42 @@ 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.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, '{') + } + v := ptrToString(p + code.Offset) + if v == "" { + code = code.NextField + } else { + b = append(b, code.EscapedKey...) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendComma(b) + code = code.Next + } case encoder.OpStructPtrHeadStringPtr: p := load(ctxptr, code.Idx) if p == 0 { @@ -1690,6 +2031,40 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + b = append(b, code.EscapedKey...) + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructPtrHeadBool: if code.Indirect { p := load(ctxptr, code.Idx) @@ -1790,6 +2165,44 @@ 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, '{') + } + v := ptrToBool(p + code.Offset) + if v { + 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 { @@ -1898,6 +2311,42 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -2144,6 +2593,47 @@ 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, '{') + } + v := ptrToNumber(p + code.Offset) + if v == "" { + code = code.NextField + } else { + 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 { @@ -2262,6 +2752,45 @@ 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, '{') + } + if code.Indirect { + p = ptrToNPtr(p+code.Offset, code.PtrNum) + } + if p != 0 { + 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) @@ -2960,6 +3489,18 @@ 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 = 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 = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -2993,6 +3534,17 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3017,6 +3569,18 @@ 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 = 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 = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -3050,6 +3614,17 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3073,6 +3648,17 @@ 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 = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat32Ptr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -3106,6 +3692,17 @@ 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 = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat64: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3140,6 +3737,20 @@ 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 = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldFloat64Ptr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -3187,6 +3798,21 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3209,6 +3835,15 @@ 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 = append(b, code.EscapedKey...) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldStringPtr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -3240,6 +3875,15 @@ 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 = append(b, code.EscapedKey...) + b = appendString(b, string(appendString([]byte{}, ptrToString(p)))) + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBool: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3263,6 +3907,17 @@ 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 = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBoolPtr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -3296,6 +3951,17 @@ 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 = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendComma(b) + } + code = code.Next case encoder.OpStructFieldBytes: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3363,6 +4029,20 @@ 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 = 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 = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -3406,6 +4086,20 @@ 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 = 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: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3666,13 +4360,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendInt(b, u64, code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndIntString: @@ -3683,6 +4371,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyIntString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendInt(b, u64, code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndIntPtr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -3702,13 +4404,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendInt(b, ptrToUint64(p), code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndIntPtrString: @@ -3724,6 +4420,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyIntPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendInt(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndUint: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3739,13 +4448,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendUint(b, u64, code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndUintString: @@ -3756,6 +4459,20 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyUintString: + p := load(ctxptr, code.HeadIdx) + u64 := ptrToUint64(p + code.Offset) + v := u64 & code.Mask + if v != 0 { + b = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendUint(b, u64, code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndUintPtr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -3775,13 +4492,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendUint(b, ptrToUint64(p), code) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndUintPtrString: @@ -3797,6 +4508,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyUintPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendUint(b, ptrToUint64(p), code) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat32: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3811,13 +4535,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat32(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat32String: @@ -3828,6 +4546,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat32String: + p := load(ctxptr, code.HeadIdx) + v := ptrToFloat32(p + code.Offset) + if v != 0 { + b = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendFloat32(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat32Ptr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -3847,13 +4578,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat32(b, ptrToFloat32(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat32PtrString: @@ -3869,6 +4594,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat32PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendFloat32(b, ptrToFloat32(p)) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat64: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3890,13 +4628,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat64(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat64String: @@ -3911,6 +4643,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat64String: + 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 = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndFloat64Ptr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -3940,13 +4688,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendFloat64(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndFloat64PtrString: @@ -3966,6 +4708,23 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyFloat64PtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.EscapedKey...) + v := ptrToFloat64(p) + if math.IsInf(v, 0) || math.IsNaN(v) { + return nil, errUnsupportedFloat(v) + } + b = append(b, '"') + b = appendFloat64(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndString: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -3980,13 +4739,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndStringString: @@ -3996,6 +4749,17 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, string(appendString([]byte{}, s))) b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyStringString: + p := load(ctxptr, code.HeadIdx) + v := ptrToString(p + code.Offset) + if v != "" { + b = append(b, code.EscapedKey...) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndStringPtr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -4015,13 +4779,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendString(b, ptrToString(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndStringPtrString: @@ -4036,6 +4794,18 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyStringPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.EscapedKey...) + v := ptrToString(p) + b = appendString(b, string(appendString([]byte{}, v))) + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndBool: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -4050,13 +4820,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendBool(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndBoolString: @@ -4067,6 +4831,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyBoolString: + p := load(ctxptr, code.HeadIdx) + v := ptrToBool(p + code.Offset) + if v { + b = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendBool(b, v) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndBoolPtr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -4086,13 +4863,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendBool(b, ptrToBool(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndBoolPtrString: @@ -4108,6 +4879,19 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyBoolPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + b = append(b, code.EscapedKey...) + b = append(b, '"') + b = appendBool(b, ptrToBool(p)) + b = append(b, '"') + b = appendStructEnd(b) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndBytes: p := load(ctxptr, code.HeadIdx) b = append(b, code.EscapedKey...) @@ -4122,13 +4906,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendByteSlice(b, v) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndBytesPtr: @@ -4150,13 +4928,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = appendByteSlice(b, ptrToBytes(p)) b = appendStructEnd(b) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndNumber: @@ -4179,13 +4951,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(bb) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndNumberString: @@ -4199,6 +4965,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(bb, '"') b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyNumberString: + p := load(ctxptr, code.HeadIdx) + v := ptrToNumber(p + code.Offset) + if v != "" { + b = append(b, code.EscapedKey...) + b = append(b, '"') + bb, err := appendNumber(b, v) + if err != nil { + return nil, err + } + b = append(b, '"') + b = appendStructEnd(bb) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpStructEndNumberPtr: b = append(b, code.EscapedKey...) p := load(ctxptr, code.HeadIdx) @@ -4225,13 +5007,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(bb) } else { - last := len(b) - 1 - if b[last] == ',' { - b[last] = '}' - b = appendComma(b) - } else { - b = appendStructEnd(b) - } + b = appendStructEndSkipLast(b) } code = code.Next case encoder.OpStructEndNumberPtrString: @@ -4250,6 +5026,22 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt } b = appendStructEnd(b) code = code.Next + case encoder.OpStructEndOmitEmptyNumberPtrString: + p := load(ctxptr, code.HeadIdx) + p = ptrToNPtr(p+code.Offset, code.PtrNum) + if p != 0 { + 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(bb) + } else { + b = appendStructEndSkipLast(b) + } + code = code.Next case encoder.OpEnd: goto END }