scanString scans the content inside '...'. This is used for simple string literals '...' but also e'....' and b'...'. For x'...', see scanHexString().
(lval *sqlSymType, ch int, allowEscapes, requireUTF8 bool)
| 788 | // string literals '...' but also e'....' and b'...'. For x'...', see |
| 789 | // scanHexString(). |
| 790 | func (s *scanner) scanString(lval *sqlSymType, ch int, allowEscapes, requireUTF8 bool) bool { |
| 791 | buf := s.buffer() |
| 792 | var runeTmp [utf8.UTFMax]byte |
| 793 | start := s.pos |
| 794 | |
| 795 | outer: |
| 796 | for { |
| 797 | switch s.next() { |
| 798 | case ch: |
| 799 | buf = append(buf, s.in[start:s.pos-1]...) |
| 800 | if s.peek() == ch { |
| 801 | // Double quote is translated into a single quote that is part of the |
| 802 | // string. |
| 803 | start = s.pos |
| 804 | s.pos++ |
| 805 | continue |
| 806 | } |
| 807 | |
| 808 | newline, ok := s.skipWhitespace(lval, false) |
| 809 | if !ok { |
| 810 | return false |
| 811 | } |
| 812 | // SQL allows joining adjacent strings separated by whitespace |
| 813 | // as long as that whitespace contains at least one |
| 814 | // newline. Kind of strange to require the newline, but that |
| 815 | // is the standard. |
| 816 | if s.peek() == ch && newline { |
| 817 | s.pos++ |
| 818 | start = s.pos |
| 819 | continue |
| 820 | } |
| 821 | break outer |
| 822 | |
| 823 | case '\\': |
| 824 | t := s.peek() |
| 825 | |
| 826 | if allowEscapes { |
| 827 | buf = append(buf, s.in[start:s.pos-1]...) |
| 828 | if t == ch { |
| 829 | start = s.pos |
| 830 | s.pos++ |
| 831 | continue |
| 832 | } |
| 833 | |
| 834 | switch t { |
| 835 | case 'a', 'b', 'f', 'n', 'r', 't', 'v', 'x', 'X', 'u', 'U', '\\', |
| 836 | '0', '1', '2', '3', '4', '5', '6', '7': |
| 837 | var tmp string |
| 838 | if t == 'X' && len(s.in[s.pos:]) >= 3 { |
| 839 | // UnquoteChar doesn't handle 'X' so we create a temporary string |
| 840 | // for it to parse. |
| 841 | tmp = "\\x" + s.in[s.pos+1:s.pos+3] |
| 842 | } else { |
| 843 | tmp = s.in[s.pos-1:] |
| 844 | } |
| 845 | v, multibyte, tail, err := strconv.UnquoteChar(tmp, byte(ch)) |
| 846 | if err != nil { |
| 847 | lval.id = ERROR |
no test coverage detected