static PyObject* slice_indices(PySliceObject* self, PyObject* len) { PyObject *start, *stop, *step; PyObject *length; int error; /* Convert length to an integer if necessary; raise for negative length. */ length = PyNumber_Index(len); if (length == NULL) return NULL; if (_PyLong_Sign(length) < 0) { PyErr_SetString(PyExc_ValueError, "length should not be negative"); Py_DECREF(length); return NULL; } error = _PySlice_GetLongIndices(self, length, &start, &stop, &step); Py_DECREF(length); if (error == -1) return NULL; else return Py_BuildValue("(NNN)", start, stop, step); }
extern "C" void* PyLong_AsVoidPtr(PyObject* vv) noexcept { /* This function will allow int or long objects. If vv is neither, then the PyLong_AsLong*() functions will raise the exception: PyExc_SystemError, "bad argument to internal function" */ #if SIZEOF_VOID_P <= SIZEOF_LONG long x; if (PyInt_Check(vv)) x = PyInt_AS_LONG(vv); else if (PyLong_Check(vv) && _PyLong_Sign(vv) < 0) x = PyLong_AsLong(vv); else x = PyLong_AsUnsignedLong(vv); #else #ifndef HAVE_LONG_LONG #error "PyLong_AsVoidPtr: sizeof(void*) > sizeof(long), but no long long" #endif #if SIZEOF_LONG_LONG < SIZEOF_VOID_P #error "PyLong_AsVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)" #endif PY_LONG_LONG x; if (PyInt_Check(vv)) x = PyInt_AS_LONG(vv); else if (PyLong_Check(vv) && _PyLong_Sign(vv) < 0) x = PyLong_AsLongLong(vv); else x = PyLong_AsUnsignedLongLong(vv); #endif /* SIZEOF_VOID_P <= SIZEOF_LONG */ if (x == -1 && PyErr_Occurred()) return NULL; return (void*)x; }
Py_off_t PyNumber_AsOff_t(PyObject *item, PyObject *err) { Py_off_t result; PyObject *runerr; PyObject *value = PyNumber_Index(item); if (value == NULL) return -1; if (PyInt_Check(value)) { /* We assume a long always fits in a Py_off_t... */ result = (Py_off_t) PyInt_AS_LONG(value); goto finish; } /* We're done if PyLong_AsSsize_t() returns without error. */ result = PyLong_AsOff_t(value); if (result != -1 || !(runerr = PyErr_Occurred())) goto finish; /* Error handling code -- only manage OverflowError differently */ if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) goto finish; PyErr_Clear(); /* If no error-handling desired then the default clipping is sufficient. */ if (!err) { assert(PyLong_Check(value)); /* Whether or not it is less than or equal to zero is determined by the sign of ob_size */ if (_PyLong_Sign(value) < 0) result = PY_OFF_T_MIN; else result = PY_OFF_T_MAX; } else { /* Otherwise replace the error with caller's error object. */ PyErr_Format(err, "cannot fit '%.200s' into an offset-sized integer", item->ob_type->tp_name); } finish: Py_DECREF(value); return result; }
/* Helper function for validating step. Always returns a new reference or NULL on error. */ static PyObject * validate_step(PyObject *step) { /* No step specified, use a step of 1. */ if (!step) return PyLong_FromLong(1); step = PyNumber_Index(step); if (step && _PyLong_Sign(step) == 0) { PyErr_SetString(PyExc_ValueError, "range() arg 3 must not be zero"); Py_CLEAR(step); } return step; }
/* Simple test of _PyLong_NumBits and _PyLong_Sign. */ static PyObject * test_long_numbits(PyObject *self) { struct triple { long input; size_t nbits; int sign; } testcases[] = {{0, 0, 0}, {1L, 1, 1}, {-1L, 1, -1}, {2L, 2, 1}, {-2L, 2, -1}, {3L, 2, 1}, {-3L, 2, -1}, {4L, 3, 1}, {-4L, 3, -1}, {0x7fffL, 15, 1}, /* one Python long digit */ {-0x7fffL, 15, -1}, {0xffffL, 16, 1}, {-0xffffL, 16, -1}, {0xfffffffL, 28, 1}, {-0xfffffffL, 28, -1}}; int i; for (i = 0; i < sizeof(testcases) / sizeof(struct triple); ++i) { PyObject *plong = PyLong_FromLong(testcases[i].input); size_t nbits = _PyLong_NumBits(plong); int sign = _PyLong_Sign(plong); Py_DECREF(plong); if (nbits != testcases[i].nbits) return raiseTestError("test_long_numbits", "wrong result for _PyLong_NumBits"); if (sign != testcases[i].sign) return raiseTestError("test_long_numbits", "wrong result for _PyLong_Sign"); } Py_INCREF(Py_None); return Py_None; }
/* py2sq: Create and return a Squeak oop from a PyObject. Returns the new OOP or NULL on failure. Arguments: obj: The PyObject reference to convert to Squeak. */ OOP py2sq(PyObject *obj) { if(obj == NULL) { pyErr = "py2sq: NULL PyObject reference encountered"; return 0; } /* nil, true, false */ if(obj == Py_None) { return vm->nilObject(); } if(obj == Py_True) { return vm->trueObject(); } if(obj == Py_False) { return vm->falseObject(); } /* 32bit signed integer value */ if(PyObject_TypeCheck(obj, &PyInt_Type)) { return vm->signed32BitIntegerFor(PyInt_AsLong(obj)); } /* BigNums */ if(PyObject_TypeCheck(obj, &PyLong_Type)) { int nBits = _PyLong_NumBits(obj); int i, nBytes = (nBits + 7) / 8; OOP sqInt, sqIntClass; /* Cover PyLongs <= 32 bit */ if(nBits < 32) { int value = PyLong_AsLong(obj); return vm->signed32BitIntegerFor(value); } #if 0 /* At this point (VM proxy 1.x), Squeak's signed64BitIntegerFor() is HORRIBLY broken. Once a fixed version exists the above should be defined as if VM_PROXY_MINOR > xxx to enable the fast conversion below */ /* Cover PyLongs <= 64 bit */ if(nBits < 64) { long long veryLong = PyLong_AsLongLong(obj); return vm->signed64BitIntegerFor(veryLong); } #endif /* Cover large positive integers */ if(_PyLong_Sign(obj) >= 0) { sqIntClass = vm->classLargePositiveInteger(); sqInt = vm->instantiateClassindexableSize(sqIntClass, nBytes); _PyLong_AsByteArray((PyLongObject*)obj, vm->firstIndexableField(sqInt), nBytes, 1, 0); return sqInt; } /* Cover the remaining case of large negative integers. Unfortunately, Python only gives us an interface using the 2s complement so we have to recompute the magnitude from it. Sigh. */ nBytes++; /* one extra in case we need the sign bit */ if(nBytes >= longBufMax) { longBufMax = nBytes; if(longBuf) free(longBuf); longBuf = malloc(longBufMax); } _PyLong_AsByteArray((PyLongObject*)obj, longBuf, nBytes, 1, 1); for(i=0; i < nBytes; i++) longBuf[i] ^= 255; for(i=0; i < nBytes; i++) if(++longBuf[i]) break; while(longBuf[nBytes-1] == 0) nBytes--; sqIntClass = vm->classLargeNegativeInteger(); sqInt = vm->instantiateClassindexableSize(sqIntClass, nBytes); memcpy(vm->firstIndexableField(sqInt), longBuf, nBytes); return sqInt; } /* 64bit double float value */ if(PyObject_TypeCheck(obj, &PyFloat_Type)) { return vm->floatObjectOf(PyFloat_AsDouble(obj)); } /* string -- only deals with byte strings here */ if(PyObject_TypeCheck(obj, &PyString_Type)) { int sz = PyString_Size(obj); char *src = PyString_AsString(obj); OOP strOop = vm->instantiateClassindexableSize(vm->classString(), sz); char *dst = vm->firstIndexableField(strOop); memcpy(dst, src, sz); return strOop; } /* tuples -- convert those to arrays */ if(PyObject_TypeCheck(obj, &PyTuple_Type)) { int i, sz; OOP arrayOop, itemOop; sz = PyObject_Length(obj); arrayOop = vm->instantiateClassindexableSize(vm->classArray(), sz); for(i = 0; i < sz; i++) { vm->pushRemappableOop(arrayOop); itemOop = py2sq(PyTuple_GetItem(obj, i)); arrayOop = vm->popRemappableOop(); if(itemOop == 0) return 0; vm->storePointerofObjectwithValue(i, arrayOop, itemOop); } return arrayOop; } return py2sqGeneric(obj); }
int _PySlice_GetLongIndices(PySliceObject *self, PyObject *length, PyObject **start_ptr, PyObject **stop_ptr, PyObject **step_ptr) { PyObject *start=NULL, *stop=NULL, *step=NULL; PyObject *upper=NULL, *lower=NULL; int step_is_negative, cmp_result; /* Convert step to an integer; raise for zero step. */ if (self->step == Py_None) { step = _PyLong_One; Py_INCREF(step); step_is_negative = 0; } else { int step_sign; step = evaluate_slice_index(self->step); if (step == NULL) goto error; step_sign = _PyLong_Sign(step); if (step_sign == 0) { PyErr_SetString(PyExc_ValueError, "slice step cannot be zero"); goto error; } step_is_negative = step_sign < 0; } /* Find lower and upper bounds for start and stop. */ if (step_is_negative) { lower = PyLong_FromLong(-1L); if (lower == NULL) goto error; upper = PyNumber_Add(length, lower); if (upper == NULL) goto error; } else { lower = _PyLong_Zero; Py_INCREF(lower); upper = length; Py_INCREF(upper); } /* Compute start. */ if (self->start == Py_None) { start = step_is_negative ? upper : lower; Py_INCREF(start); } else { start = evaluate_slice_index(self->start); if (start == NULL) goto error; if (_PyLong_Sign(start) < 0) { /* start += length */ PyObject *tmp = PyNumber_Add(start, length); Py_DECREF(start); start = tmp; if (start == NULL) goto error; cmp_result = PyObject_RichCompareBool(start, lower, Py_LT); if (cmp_result < 0) goto error; if (cmp_result) { Py_INCREF(lower); Py_DECREF(start); start = lower; } } else { cmp_result = PyObject_RichCompareBool(start, upper, Py_GT); if (cmp_result < 0) goto error; if (cmp_result) { Py_INCREF(upper); Py_DECREF(start); start = upper; } } } /* Compute stop. */ if (self->stop == Py_None) { stop = step_is_negative ? lower : upper; Py_INCREF(stop); } else { stop = evaluate_slice_index(self->stop); if (stop == NULL) goto error; if (_PyLong_Sign(stop) < 0) { /* stop += length */ PyObject *tmp = PyNumber_Add(stop, length); Py_DECREF(stop); stop = tmp; if (stop == NULL) goto error; cmp_result = PyObject_RichCompareBool(stop, lower, Py_LT); if (cmp_result < 0) goto error; if (cmp_result) { Py_INCREF(lower); Py_DECREF(stop); stop = lower; } } else { cmp_result = PyObject_RichCompareBool(stop, upper, Py_GT); if (cmp_result < 0) goto error; if (cmp_result) { Py_INCREF(upper); Py_DECREF(stop); stop = upper; } } } *start_ptr = start; *stop_ptr = stop; *step_ptr = step; Py_DECREF(upper); Py_DECREF(lower); return 0; error: *start_ptr = *stop_ptr = *step_ptr = NULL; Py_XDECREF(start); Py_XDECREF(stop); Py_XDECREF(step); Py_XDECREF(upper); Py_XDECREF(lower); return -1; }