1 package lxstrconv 2 3 import ( 4 "sort" 5 ) 6 7 // Unicode standard guarantees that this codepoint is never assigned 8 const runeNone = rune(0xFFFF) 9 10 // NumberFormat defines an interface for parsing numbers in a specific format 11 // (such as a decimal number in a specific locale, with support for a digit 12 // separator such as commas and a decimal point). Numbers are assumed to be 13 // in the normal base (e.g. base 10 for decimal) for that locale. 14 // 15 // Errors are either nil, strconv.ErrSyntax or strconv.ErrRange 16 type NumberFormat interface { 17 ParseInt(string) (int64, error) 18 ParseFloat(string) (float64, error) 19 20 // AcceptInt parses as much of an integer as possible. The second return 21 // value is the number of bytes (not runes) successfully parsed. The error 22 // value is always either nil or strconv.ErrRange. 23 AcceptInt(string) (int64, int, error) 24 25 // AcceptFloat parses as much of a float as possible. The second return 26 // value is the number of bytes (not runes) successfully parsed. The error 27 // value is always either nil or strconv.ErrRange. 28 AcceptFloat(string) (float64, int, error) 29 } 30 31 // repeatingRune returns any rune that appears more than once in a given string 32 func repeatingRune(s string) rune { 33 // easy efficient algorithm: sort the string, then walk it and see if the 34 // current rune repeats 35 sl := []rune(s) 36 sort.Slice(sl, func(i int, j int) bool { return sl[i] < sl[j] }) 37 38 current := runeNone 39 40 for _, c := range sl { 41 if c == current { 42 return c 43 } 44 current = c 45 } 46 47 return runeNone 48 } 49 50 51 52