| package types |
| |
| import ( |
| "fmt" |
| "strings" |
| ) |
| |
| // An IntMode is a mode for parsing integer values, representing a set of |
| // accepted bases. |
| type IntMode uint8 |
| |
| // IntMode values for ParseInt; can be combined using binary or. |
| const ( |
| Dec IntMode = 1 << iota |
| Hex |
| Oct |
| ) |
| |
| // String returns a string representation of IntMode; e.g. `IntMode(Dec|Hex)`. |
| func (m IntMode) String() string { |
| var modes []string |
| if m&Dec != 0 { |
| modes = append(modes, "Dec") |
| } |
| if m&Hex != 0 { |
| modes = append(modes, "Hex") |
| } |
| if m&Oct != 0 { |
| modes = append(modes, "Oct") |
| } |
| return "IntMode(" + strings.Join(modes, "|") + ")" |
| } |
| |
| var errIntAmbig = fmt.Errorf("ambiguous integer value; must include '0' prefix") |
| |
| func prefix0(val string) bool { |
| return strings.HasPrefix(val, "0") || strings.HasPrefix(val, "-0") |
| } |
| |
| func prefix0x(val string) bool { |
| return strings.HasPrefix(val, "0x") || strings.HasPrefix(val, "-0x") |
| } |
| |
| // ParseInt parses val using mode into intptr, which must be a pointer to an |
| // integer kind type. Non-decimal value require prefix `0` or `0x` in the cases |
| // when mode permits ambiguity of base; otherwise the prefix can be omitted. |
| func ParseInt(intptr interface{}, val string, mode IntMode) error { |
| val = strings.TrimSpace(val) |
| verb := byte(0) |
| switch mode { |
| case Dec: |
| verb = 'd' |
| case Dec + Hex: |
| if prefix0x(val) { |
| verb = 'v' |
| } else { |
| verb = 'd' |
| } |
| case Dec + Oct: |
| if prefix0(val) && !prefix0x(val) { |
| verb = 'v' |
| } else { |
| verb = 'd' |
| } |
| case Dec + Hex + Oct: |
| verb = 'v' |
| case Hex: |
| if prefix0x(val) { |
| verb = 'v' |
| } else { |
| verb = 'x' |
| } |
| case Oct: |
| verb = 'o' |
| case Hex + Oct: |
| if prefix0(val) { |
| verb = 'v' |
| } else { |
| return errIntAmbig |
| } |
| } |
| if verb == 0 { |
| panic("unsupported mode") |
| } |
| return ScanFully(intptr, val, verb) |
| } |