package main import ( "fmt" "log" "math" "os" "regexp" "strconv" "github.com/urfave/cli" ) const ( BASE = 62 DIGIT_OFFSET = 48 LOWERCASE_OFFSET = 61 UPPERCASE_OFFSET = 55 ) func reverse(s string) string { runes := []rune(s) for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { runes[i], runes[j] = runes[j], runes[i] } return string(runes) } func char2ord(char string) (int, error) { if matched, _ := regexp.MatchString("[0-9]", char); matched { return int([]rune(char)[0] - DIGIT_OFFSET), nil } else if matched, _ := regexp.MatchString("[A-Z]", char); matched { return int([]rune(char)[0] - UPPERCASE_OFFSET), nil } else if matched, _ := regexp.MatchString("[a-z]", char); matched { return int([]rune(char)[0] - LOWERCASE_OFFSET), nil } else { return -1, fmt.Errorf("%s is not a valid character", char) } } func ord2char(ord int) (string, error) { switch { case ord < 10: return string(ord + DIGIT_OFFSET), nil case ord >= 10 && ord <= 35: return string(ord + UPPERCASE_OFFSET), nil case ord >= 36 && ord < 62: return string(ord + LOWERCASE_OFFSET), nil default: return "", fmt.Errorf("%d is not a valid integer in the range of base %d", ord, BASE) } } func Decode(str string) (int, error) { sum := 0 for i, c := range reverse(str) { if d, err := char2ord(string(c)); err == nil { sum = sum + d*int(math.Pow(BASE, float64(i))) } else { return -1, err } } return sum, nil } func Encode(digits int) (string, error) { if digits == 0 { return "0", nil } str := "" for digits >= 0 { remainder := digits % BASE if s, err := ord2char(remainder); err != nil { return "", err } else { str = s + str } if digits == 0 { break } digits = int(digits / BASE) } return str, nil } func main() { var decode bool app := cli.NewApp() app.Name = "Base62Convertor" app.Usage = "Encode digits to short strings or decode short strings to digits" app.Flags = []cli.Flag{ cli.BoolFlag{ Name: "decode, d", Usage: "Use decode function", Destination: &decode, }, } app.Action = func(c *cli.Context) error { for _, arg := range c.Args() { if decode { if d, err := Decode(arg); err != nil { return err } else { fmt.Printf("Decode: %s => %d\n", arg, d) } } else { d, err := strconv.Atoi(arg) if err != nil { return err } if s, err := Encode(d); err != nil { return err } else { fmt.Printf("Encode: %s => %s\n", arg, s) } } } return nil } err := app.Run(os.Args) if err != nil { log.Fatal(err) } }