number_helper.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package ini
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strconv"
  6. )
  7. const (
  8. none = numberFormat(iota)
  9. binary
  10. octal
  11. decimal
  12. hex
  13. exponent
  14. )
  15. type numberFormat int
  16. // numberHelper is used to dictate what format a number is in
  17. // and what to do for negative values. Since -1e-4 is a valid
  18. // number, we cannot just simply check for duplicate negatives.
  19. type numberHelper struct {
  20. numberFormat numberFormat
  21. negative bool
  22. negativeExponent bool
  23. }
  24. func (b numberHelper) Exists() bool {
  25. return b.numberFormat != none
  26. }
  27. func (b numberHelper) IsNegative() bool {
  28. return b.negative || b.negativeExponent
  29. }
  30. func (b *numberHelper) Determine(c rune) error {
  31. if b.Exists() {
  32. return NewParseError(fmt.Sprintf("multiple number formats: 0%v", string(c)))
  33. }
  34. switch c {
  35. case 'b':
  36. b.numberFormat = binary
  37. case 'o':
  38. b.numberFormat = octal
  39. case 'x':
  40. b.numberFormat = hex
  41. case 'e', 'E':
  42. b.numberFormat = exponent
  43. case '-':
  44. if b.numberFormat != exponent {
  45. b.negative = true
  46. } else {
  47. b.negativeExponent = true
  48. }
  49. case '.':
  50. b.numberFormat = decimal
  51. default:
  52. return NewParseError(fmt.Sprintf("invalid number character: %v", string(c)))
  53. }
  54. return nil
  55. }
  56. func (b numberHelper) CorrectByte(c rune) bool {
  57. switch {
  58. case b.numberFormat == binary:
  59. if !isBinaryByte(c) {
  60. return false
  61. }
  62. case b.numberFormat == octal:
  63. if !isOctalByte(c) {
  64. return false
  65. }
  66. case b.numberFormat == hex:
  67. if !isHexByte(c) {
  68. return false
  69. }
  70. case b.numberFormat == decimal:
  71. if !isDigit(c) {
  72. return false
  73. }
  74. case b.numberFormat == exponent:
  75. if !isDigit(c) {
  76. return false
  77. }
  78. case b.negativeExponent:
  79. if !isDigit(c) {
  80. return false
  81. }
  82. case b.negative:
  83. if !isDigit(c) {
  84. return false
  85. }
  86. default:
  87. if !isDigit(c) {
  88. return false
  89. }
  90. }
  91. return true
  92. }
  93. func (b numberHelper) Base() int {
  94. switch b.numberFormat {
  95. case binary:
  96. return 2
  97. case octal:
  98. return 8
  99. case hex:
  100. return 16
  101. default:
  102. return 10
  103. }
  104. }
  105. func (b numberHelper) String() string {
  106. buf := bytes.Buffer{}
  107. i := 0
  108. switch b.numberFormat {
  109. case binary:
  110. i++
  111. buf.WriteString(strconv.Itoa(i) + ": binary format\n")
  112. case octal:
  113. i++
  114. buf.WriteString(strconv.Itoa(i) + ": octal format\n")
  115. case hex:
  116. i++
  117. buf.WriteString(strconv.Itoa(i) + ": hex format\n")
  118. case exponent:
  119. i++
  120. buf.WriteString(strconv.Itoa(i) + ": exponent format\n")
  121. default:
  122. i++
  123. buf.WriteString(strconv.Itoa(i) + ": integer format\n")
  124. }
  125. if b.negative {
  126. i++
  127. buf.WriteString(strconv.Itoa(i) + ": negative format\n")
  128. }
  129. if b.negativeExponent {
  130. i++
  131. buf.WriteString(strconv.Itoa(i) + ": negative exponent format\n")
  132. }
  133. return buf.String()
  134. }