1package types 2 3import ( 4 "fmt" 5 "strings" 6) 7 8// An IntMode is a mode for parsing integer values, representing a set of 9// accepted bases. 10type IntMode uint8 11 12// IntMode values for ParseInt; can be combined using binary or. 13const ( 14 Dec IntMode = 1 << iota 15 Hex 16 Oct 17) 18 19// String returns a string representation of IntMode; e.g. `IntMode(Dec|Hex)`. 20func (m IntMode) String() string { 21 var modes []string 22 if m&Dec != 0 { 23 modes = append(modes, "Dec") 24 } 25 if m&Hex != 0 { 26 modes = append(modes, "Hex") 27 } 28 if m&Oct != 0 { 29 modes = append(modes, "Oct") 30 } 31 return "IntMode(" + strings.Join(modes, "|") + ")" 32} 33 34var errIntAmbig = fmt.Errorf("ambiguous integer value; must include '0' prefix") 35 36func prefix0(val string) bool { 37 return strings.HasPrefix(val, "0") || strings.HasPrefix(val, "-0") 38} 39 40func prefix0x(val string) bool { 41 return strings.HasPrefix(val, "0x") || strings.HasPrefix(val, "-0x") 42} 43 44// ParseInt parses val using mode into intptr, which must be a pointer to an 45// integer kind type. Non-decimal value require prefix `0` or `0x` in the cases 46// when mode permits ambiguity of base; otherwise the prefix can be omitted. 47func ParseInt(intptr interface{}, val string, mode IntMode) error { 48 val = strings.TrimSpace(val) 49 verb := byte(0) 50 switch mode { 51 case Dec: 52 verb = 'd' 53 case Dec + Hex: 54 if prefix0x(val) { 55 verb = 'v' 56 } else { 57 verb = 'd' 58 } 59 case Dec + Oct: 60 if prefix0(val) && !prefix0x(val) { 61 verb = 'v' 62 } else { 63 verb = 'd' 64 } 65 case Dec + Hex + Oct: 66 verb = 'v' 67 case Hex: 68 if prefix0x(val) { 69 verb = 'v' 70 } else { 71 verb = 'x' 72 } 73 case Oct: 74 verb = 'o' 75 case Hex + Oct: 76 if prefix0(val) { 77 verb = 'v' 78 } else { 79 return errIntAmbig 80 } 81 } 82 if verb == 0 { 83 panic("unsupported mode") 84 } 85 return ScanFully(intptr, val, verb) 86} 87