Skip to content

Commit

Permalink
Fixed writeRef & setWriterRef
Browse files Browse the repository at this point in the history
  • Loading branch information
andot committed May 17, 2018
1 parent bd05b81 commit f6d5d0c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 31 deletions.
33 changes: 19 additions & 14 deletions io/encoder.go
Expand Up @@ -12,7 +12,7 @@
* *
* hprose encoder for Go. *
* *
* LastModified: Oct 19, 2016 *
* LastModified: May 17, 2018 *
* Author: Ma Bingyao <andot@hprose.com> *
* *
\**********************************************************/
Expand Down Expand Up @@ -75,19 +75,20 @@ func interfaceEncoder(w *Writer, v reflect.Value) {
}

func arrayEncoder(w *Writer, v reflect.Value) {
setWriterRef(w, nil)
setWriterRef(w, nil, v.Type())
writeArray(w, v)
}

func sliceEncoder(w *Writer, v reflect.Value) {
setWriterRef(w, nil)
setWriterRef(w, nil, v.Type())
writeSlice(w, v)
}

func mapEncoder(w *Writer, v reflect.Value) {
ptr := (*reflectValue)(unsafe.Pointer(&v)).ptr
if !writeRef(w, ptr) {
setWriterRef(w, ptr)
typ := v.Type()
if !writeRef(w, ptr, typ) {
setWriterRef(w, ptr, typ)
writeMap(w, v)
}
}
Expand All @@ -102,22 +103,25 @@ func structEncoder(w *Writer, v reflect.Value) {
}

func arrayPtrEncoder(w *Writer, v reflect.Value, ptr unsafe.Pointer) {
if !writeRef(w, ptr) {
setWriterRef(w, ptr)
typ := v.Type()
if !writeRef(w, ptr, typ) {
setWriterRef(w, ptr, typ)
writeArray(w, v)
}
}

func mapPtrEncoder(w *Writer, v reflect.Value, ptr unsafe.Pointer) {
if !writeRef(w, ptr) {
setWriterRef(w, ptr)
typ := v.Type()
if !writeRef(w, ptr, typ) {
setWriterRef(w, ptr, typ)
writeMap(w, v)
}
}

func slicePtrEncoder(w *Writer, v reflect.Value, ptr unsafe.Pointer) {
if !writeRef(w, ptr) {
setWriterRef(w, ptr)
typ := v.Type()
if !writeRef(w, ptr, typ) {
setWriterRef(w, ptr, typ)
writeSlice(w, v)
}
}
Expand All @@ -134,8 +138,9 @@ func stringPtrEncoder(w *Writer, v reflect.Value, ptr unsafe.Pointer) {
w.writeByte(TagUTF8Char)
w.writeString(str)
default:
if !writeRef(w, ptr) {
setWriterRef(w, ptr)
typ := v.Type()
if !writeRef(w, ptr, typ) {
setWriterRef(w, ptr, typ)
writeString(w, str, length)
}
}
Expand All @@ -156,7 +161,7 @@ func structPtrEncoder(w *Writer, v reflect.Value, ptr unsafe.Pointer) {
case reflectValueType:
w.WriteValue(*(*reflect.Value)(ptr))
default:
if !writeRef(w, ptr) {
if !writeRef(w, ptr, v.Type()) {
writeStruct(w, v)
}
}
Expand Down
45 changes: 28 additions & 17 deletions io/writer.go
Expand Up @@ -12,7 +12,7 @@
* *
* hprose writer for Go. *
* *
* LastModified: Oct 19, 2016 *
* LastModified: May 17, 2018 *
* Author: Ma Bingyao <andot@hprose.com> *
* *
\**********************************************************/
Expand All @@ -37,6 +37,7 @@ type Writer struct {
Simple bool
structRef map[uintptr]int
ref map[uintptr]int
typeRef []reflect.Type
refCount int
}

Expand Down Expand Up @@ -137,7 +138,7 @@ func (w *Writer) WriteComplex64(c complex64) {
w.WriteFloat(float64(real(c)), 32)
return
}
setWriterRef(w, nil)
setWriterRef(w, nil, nil)
writeListHeader(w, 2)
w.WriteFloat(float64(real(c)), 32)
w.WriteFloat(float64(imag(c)), 32)
Expand All @@ -150,7 +151,7 @@ func (w *Writer) WriteComplex128(c complex128) {
w.WriteFloat(real(c), 64)
return
}
setWriterRef(w, nil)
setWriterRef(w, nil, nil)
writeListHeader(w, 2)
w.WriteFloat(real(c), 64)
w.WriteFloat(imag(c), 64)
Expand All @@ -169,14 +170,14 @@ func (w *Writer) WriteString(str string) {
w.writeByte(TagUTF8Char)
w.writeString(str)
default:
setWriterRef(w, nil)
setWriterRef(w, nil, nil)
writeString(w, str, length)
}
}

// WriteBytes to the writer
func (w *Writer) WriteBytes(bytes []byte) {
setWriterRef(w, nil)
setWriterRef(w, nil, nil)
writeBytes(w, bytes)
}

Expand All @@ -193,7 +194,7 @@ func (w *Writer) WriteBigRat(br *big.Rat) {
w.WriteBigInt(br.Num())
} else {
str := br.String()
setWriterRef(w, nil)
setWriterRef(w, nil, nil)
writeString(w, str, len(str))
}
}
Expand Down Expand Up @@ -223,10 +224,11 @@ func writeTime(w *Writer, buf []byte, hour, min, sec, nsec int) {
// WriteTime to the writer
func (w *Writer) WriteTime(t *time.Time) {
ptr := unsafe.Pointer(t)
if writeRef(w, ptr) {
typ := reflect.TypeOf(t)
if writeRef(w, ptr, typ) {
return
}
setWriterRef(w, ptr)
setWriterRef(w, ptr, typ)
year, month, day := t.Date()
hour, min, sec := t.Clock()
nsec := t.Nanosecond()
Expand All @@ -249,10 +251,11 @@ func (w *Writer) WriteTime(t *time.Time) {
// WriteList to the writer
func (w *Writer) WriteList(lst *list.List) {
ptr := unsafe.Pointer(lst)
if writeRef(w, ptr) {
typ := reflect.TypeOf(lst)
if writeRef(w, ptr, typ) {
return
}
setWriterRef(w, ptr)
setWriterRef(w, ptr, typ)
count := lst.Len()
if count == 0 {
writeEmptyList(w)
Expand All @@ -267,7 +270,7 @@ func (w *Writer) WriteList(lst *list.List) {

// WriteTuple to the writer
func (w *Writer) WriteTuple(tuple ...interface{}) {
setWriterRef(w, nil)
setWriterRef(w, nil, nil)
count := len(tuple)
if count == 0 {
writeEmptyList(w)
Expand All @@ -282,7 +285,7 @@ func (w *Writer) WriteTuple(tuple ...interface{}) {

// WriteSlice to the writer
func (w *Writer) WriteSlice(slice []reflect.Value) {
setWriterRef(w, nil)
setWriterRef(w, nil, nil)
count := len(slice)
if count == 0 {
writeEmptyList(w)
Expand All @@ -297,7 +300,7 @@ func (w *Writer) WriteSlice(slice []reflect.Value) {

// WriteStringSlice to the writer
func (w *Writer) WriteStringSlice(slice []string) {
setWriterRef(w, nil)
setWriterRef(w, nil, nil)
count := len(slice)
if count == 0 {
writeEmptyList(w)
Expand All @@ -324,11 +327,14 @@ func (w *Writer) Reset() {
delete(w.ref, k)
}
}
if w.typeRef != nil {
w.typeRef = w.typeRef[:0]
}
}

// private functions

func writeRef(w *Writer, ref unsafe.Pointer) bool {
func writeRef(w *Writer, ref unsafe.Pointer, typ reflect.Type) bool {
if w.Simple {
return false
}
Expand All @@ -337,6 +343,9 @@ func writeRef(w *Writer, ref unsafe.Pointer) bool {
}
n, found := w.ref[uintptr(ref)]
if found {
if w.typeRef[n] != typ {
return false
}
w.writeByte(TagRef)
var buf [20]byte
w.write(util.GetIntBytes(buf[:], int64(n)))
Expand All @@ -345,7 +354,7 @@ func writeRef(w *Writer, ref unsafe.Pointer) bool {
return found
}

func setWriterRef(w *Writer, ref unsafe.Pointer) {
func setWriterRef(w *Writer, ref unsafe.Pointer, typ reflect.Type) {
if w.Simple {
return
}
Expand All @@ -355,6 +364,7 @@ func setWriterRef(w *Writer, ref unsafe.Pointer) {
}
w.ref[uintptr(ref)] = w.refCount
}
w.typeRef = append(w.typeRef, typ)
w.refCount++
}

Expand Down Expand Up @@ -504,7 +514,8 @@ func writeMap(w *Writer, v reflect.Value) {

func writeStruct(w *Writer, v reflect.Value) {
val := (*reflectValue)(unsafe.Pointer(&v))
cache := getStructCache(v.Type())
typ := v.Type()
cache := getStructCache(typ)
if w.structRef == nil {
w.structRef = map[uintptr]int{}
}
Expand All @@ -518,7 +529,7 @@ func writeStruct(w *Writer, v reflect.Value) {
w.structRef[val.typ] = index
}
ptr := val.ptr
setWriterRef(w, ptr)
setWriterRef(w, ptr, typ)
w.writeByte(TagObject)
var buf [20]byte
w.write(util.GetIntBytes(buf[:], int64(index)))
Expand Down

0 comments on commit f6d5d0c

Please sign in to comment.