diff --git a/encode.go b/encode.go index e5f6e8a..ea2bc7c 100644 --- a/encode.go +++ b/encode.go @@ -43,9 +43,9 @@ func (e *Encoder) EncodeWithOption(v interface{}, optFuncs ...EncodeOptionFunc) } func (e *Encoder) encodeWithOption(ctx *encoder.RuntimeContext, v interface{}, optFuncs ...EncodeOptionFunc) error { - initOption(ctx.Option) + ctx.Option.Flag = 0 if e.enabledHTMLEscape { - ctx.Option.HTMLEscape = true + ctx.Option.Flag |= encoder.HTMLEscapeOption } for _, optFunc := range optFuncs { optFunc(ctx.Option) @@ -97,8 +97,8 @@ func (e *Encoder) SetIndent(prefix, indent string) { func marshal(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) { ctx := encoder.TakeRuntimeContext() - initOption(ctx.Option) - ctx.Option.HTMLEscape = true + ctx.Option.Flag = 0 + ctx.Option.Flag |= encoder.HTMLEscapeOption for _, optFunc := range optFuncs { optFunc(ctx.Option) } @@ -124,8 +124,8 @@ func marshal(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) { func marshalNoEscape(v interface{}) ([]byte, error) { ctx := encoder.TakeRuntimeContext() - initOption(ctx.Option) - ctx.Option.HTMLEscape = true + ctx.Option.Flag = 0 + ctx.Option.Flag |= encoder.HTMLEscapeOption buf, err := encodeNoEscape(ctx, v) if err != nil { @@ -148,9 +148,8 @@ func marshalNoEscape(v interface{}) ([]byte, error) { func marshalIndent(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) { ctx := encoder.TakeRuntimeContext() - initOption(ctx.Option) - ctx.Option.HTMLEscape = true - ctx.Option.Indent = true + ctx.Option.Flag = 0 + ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.IndentOption) for _, optFunc := range optFuncs { optFunc(ctx.Option) } @@ -255,13 +254,13 @@ func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent str } func encodeRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { - if ctx.Option.Debug { - if ctx.Option.Colorize { + if (ctx.Option.Flag & encoder.DebugOption) != 0 { + if (ctx.Option.Flag & encoder.ColorizeOption) != 0 { return vm_color.DebugRun(ctx, b, codeSet) } return vm.DebugRun(ctx, b, codeSet) } - if ctx.Option.Colorize { + if (ctx.Option.Flag & encoder.ColorizeOption) != 0 { return vm_color.Run(ctx, b, codeSet) } return vm.Run(ctx, b, codeSet) @@ -270,22 +269,14 @@ func encodeRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.Opcod func encodeRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, prefix, indent string) ([]byte, error) { ctx.Prefix = []byte(prefix) ctx.IndentStr = []byte(indent) - if ctx.Option.Debug { - if ctx.Option.Colorize { + if (ctx.Option.Flag & encoder.DebugOption) != 0 { + if (ctx.Option.Flag & encoder.ColorizeOption) != 0 { return vm_color_indent.DebugRun(ctx, b, codeSet) } return vm_indent.DebugRun(ctx, b, codeSet) } - if ctx.Option.Colorize { + if (ctx.Option.Flag & encoder.ColorizeOption) != 0 { return vm_color_indent.Run(ctx, b, codeSet) } return vm_indent.Run(ctx, b, codeSet) } - -func initOption(opt *EncodeOption) { - opt.HTMLEscape = false - opt.Indent = false - opt.UnorderedMap = false - opt.Debug = false - opt.Colorize = false -} diff --git a/internal/cmd/generator/vm.go.tmpl b/internal/cmd/generator/vm.go.tmpl index 0f8ca7a..2091ba1 100644 --- a/internal/cmd/generator/vm.go.tmpl +++ b/internal/cmd/generator/vm.go.tmpl @@ -14,7 +14,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ptrOffset := uintptr(0) ctxptr := ctx.Ptr() var code *encoder.Opcode - if ctx.Option.HTMLEscape { + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode @@ -370,7 +370,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, code.ElemIdx, 0) store(ctxptr, code.Length, uintptr(mlen)) store(ctxptr, code.MapIter, uintptr(iter)) - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendMapKeyIndent(ctx, code.Next, b) } else { mapCtx := encoder.NewMapContext(mlen) @@ -385,7 +385,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b idx := load(ctxptr, code.ElemIdx) length := load(ctxptr, code.Length) idx++ - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { if idx < length { b = appendMapKeyIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) @@ -414,7 +414,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b } } case encoder.OpMapValue: - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendColon(ctx, b) } else { ptr := load(ctxptr, code.End.MapPos) diff --git a/internal/encoder/compiler.go b/internal/encoder/compiler.go index ea05f3f..f9937a4 100644 --- a/internal/encoder/compiler.go +++ b/internal/encoder/compiler.go @@ -1456,7 +1456,7 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) { } var key string if ctx.escapeKey { - rctx := &RuntimeContext{Option: &Option{HTMLEscape: true}} + rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}} key = fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, tag.Key))) } else { key = fmt.Sprintf(`"%s":`, tag.Key) diff --git a/internal/encoder/encoder.go b/internal/encoder/encoder.go index 0a737c9..5368ce3 100644 --- a/internal/encoder/encoder.go +++ b/internal/encoder/encoder.go @@ -375,7 +375,7 @@ func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{ } marshalBuf := ctx.MarshalBuf[:0] marshalBuf = append(append(marshalBuf, bb...), nul) - compactedBuf, err := compact(b, marshalBuf, ctx.Option.HTMLEscape) + compactedBuf, err := compact(b, marshalBuf, (ctx.Option.Flag&HTMLEscapeOption) != 0) if err != nil { return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} } @@ -410,7 +410,7 @@ func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v inte marshalBuf, string(ctx.Prefix)+strings.Repeat(string(ctx.IndentStr), int(ctx.BaseIndent+code.Indent)), string(ctx.IndentStr), - ctx.Option.HTMLEscape, + (ctx.Option.Flag&HTMLEscapeOption) != 0, ) if err != nil { return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err} diff --git a/internal/encoder/option.go b/internal/encoder/option.go index 1c947cd..3cc3502 100644 --- a/internal/encoder/option.go +++ b/internal/encoder/option.go @@ -1,12 +1,18 @@ package encoder +type OptionFlag uint8 + +const ( + HTMLEscapeOption OptionFlag = 1 << iota + IndentOption + UnorderedMapOption + DebugOption + ColorizeOption +) + type Option struct { - HTMLEscape bool - Indent bool - UnorderedMap bool - Debug bool - Colorize bool - ColorScheme *ColorScheme + Flag OptionFlag + ColorScheme *ColorScheme } type EncodeFormat struct { diff --git a/internal/encoder/string.go b/internal/encoder/string.go index da2c26d..a699dba 100644 --- a/internal/encoder/string.go +++ b/internal/encoder/string.go @@ -406,7 +406,7 @@ func stringToUint64Slice(s string) []uint64 { } func AppendString(ctx *RuntimeContext, buf []byte, s string) []byte { - if !ctx.Option.HTMLEscape { + if ctx.Option.Flag&HTMLEscapeOption == 0 { return appendString(buf, s) } valLen := len(s) diff --git a/internal/encoder/vm/debug_vm.go b/internal/encoder/vm/debug_vm.go index 7bd8d12..05509fe 100644 --- a/internal/encoder/vm/debug_vm.go +++ b/internal/encoder/vm/debug_vm.go @@ -9,7 +9,7 @@ import ( func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { defer func() { var code *encoder.Opcode - if ctx.Option.HTMLEscape { + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index 0f8ca7a..2091ba1 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -14,7 +14,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ptrOffset := uintptr(0) ctxptr := ctx.Ptr() var code *encoder.Opcode - if ctx.Option.HTMLEscape { + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode @@ -370,7 +370,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, code.ElemIdx, 0) store(ctxptr, code.Length, uintptr(mlen)) store(ctxptr, code.MapIter, uintptr(iter)) - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendMapKeyIndent(ctx, code.Next, b) } else { mapCtx := encoder.NewMapContext(mlen) @@ -385,7 +385,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b idx := load(ctxptr, code.ElemIdx) length := load(ctxptr, code.Length) idx++ - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { if idx < length { b = appendMapKeyIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) @@ -414,7 +414,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b } } case encoder.OpMapValue: - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendColon(ctx, b) } else { ptr := load(ctxptr, code.End.MapPos) diff --git a/internal/encoder/vm_color/debug_vm.go b/internal/encoder/vm_color/debug_vm.go index 5d6db1e..6a6a33d 100644 --- a/internal/encoder/vm_color/debug_vm.go +++ b/internal/encoder/vm_color/debug_vm.go @@ -8,7 +8,7 @@ import ( func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { var code *encoder.Opcode - if ctx.Option.HTMLEscape { + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode diff --git a/internal/encoder/vm_color/vm.go b/internal/encoder/vm_color/vm.go index e045f68..0ac3179 100644 --- a/internal/encoder/vm_color/vm.go +++ b/internal/encoder/vm_color/vm.go @@ -14,7 +14,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ptrOffset := uintptr(0) ctxptr := ctx.Ptr() var code *encoder.Opcode - if ctx.Option.HTMLEscape { + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode @@ -370,7 +370,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, code.ElemIdx, 0) store(ctxptr, code.Length, uintptr(mlen)) store(ctxptr, code.MapIter, uintptr(iter)) - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendMapKeyIndent(ctx, code.Next, b) } else { mapCtx := encoder.NewMapContext(mlen) @@ -385,7 +385,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b idx := load(ctxptr, code.ElemIdx) length := load(ctxptr, code.Length) idx++ - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { if idx < length { b = appendMapKeyIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) @@ -414,7 +414,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b } } case encoder.OpMapValue: - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendColon(ctx, b) } else { ptr := load(ctxptr, code.End.MapPos) diff --git a/internal/encoder/vm_color_indent/debug_vm.go b/internal/encoder/vm_color_indent/debug_vm.go index ab905d0..a68bbf6 100644 --- a/internal/encoder/vm_color_indent/debug_vm.go +++ b/internal/encoder/vm_color_indent/debug_vm.go @@ -8,7 +8,7 @@ import ( func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { var code *encoder.Opcode - if ctx.Option.HTMLEscape { + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode diff --git a/internal/encoder/vm_color_indent/vm.go b/internal/encoder/vm_color_indent/vm.go index 8bf24bb..cd619ca 100644 --- a/internal/encoder/vm_color_indent/vm.go +++ b/internal/encoder/vm_color_indent/vm.go @@ -14,7 +14,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ptrOffset := uintptr(0) ctxptr := ctx.Ptr() var code *encoder.Opcode - if ctx.Option.HTMLEscape { + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode @@ -370,7 +370,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, code.ElemIdx, 0) store(ctxptr, code.Length, uintptr(mlen)) store(ctxptr, code.MapIter, uintptr(iter)) - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendMapKeyIndent(ctx, code.Next, b) } else { mapCtx := encoder.NewMapContext(mlen) @@ -385,7 +385,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b idx := load(ctxptr, code.ElemIdx) length := load(ctxptr, code.Length) idx++ - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { if idx < length { b = appendMapKeyIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) @@ -414,7 +414,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b } } case encoder.OpMapValue: - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendColon(ctx, b) } else { ptr := load(ctxptr, code.End.MapPos) diff --git a/internal/encoder/vm_indent/debug_vm.go b/internal/encoder/vm_indent/debug_vm.go index b3822f5..4cfd17a 100644 --- a/internal/encoder/vm_indent/debug_vm.go +++ b/internal/encoder/vm_indent/debug_vm.go @@ -8,7 +8,7 @@ import ( func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) { var code *encoder.Opcode - if ctx.Option.HTMLEscape { + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index c19b254..a4eb235 100644 --- a/internal/encoder/vm_indent/vm.go +++ b/internal/encoder/vm_indent/vm.go @@ -14,7 +14,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ptrOffset := uintptr(0) ctxptr := ctx.Ptr() var code *encoder.Opcode - if ctx.Option.HTMLEscape { + if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 { code = codeSet.EscapeKeyCode } else { code = codeSet.NoescapeKeyCode @@ -370,7 +370,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, code.ElemIdx, 0) store(ctxptr, code.Length, uintptr(mlen)) store(ctxptr, code.MapIter, uintptr(iter)) - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendMapKeyIndent(ctx, code.Next, b) } else { mapCtx := encoder.NewMapContext(mlen) @@ -385,7 +385,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b idx := load(ctxptr, code.ElemIdx) length := load(ctxptr, code.Length) idx++ - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { if idx < length { b = appendMapKeyIndent(ctx, code, b) store(ctxptr, code.ElemIdx, idx) @@ -414,7 +414,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b } } case encoder.OpMapValue: - if ctx.Option.UnorderedMap { + if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 { b = appendColon(ctx, b) } else { ptr := load(ctxptr, code.End.MapPos) diff --git a/option.go b/option.go index 40d25c7..444ffd0 100644 --- a/option.go +++ b/option.go @@ -10,19 +10,19 @@ type EncodeOptionFunc func(*EncodeOption) func UnorderedMap() EncodeOptionFunc { return func(opt *EncodeOption) { - opt.UnorderedMap = true + opt.Flag |= encoder.UnorderedMapOption } } func Debug() EncodeOptionFunc { return func(opt *EncodeOption) { - opt.Debug = true + opt.Flag |= encoder.DebugOption } } func Colorize(scheme *ColorScheme) EncodeOptionFunc { return func(opt *EncodeOption) { - opt.Colorize = true + opt.Flag |= encoder.ColorizeOption opt.ColorScheme = scheme } }