diff -r b31e71644fa8 .idea/ant.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/ant.xml Wed Dec 18 21:22:47 2013 -0800
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff -r b31e71644fa8 .idea/libraries/dist.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/dist.xml Wed Dec 18 21:22:47 2013 -0800
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r b31e71644fa8 .idea/libraries/extlibs.xml
--- a/.idea/libraries/extlibs.xml Mon Dec 02 08:25:56 2013 +0000
+++ b/.idea/libraries/extlibs.xml Wed Dec 18 21:22:47 2013 -0800
@@ -8,12 +8,10 @@
-
-
@@ -22,7 +20,6 @@
-
@@ -40,6 +37,13 @@
+
+
+
+
+
+
+
diff -r b31e71644fa8 .idea/libraries/extlibs2.xml
--- a/.idea/libraries/extlibs2.xml Mon Dec 02 08:25:56 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff -r b31e71644fa8 .idea/libraries/jar.xml
--- a/.idea/libraries/jar.xml Mon Dec 02 08:25:56 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff -r b31e71644fa8 .idea/libraries/svnant_jars.xml
--- a/.idea/libraries/svnant_jars.xml Mon Dec 02 08:25:56 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff -r b31e71644fa8 .idea/libraries/test.xml
--- a/.idea/libraries/test.xml Mon Dec 02 08:25:56 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff -r b31e71644fa8 Jython27.iml
--- a/Jython27.iml Mon Dec 02 08:25:56 2013 +0000
+++ b/Jython27.iml Wed Dec 18 21:22:47 2013 -0800
@@ -17,6 +17,7 @@
+
diff -r b31e71644fa8 Lib/test/test_str_jy.py
--- a/Lib/test/test_str_jy.py Mon Dec 02 08:25:56 2013 +0000
+++ b/Lib/test/test_str_jy.py Wed Dec 18 21:22:47 2013 -0800
@@ -53,6 +53,11 @@
self.assertEquals("%+f" % -5, "-5.000000")
self.assertEquals("%+f" % 5, "+5.000000")
+ def test_format_issue2075(self):
+ self.assertEquals("%#018x" % 14, "0x000000000000000e")
+ self.assertEquals("{:#018x}".format(14), "0x000000000000000e")
+ self.assertEquals("{:+#018X}".format(14), "+0X00000000000000E")
+ self.assertEquals("{:#018X}".format(-14), "-0X00000000000000E")
def test_argument_count_exception(self):
"exception thrown when too many or too few arguments for format string"
diff -r b31e71644fa8 src/org/python/core/PyInteger.java
--- a/src/org/python/core/PyInteger.java Mon Dec 02 08:25:56 2013 +0000
+++ b/src/org/python/core/PyInteger.java Wed Dec 18 21:22:47 2013 -0800
@@ -38,6 +38,8 @@
@Deprecated
public static final BigInteger maxInt = MAX_INT;
+ private static final String LOOKUP = "0123456789abcdef";
+
private final int value;
public PyInteger(PyType subType, int v) {
@@ -1047,6 +1049,7 @@
if (spec.precision != -1) {
throw new IllegalArgumentException("Precision not allowed in integer format specifier");
}
+
int sign;
if (value instanceof Integer) {
int intValue = (Integer) value;
@@ -1054,7 +1057,11 @@
} else {
sign = ((BigInteger) value).signum();
}
+
String strValue;
+ String strPrefix = "";
+ String strSign = "";
+
if (spec.type == 'c') {
if (spec.sign != '\0') {
throw new IllegalArgumentException("Sign not allowed with integer format "
@@ -1090,13 +1097,26 @@
format.setGroupingUsed(true);
strValue = format.format(value);
} else if (value instanceof BigInteger) {
- strValue = ((BigInteger) value).toString(radix);
+ switch (radix) {
+ case 2:
+ strValue = toBinString((BigInteger) value);
+ break;
+ case 8:
+ strValue = toOctString((BigInteger) value);
+ break;
+ case 16:
+ strValue = toHexString((BigInteger) value);
+ break;
+ default:
+ // TODO: emulate CPython's _PyLong_Format() for efficiency
+ strValue = ((BigInteger) value).toString(radix);
+ break;
+ }
} else {
strValue = Integer.toString((Integer) value, radix);
}
if (spec.alternate) {
- String strPrefix = "";
switch (radix) {
case 2:
strPrefix = "0b";
@@ -1109,32 +1129,145 @@
break;
}
- if (strValue.startsWith("-")) {
- //assert (sign < 0);
- if (!strPrefix.equals(""))
- strValue = "-" + strPrefix + strValue.substring(1, strValue.length());
- } else {
- strValue = strPrefix + strValue;
+ if (sign < 0) {
+ assert (strValue.startsWith("-"));
+ strSign = "-";
+ strValue = strValue.substring(1);
}
}
if (spec.type == 'X') {
+ strPrefix = strPrefix.toUpperCase();
strValue = strValue.toUpperCase();
}
if (sign >= 0) {
- if (spec.sign == '+') {
- strValue = "+" + strValue;
- } else if (spec.sign == ' ') {
- strValue = " " + strValue;
+ switch (spec.sign) {
+ case '+':
+ case ' ':
+ strSign = Character.toString(spec.sign);
+ break;
}
}
}
- if (spec.align == '=' && (sign < 0 || spec.sign == '+' || spec.sign == ' ')) {
- char signChar = strValue.charAt(0);
- return signChar + spec.pad(strValue.substring(1), '>', 1);
+
+ if (spec.align == '=' && (spec.sign == '-' || spec.sign == '+' || spec.sign == ' ')) {
+ assert (strSign.length() == 1);
+ return strSign + strPrefix + spec.pad(strValue, '>', 1 + strPrefix.length());
}
- return spec.pad(strValue, '>', 0);
+
+ if (spec.fill_char == 0) {
+ return spec.pad(strSign + strPrefix + strValue, '>', 0);
+ }
+
+ return strSign + strPrefix + spec.pad(strValue, '>', strSign.length() + strPrefix.length());
+ }
+
+ /**
+ * A more efficient algorithm for generating a hexadecimal representation of a byte array.
+ * {@link BigInteger#toString(int)} is too slow because it generalizes to any radix and, consequently,
+ * is implemented using expensive mathematical operations.
+ *
+ * @param value the value to generate a hexadecimal string from
+ * @return the hexadecimal representation of value, with "-" sign prepended if necessary
+ */
+ static final String toHexString(BigInteger value) {
+ int signum = value.signum();
+
+ // obvious shortcut
+ if (signum == 0) {
+ return "0";
+ }
+
+ // we want to work in absolute numeric value (negative sign is added afterward)
+ byte[] input = value.abs().toByteArray();
+ StringBuilder sb = new StringBuilder(input.length * 2);
+
+ int b;
+ for (int i = 0; i < input.length; i++) {
+ b = input[i] & 0xFF;
+ sb.append(LOOKUP.charAt(b >> 4));
+ sb.append(LOOKUP.charAt(b & 0x0F));
+ }
+
+ // before returning the char array as string, remove leading zeroes, but not the last one
+ String result = sb.toString().replaceFirst("^0+(?!$)", "");
+ return signum < 0 ? "-" + result : result;
+ }
+
+ /**
+ * A more efficient algorithm for generating an octal representation of a byte array.
+ * {@link BigInteger#toString(int)} is too slow because it generalizes to any radix and, consequently,
+ * is implemented using expensive mathematical operations.
+ *
+ * @param value the value to generate an octal string from
+ * @return the octal representation of value, with "-" sign prepended if necessary
+ */
+ static final String toOctString(BigInteger value) {
+ int signum = value.signum();
+
+ // obvious shortcut
+ if (signum == 0) {
+ return "0";
+ }
+
+ byte[] input = value.abs().toByteArray();
+ if (input.length < 3) {
+ return value.toString(8);
+ }
+
+ StringBuilder sb = new StringBuilder(input.length * 3);
+
+ // working backwards, three bytes at a time
+ int threebytes;
+ int trip1, trip2, trip3; // respectively: most, middle, and least significant bytes in the triplet
+ for (int i = input.length - 1; i >= 0; i -= 3) {
+ trip3 = input[i] & 0xFF;
+ trip2 = ((i - 1) >= 0) ? (input[i - 1] & 0xFF) : 0x00;
+ trip1 = ((i - 2) >= 0) ? (input[i - 2] & 0xFF) : 0x00;
+ threebytes = trip3 | (trip2 << 8) | (trip1 << 16);
+
+ // convert the three-byte value into an eight-character octal string
+ for (int j = 0; j < 8; j++) {
+ sb.append(LOOKUP.charAt((threebytes >> (j * 3)) & 0x000007));
+ }
+ }
+
+ String result = sb.reverse().toString().replaceFirst("^0+(?!%)", "");
+ return signum < 0 ? "-" + result : result;
+ }
+
+ /**
+ * A more efficient algorithm for generating a binary representation of a byte array.
+ * {@link BigInteger#toString(int)} is too slow because it generalizes to any radix and, consequently,
+ * is implemented using expensive mathematical operations.
+ *
+ * @param value the value to generate a binary string from
+ * @return the binary representation of value, with "-" sign prepended if necessary
+ */
+ static final String toBinString(BigInteger value) {
+ int signum = value.signum();
+
+ // obvious shortcut
+ if (signum == 0) {
+ return "0";
+ }
+
+ // we want to work in absolute numeric value (negative sign is added afterward)
+ byte[] input = value.abs().toByteArray();
+ StringBuilder sb = new StringBuilder(value.bitCount());
+
+ int b;
+ for (int i = 0; i < input.length; i++) {
+ b = input[i] & 0xFF;
+ for (int bit = 7; bit >= 0; bit--) {
+ sb.append(((b >> bit) & 0x1) > 0 ? "1" : "0");
+ }
+ }
+
+ // before returning the char array as string, remove leading zeroes, but not the last one
+ String result = sb.toString().replaceFirst("^0+(?!$)", "");
+ return signum < 0 ? "-" + result : result;
}
@Override