Skip to content

Commit bd13450

Browse files
wetorsbinet
authored andcommitted
builtin: implement oct and optimise hex
1 parent 32f9086 commit bd13450

File tree

2 files changed

+70
-7
lines changed

2 files changed

+70
-7
lines changed

stdlib/builtin/builtin.go

+64-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package builtin
88
import (
99
"fmt"
1010
"math/big"
11+
"strconv"
1112
"unicode/utf8"
1213

1314
"github.com/go-python/gpython/compile"
@@ -53,7 +54,7 @@ func init() {
5354
py.MustNewMethod("min", builtin_min, 0, min_doc),
5455
py.MustNewMethod("next", builtin_next, 0, next_doc),
5556
py.MustNewMethod("open", builtin_open, 0, open_doc),
56-
// py.MustNewMethod("oct", builtin_oct, 0, oct_doc),
57+
py.MustNewMethod("oct", builtin_oct, 0, oct_doc),
5758
py.MustNewMethod("ord", builtin_ord, 0, ord_doc),
5859
py.MustNewMethod("pow", builtin_pow, 0, pow_doc),
5960
py.MustNewMethod("print", builtin_print, 0, print_doc),
@@ -592,6 +593,56 @@ func builtin_open(self py.Object, args py.Tuple, kwargs py.StringDict) (py.Objec
592593
int(buffering.(py.Int)))
593594
}
594595

596+
const oct_doc = `oct(number) -> string
597+
598+
Return the octal representation of an integer.
599+
600+
>>> oct(342391)
601+
'0o1234567'
602+
`
603+
604+
func builtin_oct(self, v py.Object) (py.Object, error) {
605+
var (
606+
i int64
607+
err error
608+
)
609+
switch v := v.(type) {
610+
case *py.BigInt:
611+
vv := (*big.Int)(v)
612+
neg := false
613+
if vv.Cmp(big.NewInt(0)) == -1 {
614+
neg = true
615+
}
616+
str := vv.Text(8)
617+
if neg {
618+
str = "-0o" + str[1:]
619+
} else {
620+
str = "0o" + str
621+
}
622+
return py.String(str), nil
623+
case py.IGoInt64:
624+
i, err = v.GoInt64()
625+
case py.IGoInt:
626+
var vv int
627+
vv, err = v.GoInt()
628+
i = int64(vv)
629+
default:
630+
return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", v.Type().Name)
631+
}
632+
633+
if err != nil {
634+
return nil, err
635+
}
636+
637+
str := strconv.FormatInt(i, 8)
638+
if i < 0 {
639+
str = "-0o" + str[1:]
640+
} else {
641+
str = "0o" + str
642+
}
643+
return py.String(str), nil
644+
}
645+
595646
const ord_doc = `ord(c) -> integer
596647
597648
Return the integer ordinal of a one-character string.`
@@ -865,11 +916,16 @@ func builtin_hex(self, v py.Object) (py.Object, error) {
865916
// test bigint first to make sure we correctly handle the case
866917
// where int64 isn't large enough.
867918
vv := (*big.Int)(v)
868-
format := "%#x"
919+
neg := false
869920
if vv.Cmp(big.NewInt(0)) == -1 {
870-
format = "%+#x"
921+
neg = true
922+
}
923+
str := vv.Text(16)
924+
if neg {
925+
str = "-0x" + str[1:]
926+
} else {
927+
str = "0x" + str
871928
}
872-
str := fmt.Sprintf(format, vv)
873929
return py.String(str), nil
874930
case py.IGoInt64:
875931
i, err = v.GoInt64()
@@ -885,11 +941,12 @@ func builtin_hex(self, v py.Object) (py.Object, error) {
885941
return nil, err
886942
}
887943

888-
format := "%#x"
944+
str := strconv.FormatInt(i, 16)
889945
if i < 0 {
890-
format = "%+#x"
946+
str = "-0x" + str[1:]
947+
} else {
948+
str = "0x" + str
891949
}
892-
str := fmt.Sprintf(format, i)
893950
return py.String(str), nil
894951
}
895952

stdlib/builtin/tests/builtin.py

+6
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,12 @@ def gen2():
275275
ok = True
276276
assert ok, "ValueError not raised"
277277

278+
doc="oct"
279+
assert oct(0) == '0o0'
280+
assert oct(100) == '0o144'
281+
assert oct(-100) == '-0o144'
282+
assertRaises(TypeError, oct, ())
283+
278284
doc="ord"
279285
assert 65 == ord("A")
280286
assert 163 == ord("£")

0 commit comments

Comments
 (0)