diff --git a/encode_compile.go b/encode_compile.go index 23284cd..9c1792d 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -765,10 +765,10 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, named } else if op != f.op { if existsKey { f.op = opStructFieldAnonymousHead - } else { + } else if named == "" { f.op = op } - } else if f.op == opStructEnd { + } else if named == "" && f.op == opStructEnd { f.op = opStructAnonymousEnd } else if existsKey { diff := f.nextField.displayIdx - f.displayIdx @@ -808,9 +808,9 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, named } func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPair) { - fmt.Printf("anonymousFields = %+v\n", anonymousFields) + //fmt.Printf("anonymousFields = %+v\n", anonymousFields) removedFields := map[*opcode]struct{}{} - for name, fieldPairs := range anonymousFields { + for _, fieldPairs := range anonymousFields { if len(fieldPairs) == 1 { continue } @@ -823,24 +823,24 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s if !fieldPair.linked { if fieldPair.prevField == nil { // head operation - fmt.Println("omit:", fieldPair.curField.displayKey) + //fmt.Println("omit:", fieldPair.curField.displayKey) fieldPair.curField.op = opStructFieldAnonymousHead } else { - fmt.Println("remove", name) + //fmt.Println("remove", name) diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx - fmt.Println("link:", fieldPair.prevField.displayKey, "=>", fieldPair.curField.nextField.displayKey) - fmt.Println("diff = ", diff) + //fmt.Println("link:", fieldPair.prevField.displayKey, "=>", fieldPair.curField.nextField.displayKey) + //fmt.Println("diff = ", diff) for i := 0; i < diff; i++ { fieldPair.curField.nextField.decOpcodeIndex() } - fmt.Println("cur.nextField") - fmt.Println(fieldPair.curField.nextField.dump()) - fmt.Println("===========") + //fmt.Println("cur.nextField") + //fmt.Println(fieldPair.curField.nextField.dump()) + //fmt.Println("===========") removedFields[fieldPair.curField] = struct{}{} linkPrevToNextField(fieldPair.curField, removedFields) - fmt.Println("linked. prevField") - fmt.Println(fieldPair.prevField.dump()) - fmt.Println("===========") + //fmt.Println("linked. prevField") + //fmt.Println(fieldPair.prevField.dump()) + //fmt.Println("===========") // tagggedPairs に入れた方にもこの結果を反映させないといけない } fieldPair.linked = true @@ -854,13 +854,13 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s // head operation fieldPair.curField.op = opStructFieldAnonymousHead } else { - fmt.Println("TAGGED PAIRS REMOVE") - fmt.Println("remove", name) - fmt.Println("removedFields = ", removedFields) - fmt.Printf("prev = %p cur = %p next = %p\n", fieldPair.curField.prevField, fieldPair.curField, fieldPair.curField.nextField) + //fmt.Println("TAGGED PAIRS REMOVE") + //fmt.Println("remove", name) + //fmt.Println("removedFields = ", removedFields) + //fmt.Printf("prev = %p cur = %p next = %p\n", fieldPair.curField.prevField, fieldPair.curField, fieldPair.curField.nextField) diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx - fmt.Println("link:", fieldPair.prevField.displayKey, "=>", fieldPair.curField.nextField.displayKey) - fmt.Println("diff = ", diff) + //fmt.Println("link:", fieldPair.prevField.displayKey, "=>", fieldPair.curField.nextField.displayKey) + //fmt.Println("diff = ", diff) removedFields[fieldPair.curField] = struct{}{} for i := 0; i < diff; i++ { fieldPair.curField.nextField.decOpcodeIndex() @@ -1035,23 +1035,23 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, head.end = structEndCode code.next = structEndCode - - fmt.Println("head") - fmt.Println(head.dump()) - fmt.Println("===============") - + /* + fmt.Println("head") + fmt.Println(head.dump()) + fmt.Println("===============") + */ e.optimizeConflictAnonymousFields(anonymousFields) - - fmt.Println("remove conflicted key head") - fmt.Println(head.dump()) - fmt.Println("===============") - + /* + fmt.Println("remove conflicted key head") + fmt.Println(head.dump()) + fmt.Println("===============") + */ e.optimizeAnonymousFields(head) - - fmt.Println("optimized head") - fmt.Println(head.dump()) - fmt.Println("===============") - + /* + fmt.Println("optimized head") + fmt.Println(head.dump()) + fmt.Println("===============") + */ ret := (*opcode)(unsafe.Pointer(head)) compiled.code = ret diff --git a/encode_vm.go b/encode_vm.go index 8ffa0d4..49d4a9e 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -38,10 +38,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { seenPtr := map[uintptr]struct{}{} ptrOffset := uintptr(0) ctxptr := ctx.ptr() - fmt.Println(code.dump()) + //fmt.Println(code.dump()) for { - fmt.Printf("[%d]:[%s]\n", code.displayIdx, code.op) + //fmt.Printf("[%d]:[%s]\n", code.displayIdx, code.op) switch code.op { default: return fmt.Errorf("failed to handle opcode. doesn't implement %s", code.op) @@ -4195,7 +4195,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { code = code.next } case opStructField: - if e.buf[len(e.buf)-1] != '{' { + if e.buf[len(e.buf)-1] != '{' && e.buf[len(e.buf)-1] != ',' { e.encodeByte(',') } if !code.anonymousKey { @@ -4218,7 +4218,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } code = code.next case opStructFieldInt: - if e.buf[len(e.buf)-1] != '{' { + if e.buf[len(e.buf)-1] != '{' && e.buf[len(e.buf)-1] != ',' { e.encodeByte(',') } ptr := load(ctxptr, code.headIdx) @@ -5900,7 +5900,12 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeString(*(*string)(unsafe.Pointer(&bytes))) code = code.next case opStructEnd: - e.encodeByte('}') + last := len(e.buf) - 1 + if e.buf[last] == ',' { + e.buf[last] = '}' + } else { + e.encodeByte('}') + } code = code.next case opStructAnonymousEnd: code = code.next diff --git a/json.go b/json.go index b25f191..e6922b7 100644 --- a/json.go +++ b/json.go @@ -317,6 +317,9 @@ func (n Number) Int64() (int64, error) { } func (n Number) MarshalJSON() ([]byte, error) { + if n == "" { + return []byte("0"), nil + } if _, err := n.Float64(); err != nil { return nil, err }