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