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 }