diff options
Diffstat (limited to 'vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go')
-rw-r--r-- | vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go | 158 |
1 files changed, 58 insertions, 100 deletions
diff --git a/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go b/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go index 7a18b50b1..fec401786 100644 --- a/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go +++ b/vendor/github.com/uptrace/bun/dialect/pgdialect/hstore_parser.go @@ -3,140 +3,98 @@ package pgdialect import ( "bytes" "fmt" + "io" ) type hstoreParser struct { - *streamParser - err error + p pgparser + + key string + value string + err error } func newHStoreParser(b []byte) *hstoreParser { - p := &hstoreParser{ - streamParser: newStreamParser(b, 0), - } - if len(b) < 6 || b[0] != '"' { - p.err = fmt.Errorf("bun: can't parse hstore: %q", b) + p := new(hstoreParser) + if len(b) != 0 && (len(b) < 6 || b[0] != '"') { + p.err = fmt.Errorf("pgdialect: can't parse hstore: %q", b) + return p } + p.p.Reset(b) return p } -func (p *hstoreParser) NextKey() (string, error) { +func (p *hstoreParser) Next() bool { if p.err != nil { - return "", p.err + return false } + p.err = p.readNext() + return p.err == nil +} - err := p.skipByte('"') - if err != nil { - return "", err +func (p *hstoreParser) Err() error { + if p.err != io.EOF { + return p.err } + return nil +} - key, err := p.readSubstring() - if err != nil { - return "", err - } +func (p *hstoreParser) Key() string { + return p.key +} - const separator = "=>" +func (p *hstoreParser) Value() string { + return p.value +} - for i := range separator { - err = p.skipByte(separator[i]) - if err != nil { - return "", err - } +func (p *hstoreParser) readNext() error { + if !p.p.Valid() { + return io.EOF } - return string(key), nil -} + if err := p.p.Skip('"'); err != nil { + return err + } -func (p *hstoreParser) NextValue() (string, error) { - if p.err != nil { - return "", p.err + key, err := p.p.ReadUnescapedSubstring('"') + if err != nil { + return err + } + p.key = string(key) + + if err := p.p.SkipPrefix([]byte("=>")); err != nil { + return err } - c, err := p.readByte() + ch, err := p.p.ReadByte() if err != nil { - return "", err + return err } - switch c { + switch ch { case '"': - value, err := p.readSubstring() + value, err := p.p.ReadUnescapedSubstring(ch) if err != nil { - return "", err - } - - if p.peek() == ',' { - p.skipNext() - } - - if p.peek() == ' ' { - p.skipNext() + return err } - - return string(value), nil + p.skipComma() + p.value = string(value) + return nil default: - value := p.readSimple() + value := p.p.ReadLiteral(ch) if bytes.Equal(value, []byte("NULL")) { - value = nil - } - - if p.peek() == ',' { - p.skipNext() + p.value = "" } - - return string(value), nil - } -} - -func (p *hstoreParser) readSimple() []byte { - p.unreadByte() - - if i := bytes.IndexByte(p.b[p.i:], ','); i >= 0 { - b := p.b[p.i : p.i+i] - p.i += i - return b + p.skipComma() + return nil } - - b := p.b[p.i:len(p.b)] - p.i = len(p.b) - return b } -func (p *hstoreParser) readSubstring() ([]byte, error) { - c, err := p.readByte() - if err != nil { - return nil, err +func (p *hstoreParser) skipComma() { + if p.p.Peek() == ',' { + p.p.Advance() } - - p.buf = p.buf[:0] - for { - if c == '"' { - break - } - - next, err := p.readByte() - if err != nil { - return nil, err - } - - if c == '\\' { - switch next { - case '\\', '"': - p.buf = append(p.buf, next) - - c, err = p.readByte() - if err != nil { - return nil, err - } - default: - p.buf = append(p.buf, '\\') - c = next - } - continue - } - - p.buf = append(p.buf, c) - c = next + if p.p.Peek() == ' ' { + p.p.Advance() } - - return p.buf, nil } |