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

     1  package jzon
     2  
     3  import (
     4  	"io"
     5  	"unsafe"
     6  )
     7  
     8  // bool decoder
     9  type boolDecoder struct{}
    10  
    11  func (*boolDecoder) Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error {
    12  	c, err := it.nextToken()
    13  	if err != nil {
    14  		return err
    15  	}
    16  	switch c {
    17  	case 'n':
    18  		it.head++
    19  		return it.expectBytes("ull")
    20  	case 't':
    21  		it.head++
    22  		if err := it.expectBytes("rue"); err != nil {
    23  			return err
    24  		}
    25  		*(*bool)(ptr) = true
    26  		return nil
    27  	case 'f':
    28  		it.head++
    29  		if err := it.expectBytes("alse"); err != nil {
    30  			return err
    31  		}
    32  		*(*bool)(ptr) = false
    33  		return nil
    34  	case '"':
    35  		quoted := (opts != nil) && opts.Quoted
    36  		if !quoted {
    37  			return UnexpectedByteError{got: c}
    38  		}
    39  		it.head++
    40  		c, err := it.nextToken()
    41  		if err != nil {
    42  			return err
    43  		}
    44  		it.head++
    45  		switch c {
    46  		case 't':
    47  			if err := it.expectBytes(`rue"`); err != nil {
    48  				return err
    49  			}
    50  			*(*bool)(ptr) = true
    51  			return nil
    52  		case 'f':
    53  			if err := it.expectBytes(`alse"`); err != nil {
    54  				return err
    55  			}
    56  			*(*bool)(ptr) = false
    57  			return nil
    58  		case 'n':
    59  			return it.expectBytes(`ull"`)
    60  		default:
    61  			return UnexpectedByteError{got: c}
    62  		}
    63  	default:
    64  		return UnexpectedByteError{got: c}
    65  	}
    66  }
    67  
    68  // string decoder
    69  type stringDecoder struct{}
    70  
    71  func (*stringDecoder) Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error {
    72  	c, err := it.nextToken()
    73  	if err != nil {
    74  		return err
    75  	}
    76  	switch c {
    77  	case '"':
    78  		it.head++
    79  		s, err := it.readString()
    80  		if err != nil {
    81  			return err
    82  		}
    83  		quoted := (opts != nil) && opts.Quoted
    84  		if !quoted {
    85  			*(*string)(ptr) = s
    86  			return nil
    87  		}
    88  		l := len(s)
    89  		if l < 2 {
    90  			return BadQuotedStringError(s)
    91  		}
    92  		switch s[0] {
    93  		case 'n':
    94  			if s != "null" {
    95  				return BadQuotedStringError(s)
    96  			}
    97  			return nil
    98  		case '"':
    99  			if s[l-1] != '"' {
   100  				return BadQuotedStringError(s)
   101  			}
   102  			// borrow another iterator
   103  			subIt := it.cfg.NewIterator()
   104  			defer subIt.Release()
   105  			subIt.ResetBytes(localStringToBytes(s))
   106  			subStr, err := subIt.ReadString()
   107  			if err != nil {
   108  				return BadQuotedStringError(s)
   109  			}
   110  			// check eof
   111  			_, err = subIt.nextToken()
   112  			if err != io.EOF {
   113  				return BadQuotedStringError(s)
   114  			}
   115  			*(*string)(ptr) = subStr
   116  			return nil
   117  		default:
   118  			return BadQuotedStringError(s)
   119  		}
   120  	case 'n':
   121  		it.head++
   122  		return it.expectBytes("ull")
   123  	default:
   124  		return UnexpectedByteError{got: c, exp: '"', exp2: 'n'}
   125  	}
   126  }