github.com/RevenueMonster/sqlike@v1.0.6/jsonb/skip.go (about)

     1  package jsonb
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"errors"
     8  )
     9  
    10  func (r *Reader) skip() (err error) {
    11  	typ := r.peekType()
    12  	switch typ {
    13  	case jsonString:
    14  		err = r.skipString()
    15  	case jsonNumber:
    16  		r.skipNumber()
    17  	case jsonBoolean:
    18  		r.skipBoolean()
    19  	case jsonNull:
    20  		err = r.skipBytes([]byte{'n', 'u', 'l', 'l'})
    21  	case jsonArray:
    22  		r.skipArray()
    23  	case jsonObject:
    24  		r.skipObject()
    25  	}
    26  	return err
    27  }
    28  
    29  func (r *Reader) skipBytes(b []byte) error {
    30  	offset := r.pos + len(b)
    31  	if offset > r.len {
    32  		return errors.New("unexpected json length")
    33  	}
    34  	cutset := r.b[r.pos:offset]
    35  	if !bytes.Equal(b, cutset) {
    36  		return ErrInvalidJSON{
    37  			callback: "skipBytes",
    38  			message:  fmt.Sprintf("expected %s", b),
    39  		}
    40  	}
    41  	r.pos = offset
    42  	return nil
    43  }
    44  
    45  func (r *Reader) skipNull() error {
    46  	c := r.nextToken()
    47  	r.unreadByte()
    48  	if c == 'n' {
    49  		return r.skipBytes([]byte{'n', 'u', 'l', 'l'})
    50  	}
    51  	return ErrInvalidJSON{}
    52  }
    53  
    54  func (r *Reader) skipBoolean() {
    55  	c := r.nextToken()
    56  	r.unreadByte()
    57  	if c == 'n' {
    58  		r.skipBytes([]byte{'n', 'u', 'l', 'l'})
    59  		return
    60  	}
    61  	if c == 't' {
    62  		r.skipBytes([]byte{'t', 'r', 'u', 'e'})
    63  		return
    64  	}
    65  	if c == 'f' {
    66  		r.skipBytes([]byte{'f', 'a', 'l', 's', 'e'})
    67  		return
    68  	}
    69  }
    70  
    71  func (r *Reader) skipObject() error {
    72  	c := r.nextToken()
    73  	if c != '{' {
    74  		return errors.New("object should start with {")
    75  	}
    76  
    77  loop:
    78  	for {
    79  		c = r.nextToken()
    80  
    81  		// key: value
    82  		switch c {
    83  		case '}':
    84  			break loop
    85  
    86  		case '"': // expect key
    87  			r.unreadByte()
    88  			if err := r.skipString(); err != nil {
    89  				return errors.New("object key must be string")
    90  			}
    91  
    92  			c = r.nextToken()
    93  			if c != ':' {
    94  				return errors.New("character : must place within key and value")
    95  			}
    96  
    97  			// skip anything
    98  			if err := r.skip(); err != nil {
    99  				return err
   100  			}
   101  
   102  			c = r.nextToken()
   103  			switch c {
   104  			case '}':
   105  				break loop
   106  			case ',':
   107  				continue
   108  			default:
   109  				return fmt.Errorf("expected , or } after object value")
   110  			}
   111  
   112  		default:
   113  			return fmt.Errorf("invalid character %s in object", string(c))
   114  		}
   115  	}
   116  
   117  	if r.b[r.pos] != '}' {
   118  		return errors.New("invalid char on end of object")
   119  	}
   120  
   121  	return nil
   122  }