github.com/3JoB/go-json@v0.10.4/internal/decoder/array.go (about)

     1  package decoder
     2  
     3  import (
     4  	"unsafe"
     5  
     6  	"github.com/3JoB/go-json/internal/errors"
     7  	"github.com/3JoB/go-json/internal/runtime"
     8  )
     9  
    10  type arrayDecoder struct {
    11  	elemType     *runtime.Type
    12  	size         uintptr
    13  	valueDecoder Decoder
    14  	alen         int
    15  	structName   string
    16  	fieldName    string
    17  	zeroValue    unsafe.Pointer
    18  }
    19  
    20  func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder {
    21  	// workaround to avoid checkptr errors. cannot use `*(*unsafe.Pointer)(unsafe_New(elemType))` directly.
    22  	zeroValuePtr := unsafe_New(elemType)
    23  	zeroValue := **(**unsafe.Pointer)(unsafe.Pointer(&zeroValuePtr))
    24  	return &arrayDecoder{
    25  		valueDecoder: dec,
    26  		elemType:     elemType,
    27  		size:         elemType.Size(),
    28  		alen:         alen,
    29  		structName:   structName,
    30  		fieldName:    fieldName,
    31  		zeroValue:    zeroValue,
    32  	}
    33  }
    34  
    35  func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
    36  	depth++
    37  	if depth > maxDecodeNestingDepth {
    38  		return errors.ErrExceededMaxDepth(s.char(), s.cursor)
    39  	}
    40  
    41  	for {
    42  		switch s.char() {
    43  		case ' ', '\n', '\t', '\r':
    44  		case 'n':
    45  			if err := nullBytes(s); err != nil {
    46  				return err
    47  			}
    48  			return nil
    49  		case '[':
    50  			idx := 0
    51  			s.cursor++
    52  			if s.skipWhiteSpace() == ']' {
    53  				for idx < d.alen {
    54  					*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
    55  					idx++
    56  				}
    57  				s.cursor++
    58  				return nil
    59  			}
    60  			for {
    61  				if idx < d.alen {
    62  					if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil {
    63  						return err
    64  					}
    65  				} else {
    66  					if err := s.skipValue(depth); err != nil {
    67  						return err
    68  					}
    69  				}
    70  				idx++
    71  				switch s.skipWhiteSpace() {
    72  				case ']':
    73  					for idx < d.alen {
    74  						*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
    75  						idx++
    76  					}
    77  					s.cursor++
    78  					return nil
    79  				case ',':
    80  					s.cursor++
    81  					continue
    82  				case nul:
    83  					if s.read() {
    84  						s.cursor++
    85  						continue
    86  					}
    87  					goto ERROR
    88  				default:
    89  					goto ERROR
    90  				}
    91  			}
    92  		case nul:
    93  			if s.read() {
    94  				continue
    95  			}
    96  			goto ERROR
    97  		default:
    98  			goto ERROR
    99  		}
   100  		s.cursor++
   101  	}
   102  ERROR:
   103  	return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset())
   104  }
   105  
   106  func (d *arrayDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
   107  	buf := ctx.Buf
   108  	depth++
   109  	if depth > maxDecodeNestingDepth {
   110  		return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
   111  	}
   112  
   113  	for {
   114  		switch buf[cursor] {
   115  		case ' ', '\n', '\t', '\r':
   116  			cursor++
   117  			continue
   118  		case 'n':
   119  			if err := validateNull(buf, cursor); err != nil {
   120  				return 0, err
   121  			}
   122  			cursor += 4
   123  			return cursor, nil
   124  		case '[':
   125  			idx := 0
   126  			cursor++
   127  			cursor = skipWhiteSpace(buf, cursor)
   128  			if buf[cursor] == ']' {
   129  				for idx < d.alen {
   130  					*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
   131  					idx++
   132  				}
   133  				cursor++
   134  				return cursor, nil
   135  			}
   136  			for {
   137  				if idx < d.alen {
   138  					c, err := d.valueDecoder.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
   139  					if err != nil {
   140  						return 0, err
   141  					}
   142  					cursor = c
   143  				} else {
   144  					c, err := skipValue(buf, cursor, depth)
   145  					if err != nil {
   146  						return 0, err
   147  					}
   148  					cursor = c
   149  				}
   150  				idx++
   151  				cursor = skipWhiteSpace(buf, cursor)
   152  				switch buf[cursor] {
   153  				case ']':
   154  					for idx < d.alen {
   155  						*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
   156  						idx++
   157  					}
   158  					cursor++
   159  					return cursor, nil
   160  				case ',':
   161  					cursor++
   162  					continue
   163  				default:
   164  					return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor)
   165  				}
   166  			}
   167  		default:
   168  			return 0, errors.ErrUnexpectedEndOfJSON("array", cursor)
   169  		}
   170  	}
   171  }
   172  
   173  func (d *arrayDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
   174  	return nil, 0, errors.New("json: array decoder does not support decode path")
   175  }