Skip to content

Commit

Permalink
added functions for parsing from base, tests
Browse files Browse the repository at this point in the history
  • Loading branch information
david-littlefarmer committed Sep 25, 2024
1 parent c416b78 commit 894189f
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 7 deletions.
55 changes: 51 additions & 4 deletions lib/prototyp/bigint.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,20 @@ func NewBigInt(n int64) BigInt {
return BigInt(*b)
}

// Decimal number string
func NewBigIntFromNumberString(hs string) BigInt {
return NewBigIntFromDecimalString(hs)
}

func NewBigIntFromBinaryString(hs string) BigInt {
return NewBigIntFromString(hs, 2)
}

func NewBigIntFromOctalString(hs string) BigInt {
return NewBigIntFromString(hs, 8)
}

func NewBigIntFromDecimalString(hs string) BigInt {
return NewBigIntFromString(hs, 10)
}

Expand All @@ -30,11 +43,16 @@ func NewBigIntFromHexString(hs string) BigInt {

func NewBigIntFromString(s string, base int) BigInt {
b := big.NewInt(0)
if base != 0 && (2 > base || base > big.MaxBase) {
return BigInt{}
}

b, ok := b.SetString(s, base)
if !ok {
n, _ := ParseNumberString(s, base)
b = big.NewInt(n)
}

return BigInt(*b)
}

Expand Down Expand Up @@ -228,29 +246,58 @@ func (b *BigInt) UnmarshalBinary(buff []byte) error {

func ParseNumberString(s string, base int) (int64, bool) {
var ns strings.Builder
if base == 10 {
switch base {
case 2:
for _, char := range s {
// 0-9 || B || b
if (char >= 48 && char <= 57) || char == 45 || char == 66 || char == 98 {
ns.WriteRune(char)
}
}
s = ns.String()
s = strings.TrimPrefix(s, "0B")
s = strings.TrimPrefix(s, "0b")

case 8:
for _, char := range s {
// 0-9 || O || o
if (char >= 48 && char <= 57) || char == 79 || char == 111 {
ns.WriteRune(char)
}
}
s = ns.String()
s = strings.TrimPrefix(s, "0O")
s = strings.TrimPrefix(s, "0o")

case 10:
for _, char := range s {
// 0-9
if char >= 48 && char <= 57 {
ns.WriteRune(char)
}
}
s = ns.String()
} else if base == 16 {

case 16:
for _, char := range s {
if (char >= 48 && char <= 57) || (char == 120) || (char >= 65 && char <= 70) || (char >= 97 && char <= 102) {
// 0-9 || A-Z || a-z || X || x
if (char >= 48 && char <= 57) || (char >= 65 && char <= 70) || (char >= 97 && char <= 102) || char == 88 || char == 120 {
ns.WriteRune(char)
}
}

s = ns.String()
s = strings.TrimPrefix(s, "0X")
s = strings.TrimPrefix(s, "0x")
} else {
default:
return 0, false
}

n, err := strconv.ParseInt(s, base, 64)
if err != nil {
return 0, false
}

return n, true
}

Expand Down
50 changes: 47 additions & 3 deletions lib/prototyp/bigint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package prototyp

import (
"encoding/json"
"fmt"
"math/big"
"testing"

Expand Down Expand Up @@ -58,6 +57,46 @@ func TestBigIntScan(t *testing.T) {
assert.Error(t, b.Scan("1."))
}

func TestBigIntFromBaseString(t *testing.T) {
testCases := []struct {
fn func(string) BigInt
input string
expected int64
testName string
}{
// Binary tests
{NewBigIntFromBinaryString, "00101010", 42, "Binary 42"},
{NewBigIntFromBinaryString, "-00101010", -42, "Binary -42"},
{NewBigIntFromBinaryString, "0B00101010", 42, "Binary with 0B 42"},
{NewBigIntFromBinaryString, "0b00101010", 42, "Binary with 0b 42"},

// Octal tests
{NewBigIntFromOctalString, "52", 42, "Octal 42"},
{NewBigIntFromOctalString, "-52", -42, "Octal -42"},
{NewBigIntFromOctalString, "0O52", 42, "Octal with 0O 42"},
{NewBigIntFromOctalString, "0o52", 42, "Octal with 0o 42"},

// Decimal tests
{NewBigIntFromDecimalString, "42", 42, "Decimal 42"},
{NewBigIntFromDecimalString, "-42", -42, "Decimal -42"},

// Hexadecimal tests
{NewBigIntFromHexString, "2A", 42, "Hex 2A"},
{NewBigIntFromHexString, "2a", 42, "Hex 2a"},
{NewBigIntFromHexString, "-2A", -42, "Hex -2A"},
{NewBigIntFromHexString, "-2a", -42, "Hex -2a"},
{NewBigIntFromHexString, "0x2a", 42, "Hex with 0x 42"},
{NewBigIntFromHexString, "0X2a", 42, "Hex with 0X 42"},
}

for _, tc := range testCases {
t.Run(tc.testName, func(t *testing.T) {
b := tc.fn(tc.input)
assert.Equal(t, tc.expected, b.Int64())
})
}
}

func TestBigIntInvalidInput(t *testing.T) {
b := NewBigIntFromNumberString("1234")
assert.Equal(t, int64(1234), b.Int64())
Expand All @@ -69,12 +108,17 @@ func TestBigIntInvalidInput(t *testing.T) {
// if invalid, it will parse out the number
b = NewBigIntFromHexString("/0xaBc-$$2Efg")
assert.Equal(t, int64(0xaBc2Ef), b.Int64())

// should return 0, since base is not valid
b = NewBigIntFromString("1234", 666)
assert.Equal(t, int64(0), b.Int64())
}

func TestBigIntCopy(t *testing.T) {
a := ToBigInt(big.NewInt(1))
b := ToBigInt(a.Int())
a.Sub(big.NewInt(1))
fmt.Println(a.String())
fmt.Println(b.String())

assert.Equal(t, int64(0), a.Int64())
assert.Equal(t, int64(1), b.Int64())
}

0 comments on commit 894189f

Please sign in to comment.