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)
| 844 | // string literals '...' but also e'....' and b'...'. For x'...', see |
| 845 | // scanHexString(). |
| 846 | func (s *scanner) scanString(lval *sqlSymType, ch int, allowEscapes, requireUTF8 bool) bool { |
| 847 | buf := s.buffer() |
| 848 | var runeTmp [utf8.UTFMax]byte |
| 849 | start := s.pos |
| 850 | |
| 851 | outer: |
| 852 | for { |
| 853 | switch s.next() { |
| 854 | case ch: |
| 855 | buf = append(buf, s.in[start:s.pos-1]...) |
| 856 | if s.peek() == ch { |
| 857 | // Double quote is translated into a single quote that is part of the |
| 858 | // string. |
| 859 | start = s.pos |
| 860 | s.pos++ |
| 861 | continue |
| 862 | } |
| 863 | |
| 864 | _, newline, ok := s.skipWhitespace(lval, false) |
| 865 | if !ok { |
| 866 | return false |
| 867 | } |
| 868 | // SQL allows joining adjacent strings separated by whitespace |
| 869 | // as long as that whitespace contains at least one |
| 870 | // newline. Kind of strange to require the newline, but that |
| 871 | // is the standard. |
| 872 | if s.peek() == ch && newline { |
| 873 | s.pos++ |
| 874 | start = s.pos |
| 875 | continue |
| 876 | } |
| 877 | break outer |
| 878 | |
| 879 | case '\\': |
| 880 | t := s.peek() |
| 881 | |
| 882 | if allowEscapes { |
| 883 | buf = append(buf, s.in[start:s.pos-1]...) |
| 884 | if t == ch { |
| 885 | start = s.pos |
| 886 | s.pos++ |
| 887 | continue |
| 888 | } |
| 889 | |
| 890 | switch t { |
| 891 | case 'a', 'b', 'f', 'n', 'r', 't', 'v', 'x', 'X', 'u', 'U', '\\', |
| 892 | '0', '1', '2', '3', '4', '5', '6', '7': |
| 893 | var tmp string |
| 894 | if t == 'X' && len(s.in[s.pos:]) >= 3 { |
| 895 | // UnquoteChar doesn't handle 'X' so we create a temporary string |
| 896 | // for it to parse. |
| 897 | tmp = "\\x" + s.in[s.pos+1:s.pos+3] |
| 898 | } else { |
| 899 | tmp = s.in[s.pos-1:] |
| 900 | } |
| 901 | v, multibyte, tail, err := strconv.UnquoteChar(tmp, byte(ch)) |
| 902 | if err != nil { |
| 903 | lval.id = ERROR |
no test coverage detected