core: remove System.Binary.Itoa and System.Binary.Atoi syscalls
And move their tests to native StdLib.
This commit is contained in:
parent
2b90d4455f
commit
f65485b735
10 changed files with 117 additions and 241 deletions
|
@ -2,8 +2,8 @@ package timer
|
|||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/std"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||
|
@ -35,7 +35,7 @@ func _deploy(_ interface{}, isUpdate bool) {
|
|||
sh := runtime.GetCallingScriptHash()
|
||||
storage.Put(ctx, mgmtKey, sh)
|
||||
storage.Put(ctx, ticksKey, defaultTicks)
|
||||
i := binary.Itoa(defaultTicks, 10)
|
||||
i := std.Itoa(defaultTicks, 10)
|
||||
runtime.Log("Timer set to " + i + " ticks.")
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ func Tick() bool {
|
|||
return contract.Call(runtime.GetExecutingScriptHash(), "selfDestroy", contract.All).(bool)
|
||||
}
|
||||
storage.Put(ctx, ticksKey, ticksLeft)
|
||||
i := binary.Itoa(ticksLeft.(int), 10)
|
||||
i := std.Itoa(ticksLeft.(int), 10)
|
||||
runtime.Log(i + " ticks left.")
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -118,13 +118,14 @@ func TestInline(t *testing.T) {
|
|||
func TestInlineInLoop(t *testing.T) {
|
||||
t.Run("simple", func(t *testing.T) {
|
||||
src := `package foo
|
||||
import "github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
||||
import "github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline"
|
||||
func Main() int {
|
||||
sum := 0
|
||||
values := []int{10, 11}
|
||||
for _, v := range values {
|
||||
binary.Itoa(v, 10)
|
||||
_ = v // use 'v'
|
||||
storage.GetContext() // push something on stack to check it's dropped
|
||||
sum += inline.VarSum(1, 2, 3, 4)
|
||||
}
|
||||
return sum
|
||||
|
@ -133,14 +134,16 @@ func TestInlineInLoop(t *testing.T) {
|
|||
})
|
||||
t.Run("inlined argument", func(t *testing.T) {
|
||||
src := `package foo
|
||||
import "github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
||||
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||
import "github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline"
|
||||
func Main() int {
|
||||
sum := 0
|
||||
values := []int{10, 11}
|
||||
for _, v := range values {
|
||||
binary.Itoa(v, 10)
|
||||
sum += inline.VarSum(1, 2, 3, binary.Atoi("4", 10))
|
||||
_ = v // use 'v'
|
||||
storage.GetContext() // push something on stack to check it's dropped
|
||||
sum += inline.VarSum(1, 2, 3, runtime.GetTime()) // runtime.GetTime always returns 4 in these tests
|
||||
}
|
||||
return sum
|
||||
}`
|
||||
|
@ -148,12 +151,12 @@ func TestInlineInLoop(t *testing.T) {
|
|||
})
|
||||
t.Run("check clean stack on return", func(t *testing.T) {
|
||||
src := `package foo
|
||||
import "github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
||||
import "github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline"
|
||||
func Main() int {
|
||||
values := []int{10, 11, 12}
|
||||
for _, v := range values {
|
||||
binary.Itoa(v, 10)
|
||||
storage.GetContext() // push something on stack to check it's dropped
|
||||
if v == 11 {
|
||||
return inline.VarSum(2, 20, 200)
|
||||
}
|
||||
|
|
|
@ -61,13 +61,11 @@ func TestSyscallExecution(t *testing.T) {
|
|||
sigs := "[]interop.Signature{" + sig + "}"
|
||||
sctx := "storage.Context{}"
|
||||
interops := map[string]syscallTestCase{
|
||||
"binary.Atoi": {interopnames.SystemBinaryAtoi, []string{`"123"`, "10"}, false},
|
||||
"binary.Base58Decode": {interopnames.SystemBinaryBase58Decode, []string{b}, false},
|
||||
"binary.Base58Encode": {interopnames.SystemBinaryBase58Encode, []string{b}, false},
|
||||
"binary.Base64Decode": {interopnames.SystemBinaryBase64Decode, []string{b}, false},
|
||||
"binary.Base64Encode": {interopnames.SystemBinaryBase64Encode, []string{b}, false},
|
||||
"binary.Deserialize": {interopnames.SystemBinaryDeserialize, []string{b}, false},
|
||||
"binary.Itoa": {interopnames.SystemBinaryItoa, []string{"123", "10"}, false},
|
||||
"binary.Serialize": {interopnames.SystemBinarySerialize, []string{"10"}, false},
|
||||
"contract.Call": {interopnames.SystemContractCall, []string{u160, `"m"`, "1", "3"}, false},
|
||||
"contract.CreateMultisigAccount": {interopnames.SystemContractCreateMultisigAccount, []string{"1", pubs}, false},
|
||||
|
|
|
@ -3,8 +3,6 @@ package compiler_test
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -109,8 +107,7 @@ func newStoragePlugin() *storagePlugin {
|
|||
s.interops[interopnames.ToID([]byte(interopnames.SystemStoragePut))] = s.Put
|
||||
s.interops[interopnames.ToID([]byte(interopnames.SystemStorageGetContext))] = s.GetContext
|
||||
s.interops[interopnames.ToID([]byte(interopnames.SystemRuntimeNotify))] = s.Notify
|
||||
s.interops[interopnames.ToID([]byte(interopnames.SystemBinaryAtoi))] = s.Atoi
|
||||
s.interops[interopnames.ToID([]byte(interopnames.SystemBinaryItoa))] = s.Itoa
|
||||
s.interops[interopnames.ToID([]byte(interopnames.SystemRuntimeGetTime))] = s.GetTime
|
||||
return s
|
||||
|
||||
}
|
||||
|
@ -126,24 +123,6 @@ func (s *storagePlugin) syscallHandler(v *vm.VM, id uint32) error {
|
|||
return errors.New("syscall not found")
|
||||
}
|
||||
|
||||
func (s *storagePlugin) Atoi(v *vm.VM) error {
|
||||
str := v.Estack().Pop().String()
|
||||
base := v.Estack().Pop().BigInt().Int64()
|
||||
n, err := strconv.ParseInt(str, int(base), 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.Estack().PushVal(big.NewInt(n))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *storagePlugin) Itoa(v *vm.VM) error {
|
||||
n := v.Estack().Pop().BigInt()
|
||||
base := v.Estack().Pop().BigInt()
|
||||
v.Estack().PushVal(n.Text(int(base.Int64())))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *storagePlugin) Notify(v *vm.VM) error {
|
||||
name := v.Estack().Pop().String()
|
||||
item := stackitem.NewArray(v.Estack().Pop().Array())
|
||||
|
@ -185,3 +164,10 @@ func (s *storagePlugin) GetContext(vm *vm.VM) error {
|
|||
vm.Estack().PushVal(10)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *storagePlugin) GetTime(vm *vm.VM) error {
|
||||
// Pushing anything on the stack here will work. This is just to satisfy
|
||||
// the compiler, thinking it has pushed the context ^^.
|
||||
vm.Estack().PushVal(4)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
package binary
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidBase is returned when base is invalid.
|
||||
ErrInvalidBase = errors.New("invalid base")
|
||||
// ErrInvalidFormat is returned when string is not a number.
|
||||
ErrInvalidFormat = errors.New("invalid format")
|
||||
)
|
||||
|
||||
// Itoa converts number to string.
|
||||
func Itoa(ic *interop.Context) error {
|
||||
num := ic.VM.Estack().Pop().BigInt()
|
||||
base := ic.VM.Estack().Pop().BigInt()
|
||||
if !base.IsInt64() {
|
||||
return ErrInvalidBase
|
||||
}
|
||||
var s string
|
||||
switch b := base.Int64(); b {
|
||||
case 10:
|
||||
s = num.Text(10)
|
||||
case 16:
|
||||
if num.Sign() == 0 {
|
||||
s = "0"
|
||||
break
|
||||
}
|
||||
bs := bigint.ToBytes(num)
|
||||
reverse(bs)
|
||||
s = hex.EncodeToString(bs)
|
||||
if pad := bs[0] & 0xF8; pad == 0 || pad == 0xF8 {
|
||||
s = s[1:]
|
||||
}
|
||||
s = strings.ToUpper(s)
|
||||
default:
|
||||
return ErrInvalidBase
|
||||
}
|
||||
ic.VM.Estack().PushVal(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Atoi converts string to number.
|
||||
func Atoi(ic *interop.Context) error {
|
||||
num := ic.VM.Estack().Pop().String()
|
||||
base := ic.VM.Estack().Pop().BigInt()
|
||||
if !base.IsInt64() {
|
||||
return ErrInvalidBase
|
||||
}
|
||||
var bi *big.Int
|
||||
switch b := base.Int64(); b {
|
||||
case 10:
|
||||
var ok bool
|
||||
bi, ok = new(big.Int).SetString(num, int(b))
|
||||
if !ok {
|
||||
return ErrInvalidFormat
|
||||
}
|
||||
case 16:
|
||||
changed := len(num)%2 != 0
|
||||
if changed {
|
||||
num = "0" + num
|
||||
}
|
||||
bs, err := hex.DecodeString(num)
|
||||
if err != nil {
|
||||
return ErrInvalidFormat
|
||||
}
|
||||
if changed && bs[0]&0x8 != 0 {
|
||||
bs[0] |= 0xF0
|
||||
}
|
||||
reverse(bs)
|
||||
bi = bigint.FromBytes(bs)
|
||||
default:
|
||||
return ErrInvalidBase
|
||||
}
|
||||
ic.VM.Estack().PushVal(bi)
|
||||
return nil
|
||||
}
|
||||
|
||||
func reverse(b []byte) {
|
||||
l := len(b)
|
||||
for i := 0; i < l/2; i++ {
|
||||
b[i], b[l-i-1] = b[l-i-1], b[i]
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
package binary
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestItoa(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
num *big.Int
|
||||
base *big.Int
|
||||
result string
|
||||
}{
|
||||
{big.NewInt(0), big.NewInt(10), "0"},
|
||||
{big.NewInt(0), big.NewInt(16), "0"},
|
||||
{big.NewInt(1), big.NewInt(10), "1"},
|
||||
{big.NewInt(-1), big.NewInt(10), "-1"},
|
||||
{big.NewInt(1), big.NewInt(16), "1"},
|
||||
{big.NewInt(7), big.NewInt(16), "7"},
|
||||
{big.NewInt(8), big.NewInt(16), "08"},
|
||||
{big.NewInt(65535), big.NewInt(16), "0FFFF"},
|
||||
{big.NewInt(15), big.NewInt(16), "0F"},
|
||||
{big.NewInt(-1), big.NewInt(16), "F"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ic := &interop.Context{VM: vm.New()}
|
||||
ic.VM.Estack().PushVal(tc.base)
|
||||
ic.VM.Estack().PushVal(tc.num)
|
||||
require.NoError(t, Itoa(ic))
|
||||
require.Equal(t, tc.result, ic.VM.Estack().Pop().String())
|
||||
|
||||
ic = &interop.Context{VM: vm.New()}
|
||||
ic.VM.Estack().PushVal(tc.base)
|
||||
ic.VM.Estack().PushVal(tc.result)
|
||||
|
||||
require.NoError(t, Atoi(ic))
|
||||
require.Equal(t, tc.num, ic.VM.Estack().Pop().BigInt())
|
||||
}
|
||||
|
||||
t.Run("-1", func(t *testing.T) {
|
||||
for _, s := range []string{"FF", "FFF", "FFFF"} {
|
||||
ic := &interop.Context{VM: vm.New()}
|
||||
ic.VM.Estack().PushVal(16)
|
||||
ic.VM.Estack().PushVal(s)
|
||||
|
||||
require.NoError(t, Atoi(ic))
|
||||
require.Equal(t, big.NewInt(-1), ic.VM.Estack().Pop().BigInt())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestItoaError(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
num *big.Int
|
||||
base *big.Int
|
||||
err error
|
||||
}{
|
||||
{big.NewInt(1), big.NewInt(13), ErrInvalidBase},
|
||||
{big.NewInt(-1), new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(10)), ErrInvalidBase},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ic := &interop.Context{VM: vm.New()}
|
||||
ic.VM.Estack().PushVal(tc.base)
|
||||
ic.VM.Estack().PushVal(tc.num)
|
||||
err := Itoa(ic)
|
||||
require.True(t, errors.Is(err, tc.err), "got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAtoiError(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
num string
|
||||
base *big.Int
|
||||
err error
|
||||
}{
|
||||
{"1", big.NewInt(13), ErrInvalidBase},
|
||||
{"1", new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(16)), ErrInvalidBase},
|
||||
{"1_000", big.NewInt(10), ErrInvalidFormat},
|
||||
{"FE", big.NewInt(10), ErrInvalidFormat},
|
||||
{"XD", big.NewInt(16), ErrInvalidFormat},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
ic := &interop.Context{VM: vm.New()}
|
||||
ic.VM.Estack().PushVal(tc.base)
|
||||
ic.VM.Estack().PushVal(tc.num)
|
||||
err := Atoi(ic)
|
||||
require.True(t, errors.Is(err, tc.err), "got: %v", err)
|
||||
}
|
||||
}
|
|
@ -2,13 +2,11 @@ package interopnames
|
|||
|
||||
// Names of all used interops.
|
||||
const (
|
||||
SystemBinaryAtoi = "System.Binary.Atoi"
|
||||
SystemBinaryBase58Decode = "System.Binary.Base58Decode"
|
||||
SystemBinaryBase58Encode = "System.Binary.Base58Encode"
|
||||
SystemBinaryBase64Decode = "System.Binary.Base64Decode"
|
||||
SystemBinaryBase64Encode = "System.Binary.Base64Encode"
|
||||
SystemBinaryDeserialize = "System.Binary.Deserialize"
|
||||
SystemBinaryItoa = "System.Binary.Itoa"
|
||||
SystemBinarySerialize = "System.Binary.Serialize"
|
||||
SystemCallbackCreate = "System.Callback.Create"
|
||||
SystemCallbackCreateFromMethod = "System.Callback.CreateFromMethod"
|
||||
|
@ -54,13 +52,11 @@ const (
|
|||
)
|
||||
|
||||
var names = []string{
|
||||
SystemBinaryAtoi,
|
||||
SystemBinaryBase58Decode,
|
||||
SystemBinaryBase58Encode,
|
||||
SystemBinaryBase64Decode,
|
||||
SystemBinaryBase64Encode,
|
||||
SystemBinaryDeserialize,
|
||||
SystemBinaryItoa,
|
||||
SystemBinarySerialize,
|
||||
SystemCallbackCreate,
|
||||
SystemCallbackCreateFromMethod,
|
||||
|
|
|
@ -32,13 +32,11 @@ func SpawnVM(ic *interop.Context) *vm.VM {
|
|||
|
||||
// All lists are sorted, keep 'em this way, please.
|
||||
var systemInterops = []interop.Function{
|
||||
{Name: interopnames.SystemBinaryAtoi, Func: binary.Atoi, Price: 1 << 12, ParamCount: 2},
|
||||
{Name: interopnames.SystemBinaryBase58Decode, Func: binary.DecodeBase58, Price: 1 << 12, ParamCount: 1},
|
||||
{Name: interopnames.SystemBinaryBase58Encode, Func: binary.EncodeBase58, Price: 1 << 12, ParamCount: 1},
|
||||
{Name: interopnames.SystemBinaryBase64Decode, Func: binary.DecodeBase64, Price: 1 << 12, ParamCount: 1},
|
||||
{Name: interopnames.SystemBinaryBase64Encode, Func: binary.EncodeBase64, Price: 1 << 12, ParamCount: 1},
|
||||
{Name: interopnames.SystemBinaryDeserialize, Func: binary.Deserialize, Price: 1 << 14, ParamCount: 1},
|
||||
{Name: interopnames.SystemBinaryItoa, Func: binary.Itoa, Price: 1 << 12, ParamCount: 2},
|
||||
{Name: interopnames.SystemBinarySerialize, Func: binary.Serialize, Price: 1 << 12, ParamCount: 1},
|
||||
{Name: interopnames.SystemContractCall, Func: contract.Call, Price: 1 << 15,
|
||||
RequiredFlags: callflag.ReadStates | callflag.AllowCall, ParamCount: 4},
|
||||
|
|
96
pkg/core/native/std_test.go
Normal file
96
pkg/core/native/std_test.go
Normal file
|
@ -0,0 +1,96 @@
|
|||
package native
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestStdLibItoaAtoi(t *testing.T) {
|
||||
s := newStd()
|
||||
ic := &interop.Context{VM: vm.New()}
|
||||
var actual stackitem.Item
|
||||
|
||||
t.Run("itoa-atoi", func(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
num *big.Int
|
||||
base *big.Int
|
||||
result string
|
||||
}{
|
||||
{big.NewInt(0), big.NewInt(10), "0"},
|
||||
{big.NewInt(0), big.NewInt(16), "0"},
|
||||
{big.NewInt(1), big.NewInt(10), "1"},
|
||||
{big.NewInt(-1), big.NewInt(10), "-1"},
|
||||
{big.NewInt(1), big.NewInt(16), "1"},
|
||||
{big.NewInt(7), big.NewInt(16), "7"},
|
||||
{big.NewInt(8), big.NewInt(16), "08"},
|
||||
{big.NewInt(65535), big.NewInt(16), "0FFFF"},
|
||||
{big.NewInt(15), big.NewInt(16), "0F"},
|
||||
{big.NewInt(-1), big.NewInt(16), "F"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
require.NotPanics(t, func() {
|
||||
actual = s.itoa(ic, []stackitem.Item{stackitem.Make(tc.num), stackitem.Make(tc.base)})
|
||||
})
|
||||
require.Equal(t, stackitem.Make(tc.result), actual)
|
||||
|
||||
require.NotPanics(t, func() {
|
||||
actual = s.atoi(ic, []stackitem.Item{stackitem.Make(tc.result), stackitem.Make(tc.base)})
|
||||
})
|
||||
require.Equal(t, stackitem.Make(tc.num), actual)
|
||||
}
|
||||
|
||||
t.Run("-1", func(t *testing.T) {
|
||||
for _, str := range []string{"FF", "FFF", "FFFF"} {
|
||||
require.NotPanics(t, func() {
|
||||
actual = s.atoi(ic, []stackitem.Item{stackitem.Make(str), stackitem.Make(16)})
|
||||
})
|
||||
|
||||
require.Equal(t, stackitem.Make(-1), actual)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("itoa error", func(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
num *big.Int
|
||||
base *big.Int
|
||||
err error
|
||||
}{
|
||||
{big.NewInt(1), big.NewInt(13), ErrInvalidBase},
|
||||
{big.NewInt(-1), new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(10)), ErrInvalidBase},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
require.PanicsWithError(t, tc.err.Error(), func() {
|
||||
_ = s.itoa(ic, []stackitem.Item{stackitem.Make(tc.num), stackitem.Make(tc.base)})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("atoi error", func(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
num string
|
||||
base *big.Int
|
||||
err error
|
||||
}{
|
||||
{"1", big.NewInt(13), ErrInvalidBase},
|
||||
{"1", new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(16)), ErrInvalidBase},
|
||||
{"1_000", big.NewInt(10), ErrInvalidFormat},
|
||||
{"FE", big.NewInt(10), ErrInvalidFormat},
|
||||
{"XD", big.NewInt(16), ErrInvalidFormat},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
require.PanicsWithError(t, tc.err.Error(), func() {
|
||||
_ = s.atoi(ic, []stackitem.Item{stackitem.Make(tc.num), stackitem.Make(tc.base)})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
|
@ -44,15 +44,3 @@ func Base58Encode(b []byte) string {
|
|||
func Base58Decode(b []byte) []byte {
|
||||
return neogointernal.Syscall1("System.Binary.Base58Decode", b).([]byte)
|
||||
}
|
||||
|
||||
// Itoa converts num in a given base to string. Base should be either 10 or 16.
|
||||
// It uses `System.Binary.Itoa` syscall.
|
||||
func Itoa(num int, base int) string {
|
||||
return neogointernal.Syscall2("System.Binary.Itoa", num, base).(string)
|
||||
}
|
||||
|
||||
// Atoi converts string to a number in a given base. Base should be either 10 or 16.
|
||||
// It uses `System.Binary.Atoi` syscall.
|
||||
func Atoi(s string, base int) int {
|
||||
return neogointernal.Syscall2("System.Binary.Atoi", s, base).(int)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue