1/* 2 * Minimal support for the C-type NSDecimal 3 * 4 * There is no implicit conversion to/from Python numbers, because NSDecimal 5 * numbers behave differently from Python numbers (explicit rounding) 6 * 7 * - number methods 8 * NSDecimal objects support +, -, *, /, +=, -=, *= and /=, which directly 9 * correspond with NSDecimal* functions with the NSRoundPlain argument. 10 * They also support unary -, unary + and abs, with the obvious semantics. 11 */ 12#ifndef _C_CONST 13#define _C_CONST 'r' 14#endif 15 16typedef struct { 17 PyObject_HEAD 18 NSDecimal value; 19 NSDecimalNumber *objc_value; 20} DecimalObject; 21 22#define Decimal_Value(v) ((DecimalObject*)(v))->value 23 24static PyObject* Decimal_New(NSDecimal* aDecimal); 25static PyObject* decimal_repr(PyObject* self); 26static PyObject* decimal_richcompare(PyObject* self, PyObject* other, int type); 27static void decimal_dealloc(PyObject* self); 28static int decimal_init(PyObject* self, PyObject* args, PyObject* kwds); 29static PyObject* decimal_new(PyTypeObject* type, PyObject* args, PyObject* kwds); 30static PyObject* decimal_asint(PyObject* self); 31static PyObject* decimal_asfloat(PyObject* self); 32static PyObject* decimal_add(PyObject* left, PyObject* right); 33static PyObject* decimal_subtract(PyObject* left, PyObject* right); 34static PyObject* decimal_multiply(PyObject* left, PyObject* right); 35static PyObject* decimal_divide(PyObject* left, PyObject* right); 36static PyObject* decimal_power(PyObject* left, PyObject* right, PyObject* power); 37static int decimal_nonzero(PyObject* self); 38static int decimal_coerce(PyObject** l, PyObject** r); 39static PyObject* decimal_inplace_add(PyObject* left, PyObject* right); 40static PyObject* decimal_inplace_subtract(PyObject* left, PyObject* right); 41static PyObject* decimal_inplace_multiply(PyObject* left, PyObject* right); 42static PyObject* decimal_inplace_divide(PyObject* left, PyObject* right); 43static PyObject* decimal_positive(PyObject* self); 44static PyObject* decimal_negative(PyObject* self); 45static PyObject* decimal_absolute(PyObject* self); 46 47static PyNumberMethods decimal_asnumber = { 48 decimal_add, /* nb_add */ 49 decimal_subtract, /* nb_subtract */ 50 decimal_multiply, /* nb_multiply */ 51#if PY_MAJOR_VERSION == 2 52 decimal_divide, /* nb_divide */ 53#endif 54 NULL, /* nb_remainder */ 55 NULL, /* nb_divmod */ 56 decimal_power, /* nb_power */ 57 decimal_negative, /* nb_negative */ 58 decimal_positive, /* nb_positive */ 59 decimal_absolute, /* nb_absolute */ 60 decimal_nonzero, /* nb_nonzero */ 61 NULL, /* nb_invert */ 62 NULL, /* nb_lshift */ 63 NULL, /* nb_rshift */ 64 NULL, /* nb_and */ 65 NULL, /* nb_xor */ 66 NULL, /* nb_or */ 67 68#if PY_MAJOR_VERSION == 2 69 decimal_coerce, /* nb_coerce */ 70#endif 71 NULL, /* nb_int */ 72 NULL, /* nb_long */ 73 NULL, /* nb_float */ 74#if PY_MAJOR_VERSION == 2 75 NULL, /* nb_oct */ 76 NULL, /* nb_hex */ 77#endif 78 decimal_inplace_add, /* nb_inplace_add */ 79 decimal_inplace_subtract, /* nb_inplace_subtract */ 80 decimal_inplace_multiply, /* nb_inplace_multiply */ 81#if PY_MAJOR_VERSION == 2 82 decimal_inplace_divide, /* nb_inplace_divide */ 83#endif 84 NULL, /* nb_inplace_remainder */ 85 NULL, /* nb_inplace_power */ 86 NULL, /* nb_inplace_lshift */ 87 NULL, /* nb_inplace_rshift */ 88 NULL, /* nb_inplace_and */ 89 NULL, /* nb_inplace_xor */ 90 NULL, /* nb_inplace_or */ 91 NULL, /* nb_floor_divide */ 92 decimal_divide, /* nb_true_divide */ 93 NULL, /* nb_inplace_floor_divide */ 94 decimal_inplace_divide /* nb_inplace_true_divide */ 95#if (PY_VERSION_HEX >= 0x02050000) 96 ,NULL /* nb_index */ 97#endif 98}; 99 100static NSDecimalNumber * 101Decimal_ObjCValue(PyObject *self) { 102 DecimalObject *pyself = (DecimalObject *)self; 103 NSDecimalNumber *res = pyself->objc_value; 104 if (!res) { 105 res = pyself->objc_value = [[NSDecimalNumber alloc] initWithDecimal:Decimal_Value(self)]; 106 } 107 return res; 108} 109 110static PyObject *decimal_get__pyobjc_object__(PyObject *self, void *closure __attribute__((__unused__))) { 111 PyObject *rval = PyObjCObject_New(Decimal_ObjCValue(self), 0, YES); 112 return rval; 113} 114 115static PyGetSetDef decimal_getseters[] = { 116 { 117 "__pyobjc_object__", 118 (getter)decimal_get__pyobjc_object__, NULL, 119 "NSDecimalNumber instance", 120 NULL 121 }, 122 { 123 NULL, 124 NULL, NULL, 125 NULL, 126 NULL 127 } 128}; 129 130static PyMethodDef decimal_methods[] = { 131 { 132 "as_int", 133 (PyCFunction)decimal_asint, 134 METH_NOARGS, 135 "Convert decimal to a Python int" 136 }, 137 { 138 "as_float", 139 (PyCFunction)decimal_asfloat, 140 METH_NOARGS, 141 "Convert decimal to a Python float" 142 }, 143 { 144 NULL, 145 NULL, 146 0, 147 NULL 148 } 149}; 150 151static PyObject* 152decimal_getattro(PyObject *o, PyObject *attr_name) 153{ 154 PyObject *res; 155 res = PyObject_GenericGetAttr(o, attr_name); 156 if (res == NULL) { 157 PyObject *tmp; 158 PyErr_Clear(); 159 tmp = decimal_get__pyobjc_object__(o, NULL); 160 res = PyObject_GenericGetAttr(tmp, attr_name); 161 Py_XDECREF(tmp); 162 } 163 return res; 164} 165 166static PyTypeObject Decimal_Type = { 167 PyVarObject_HEAD_INIT(&PyType_Type, 0) 168 "Foundation.NSDecimal", /* tp_name */ 169 sizeof (DecimalObject), /* tp_basicsize */ 170 0, /* tp_itemsize */ 171 /* methods */ 172 decimal_dealloc, /* tp_dealloc */ 173 0, /* tp_print */ 174 0, /* tp_getattr */ 175 0, /* tp_setattr */ 176 0, /* tp_compare */ 177 decimal_repr, /* tp_repr */ 178 &decimal_asnumber, /* tp_as_number */ 179 0, /* tp_as_sequence */ 180 0, /* tp_as_mapping */ 181 0, /* tp_hash */ 182 0, /* tp_call */ 183 decimal_repr, /* tp_str */ 184 decimal_getattro, /* tp_getattro */ 185 PyObject_GenericSetAttr, /* tp_setattro */ 186 0, /* tp_as_buffer */ 187 Py_TPFLAGS_DEFAULT 188#if PY_MAJOR_VERSION == 2 189 | Py_TPFLAGS_HAVE_RICHCOMPARE | Py_TPFLAGS_HAVE_INPLACEOPS 190#endif 191 , /* tp_flags */ 192 "NSDecimal wrapper", /* tp_doc */ 193 0, /* tp_traverse */ 194 0, /* tp_clear */ 195 decimal_richcompare, /* tp_richcompare */ 196 0, /* tp_weaklistoffset */ 197 0, /* tp_iter */ 198 0, /* tp_iternext */ 199 decimal_methods, /* tp_methods */ 200 0, /* tp_members */ 201 decimal_getseters, /* tp_getset */ 202 0, /* tp_base */ 203 0, /* tp_dict */ 204 0, /* tp_descr_get */ 205 0, /* tp_descr_set */ 206 0, /* tp_dictoffset */ 207 0, /* tp_init */ 208 0, /* tp_alloc */ 209 decimal_new, /* tp_new */ 210 0, /* tp_free */ 211 0, /* tp_is_gc */ 212 0, /* tp_bases */ 213 0, /* tp_mro */ 214 0, /* tp_cache */ 215 0, /* tp_subclasses */ 216 0 /* tp_weaklist */ 217#if PY_VERSION_HEX >= 0x020300A2 218 , 0, /* tp_del */ 219#endif 220}; 221 222#define Decimal_Check(obj) PyObject_TypeCheck(obj, &Decimal_Type) 223 224static void DecimalFromString(NSDecimal* aDecimal, NSString* aString, void* locale __attribute__((__unused__))) 225{ 226 NSDecimalNumber* num; 227 228 num = [[NSDecimalNumber alloc] initWithString:aString]; 229 *aDecimal = [num decimalValue]; 230 [num release]; 231} 232 233static void DecimalFromComponents(NSDecimal* aDecimal, unsigned long long mantissa, unsigned short exponent, BOOL negative) 234{ 235 NSDecimalNumber* num; 236 237 num = [[NSDecimalNumber alloc] 238 initWithMantissa:mantissa 239 exponent:exponent 240 isNegative:negative]; 241 242 *aDecimal = [num decimalValue]; 243 [num release]; 244} 245 246static PyObject* 247decimal_new(PyTypeObject* type __attribute__((__unused__)), PyObject* args, PyObject* kwds) 248{ 249 DecimalObject* self; 250 251 252 self = PyObject_New(DecimalObject, &Decimal_Type); 253 if (self == NULL) { 254 return PyErr_NoMemory(); 255 } 256 257 memset(&self->value, 0, sizeof(self->value)); 258 self->objc_value = nil; 259 if ((args == NULL || PyTuple_Size(args) == 0) && (kwds == NULL || PyDict_Size(kwds) == 0)) { 260 DecimalFromComponents(&self->value, 0, 0, 0); 261 return (PyObject*)self; 262 } 263 if (decimal_init((PyObject*)self, args, kwds) == -1) { 264 Py_DECREF(self); 265 self = NULL; 266 return NULL; 267 } 268 return (PyObject*)self; 269} 270 271static void 272decimal_dealloc(PyObject* self) 273{ 274 [((DecimalObject *)self)->objc_value release]; 275 PyObject_Free(self); 276} 277 278 279static int 280decimal_init(PyObject* self, PyObject* args, PyObject* kwds) 281{ 282static char* keywords[] = { "mantissa", "exponent", "isNegative", NULL }; 283static char* keywords2[] = { "string", NULL }; 284 PyObject* pyMantissa; 285 PyObject* pyExponent; 286 PyObject* pyNegative; 287 BOOL negative; 288 unsigned long long mantissa; 289 short int exponent; 290 291 ((DecimalObject*)self)->objc_value = nil; 292 293 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO", keywords, &pyMantissa, &pyExponent, &pyNegative)) { 294 PyObject* pyValue; 295 NSString* volatile stringVal; 296 297 PyErr_Clear(); 298 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", keywords2, &pyValue)) { 299 PyErr_SetString(PyExc_TypeError, 300 "NSDecimal(stringValue) or NSDecimal(mantissa, exponent, isNegative)"); 301 return -1; 302 } 303 if (PyLong_Check(pyValue)) { 304 mantissa = PyLong_AsUnsignedLongLong(pyValue); 305 if (PyErr_Occurred()) { 306 long long lng; 307 PyErr_Clear(); 308 lng = PyLong_AsLongLong(pyValue); 309 if (PyErr_Occurred()) { 310 return -1; 311 } 312 if (lng < 0) { 313 mantissa = -lng; 314 exponent = 0; 315 negative = YES; 316 } else { 317 mantissa = lng; 318 exponent = 0; 319 negative = NO; 320 } 321 DecimalFromComponents(&Decimal_Value(self), 322 mantissa, exponent, negative); 323 return 0; 324 } else { 325 DecimalFromComponents(&Decimal_Value(self), 326 mantissa, 0, NO); 327 return 0; 328 } 329#if PY_MAJOR_VERSION == 2 330 } else if (PyInt_Check(pyValue)) { 331 long lng = PyInt_AsLong(pyValue); 332 if (lng < 0) { 333 mantissa = -lng; 334 exponent = 0; 335 negative = YES; 336 } else{ 337 mantissa = lng; 338 exponent = 0; 339 negative = NO; 340 } 341 342 DecimalFromComponents(&Decimal_Value(self), 343 mantissa, exponent, negative); 344 return 0; 345#endif 346 } else if (PyFloat_Check(pyValue)) { 347 /* Explicit conversion from float to NSDecimal 348 * first convert the float to a string using repr, that 349 * is easier than extracting the components of the 350 * float. 351 */ 352 PyObject* strVal = PyObject_Repr(pyValue); 353 PyObject* uniVal = NULL; 354 355 if (strVal == NULL) return -1; 356 357 uniVal = PyUnicode_FromEncodedObject(strVal, "ascii", "strict"); 358 Py_DECREF(strVal); 359 360 if (uniVal == NULL) return -1; 361 362 stringVal = PyObjC_PythonToId(uniVal); 363 Py_DECREF(uniVal); 364 365 PyObjC_DURING 366 DecimalFromString(&Decimal_Value(self), stringVal, NULL); 367 PyObjC_HANDLER 368 PyObjCErr_FromObjC(localException); 369 PyObjC_ENDHANDLER 370 371 if (PyErr_Occurred()) return -1; 372 return 0; 373 374 375 } else if (PyObjCObject_Check(pyValue)) { 376 NSObject* value = PyObjC_PythonToId(pyValue); 377 if ([value isKindOfClass:[NSDecimalNumber class]]) { 378 ((DecimalObject*)self)->value = [ 379 (NSDecimalNumber*)value decimalValue 380 ]; 381 382 ((DecimalObject*)self)->objc_value = 383 (NSDecimalNumber*)value; 384 [value retain]; 385 return 0; 386 } 387 PyErr_Format(PyExc_TypeError, "cannot convert object of %s to NSDecimal", pyValue->ob_type->tp_name); 388 return -1; 389 } else if ( 390#if PY_MAJOR_VERSION == 2 391 !PyString_Check(pyValue) && 392#endif 393 !PyUnicode_Check(pyValue)) { 394 PyErr_Format(PyExc_TypeError, "cannot convert object of %s to NSDecimal", pyValue->ob_type->tp_name); 395 return -1; 396 } 397 398 stringVal = PyObjC_PythonToId(pyValue); 399 PyObjC_DURING 400 DecimalFromString(&Decimal_Value(self), stringVal, NULL); 401 PyObjC_HANDLER 402 PyObjCErr_FromObjC(localException); 403 PyObjC_ENDHANDLER 404 405 if (PyErr_Occurred()) return -1; 406 return 0; 407 408 } 409 410 negative = PyObject_IsTrue(pyNegative); 411 if (PyObjC_PythonToObjC(@encode(short int), pyExponent, &exponent) == -1) { 412 return -1; 413 } 414 415 if (PyObjC_PythonToObjC(@encode(unsigned long long), pyMantissa, &mantissa) == -1) { 416 return -1; 417 } 418 419 420 DecimalFromComponents(&Decimal_Value(self), 421 mantissa, 422 exponent, 423 negative); 424 425 return 0; 426} 427 428static PyObject* 429decimal_richcompare(PyObject* self, PyObject* other, int type) 430{ 431 NSComparisonResult res; 432 433 if (!Decimal_Check(other)) { 434 if (type == Py_EQ) { 435 return PyBool_FromLong(0); 436 } 437 PyErr_Format(PyExc_TypeError, 438 "Cannot compare NSDecimal and %s", 439 other->ob_type->tp_name); 440 return NULL; 441 } 442 443 res = NSDecimalCompare(&Decimal_Value(self), &Decimal_Value(other)); 444 445 switch (type) { 446 case Py_LT: return PyBool_FromLong(res == NSOrderedAscending); 447 case Py_LE: return PyBool_FromLong(res != NSOrderedDescending); 448 case Py_EQ: return PyBool_FromLong(res == NSOrderedSame); 449 case Py_NE: return PyBool_FromLong(res != NSOrderedSame); 450 case Py_GE: return PyBool_FromLong(res != NSOrderedAscending); 451 case Py_GT: return PyBool_FromLong(res == NSOrderedDescending); 452 default: 453 PyErr_SetString(PyExc_TypeError, 454 "Bad comparison arg"); 455 return NULL; 456 } 457} 458 459 460static PyObject* decimal_asint(PyObject* self) 461{ 462 NSDecimalNumber* tmp = Decimal_ObjCValue(self); 463 return PyInt_FromLong([tmp longValue]); 464} 465 466static PyObject* decimal_asfloat(PyObject* self) 467{ 468 NSDecimalNumber* tmp = Decimal_ObjCValue(self); 469 return PyFloat_FromDouble([tmp doubleValue]); 470} 471 472static PyObject* decimal_power( 473 PyObject* left __attribute__((__unused__)), 474 PyObject* right __attribute__((__unused__)), 475 PyObject* extra __attribute__((__unused__))) 476{ 477 PyErr_SetString(PyExc_TypeError, 478 "pow() and ** are not supported for NSDecimal"); 479 return NULL; 480} 481 482static PyObject* decimal_add(PyObject* left, PyObject* right) 483{ 484 NSDecimal result; 485 NSCalculationError err; 486 487 err = NSDecimalAdd(&result, 488 &Decimal_Value(left), 489 &Decimal_Value(right), 490 NSRoundPlain); 491 if (err == NSCalculationOverflow) { 492 PyErr_SetString(PyExc_OverflowError, "Numeric overflow"); 493 return NULL; 494 } else if (err == NSCalculationUnderflow) { 495 PyErr_SetString(PyExc_OverflowError, "Numeric underflow"); 496 return NULL; 497 } else { 498 NSDecimalCompact(&result); 499 return Decimal_New(&result); 500 } 501} 502 503static PyObject* decimal_subtract(PyObject* left, PyObject* right) 504{ 505 NSDecimal result; 506 NSCalculationError err; 507 508 err = NSDecimalSubtract(&result, 509 &Decimal_Value(left), 510 &Decimal_Value(right), 511 NSRoundPlain); 512 if (err == NSCalculationOverflow) { 513 PyErr_SetString(PyExc_OverflowError, "Numeric overflow"); 514 return NULL; 515 } else if (err == NSCalculationUnderflow) { 516 PyErr_SetString(PyExc_OverflowError, "Numeric underflow"); 517 return NULL; 518 } else { 519 NSDecimalCompact(&result); 520 return Decimal_New(&result); 521 } 522} 523 524static PyObject* decimal_multiply(PyObject* left, PyObject* right) 525{ 526 NSDecimal result; 527 NSCalculationError err; 528 529 err = NSDecimalMultiply(&result, 530 &Decimal_Value(left), 531 &Decimal_Value(right), 532 NSRoundPlain); 533 if (err == NSCalculationOverflow) { 534 PyErr_SetString(PyExc_OverflowError, "Numeric overflow"); 535 return NULL; 536 } else if (err == NSCalculationUnderflow) { 537 PyErr_SetString(PyExc_OverflowError, "Numeric underflow"); 538 return NULL; 539 } else { 540 NSDecimalCompact(&result); 541 return Decimal_New(&result); 542 } 543} 544 545static PyObject* decimal_divide(PyObject* left, PyObject* right) 546{ 547 NSDecimal result; 548 NSCalculationError err; 549 550 err = NSDecimalDivide(&result, 551 &Decimal_Value(left), 552 &Decimal_Value(right), 553 NSRoundPlain); 554 if (err == NSCalculationOverflow) { 555 PyErr_SetString(PyExc_OverflowError, "Numeric overflow"); 556 return NULL; 557 } else if (err == NSCalculationUnderflow) { 558 PyErr_SetString(PyExc_OverflowError, "Numeric underflow"); 559 return NULL; 560 } else { 561 NSDecimalCompact(&result); 562 return Decimal_New(&result); 563 } 564} 565 566static PyObject* decimal_inplace_add(PyObject* left, PyObject* right) 567{ 568 NSDecimal result; 569 NSCalculationError err; 570 int r = decimal_coerce(&left, &right); 571 if (r == 1) { 572 PyErr_Format(PyExc_TypeError, 573 "unsupported operand type(s) for +=: '%s' and '%s'", 574 left->ob_type->tp_name, 575 right->ob_type->tp_name); 576 return NULL; 577 } 578 579 err = NSDecimalAdd(&result, 580 &Decimal_Value(left), 581 &Decimal_Value(right), 582 NSRoundPlain); 583 if (err == NSCalculationOverflow) { 584 Py_DECREF(left); Py_DECREF(right); 585 PyErr_SetString(PyExc_OverflowError, "Numeric overflow"); 586 return NULL; 587 } else if (err == NSCalculationUnderflow) { 588 Py_DECREF(left); Py_DECREF(right); 589 PyErr_SetString(PyExc_OverflowError, "Numeric underflow"); 590 return NULL; 591 } else { 592 Py_DECREF(right); 593 NSDecimalCompact(&result); 594 Decimal_Value(left) = result; 595 return left; 596 } 597} 598 599static PyObject* decimal_inplace_subtract(PyObject* left, PyObject* right) 600{ 601 NSDecimal result; 602 NSCalculationError err; 603 int r = decimal_coerce(&left, &right); 604 if (r == 1) { 605 PyErr_Format(PyExc_TypeError, 606 "unsupported operand type(s) for -=: '%s' and '%s'", 607 left->ob_type->tp_name, 608 right->ob_type->tp_name); 609 return NULL; 610 } 611 612 err = NSDecimalSubtract(&result, 613 &Decimal_Value(left), 614 &Decimal_Value(right), 615 NSRoundPlain); 616 if (err == NSCalculationOverflow) { 617 Py_DECREF(left); Py_DECREF(right); 618 PyErr_SetString(PyExc_OverflowError, "Numeric overflow"); 619 return NULL; 620 } else if (err == NSCalculationUnderflow) { 621 Py_DECREF(left); Py_DECREF(right); 622 PyErr_SetString(PyExc_OverflowError, "Numeric underflow"); 623 return NULL; 624 } else { 625 Py_DECREF(right); 626 NSDecimalCompact(&result); 627 Decimal_Value(left) = result; 628 return left; 629 } 630} 631 632static PyObject* decimal_inplace_multiply(PyObject* left, PyObject* right) 633{ 634 NSDecimal result; 635 NSCalculationError err; 636 int r = decimal_coerce(&left, &right); 637 if (r == 1) { 638 PyErr_Format(PyExc_TypeError, 639 "unsupported operand type(s) for *=: '%s' and '%s'", 640 left->ob_type->tp_name, 641 right->ob_type->tp_name); 642 return NULL; 643 } 644 645 err = NSDecimalMultiply(&result, 646 &Decimal_Value(left), 647 &Decimal_Value(right), 648 NSRoundPlain); 649 if (err == NSCalculationOverflow) { 650 Py_DECREF(left); Py_DECREF(right); 651 PyErr_SetString(PyExc_OverflowError, "Numeric overflow"); 652 return NULL; 653 } else if (err == NSCalculationUnderflow) { 654 Py_DECREF(left); Py_DECREF(right); 655 PyErr_SetString(PyExc_OverflowError, "Numeric underflow"); 656 return NULL; 657 } else { 658 Py_DECREF(right); 659 NSDecimalCompact(&result); 660 Decimal_Value(left) = result; 661 return left; 662 } 663} 664 665static PyObject* decimal_inplace_divide(PyObject* left, PyObject* right) 666{ 667 NSDecimal result; 668 NSCalculationError err; 669 int r = decimal_coerce(&left, &right); 670 if (r == 1) { 671 PyErr_Format(PyExc_TypeError, 672 "unsupported operand type(s) for /=: '%s' and '%s'", 673 left->ob_type->tp_name, 674 right->ob_type->tp_name); 675 return NULL; 676 } 677 678 err = NSDecimalDivide(&result, 679 &Decimal_Value(left), 680 &Decimal_Value(right), 681 NSRoundPlain); 682 if (err == NSCalculationOverflow) { 683 Py_DECREF(left); Py_DECREF(right); 684 PyErr_SetString(PyExc_OverflowError, "Numeric overflow"); 685 return NULL; 686 } else if (err == NSCalculationUnderflow) { 687 Py_DECREF(left); Py_DECREF(right); 688 PyErr_SetString(PyExc_OverflowError, "Numeric underflow"); 689 return NULL; 690 } else { 691 Py_DECREF(right); 692 NSDecimalCompact(&result); 693 Decimal_Value(left) = result; 694 return left; 695 } 696} 697 698static int decimal_nonzero(PyObject* self) 699{ 700 NSDecimal zero; 701 702 DecimalFromComponents(&zero, 0, 0, 0); 703 704 return NSDecimalCompare(&zero, &Decimal_Value(self)) == NSOrderedSame; 705} 706 707static PyObject* decimal_positive(PyObject* self) 708{ 709 Py_INCREF(self); 710 return self; 711} 712 713static PyObject* decimal_negative(PyObject* self) 714{ 715 NSDecimal result; 716 NSCalculationError err; 717 NSDecimal zero; 718 DecimalFromComponents(&zero, 0, 0, 0); 719 720 err = NSDecimalSubtract(&result, 721 &zero, 722 &Decimal_Value(self), 723 NSRoundPlain); 724 if (err == NSCalculationOverflow) { 725 PyErr_SetString(PyExc_OverflowError, "Numeric overflow"); 726 return NULL; 727 } else if (err == NSCalculationUnderflow) { 728 PyErr_SetString(PyExc_OverflowError, "Numeric underflow"); 729 return NULL; 730 } else { 731 NSDecimalCompact(&result); 732 return Decimal_New(&result); 733 } 734} 735 736static PyObject* decimal_absolute(PyObject* self) 737{ 738 NSDecimal result; 739 NSCalculationError err; 740 NSDecimal zero; 741 DecimalFromComponents(&zero, 0, 0, 0); 742 743 744 switch (NSDecimalCompare(&zero, &Decimal_Value(self))) { 745 case NSOrderedSame: 746 case NSOrderedAscending: 747 /* self >= 0 */ 748 Py_INCREF(self); 749 return self; 750 751 case NSOrderedDescending: ; 752 } 753 754 755 err = NSDecimalSubtract(&result, 756 &zero, 757 &Decimal_Value(self), 758 NSRoundPlain); 759 if (err == NSCalculationOverflow) { 760 PyErr_SetString(PyExc_OverflowError, "Numeric overflow"); 761 return NULL; 762 } else if (err == NSCalculationUnderflow) { 763 PyErr_SetString(PyExc_OverflowError, "Numeric underflow"); 764 return NULL; 765 } else { 766 NSDecimalCompact(&result); 767 return Decimal_New(&result); 768 } 769} 770 771static int decimal_coerce(PyObject** l, PyObject** r) 772{ 773 PyObject* right = NULL; 774 PyObject* left = NULL; 775 PyObject* args = NULL; 776 int res; 777 778 if (Decimal_Check(*l) && Decimal_Check(*r)) { 779 Py_INCREF(*l); 780 Py_INCREF(*r); 781 return 0; 782 } 783 784 if (!Decimal_Check(*l)) { 785 /* The test is needed to avoid silently converting strings */ 786 if (PyBytes_Check(*l) || PyUnicode_Check(*l) || PyFloat_Check(*l)) goto error; 787 788 left = (PyObject*)PyObject_New(DecimalObject, &Decimal_Type); 789 if (left == NULL) goto error; 790 791 args = Py_BuildValue("(O)", *l); 792 if (args == NULL) goto error; 793 794 res = decimal_init(left, args, NULL); 795 if (res == -1) goto error; 796 797 Py_DECREF(args); args = NULL; 798 } 799 800 if (!Decimal_Check(*r)) { 801 /* The test is needed to avoid silently converting strings */ 802 if (PyBytes_Check(*r) || PyUnicode_Check(*r) || PyFloat_Check(*r)) goto error; 803 804 right = (PyObject*)PyObject_New(DecimalObject, &Decimal_Type); 805 if (right == NULL) goto error; 806 807 args = Py_BuildValue("(O)", *r); 808 if (args == NULL) goto error; 809 810 res = decimal_init(right, args, NULL); 811 if (res == -1) goto error; 812 813 Py_DECREF(args); args = NULL; 814 } 815 816 if (left != NULL) { 817 *l = left; 818 } else { 819 Py_INCREF(*l); 820 } 821 822 if (right != NULL) { 823 *r = right; 824 } else { 825 Py_INCREF(*r); 826 } 827 828 return 0; 829 830error: 831 Py_XDECREF(args); 832 Py_XDECREF(left); 833 Py_XDECREF(right); 834 return 1; 835} 836 837static PyObject* 838decimal_repr(PyObject* self) 839{ 840 NSString* val = NSDecimalString(&Decimal_Value(self), NULL); 841 PyObject* tmp = PyObjC_IdToPython(val); 842 PyObject* repr = PyObject_Str(tmp); 843 Py_DECREF(tmp); 844 return repr; 845} 846 847static inline int 848Decimal_Convert(PyObject* self, void* val) 849{ 850 if (Decimal_Check(self)) { 851 *(NSDecimal**)val = &Decimal_Value(self); 852 return 1; 853 } 854 PyErr_SetString(PyExc_TypeError, "Expecting an NSDecimal"); 855 return 0; 856} 857 858 859static PyObject* 860Decimal_New(NSDecimal* aDecimal) 861{ 862 DecimalObject* result; 863 864 result = PyObject_New(DecimalObject, &Decimal_Type); 865 if (result == NULL) return NULL; 866 867 result->objc_value = nil; 868 result->value = *aDecimal; 869 return (PyObject*)result; 870} 871 872 873 874 875static PyObject* 876pythonify_nsdecimal(void* value) 877{ 878 return Decimal_New((NSDecimal*)value); 879} 880 881static int depythonify_nsdecimal(PyObject* value, void* out) 882{ 883 return Decimal_Convert(value, out) == 1 ? 0 : -1; 884} 885 886static PyObject* 887call_NSDecimalNumber_decimalWithDecimal_( 888 PyObject* method, PyObject* self, PyObject* arguments) 889{ 890 struct objc_super super; 891 NSDecimal* aDecimal; 892 id res; 893 894 if (!PyArg_ParseTuple(arguments, "O&", Decimal_Convert, &aDecimal)) { 895 return NULL; 896 } 897 898 PyObjC_DURING 899 PyObjC_InitSuperCls(&super, 900 PyObjCSelector_GetClass(method), 901 PyObjCClass_GetClass(self)); 902 903 res = objc_msgSendSuper(&super, 904 PyObjCSelector_GetSelector(method), 905 *aDecimal); 906 PyObjC_HANDLER 907 PyObjCErr_FromObjC(localException); 908 res = nil; 909 PyObjC_ENDHANDLER 910 911 if (res == nil && PyErr_Occurred()) { 912 return NULL; 913 } 914 915 return PyObjC_IdToPython(res); 916} 917 918static PyObject* 919call_NSDecimalNumber_initWithDecimal_( 920 PyObject* method, PyObject* self, PyObject* arguments) 921{ 922 struct objc_super super; 923 NSDecimal* aDecimal; 924 id res; 925 926 if (!PyArg_ParseTuple(arguments, "O&", Decimal_Convert, &aDecimal)) { 927 return NULL; 928 } 929 930 PyObjC_DURING 931 PyObjC_InitSuper(&super, 932 PyObjCSelector_GetClass(method), 933 PyObjCObject_GetObject(self)); 934 935 res = objc_msgSendSuper(&super, 936 PyObjCSelector_GetSelector(method), 937 *aDecimal); 938 PyObjC_HANDLER 939 PyObjCErr_FromObjC(localException); 940 res = nil; 941 PyObjC_ENDHANDLER 942 943 if (res == nil && PyErr_Occurred()) { 944 return NULL; 945 } 946 947 return PyObjC_IdToPython(res); 948} 949 950static void 951imp_NSDecimalNumber_initWithDecimal_( 952 void* cif __attribute__((__unused__)), 953 void* resp, 954 void** args, 955 void* callable) 956{ 957 id self = *(id*)args[0]; 958 //SEL _meth = *(SEL*)args[1]; 959 NSDecimal aDecimal = *(NSDecimal*)args[2]; 960 id* pretval = (id*)resp; 961 962 PyObject* result = NULL; 963 PyObject* arglist = NULL; 964 PyObject* v = NULL; 965 PyObject* pyself = NULL; 966 int cookie = 0; 967 968 PyGILState_STATE state = PyGILState_Ensure(); 969 970 arglist = PyTuple_New(2); 971 if (arglist == NULL) goto error; 972 973 pyself = PyObjCObject_NewTransient(self, &cookie); 974 if (pyself == NULL) goto error; 975 PyTuple_SetItem(arglist, 0, pyself); 976 Py_INCREF(pyself); 977 978 v = Decimal_New(&aDecimal); 979 if (v == NULL) goto error; 980 PyTuple_SetItem(arglist, 1, v); 981 982 result = PyObject_Call((PyObject*)callable, arglist, NULL); 983 Py_DECREF(arglist); arglist = NULL; 984 PyObjCObject_ReleaseTransient(pyself, cookie); pyself = NULL; 985 if (result == NULL) goto error; 986 987 *pretval = PyObjC_PythonToId(result); 988 Py_DECREF(result); 989 PyGILState_Release(state); 990 return; 991 992error: 993 *pretval = nil; 994 Py_XDECREF(arglist); 995 if (pyself) { 996 PyObjCObject_ReleaseTransient(pyself, cookie); 997 } 998 PyObjCErr_ToObjCWithGILState(&state); 999} 1000 1001static PyObject* 1002call_NSDecimalNumber_decimalValue( 1003 PyObject* method, PyObject* self, PyObject* arguments) 1004{ 1005 struct objc_super super; 1006 NSDecimal aDecimal; 1007 if (!PyArg_ParseTuple(arguments, "")) { 1008 return NULL; 1009 } 1010 1011 PyObjC_DURING 1012 PyObjC_InitSuper(&super, 1013 PyObjCSelector_GetClass(method), 1014 PyObjCObject_GetObject(self)); 1015 1016#if defined(__i386__) 1017 /* The call below doesn't work on i386, I'm not sure why. 1018 * Because nobody will every subclass NSDecimalNumber this is not 1019 * really a problem. 1020 */ 1021 aDecimal = [PyObjCObject_GetObject(self) decimalValue]; 1022#else 1023 ((void(*)(void*, struct objc_super*, SEL))objc_msgSendSuper_stret)(&aDecimal, &super, 1024 PyObjCSelector_GetSelector(method)); 1025#endif 1026 1027 PyObjC_HANDLER 1028 PyObjCErr_FromObjC(localException); 1029 PyObjC_ENDHANDLER 1030 1031 if (PyErr_Occurred()) { 1032 return NULL; 1033 } 1034 1035 return Decimal_New(&aDecimal); 1036} 1037 1038static void 1039imp_NSDecimalNumber_decimalValue( 1040 void* cif __attribute__((__unused__)), 1041 void* resp, 1042 void** args, 1043 void* callable) 1044{ 1045 id self = *(id*)args[0]; 1046 //SEL _meth = *(SEL*)args[1]; 1047 NSDecimal* pretval = (NSDecimal*)resp; 1048 NSDecimal* res = NULL; 1049 1050 PyObject* result = NULL; 1051 PyObject* arglist = NULL; 1052 PyObject* v = NULL; 1053 PyObject* pyself = NULL; 1054 int cookie = 0; 1055 1056 PyGILState_STATE state = PyGILState_Ensure(); 1057 1058 arglist = PyTuple_New(1); 1059 if (arglist == NULL) goto error; 1060 1061 v = PyObjC_IdToPython(self); 1062 if (v == NULL) goto error; 1063 PyTuple_SetItem(arglist, 0, v); 1064 1065 result = PyObject_Call((PyObject*)callable, arglist, NULL); 1066 Py_DECREF(arglist); arglist = NULL; 1067 PyObjCObject_ReleaseTransient(pyself, cookie); pyself = NULL; 1068 if (result == NULL) goto error; 1069 1070 Decimal_Convert(result, &res); 1071 *pretval = *res; 1072 Py_DECREF(result); 1073 PyGILState_Release(state); 1074 return; 1075 1076error: 1077 Py_XDECREF(arglist); 1078 if (pyself) { 1079 PyObjCObject_ReleaseTransient(pyself, cookie); 1080 } 1081 PyObjCErr_ToObjCWithGILState(&state); 1082} 1083 1084 1085static int setup_nsdecimal(PyObject* m) 1086{ 1087 PyType_Ready(&Decimal_Type); 1088 1089 if (PyModule_AddObject(m, "NSDecimal", (PyObject*)&Decimal_Type) == -1) { 1090 return -1; 1091 } 1092 1093 if (PyObjCPointerWrapper_Register(@encode(NSDecimal*), 1094 pythonify_nsdecimal, 1095 depythonify_nsdecimal) < 0) { 1096 return -1; 1097 } 1098 1099 if (PyObjCPointerWrapper_Register(@encode(const NSDecimal*), 1100 pythonify_nsdecimal, 1101 depythonify_nsdecimal) < 0) { 1102 return -1; 1103 } 1104 1105 /* Also register some variations of the encoded name because NSDecimal 1106 * doesn't have a struct tag and the metadata generators make up one 1107 * when creating the metadata. 1108 */ 1109 if (@encode(NSDecimal)[1] == '?') { 1110 char buffer[1024]; 1111 1112 buffer[0] = _C_CONST; 1113 buffer[1] = _C_PTR; 1114 buffer[2] = _C_STRUCT_B; 1115 1116 snprintf(buffer+3, sizeof(buffer) - 3, "_NSDecimal"); 1117 snprintf(buffer+2+sizeof("_NSDecimal"), 1118 sizeof(buffer)-2-sizeof("_NSDecimal"), 1119 @encode(NSDecimal) + 2); 1120 1121 if (PyObjCPointerWrapper_Register(buffer+1, 1122 pythonify_nsdecimal, 1123 depythonify_nsdecimal) < 0) { 1124 return -1; 1125 } 1126 1127 if (PyObjCPointerWrapper_Register(buffer, 1128 pythonify_nsdecimal, 1129 depythonify_nsdecimal) < 0) { 1130 return -1; 1131 } 1132 } 1133 1134 1135 Class classNSDecimalNumber = objc_lookUpClass("NSDecimalNumber"); 1136 Class classNSNumber = objc_lookUpClass("NSNumber"); 1137 1138 if (PyObjC_RegisterMethodMapping( 1139 classNSDecimalNumber, 1140 @selector(initWithDecimal:), 1141 call_NSDecimalNumber_initWithDecimal_, 1142 imp_NSDecimalNumber_initWithDecimal_) < 0) { 1143 return -1; 1144 } 1145 1146 Class classNSDecimalNumberPlaceholder = objc_lookUpClass("NSDecimalNumberPlaceholder"); 1147 if (classNSDecimalNumberPlaceholder != nil) { 1148 if (PyObjC_RegisterMethodMapping( 1149 classNSDecimalNumberPlaceholder, 1150 @selector(initWithDecimal:), 1151 call_NSDecimalNumber_initWithDecimal_, 1152 imp_NSDecimalNumber_initWithDecimal_) < 0) { 1153 1154 return -1; 1155 } 1156 } 1157 1158 if (PyObjC_RegisterMethodMapping( 1159 classNSDecimalNumber, 1160 @selector(decimalNumberWithDecimal:), 1161 call_NSDecimalNumber_decimalWithDecimal_, 1162 imp_NSDecimalNumber_initWithDecimal_) < 0) { 1163 return -1; 1164 } 1165 1166 if (PyObjC_RegisterMethodMapping( 1167 classNSNumber, 1168 @selector(decimalValue), 1169 call_NSDecimalNumber_decimalValue, 1170 imp_NSDecimalNumber_decimalValue) < 0) { 1171 return -1; 1172 } 1173 1174 return 0; 1175} 1176