scanString scans the content inside '...'. This is used for simple string literals '...' but also e'....' and b'...'. For x'...', see scanHexString().
(lval ScanSymType, ch int, allowEscapes, requireUTF8 bool)
| 922 | // string literals '...' but also e'....' and b'...'. For x'...', see |
| 923 | // scanHexString(). |
| 924 | func (s *Scanner) scanString(lval ScanSymType, ch int, allowEscapes, requireUTF8 bool) bool { |
| 925 | buf := s.buffer() |
| 926 | var runeTmp [utf8.UTFMax]byte |
| 927 | start := s.pos |
| 928 | outer: |
| 929 | for { |
| 930 | switch s.next() { |
| 931 | case ch: |
| 932 | buf = append(buf, s.in[start:s.pos-1]...) |
| 933 | if s.peek() == ch { |
| 934 | // Double quote is translated into a single quote that is part of the |
| 935 | // string. |
| 936 | start = s.pos |
| 937 | s.pos++ |
| 938 | continue |
| 939 | } |
| 940 | |
| 941 | newline, ok := s.skipWhitespace(lval, false) |
| 942 | if !ok { |
| 943 | return false |
| 944 | } |
| 945 | |
| 946 | // SQL allows joining adjacent single-quoted strings separated by |
| 947 | // whitespace as long as that whitespace contains at least one |
| 948 | // newline. Kind of strange to require the newline, but that is the |
| 949 | // standard. |
| 950 | if ch == singleQuote && s.peek() == singleQuote && newline { |
| 951 | s.pos++ |
| 952 | start = s.pos |
| 953 | continue |
| 954 | } |
| 955 | break outer |
| 956 | |
| 957 | case '\\': |
| 958 | t := s.peek() |
| 959 | |
| 960 | if allowEscapes { |
| 961 | buf = append(buf, s.in[start:s.pos-1]...) |
| 962 | if t == ch { |
| 963 | start = s.pos |
| 964 | s.pos++ |
| 965 | continue |
| 966 | } |
| 967 | |
| 968 | switch t { |
| 969 | case 'a', 'b', 'f', 'n', 'r', 't', 'v', 'x', 'X', 'u', 'U', '\\', |
| 970 | '0', '1', '2', '3', '4', '5', '6', '7': |
| 971 | var tmp string |
| 972 | if t == 'X' && len(s.in[s.pos:]) >= 3 { |
| 973 | // UnquoteChar doesn't handle 'X' so we create a temporary string |
| 974 | // for it to parse. |
| 975 | tmp = "\\x" + s.in[s.pos+1:s.pos+3] |
| 976 | } else { |
| 977 | tmp = s.in[s.pos-1:] |
| 978 | } |
| 979 | v, multibyte, tail, err := strconv.UnquoteChar(tmp, byte(ch)) |
| 980 | if err != nil { |
| 981 | lval.SetID(lexbase.ERROR) |
no test coverage detected