github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/val_decoder_native_ptr.go (about)

     1  package jzon
     2  
     3  import (
     4  	"reflect"
     5  	"unsafe"
     6  )
     7  
     8  type pointerDecoderBuilder struct {
     9  	decoder  *pointerDecoder
    10  	ptrRType rtype
    11  }
    12  
    13  func newPointerDecoder(typ reflect.Type) *pointerDecoderBuilder {
    14  	return &pointerDecoderBuilder{
    15  		decoder: &pointerDecoder{
    16  			elemRType: rtypeOfType(typ.Elem()),
    17  		},
    18  		ptrRType: rtypeOfType(typ),
    19  	}
    20  }
    21  
    22  func (builder *pointerDecoderBuilder) build(cache decoderCache) {
    23  	builder.decoder.elemDec = cache[builder.ptrRType]
    24  }
    25  
    26  type pointerDecoder struct {
    27  	elemRType rtype
    28  
    29  	elemDec ValDecoder
    30  }
    31  
    32  func (dec *pointerDecoder) Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error {
    33  	c, err := it.nextToken()
    34  	if err != nil {
    35  		return err
    36  	}
    37  	if c == 'n' {
    38  		it.head++
    39  		if err = it.expectBytes("ull"); err != nil {
    40  			return err
    41  		}
    42  		*(*unsafe.Pointer)(ptr) = nil
    43  	} else {
    44  		elemPtr := *((*unsafe.Pointer)(ptr))
    45  		var tgtPtr unsafe.Pointer
    46  		if elemPtr == nil {
    47  			tgtPtr = unsafe_New(dec.elemRType)
    48  		} else {
    49  			tgtPtr = elemPtr
    50  		}
    51  		if err = dec.elemDec.Decode(tgtPtr, it, opts); err != nil {
    52  			return err
    53  		}
    54  		if elemPtr == nil {
    55  			*(*unsafe.Pointer)(ptr) = tgtPtr
    56  		}
    57  	}
    58  	return nil
    59  }