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

     1  package jzon
     2  
     3  // use after the first `"` is consumed
     4  // will read the object field as well as the colon
     5  func (it *Iterator) readObjectFieldAsSlice() (field []byte, err error) {
     6  	field, err = it.readStringAsSlice()
     7  	if err != nil {
     8  		return
     9  	}
    10  	c, err := it.nextToken()
    11  	if err != nil {
    12  		return
    13  	}
    14  	if c != ':' {
    15  		err = UnexpectedByteError{got: c, exp: ':'}
    16  		return
    17  	}
    18  	it.head++
    19  	return
    20  }
    21  
    22  // called only when a '"' is consumed
    23  func (it *Iterator) readObjectField() (_ string, err error) {
    24  	field, err := it.readObjectFieldAsSlice()
    25  	if err != nil {
    26  		return "", err
    27  	}
    28  	return string(field), nil
    29  }
    30  
    31  func (it *Iterator) skipObjectField() error {
    32  	err := skipString(it, '"')
    33  	if err != nil {
    34  		return err
    35  	}
    36  	c, err := it.nextToken()
    37  	if err != nil {
    38  		return err
    39  	}
    40  	if c != ':' {
    41  		return UnexpectedByteError{got: c, exp: ':'}
    42  	}
    43  	it.head++
    44  	return nil
    45  }
    46  
    47  // ReadObjectBegin starts to read an object
    48  func (it *Iterator) ReadObjectBegin() (_ bool, _ string, err error) {
    49  	c, err := it.nextToken()
    50  	if err != nil {
    51  		return
    52  	}
    53  	if c != '{' {
    54  		err = UnexpectedByteError{got: c, exp: '{'}
    55  		return
    56  	}
    57  	it.head++
    58  	c, err = it.nextToken()
    59  	if err != nil {
    60  		return
    61  	}
    62  	switch c {
    63  	case '}':
    64  		// no more items
    65  		it.head++
    66  		return
    67  	case '"':
    68  		it.head++
    69  		var fieldBytes []byte
    70  		fieldBytes, err = it.readObjectFieldAsSlice()
    71  		if err != nil {
    72  			return
    73  		}
    74  		return true, string(fieldBytes), nil
    75  	default:
    76  		err = UnexpectedByteError{got: c, exp: '}', exp2: '"'}
    77  		return
    78  	}
    79  }
    80  
    81  // ReadObjectMore tells if there is more field to read in the object
    82  func (it *Iterator) ReadObjectMore() (_ bool, _ string, err error) {
    83  	c, err := it.nextToken()
    84  	if err != nil {
    85  		return
    86  	}
    87  	switch c {
    88  	case '}':
    89  		it.head++
    90  		return
    91  	case ',':
    92  		it.head++
    93  		c, err = it.nextToken()
    94  		if err != nil {
    95  			return
    96  		}
    97  		if c != '"' {
    98  			err = UnexpectedByteError{got: c, exp: '"'}
    99  			return
   100  		}
   101  		it.head++
   102  		var fieldBytes []byte
   103  		fieldBytes, err = it.readObjectFieldAsSlice()
   104  		if err != nil {
   105  			return
   106  		}
   107  		return true, string(fieldBytes), nil
   108  	default:
   109  		err = UnexpectedByteError{got: c, exp: '}', exp2: ','}
   110  		return
   111  	}
   112  }
   113  
   114  // ReadObjectCB reads the object with a callback
   115  // The caller should make sure that the callback is correct
   116  func (it *Iterator) ReadObjectCB(cb func(it *Iterator, field string) error) error {
   117  	c, err := it.nextToken()
   118  	if err != nil {
   119  		return err
   120  	}
   121  	if c != '{' {
   122  		return UnexpectedByteError{got: c, exp: '{'}
   123  	}
   124  	it.head++
   125  	c, err = it.nextToken()
   126  	if err != nil {
   127  		return err
   128  	}
   129  	if c == '}' {
   130  		it.head++
   131  		return nil
   132  	}
   133  	if c != '"' {
   134  		return UnexpectedByteError{got: c, exp: '"', exp2: '}'}
   135  	}
   136  	it.head++
   137  	for {
   138  		field, err := it.readObjectField()
   139  		if err != nil {
   140  			return err
   141  		}
   142  		if err := cb(it, field); err != nil {
   143  			return err
   144  		}
   145  		c, err = it.nextToken()
   146  		if err != nil {
   147  			return err
   148  		}
   149  		switch c {
   150  		case '}':
   151  			it.head++
   152  			return nil
   153  		case ',':
   154  			it.head++
   155  			c, err = it.nextToken()
   156  			if err != nil {
   157  				return err
   158  			}
   159  			if c != '"' {
   160  				return UnexpectedByteError{got: c, exp: '"'}
   161  			}
   162  			it.head++
   163  		default:
   164  			return UnexpectedByteError{got: c, exp: '}', exp2: ','}
   165  		}
   166  	}
   167  }