You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
2.1 KiB

  1. // Copyright 2015 PingCAP, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package mysql
  14. import (
  15. "encoding/hex"
  16. "fmt"
  17. "strconv"
  18. "strings"
  19. "github.com/juju/errors"
  20. )
  21. // Hex is for mysql hexadecimal literal type.
  22. type Hex struct {
  23. // Value holds numeric value for hexadecimal literal.
  24. Value int64
  25. }
  26. // String implements fmt.Stringer interface.
  27. func (h Hex) String() string {
  28. s := fmt.Sprintf("%X", h.Value)
  29. if len(s)%2 != 0 {
  30. return "0x0" + s
  31. }
  32. return "0x" + s
  33. }
  34. // ToNumber changes hexadecimal type to float64 for numeric operation.
  35. // MySQL treats hexadecimal literal as double type.
  36. func (h Hex) ToNumber() float64 {
  37. return float64(h.Value)
  38. }
  39. // ToString returns the string representation for hexadecimal literal.
  40. func (h Hex) ToString() string {
  41. s := fmt.Sprintf("%x", h.Value)
  42. if len(s)%2 != 0 {
  43. s = "0" + s
  44. }
  45. // should never error.
  46. b, _ := hex.DecodeString(s)
  47. return string(b)
  48. }
  49. // ParseHex parses hexadecimal literal string.
  50. // The string format can be X'val', x'val' or 0xval.
  51. // val must in (0...9, a...z, A...Z).
  52. func ParseHex(s string) (Hex, error) {
  53. if len(s) == 0 {
  54. return Hex{}, errors.Errorf("invalid empty string for parsing hexadecimal literal")
  55. }
  56. if s[0] == 'x' || s[0] == 'X' {
  57. // format is x'val' or X'val'
  58. s = strings.Trim(s[1:], "'")
  59. if len(s)%2 != 0 {
  60. return Hex{}, errors.Errorf("invalid hexadecimal format, must even numbers, but %d", len(s))
  61. }
  62. s = "0x" + s
  63. } else if !strings.HasPrefix(s, "0x") {
  64. // here means format is not x'val', X'val' or 0xval.
  65. return Hex{}, errors.Errorf("invalid hexadecimal format %s", s)
  66. }
  67. n, err := strconv.ParseInt(s, 0, 64)
  68. if err != nil {
  69. return Hex{}, errors.Trace(err)
  70. }
  71. return Hex{Value: n}, nil
  72. }