/*
* Copyright (c) Corporation for National Research Initiatives
* Copyright (c) Jython Developers
*/
package org.python.core;
import java.io.Serializable;
import java.math.BigInteger;
import org.python.core.stringlib.InternalFormatSpec;
import org.python.core.stringlib.InternalFormatSpecParser;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
import org.python.expose.MethodType;
/**
* A builtin python int.
*/
@ExposedType(name = "int", doc = BuiltinDocs.int_doc)
public class PyInteger extends PyObject {
public static final PyType TYPE = PyType.fromClass(PyInteger.class);
/** The minimum value of an int represented by a BigInteger */
public static final BigInteger MIN_INT = BigInteger.valueOf(Integer.MIN_VALUE);
/** The maximum value of an int represented by a BigInteger */
public static final BigInteger MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE);
/** @deprecated Use MIN_INT instead. */
@Deprecated
public static final BigInteger minInt = MIN_INT;
/** @deprecated Use MAX_INT instead. */
@Deprecated
public static final BigInteger maxInt = MAX_INT;
private final int value;
public PyInteger(PyType subType, int v) {
super(subType);
value = v;
}
public PyInteger(int v) {
this(TYPE, v);
}
@ExposedNew
public static PyObject int_new(PyNewWrapper new_, boolean init, PyType subtype,
PyObject[] args, String[] keywords) {
ArgParser ap = new ArgParser("int", args, keywords, new String[] {"x", "base"}, 0);
PyObject x = ap.getPyObject(0, null);
int base = ap.getInt(1, -909);
if (new_.for_type == subtype) {
if (x == null) {
return Py.Zero;
}
if (base == -909) {
if (x instanceof PyBoolean) {
return (coerce(x) == 0) ? Py.Zero : Py.One;
}
return asPyInteger(x);
}
if (!(x instanceof PyString)) {
throw Py.TypeError("int: can't convert non-string with explicit base");
}
try {
return Py.newInteger(((PyString) x).atoi(base));
} catch (PyException pye) {
if (pye.match(Py.OverflowError)) {
return ((PyString) x).atol(base);
}
throw pye;
}
} else {
if (x == null) {
return new PyIntegerDerived(subtype, 0);
}
if (base == -909) {
PyObject intOrLong = asPyInteger(x);
if (intOrLong instanceof PyInteger) {
return new PyIntegerDerived(subtype, ((PyInteger) intOrLong).getValue());
} else {
throw Py.OverflowError("long int too large to convert to int");
}
}
if (!(x instanceof PyString)) {
throw Py.TypeError("int: can't convert non-string with explicit base");
}
return new PyIntegerDerived(subtype, ((PyString) x).atoi(base));
}
} // xxx
/**
* @return the result of x.__int__
* @throws Py.Type error if x.__int__ throws an Py.AttributeError
*/
private static PyObject asPyInteger(PyObject x) {
try {
return x.__int__();
} catch (PyException pye) {
if (!pye.match(Py.AttributeError)) {
throw pye;
}
throw Py.TypeError("int() argument must be a string or a number");
}
}
@ExposedGet(name = "real", doc = BuiltinDocs.int_real_doc)
public PyObject getReal() {
return int___int__();
}
@ExposedGet(name = "imag", doc = BuiltinDocs.int_imag_doc)
public PyObject getImag() {
return Py.newInteger(0);
}
@ExposedGet(name = "numerator", doc = BuiltinDocs.int_numerator_doc)
public PyObject getNumerator() {
return int___int__();
}
@ExposedGet(name = "denominator", doc = BuiltinDocs.int_denominator_doc)
public PyObject getDenominator() {
return Py.newInteger(1);
}
public int getValue() {
return value;
}
@Override
public String toString() {
return int_toString();
}
// XXX: need separate __doc__ for __repr__
@ExposedMethod(names = {"__str__", "__repr__"}, doc = BuiltinDocs.int___str___doc)
final String int_toString() {
return Integer.toString(getValue());
}
@Override
public int hashCode() {
return int_hashCode();
}
@ExposedMethod(names = "__hash__", doc = BuiltinDocs.int___hash___doc)
final int int_hashCode() {
return getValue();
}
@Override
public boolean __nonzero__() {
return int___nonzero__();
}
@ExposedMethod(doc = BuiltinDocs.int___nonzero___doc)
final boolean int___nonzero__() {
return getValue() != 0;
}
@Override
public Object __tojava__(Class<?> c) {
if (c == Integer.TYPE || c == Number.class || c == Object.class || c == Integer.class
|| c == Serializable.class) {
return new Integer(getValue());
}
if (c == Boolean.TYPE || c == Boolean.class) {
return new Boolean(getValue() != 0);
}
if (c == Byte.TYPE || c == Byte.class) {
return new Byte((byte) getValue());
}
if (c == Short.TYPE || c == Short.class) {
return new Short((short) getValue());
}
if (c == Long.TYPE || c == Long.class) {
return new Long(getValue());
}
if (c == Float.TYPE || c == Float.class) {
return new Float(getValue());
}
if (c == Double.TYPE || c == Double.class) {
return new Double(getValue());
}
return super.__tojava__(c);
}
@Override
public int __cmp__(PyObject other) {
return int___cmp__(other);
}
@ExposedMethod(type = MethodType.CMP, doc = BuiltinDocs.int___cmp___doc)
final int int___cmp__(PyObject other) {
if (!canCoerce(other)) {
return -2;
}
int v = coerce(other);
return getValue() < v ? -1 : getValue() > v ? 1 : 0;
}
@Override
public Object __coerce_ex__(PyObject other) {
return int___coerce_ex__(other);
}
@ExposedMethod(doc = BuiltinDocs.int___coerce___doc)
final PyObject int___coerce__(PyObject other) {
return adaptToCoerceTuple(int___coerce_ex__(other));
}
/**
* Coercion logic for int. Implemented as a final method to avoid
* invocation of virtual methods from the exposed coerced.
*/
final Object int___coerce_ex__(PyObject other) {
return other instanceof PyInteger ? other : Py.None;
}
private static final boolean canCoerce(PyObject other) {
return other instanceof PyInteger;
}
private static final int coerce(PyObject other) {
if (other instanceof PyInteger) {
return ((PyInteger) other).getValue();
}
throw Py.TypeError("xxx");
}
@Override
public PyObject __add__(PyObject right) {
return int___add__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___add___doc)
final PyObject int___add__(PyObject right) {
if (!canCoerce(right)) {
return null;
}
int rightv = coerce(right);
int a = getValue();
int b = rightv;
int x = a + b;
if ((x ^ a) >= 0 || (x ^ b) >= 0) {
return Py.newInteger(x);
}
return new PyLong((long) a + (long) b);
}
@Override
public PyObject __radd__(PyObject left) {
return int___radd__(left);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___radd___doc)
final PyObject int___radd__(PyObject left) {
return __add__(left);
}
private static PyObject _sub(int a, int b) {
int x = a - b;
if ((x ^ a) >= 0 || (x ^ ~b) >= 0) {
return Py.newInteger(x);
}
return new PyLong((long) a - (long) b);
}
@Override
public PyObject __sub__(PyObject right) {
return int___sub__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___sub___doc)
final PyObject int___sub__(PyObject right) {
if (!canCoerce(right)) {
return null;
}
return _sub(getValue(), coerce(right));
}
@Override
public PyObject __rsub__(PyObject left) {
return int___rsub__(left);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rsub___doc)
final PyObject int___rsub__(PyObject left) {
if (!canCoerce(left)) {
return null;
}
return _sub(coerce(left), getValue());
}
@Override
public PyObject __mul__(PyObject right) {
return int___mul__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___mul___doc)
final PyObject int___mul__(PyObject right) {
if (!canCoerce(right)) {
return null;
}
int rightv = coerce(right);
double x = getValue();
x *= rightv;
if (x <= Integer.MAX_VALUE && x >= Integer.MIN_VALUE) {
return Py.newInteger((int) x);
}
return __long__().__mul__(right);
}
@Override
public PyObject __rmul__(PyObject left) {
return int___rmul__(left);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rmul___doc)
final PyObject int___rmul__(PyObject left) {
return __mul__(left);
}
// Getting signs correct for integer division
// This convention makes sense when you consider it in tandem with modulo
private static long divide(long x, long y) {
if (y == 0) {
throw Py.ZeroDivisionError("integer division or modulo by zero");
}
long xdivy = x / y;
long xmody = x - xdivy * y;
// If the signs of x and y differ, and the remainder is non-0, C89 doesn't define
// whether xdivy is now the floor or the ceiling of the infinitely precise
// quotient. We want the floor, and we have it iff the remainder's sign matches
// y's.
if (xmody != 0 && ((y < 0 && xmody > 0) || (y > 0 && xmody < 0))) {
xmody += y;
--xdivy;
//assert(xmody && ((y ^ xmody) >= 0));
}
return xdivy;
}
@Override
public PyObject __div__(PyObject right) {
return int___div__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___div___doc)
final PyObject int___div__(PyObject right) {
if (!canCoerce(right)) {
return null;
}
if (Options.divisionWarning > 0) {
Py.warning(Py.DeprecationWarning, "classic int division");
}
return Py.newInteger(divide(getValue(), coerce(right)));
}
@Override
public PyObject __rdiv__(PyObject left) {
return int___rdiv__(left);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rdiv___doc)
final PyObject int___rdiv__(PyObject left) {
if (!canCoerce(left)) {
return null;
}
if (Options.divisionWarning > 0) {
Py.warning(Py.DeprecationWarning, "classic int division");
}
return Py.newInteger(divide(coerce(left), getValue()));
}
@Override
public PyObject __floordiv__(PyObject right) {
return int___floordiv__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___floordiv___doc)
final PyObject int___floordiv__(PyObject right) {
if (!canCoerce(right)) {
return null;
}
return Py.newInteger(divide(getValue(), coerce(right)));
}
@Override
public PyObject __rfloordiv__(PyObject left) {
return int___rfloordiv__(left);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rfloordiv___doc)
final PyObject int___rfloordiv__(PyObject left) {
if (!canCoerce(left)) {
return null;
}
return Py.newInteger(divide(coerce(left), getValue()));
}
@Override
public PyObject __truediv__(PyObject right) {
return int___truediv__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___truediv___doc)
final PyObject int___truediv__(PyObject right) {
if (right instanceof PyInteger) {
return __float__().__truediv__(right);
} else if (right instanceof PyLong) {
return int___long__().__truediv__(right);
} else {
return null;
}
}
@Override
public PyObject __rtruediv__(PyObject left) {
return int___rtruediv__(left);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rtruediv___doc)
final PyObject int___rtruediv__(PyObject left) {
if (left instanceof PyInteger) {
return left.__float__().__truediv__(this);
} else if (left instanceof PyLong) {
return left.__truediv__(int___long__());
} else {
return null;
}
}
private static long modulo(long x, long y, long xdivy) {
return x - xdivy * y;
}
@Override
public PyObject __mod__(PyObject right) {
return int___mod__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___mod___doc)
final PyObject int___mod__(PyObject right) {
if (!canCoerce(right)) {
return null;
}
int rightv = coerce(right);
int v = getValue();
return Py.newInteger(modulo(v, rightv, divide(v, rightv)));
}
@Override
public PyObject __rmod__(PyObject left) {
return int___rmod__(left);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rmod___doc)
final PyObject int___rmod__(PyObject left) {
if (!canCoerce(left)) {
return null;
}
int leftv = coerce(left);
int v = getValue();
return Py.newInteger(modulo(leftv, v, divide(leftv, v)));
}
@Override
public PyObject __divmod__(PyObject right) {
return int___divmod__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___divmod___doc)
final PyObject int___divmod__(PyObject right) {
if (!canCoerce(right)) {
return null;
}
int rightv = coerce(right);
int v = getValue();
long xdivy = divide(v, rightv);
return new PyTuple(Py.newInteger(xdivy), Py.newInteger(modulo(v, rightv, xdivy)));
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rdivmod___doc)
final PyObject int___rdivmod__(PyObject left) {
if (!canCoerce(left)) {
return null;
}
int leftv = coerce(left);
int v = getValue();
long xdivy = divide(leftv, v);
return new PyTuple(Py.newInteger(xdivy), Py.newInteger(modulo(leftv, v, xdivy)));
}
@Override
public PyObject __pow__(PyObject right, PyObject modulo) {
return int___pow__(right, modulo);
}
@ExposedMethod(type = MethodType.BINARY, defaults = {"null"},
doc = BuiltinDocs.int___pow___doc)
final PyObject int___pow__(PyObject right, PyObject modulo) {
if (!canCoerce(right)) {
return null;
}
if (modulo != null && !canCoerce(modulo)) {
return null;
}
return _pow(getValue(), coerce(right), modulo, this, right);
}
public PyObject __rpow__(PyObject left, PyObject modulo) {
if (!canCoerce(left)) {
return null;
}
if (modulo != null && !canCoerce(modulo)) {
return null;
}
return _pow(coerce(left), getValue(), modulo, left, this);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rpow___doc)
final PyObject int___rpow__(PyObject left) {
return __rpow__(left, null);
}
private static PyObject _pow(int value, int pow, PyObject modulo, PyObject left,
PyObject right) {
int mod = 0;
long tmp = value;
boolean neg = false;
if (tmp < 0) {
tmp = -tmp;
neg = (pow & 0x1) != 0;
}
long result = 1;
if (pow < 0) {
if (value != 0) {
return left.__float__().__pow__(right, modulo);
} else {
throw Py.ZeroDivisionError("cannot raise 0 to a negative power");
}
}
if (modulo != null) {
mod = coerce(modulo);
if (mod == 0) {
throw Py.ValueError("pow(x, y, z) with z==0");
}
}
// Standard O(ln(N)) exponentiation code
while (pow > 0) {
if ((pow & 0x1) != 0) {
result *= tmp;
if (mod != 0) {
result %= mod;
}
if (result > Integer.MAX_VALUE) {
return left.__long__().__pow__(right, modulo);
}
}
pow >>= 1;
if (pow == 0) {
break;
}
tmp *= tmp;
if (mod != 0) {
tmp %= mod;
}
if (tmp > Integer.MAX_VALUE) {
return left.__long__().__pow__(right, modulo);
}
}
if (neg) {
result = -result;
}
// Cleanup result of modulo
if (mod != 0) {
result = modulo(result, mod, divide(result, mod));
}
return Py.newInteger(result);
}
@Override
public PyObject __lshift__(PyObject right) {
return int___lshift__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___lshift___doc)
final PyObject int___lshift__(PyObject right) {
int rightv;
if (right instanceof PyInteger) {
rightv = ((PyInteger) right).getValue();
} else if (right instanceof PyLong) {
return int___long__().__lshift__(right);
} else {
return null;
}
if (rightv >= Integer.SIZE) {
return __long__().__lshift__(right);
} else if (rightv < 0) {
throw Py.ValueError("negative shift count");
}
int result = getValue() << rightv;
if (getValue() != result >> rightv) {
return __long__().__lshift__(right);
}
return Py.newInteger(result);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rlshift___doc)
final PyObject int___rlshift__(PyObject left) {
int leftv;
if (left instanceof PyInteger) {
leftv = ((PyInteger) left).getValue();
} else if (left instanceof PyLong) {
return left.__rlshift__(int___long__());
} else {
return null;
}
if (getValue() >= Integer.SIZE) {
return left.__long__().__lshift__(this);
} else if (getValue() < 0) {
throw Py.ValueError("negative shift count");
}
int result = leftv << getValue();
if (leftv != result >> getValue()) {
return left.__long__().__lshift__(this);
}
return Py.newInteger(result);
}
@Override
public PyObject __rshift__(PyObject right) {
return int___rshift__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rshift___doc)
final PyObject int___rshift__(PyObject right) {
int rightv;
if (right instanceof PyInteger) {
rightv = ((PyInteger) right).getValue();
} else if (right instanceof PyLong) {
return int___long__().__rshift__(right);
} else {
return null;
}
if (rightv < 0) {
throw Py.ValueError("negative shift count");
}
if (rightv >= Integer.SIZE) {
return Py.newInteger(getValue() < 0 ? -1 : 0);
}
return Py.newInteger(getValue() >> rightv);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rrshift___doc)
final PyObject int___rrshift__(PyObject left) {
int leftv;
if (left instanceof PyInteger) {
leftv = ((PyInteger) left).getValue();
} else if (left instanceof PyLong) {
return left.__rshift__(int___long__());
} else {
return null;
}
if (getValue() < 0) {
throw Py.ValueError("negative shift count");
}
if (getValue() >= Integer.SIZE) {
return Py.newInteger(leftv < 0 ? -1 : 0);
}
return Py.newInteger(leftv >> getValue());
}
@Override
public PyObject __and__(PyObject right) {
return int___and__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___and___doc)
final PyObject int___and__(PyObject right) {
int rightv;
if (right instanceof PyInteger) {
rightv = ((PyInteger) right).getValue();
} else if (right instanceof PyLong) {
return int___long__().__and__(right);
} else {
return null;
}
return Py.newInteger(getValue() & rightv);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rand___doc)
final PyObject int___rand__(PyObject left) {
return int___and__(left);
}
@Override
public PyObject __xor__(PyObject right) {
return int___xor__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___xor___doc)
final PyObject int___xor__(PyObject right) {
int rightv;
if (right instanceof PyInteger) {
rightv = ((PyInteger) right).getValue();
} else if (right instanceof PyLong) {
return int___long__().__xor__(right);
} else {
return null;
}
return Py.newInteger(getValue() ^ rightv);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___rxor___doc)
final PyObject int___rxor__(PyObject left) {
int leftv;
if (left instanceof PyInteger) {
leftv = ((PyInteger) left).getValue();
} else if (left instanceof PyLong) {
return left.__rxor__(int___long__());
} else {
return null;
}
return Py.newInteger(leftv ^ getValue());
}
@Override
public PyObject __or__(PyObject right) {
return int___or__(right);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___or___doc)
final PyObject int___or__(PyObject right) {
int rightv;
if (right instanceof PyInteger) {
rightv = ((PyInteger) right).getValue();
} else if (right instanceof PyLong) {
return int___long__().__or__(right);
} else {
return null;
}
return Py.newInteger(getValue() | rightv);
}
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.int___ror___doc)
final PyObject int___ror__(PyObject left) {
return int___or__(left);
}
@Override
public PyObject __neg__() {
return int___neg__();
}
@ExposedMethod(doc = BuiltinDocs.int___neg___doc)
final PyObject int___neg__() {
long x = -getValue();
return Py.newInteger(x);
}
@Override
public PyObject __pos__() {
return int___pos__();
}
@ExposedMethod(doc = BuiltinDocs.int___pos___doc)
final PyObject int___pos__() {
return int___int__();
}
@Override
public PyObject __abs__() {
return int___abs__();
}
@ExposedMethod(doc = BuiltinDocs.int___abs___doc)
final PyObject int___abs__() {
if (getValue() < 0) {
return int___neg__();
}
return int___int__();
}
@Override
public PyObject __invert__() {
return int___invert__();
}
@ExposedMethod(doc = BuiltinDocs.int___invert___doc)
final PyObject int___invert__() {
return Py.newInteger(~getValue());
}
@Override
public PyObject __int__() {
return int___int__();
}
@ExposedMethod(doc = BuiltinDocs.int___int___doc)
final PyInteger int___int__() {
return getType() == TYPE ? this : Py.newInteger(getValue());
}
@Override
public PyObject __long__() {
return int___long__();
}
@ExposedMethod(doc = BuiltinDocs.int___long___doc)
final PyObject int___long__() {
return new PyLong(getValue());
}
@Override
public PyFloat __float__() {
return int___float__();
}
@ExposedMethod(doc = BuiltinDocs.int___float___doc)
final PyFloat int___float__() {
return new PyFloat((double) getValue());
}
@Override
public PyComplex __complex__() {
return new PyComplex(getValue(), 0.);
}
@Override
public PyString __oct__() {
return int___oct__();
}
@ExposedMethod(doc = BuiltinDocs.int___oct___doc)
final PyString int___oct__() {
if (getValue() < 0) {
return new PyString("-0" + Integer.toString(getValue() * -1, 8));
} else {
return new PyString("0" + Integer.toString(getValue(), 8));
}
}
@Override
public PyString __hex__() {
return int___hex__();
}
@ExposedMethod(doc = BuiltinDocs.int___hex___doc)
final PyString int___hex__() {
if (getValue() < 0) {
return new PyString("-0x" + Integer.toString(getValue() * -1, 16));
} else {
return new PyString("0x" + Integer.toString(getValue(), 16));
}
}
@ExposedMethod(doc = BuiltinDocs.int___getnewargs___doc)
final PyTuple int___getnewargs__() {
return new PyTuple(new PyObject[]{new PyInteger(this.getValue())});
}
@Override
public PyTuple __getnewargs__() {
return int___getnewargs__();
}
@Override
public PyObject __index__() {
return int___index__();
}
@ExposedMethod(doc = BuiltinDocs.int___index___doc)
final PyObject int___index__() {
return this;
}
@Override
public PyObject __format__(PyObject formatSpec) {
return int___format__(formatSpec);
}
@ExposedMethod(doc = BuiltinDocs.int___format___doc)
final PyObject int___format__(PyObject formatSpec) {
return formatImpl(getValue(), formatSpec);
}
static PyObject formatImpl(Object value, PyObject formatSpec) {
if (!(formatSpec instanceof PyString)) {
throw Py.TypeError("__format__ requires str or unicode");
}
PyString formatSpecStr = (PyString) formatSpec;
String result;
try {
String specString = formatSpecStr.getString();
InternalFormatSpec spec = new InternalFormatSpecParser(specString).parse();
result = formatIntOrLong(value, spec);
} catch (IllegalArgumentException e) {
throw Py.ValueError(e.getMessage());
}
return formatSpecStr.createInstance(result);
}
/**
* Formats an integer or long number according to a PEP-3101 format specification.
*
* @param value Integer or BigInteger object specifying the value to format.
* @param spec parsed PEP-3101 format specification.
* @return result of the formatting.
*/
public static String formatIntOrLong(Object value, InternalFormatSpec spec) {
if (spec.precision != -1) {
throw new IllegalArgumentException("Precision not allowed in integer format specifier");
}
int sign;
if (value instanceof Integer) {
int intValue = (Integer) value;
sign = intValue < 0 ? -1 : intValue == 0 ? 0 : 1;
} else {
sign = ((BigInteger) value).signum();
}
String strValue;
if (spec.type == 'c') {
if (spec.sign != '\0') {
throw new IllegalArgumentException("Sign not allowed with integer format "
+ "specifier 'c'");
}
if (value instanceof Integer) {
int intValue = (Integer) value;
if (intValue > 0xffff) {
throw new IllegalArgumentException("%c arg not in range(0x10000)");
}
strValue = Character.toString((char) intValue);
} else {
BigInteger bigInt = (BigInteger) value;
if (bigInt.intValue() > 0xffff || bigInt.bitCount() > 16) {
throw new IllegalArgumentException("%c arg not in range(0x10000)");
}
strValue = Character.toString((char) bigInt.intValue());
}
} else {
int radix = 10;
if (spec.type == 'o') {
radix = 8;
} else if (spec.type == 'x' || spec.type == 'X') {
radix = 16;
} else if (spec.type == 'b') {
radix = 2;
}
// TODO locale-specific formatting for 'n'
if (value instanceof BigInteger) {
strValue = ((BigInteger) value).toString(radix);
} else {
strValue = Integer.toString((Integer) value, radix);
}
if (spec.alternate) {
if (radix == 2) {
strValue = "0b" + strValue;
} else if (radix == 8) {
strValue = "0o" + strValue;
} else if (radix == 16) {
strValue = "0x" + strValue;
}
}
if (spec.type == 'X') {
strValue = strValue.toUpperCase();
}
if (sign >= 0) {
if (spec.sign == '+') {
strValue = "+" + strValue;
} else if (spec.sign == ' ') {
strValue = " " + strValue;
}
}
}
if (spec.align == '=' && (sign < 0 || spec.sign == '+' || spec.sign == ' ')) {
char signChar = strValue.charAt(0);
return signChar + spec.pad(strValue.substring(1), '>', 1);
}
return spec.pad(strValue, '>', 0);
}
@Override
public boolean isIndex() {
return true;
}
@Override
public int asIndex(PyObject err) {
return getValue();
}
@Override
public boolean isMappingType() {
return false;
}
@Override
public boolean isNumberType() {
return true;
}
@Override
public boolean isSequenceType() {
return false;
}
@Override
public long asLong(int index) {
return getValue();
}
@Override
public int asInt(int index) {
return getValue();
}
@Override
public int asInt() {
return getValue();
}
@Override
public long asLong() {
return getValue();
}
}