[pypy-svn] r42214 - in pypy/branch/pypy-string-formatting/rlib: . test

arigo at codespeak.net arigo at codespeak.net
Fri Apr 20 18:33:17 CEST 2007


Author: arigo
Date: Fri Apr 20 18:33:16 2007
New Revision: 42214

Modified:
   pypy/branch/pypy-string-formatting/rlib/rbigint.py
   pypy/branch/pypy-string-formatting/rlib/test/test_rbigint.py
Log:
Clean up and generalize the string formatting routine of rbigint.


Modified: pypy/branch/pypy-string-formatting/rlib/rbigint.py
==============================================================================
--- pypy/branch/pypy-string-formatting/rlib/rbigint.py	(original)
+++ pypy/branch/pypy-string-formatting/rlib/rbigint.py	Fri Apr 20 18:33:16 2007
@@ -228,11 +228,16 @@
         # no matter what the sign is (two's complement)
         return a.digits[0] & 1
 
+    def format(self, digits, prefix='', suffix=''):
+        # 'digits' is a string whose length is the base to use,
+        # and where each character is the corresponding digit.
+        return _format(self, digits, prefix, suffix)
+
     def repr(self):
-        return _format(self, 10, True)
+        return _format(self, BASE10, '', 'L')
 
     def str(self):
-        return _format(self, 10, False)
+        return _format(self, BASE10)
 
     def eq(self, other):
         if (self.sign != other.sign or
@@ -526,10 +531,13 @@
         return _bitwise(self, '|', other)
 
     def oct(self):
-        return _format(self, 8, True)
+        if self.sign == 0:
+            return '0L'
+        else:
+            return _format(self, BASE8, '0', 'L')
 
     def hex(self):
-        return _format(self, 16, True)
+        return _format(self, BASE16, '0x', 'L')
 
     def log(self, base):
         # base is supposed to be positive or 0.0, which means we use e
@@ -1323,35 +1331,35 @@
     # math.ldexp checks and raises
     return ad
 
-    
 
+BASE8  = '01234567'
+BASE10 = '0123456789'
+BASE16 = '0123456789ABCDEF'
 
-def _format(a, base, addL):
+def _format(a, digits, prefix='', suffix=''):
     """
     Convert a bigint object to a string, using a given conversion base.
     Return a string object.
-    If base is 8 or 16, add the proper prefix '0' or '0x'.
     """
     size_a = len(a.digits)
 
+    base = len(digits)
     assert base >= 2 and base <= 36
 
-    sign = False
-
     # Compute a rough upper bound for the length of the string
     i = base
     bits = 0
     while i > 1:
         bits += 1
         i >>= 1
-    i = 5 + int(bool(addL)) + (size_a*SHIFT + bits-1) // bits
+    i = 5 + len(prefix) + len(suffix) + (size_a*SHIFT + bits-1) // bits
     s = [chr(0)] * i
     p = i
-    if addL:
+    j = len(suffix)
+    while j > 0:
         p -= 1
-        s[p] = 'L'
-    if a.sign < 0:
-        sign = True
+        j -= 1
+        s[p] = suffix[j]
 
     if a.sign == 0:
         p -= 1
@@ -1374,13 +1382,9 @@
             assert accumbits >= basebits
             while 1:
                 cdigit = accum & (base - 1)
-                if cdigit < 10:
-                    cdigit += ord('0')
-                else:
-                    cdigit += ord('A') - 10
-                assert p > 0
                 p -= 1
-                s[p] = chr(cdigit)
+                assert p >= 0
+                s[p] = digits[cdigit]
                 accumbits -= basebits
                 accum >>= basebits
                 if i < size_a - 1:
@@ -1421,13 +1425,9 @@
             while 1:
                 nextrem = rem // base
                 c = rem - nextrem * base
-                assert p > 0
-                if c < 10:
-                    c += ord('0')
-                else:
-                    c += ord('A') - 10
                 p -= 1
-                s[p] = chr(c)
+                assert p >= 0
+                s[p] = digits[c]
                 rem = nextrem
                 ntostore -= 1
                 # Termination is a bit delicate:  must not
@@ -1438,33 +1438,19 @@
             if size == 0:
                 break
 
-    if base == 8:
-        if a.sign != 0:
-            p -= 1
-            s[p] = '0'
-    elif base == 16:
+    j = len(prefix)
+    while j > 0:
         p -= 1
-        s[p] ='x'
-        p -= 1
-        s[p] = '0'
-    elif base != 10:
-        p -= 1
-        s[p] = '#'
-        p -= 1
-        s[p] = chr(ord('0') + base % 10)
-        if base > 10:
-            p -= 1
-            s[p] = chr(ord('0') + base // 10)
-    if sign:
+        j -= 1
+        s[p] = prefix[j]
+
+    if a.sign < 0:
         p -= 1
         s[p] = '-'
 
     assert p >= 0    # otherwise, buffer overflow (this is also a
                      # hint for the annotator for the slice below)
-    if p == 0:
-        return ''.join(s)
-    else:
-        return ''.join(s[p:])
+    return ''.join(s[p:])
 
 
 def _bitwise(a, op, b): # '&', '|', '^'

Modified: pypy/branch/pypy-string-formatting/rlib/test/test_rbigint.py
==============================================================================
--- pypy/branch/pypy-string-formatting/rlib/test/test_rbigint.py	(original)
+++ pypy/branch/pypy-string-formatting/rlib/test/test_rbigint.py	Fri Apr 20 18:33:16 2007
@@ -299,6 +299,20 @@
                     res2 = getattr(operator, mod)(x, y)
                     assert res1 == res2
 
+    def test_tostring(self):
+        z = rbigint.fromlong(0)
+        assert z.str() == '0'
+        assert z.repr() == '0L'
+        assert z.hex() == '0x0L'
+        assert z.oct() == '0L'
+        x = rbigint.fromlong(-18471379832321)
+        assert x.str() == '-18471379832321'
+        assert x.repr() == '-18471379832321L'
+        assert x.hex() == '-0x10CCB4088E01L'
+        assert x.oct() == '-0414626402107001L'
+        assert x.format('.!') == (
+            '-!....!!..!!..!.!!.!......!...!...!!!........!')
+        assert x.format('abcdefghijkl', '<<', '>>') == '-<<cakdkgdijffjf>>'
 
 
 class TestInternalFunctions(object):



More information about the Pypy-commit mailing list