scanHexString scans the content inside x'....'.
(lval *sqlSymType, ch int)
| 749 | |
| 750 | // scanHexString scans the content inside x'....'. |
| 751 | func (s *scanner) scanHexString(lval *sqlSymType, ch int) bool { |
| 752 | buf := s.buffer() |
| 753 | |
| 754 | var curbyte byte |
| 755 | bytep := 0 |
| 756 | const errInvalidBytesLiteral = "invalid hexadecimal bytes literal" |
| 757 | outer: |
| 758 | for { |
| 759 | b := s.next() |
| 760 | switch b { |
| 761 | case ch: |
| 762 | _, newline, ok := s.skipWhitespace(lval, false) |
| 763 | if !ok { |
| 764 | return false |
| 765 | } |
| 766 | // SQL allows joining adjacent strings separated by whitespace |
| 767 | // as long as that whitespace contains at least one |
| 768 | // newline. Kind of strange to require the newline, but that |
| 769 | // is the standard. |
| 770 | if s.peek() == ch && newline { |
| 771 | s.pos++ |
| 772 | continue |
| 773 | } |
| 774 | break outer |
| 775 | |
| 776 | case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': |
| 777 | curbyte = (curbyte << 4) | byte(b-'0') |
| 778 | case 'a', 'b', 'c', 'd', 'e', 'f': |
| 779 | curbyte = (curbyte << 4) | byte(b-'a'+10) |
| 780 | case 'A', 'B', 'C', 'D', 'E', 'F': |
| 781 | curbyte = (curbyte << 4) | byte(b-'A'+10) |
| 782 | default: |
| 783 | lval.id = ERROR |
| 784 | lval.str = errInvalidBytesLiteral |
| 785 | return false |
| 786 | } |
| 787 | bytep++ |
| 788 | |
| 789 | if bytep > 1 { |
| 790 | buf = append(buf, curbyte) |
| 791 | bytep = 0 |
| 792 | curbyte = 0 |
| 793 | } |
| 794 | } |
| 795 | |
| 796 | if bytep != 0 { |
| 797 | lval.id = ERROR |
| 798 | lval.str = errInvalidBytesLiteral |
| 799 | return false |
| 800 | } |
| 801 | |
| 802 | lval.id = BCONST |
| 803 | lval.str = s.finishString(buf) |
| 804 | return true |
| 805 | } |
| 806 | |
| 807 | // scanBitString scans the content inside B'....'. |
| 808 | func (s *scanner) scanBitString(lval *sqlSymType, ch int) bool { |
no test coverage detected