Last active
October 22, 2019 19:37
-
-
Save Pagliacii/dca0f6b732c19045d258eaee81917071 to your computer and use it in GitHub Desktop.
Golang version of the base62 algorithm. Details: https://gist.github.com/bhelx/778542
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment