1/* 2 * Wrappers for C structs 3 * 4 * Structs are represented as instance-like objects, with normal field access 5 * (e.g. myRect.size), but can also be accessed like read-write tuples (e.g. 6 * myRect[0]). 7 * 8 * Instances consist of the generic PyObject header followed by an array of 9 * fields. 10 * 11 * NOTE: The basic implementation is quite generic, but the end of this file 12 * is only usefull for PyObjC. 13 */ 14#include "pyobjc.h" 15 16/* 17 * First some helpers: easy access to the actual fields 18 */ 19static inline PyObject* 20GET_FIELD(PyObject* self, PyMemberDef* member) 21{ 22 PyObject* v; 23 24 v = *(PyObject**)(((char*)self) + member->offset); 25 if (v == NULL) { 26 return Py_None; 27 } else { 28 return v; 29 } 30} 31 32static inline void 33SET_FIELD(PyObject* self, PyMemberDef* member, PyObject* val) 34{ 35 PyObject* tmp; 36 Py_XINCREF(val); 37 38 tmp = *(PyObject**)(((char*)self) + member->offset); 39 *((PyObject**)(((char*)self) + member->offset)) = val; 40 Py_XDECREF(tmp); 41} 42 43/* 44 * Implementation of the sequence interface. 45 */ 46 47static Py_ssize_t 48struct_sq_length(PyObject* self) 49{ 50 /* The object contains the generic PyObject header followed by an 51 * array of PyObject*-s. 52 */ 53 return (Py_TYPE(self)->tp_basicsize - sizeof(PyObject)) / sizeof(PyObject*); 54} 55 56static PyObject* 57struct_sq_item(PyObject* self, Py_ssize_t offset) 58{ 59 Py_ssize_t len = struct_sq_length(self); 60 PyMemberDef* member; 61 PyObject* res; 62 63 if (offset < 0 || offset >= len) { 64 PyErr_Format(PyExc_IndexError, 65 "%s index out of range", 66 Py_TYPE(self)->tp_name); 67 return NULL; 68 } 69 70 member = Py_TYPE(self)->tp_members + offset; 71 res = GET_FIELD(self, member); 72 73 Py_INCREF(res); 74 return res; 75} 76 77static PyObject* 78struct_sq_slice(PyObject* self, Py_ssize_t ilow, Py_ssize_t ihigh) 79{ 80 PyObject* result; 81 Py_ssize_t i, len; 82 83 len = struct_sq_length(self); 84 if (ilow < 0) ilow = 0; 85 if (ihigh > len) ihigh = len; 86 87 result = PyTuple_New(ihigh - ilow); 88 if (result == NULL) { 89 return NULL; 90 } 91 92 for (i = ilow; i < ihigh; i++) { 93 PyMemberDef* member = Py_TYPE(self)->tp_members + i; 94 PyObject* v = GET_FIELD(self, member); 95 Py_INCREF(v); 96 PyTuple_SET_ITEM(result, i-ilow, v); 97 } 98 return result; 99} 100 101static int 102struct_sq_ass_item(PyObject* self, Py_ssize_t offset, PyObject* newVal) 103{ 104 Py_ssize_t len; 105 PyMemberDef* member; 106 107 if (newVal == NULL) { 108 PyErr_Format(PyExc_TypeError, 109 "Cannot delete item '%"PY_FORMAT_SIZE_T"d' in a %s instance", 110 offset, Py_TYPE(self)->tp_name); 111 return -1; 112 } 113 114 len = struct_sq_length(self); 115 116 if ((offset < 0) || (offset >= len)) { 117 PyErr_Format(PyExc_IndexError, 118 "%s index out of range", 119 Py_TYPE(self)->tp_name); 120 return -1; 121 } 122 member = Py_TYPE(self)->tp_members + offset; 123 SET_FIELD(self, member, newVal); 124 return 0; 125} 126 127static int 128struct_sq_ass_slice(PyObject* self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject* v) 129{ 130 PyObject* seq; 131 Py_ssize_t i, len; 132 133 if (v == NULL) { 134 PyErr_Format(PyExc_TypeError, 135 "Cannot delete items in an %s instance", 136 Py_TYPE(self)->tp_name); 137 return -1; 138 } 139 140 141 len = struct_sq_length(self); 142 if (ilow < 0) { 143 ilow = 0; 144 } else if (ilow > len) { 145 ilow = len; 146 } 147 148 if (ihigh < ilow) { 149 ihigh = ilow; 150 } else if (ihigh > len) { 151 ihigh = len; 152 } 153 154 seq = PySequence_Fast(v, "must assign sequence to slice"); 155 if (seq == NULL) return -1; 156 157 if (PySequence_Fast_GET_SIZE(seq) != ihigh - ilow) { 158 Py_DECREF(seq); 159 PyErr_Format(PyExc_TypeError, 160 "slice assignment would change size of %s " 161 "instance", Py_TYPE(self)->tp_name); 162 return -1; 163 } 164 165 for (i = ilow; i < ihigh; i++) { 166 PyObject* x; 167 PyMemberDef* member = Py_TYPE(self)->tp_members + i; 168 169 x = PySequence_Fast_GET_ITEM(seq, i-ilow); 170 if (x == NULL) { 171 Py_DECREF(seq); 172 return -1; 173 } 174 SET_FIELD(self, member, x); 175 } 176 Py_DECREF(seq); 177 return 0; 178} 179 180static int 181struct_sq_contains(PyObject* self, PyObject* value) 182{ 183 PyMemberDef* member = Py_TYPE(self)->tp_members; 184 185 while (member && member->name) { 186 int r; 187 PyObject* cur = GET_FIELD(self, member); 188 189 r = PyObject_RichCompareBool(cur, value, Py_EQ); 190 if (r == -1) { 191 PyErr_Clear(); 192 } else if (r) { 193 return 1; 194 } 195 } 196 return 0; 197} 198 199static PyObject* 200struct_reduce(PyObject* self) 201{ 202 PyObject* result; 203 PyObject* values; 204 Py_ssize_t i, len; 205 206 len = struct_sq_length(self); 207 values = PyTuple_New(len); 208 if (values == NULL) return NULL; 209 210 for (i = 0; i < len; i++) { 211 PyObject* v = GET_FIELD(self, Py_TYPE(self)->tp_members + i); 212 Py_INCREF(v); 213 PyTuple_SET_ITEM(values, i, v); 214 } 215 216 result = Py_BuildValue("(OO)", Py_TYPE(self), values); 217 Py_DECREF(values); 218 return result; 219} 220 221static PyObject* 222struct_copy(PyObject* self) 223{ 224 PyObject* result; 225 PyMemberDef* member = Py_TYPE(self)->tp_members; 226 227 result = PyObject_GC_New(PyObject, Py_TYPE(self)); 228 if (result == NULL) { 229 return NULL; 230 } 231 232 while (member && member->name) { 233 if (member->type != T_OBJECT) { 234 member++; 235 continue; 236 } 237 *((PyObject**)(((char*)result) + member->offset)) = NULL; 238 PyObject* t = GET_FIELD(self, member); 239 240 if (t != NULL) { 241 PyObject* m = PyObject_GetAttrString(t, "__pyobjc_copy__"); 242 if (m == NULL) { 243 PyErr_Clear(); 244 SET_FIELD(result, member, t); 245 } else { 246 PyObject* c = PyObject_CallObject(m, NULL); 247 Py_DECREF(m); 248 if (c == NULL) { 249 Py_DECREF(result); 250 return NULL; 251 } 252 SET_FIELD(result, member, c); 253 Py_DECREF(c); 254 } 255 } 256 257 member++; 258 } 259 260 PyObject_GC_Track(result); 261 return result; 262} 263 264static PyObject* 265struct_replace(PyObject* self, PyObject* args, PyObject* kwds) 266{ 267 /* XXX: This is a fairly inefficient implementation, first 268 * perform a deep copy, then replace attributes. The deep copy 269 * provides the nicest transition path to read-only structs: 270 * the result of _replace is completely independent of the original. 271 */ 272 PyObject* result; 273 Py_ssize_t pos = 0; 274 PyObject* key; 275 PyObject* value; 276 277 if (args && PySequence_Length(args) != 0) { 278 PyErr_SetString(PyExc_TypeError, 279 "_replace called with positional arguments"); 280 return NULL; 281 } 282 283 result = struct_copy(self); 284 if (result == NULL) { 285 return NULL; 286 } 287 288 while (PyDict_Next(kwds, &pos, &key, &value)) { 289 int r = PyObject_SetAttr(result, key, value); 290 if (r == -1) { 291 Py_DECREF(result); 292 return NULL; 293 } 294 } 295 296 return result; 297} 298 299static PyObject* 300struct_asdict(PyObject* self) 301{ 302 PyObject* result; 303 PyMemberDef* member = Py_TYPE(self)->tp_members; 304 int r; 305 306 result = PyDict_New(); 307 if (result == NULL) { 308 return NULL; 309 } 310 311 while (member && member->name) { 312 if (member->type != T_OBJECT) { 313 member++; 314 continue; 315 } 316 PyObject* t = GET_FIELD(self, member); 317 r = PyDict_SetItemString(result, member->name, t); 318 if (r == -1) { 319 Py_DECREF(result); 320 return NULL; 321 } 322 member++; 323 } 324 325 return result; 326} 327 328static PyObject* 329struct_mp_subscript(PyObject* self, PyObject* item) 330{ 331 if (PyIndex_Check(item)) { 332 Py_ssize_t i; 333 i = PyNumber_AsSsize_t(item, PyExc_IndexError); 334 if (i == -1 && PyErr_Occurred()) { 335 return NULL; 336 } 337 if (i < 0) { 338 i += struct_sq_length(self); 339 } 340 return struct_sq_item(self, i); 341 } else if (PySlice_Check(item)) { 342 Py_ssize_t start, stop, step, slicelength, cur, i; 343 PyObject* result; 344 PyObject* it; 345 346 if (PySlice_GetIndicesEx(SLICE_CAST(item), 347 struct_sq_length(self), 348 &start, &stop, &step, &slicelength) < 0) { 349 return NULL; 350 } 351 352 if (slicelength <= 0) { 353 return PyTuple_New(0); 354 } else if (step == 1) { 355 return struct_sq_slice(self, start, stop); 356 } else { 357 result = PyTuple_New(slicelength); 358 if (result == NULL) { 359 return NULL; 360 } 361 362 for (cur = start, i = 0; i < slicelength; 363 cur += step, i++) { 364 it = struct_sq_item(self, cur); 365 PyTuple_SET_ITEM(result, i, it); 366 } 367 return result; 368 } 369 370 } else { 371 PyErr_Format(PyExc_TypeError, 372 "struct indices must be integers, not %.200s", 373 Py_TYPE(item)->tp_name); 374 return NULL; 375 } 376} 377 378static int 379struct_mp_ass_subscript(PyObject* self, PyObject* item, PyObject* value) 380{ 381 if (PyIndex_Check(item)) { 382 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); 383 if (i == -1 && PyErr_Occurred()) { 384 return -1; 385 } 386 if (i < 0) { 387 i += struct_sq_length(self); 388 } 389 return struct_sq_ass_item(self, i, value); 390 } else if (PySlice_Check(item)) { 391 Py_ssize_t start, stop, step, slicelength; 392 393 if (PySlice_GetIndicesEx(SLICE_CAST(item), 394 struct_sq_length(self), &start, &stop, 395 &step, &slicelength) < 0) { 396 return -1; 397 } 398 if (step == 1) { 399 return struct_sq_ass_slice(self, start, stop, value); 400 } 401 402 if (value == NULL) { 403 PyErr_Format(PyExc_TypeError, 404 "Cannot delete items in an %s instance", 405 Py_TYPE(self)->tp_name); 406 return -1; 407 } 408 409 PyObject* seq = PySequence_Fast(value, 410 "must assign sequence to slice"); 411 if (seq == NULL) return -1; 412 413 if (PySequence_Fast_GET_SIZE(seq) != slicelength) { 414 Py_DECREF(seq); 415 PyErr_Format(PyExc_TypeError, 416 "slice assignment would change size of %s " 417 "instance", Py_TYPE(self)->tp_name); 418 return -1; 419 } 420 421 Py_ssize_t cur, i; 422 for (cur = start, i = 0; i < slicelength; cur += step, i++) { 423 int r = struct_sq_ass_item(self, cur, 424 PySequence_Fast_GET_ITEM(seq, i)); 425 if (r == -1) { 426 Py_DECREF(seq); 427 return -1; 428 } 429 } 430 431 Py_DECREF(seq); 432 return 0; 433 } else { 434 PyErr_Format(PyExc_TypeError, 435 "struct indices must be integers, not %.200s", 436 Py_TYPE(item)->tp_name); 437 return -1; 438 } 439} 440 441 442static PySequenceMethods struct_as_sequence = { 443 struct_sq_length, /* sq_length */ 444 NULL, /* sq_concat */ 445 NULL, /* sq_repeat */ 446 struct_sq_item, /* sq_item */ 447 struct_sq_slice, /* sq_slice */ 448 struct_sq_ass_item, /* sq_ass_item */ 449 struct_sq_ass_slice, /* sq_ass_slice */ 450 struct_sq_contains, /* sq_contains */ 451 NULL, /* sq_inplace_concat */ 452 NULL /* sq_inplace_repeat */ 453}; 454 455static PyMappingMethods struct_as_mapping = { 456 struct_sq_length, 457 struct_mp_subscript, 458 struct_mp_ass_subscript, 459}; 460 461static PyMethodDef struct_methods[] = { 462 { 463 "__reduce__", 464 (PyCFunction)struct_reduce, 465 METH_NOARGS, 466 NULL 467 }, 468 { 469 "copy", 470 (PyCFunction)struct_copy, 471 METH_NOARGS, 472 "Return a copy of the struct", 473 }, 474 { 475 "__pyobjc_copy__", 476 (PyCFunction)struct_copy, 477 METH_NOARGS, 478 NULL, 479 }, 480 /* NamedTuple interface */ 481 { 482 "_asdict", 483 (PyCFunction)struct_asdict, 484 METH_NOARGS, 485 NULL 486 }, 487 { 488 "_replace", 489 (PyCFunction)struct_replace, 490 METH_VARARGS|METH_KEYWORDS, 491 NULL 492 }, 493 { NULL, NULL, 0, NULL } 494}; 495 496 497/* 498 * Special methods 499 */ 500 501static int 502struct_setattro(PyObject* self, PyObject* name, PyObject* value) 503{ 504 if (value == NULL) { 505 PyErr_Format(PyExc_TypeError, "Cannot delete attributes of %s", 506 Py_TYPE(self)->tp_name); 507 return -1; 508 } 509 return PyObject_GenericSetAttr(self, name, value); 510} 511 512static void 513struct_dealloc(PyObject* self) 514{ 515 PyMemberDef* member = Py_TYPE(self)->tp_members; 516 517 PyObject_GC_UnTrack(self); 518 519 while (member && member->name) { 520 Py_XDECREF(*(PyObject**)(((char*)self)+member->offset)); 521 member++; 522 } 523 524 PyObject_GC_Del(self); 525} 526 527static PyObject* 528struct_new(PyTypeObject* type, PyObject* args, PyObject* kwds) 529{ 530 PyObject* result; 531 PyMemberDef* member = type->tp_members; 532 int r; 533 534 result = PyObject_GC_New(PyObject, type); 535 if (result == NULL) return NULL; 536 537 while (member && member->name) { 538 if (member->type != T_OBJECT) { 539 member++; 540 continue; 541 } 542 *((PyObject**)(((char*)result) + member->offset)) = NULL; 543 member++; 544 } 545 PyObject_GC_Track(result); 546 547 r = type->tp_init(result, args, kwds); 548 if (r == -1) { 549 Py_DECREF(result); 550 return NULL; 551 } 552 return result; 553} 554 555static int LOCATE_MEMBER(PyTypeObject* type, const char* name) 556{ 557 int i = 0; 558 PyMemberDef* member; 559 560 for (i = 0, member = type->tp_members; 561 member->name != NULL; i++, member++) { 562 if (strcmp(member->name, name) == 0) { 563 return i; 564 } 565 } 566 return -1; 567} 568 569static int set_defaults(PyObject* self, const char* typestr) 570{ 571 Py_ssize_t i = 0; 572 int r; 573 PyObject* v; 574 575 while(*typestr != _C_STRUCT_E && *typestr++ != '='); 576 while(typestr && *typestr != _C_STRUCT_E) { 577 const char* next; 578 579 if (*typestr == '"') { 580 /* embedded field names */ 581 typestr = strchr(typestr+1, '"'); 582 if (typestr) { 583 typestr++; 584 } else { 585 break; 586 } 587 } 588 next = PyObjCRT_SkipTypeSpec(typestr); 589 switch (*typestr) { 590#ifdef _C_BOOL 591 case _C_BOOL: 592 v = PyBool_FromLong(0); 593 break; 594#endif 595 case _C_NSBOOL: 596 v = PyBool_FromLong(0); 597 break; 598 599 case _C_CHAR_AS_TEXT: 600 { 601 char ch = 0; 602 v = PyText_FromStringAndSize(&ch, 1); 603 } 604 break; 605 606 case _C_UNICHAR: 607 { 608 Py_UNICODE ch = 0; 609 v = PyUnicode_FromUnicode(&ch, 1); 610 } 611 break; 612 613 case _C_CHAR_AS_INT: 614 case _C_CHR: case _C_UCHR: 615 case _C_SHT: case _C_USHT: 616 case _C_INT: case _C_UINT: 617 case _C_LNG: case _C_ULNG: 618 case _C_LNG_LNG: case _C_ULNG_LNG: 619 v = PyInt_FromLong(0); 620 break; 621 622 case _C_FLT: case _C_DBL: 623 v = PyFloat_FromDouble(0.0); 624 break; 625 626 case _C_STRUCT_B: 627 v = PyObjC_CreateRegisteredStruct(typestr, next-typestr, NULL, NULL); 628 if (v != NULL) { 629 /* call init */ 630 r = Py_TYPE(v)->tp_init(v, NULL, NULL); 631 if (r == -1) { 632 Py_DECREF(v); 633 return -1; 634 } 635 } else if (!PyErr_Occurred()) { 636 /* this is a struct-type without a struct 637 * wrapper. Default to None 638 */ 639 v = Py_None; 640 Py_INCREF(Py_None); 641 } 642 643 644 break; 645 646 default: 647 v = Py_None; 648 Py_INCREF(Py_None); 649 } 650 651 if (v == NULL) { 652 return -1; 653 } 654 655 r = PySequence_SetItem(self, i++, v); 656 Py_DECREF(v); 657 if (r != 0) { 658 return -1; 659 } 660 661 typestr = next; 662 } 663 664 return 0; 665} 666 667 668static void 669struct_init( 670 ffi_cif* cif __attribute__((__unused__)), 671 void* retval, 672 void** cargs, 673 void* userdata 674 ) 675{ 676 PyObject* self = *(PyObject**)cargs[0]; 677 PyObject* args = *(PyObject**)cargs[1]; 678 PyObject* kwds = *(PyObject**)cargs[2]; 679 const char* typestr = (char*)userdata; 680 Py_ssize_t setUntil = -1; 681 int r; 682 683 if (self == NULL) { 684 *(int**)retval = 0; 685 return; 686 } 687 688 if (args != NULL && !PyTuple_Check(args)) { 689 PyErr_Format(PyExc_TypeError, 690 "%s() argument tuple is not a tuple", 691 Py_TYPE(self)->tp_name); 692 *(int*)retval = -1; 693 return; 694 } 695 if (kwds != NULL && !PyDict_Check(kwds)) { 696 PyErr_Format(PyExc_TypeError, 697 "%s() keyword dict is not a dict", 698 Py_TYPE(self)->tp_name); 699 *(int*)retval = -1; 700 return; 701 } 702 703 r = set_defaults(self, typestr); 704 if (r != 0) { 705 *(int*)retval = r; 706 return; 707 } 708 709 if (args != NULL) { 710 Py_ssize_t i, len; 711 712 len = PyTuple_GET_SIZE(args); 713 if (len > struct_sq_length(self)) { 714 PyErr_Format(PyExc_TypeError, 715 "%s() takes at most %"PY_FORMAT_SIZE_T"d %sarguments (%"PY_FORMAT_SIZE_T"d given)", 716 Py_TYPE(self)->tp_name, 717 struct_sq_length(self), 718 kwds?"non-keyword ":"", len); 719 *(int*)retval = -1; 720 return; 721 } 722 for (i = 0; i < len; i++) { 723 PyObject* v = PyTuple_GET_ITEM(args, i); 724 725 SET_FIELD(self, Py_TYPE(self)->tp_members+i, v); 726 } 727 setUntil = len-1; 728 } 729 730 if (kwds != NULL) { 731 PyObject* keys; 732 int i, len; 733 734 keys = PyDict_Keys(kwds); 735 if (keys == NULL) { 736 *(int*)retval = -1; 737 return; 738 } 739 740 if (!PyList_Check(keys)) { 741 Py_DECREF(keys); 742 PyErr_SetString(PyExc_TypeError, 743 "dict.keys didn't return a list"); 744 *(int*)retval = -1; 745 return; 746 } 747 748 len = PyList_GET_SIZE(keys); 749 for (i = 0; i < len; i++) { 750 PyMemberDef* member; 751 Py_ssize_t off; 752 PyObject* k; 753 PyObject* v; 754 PyObject* k_bytes = NULL; 755 756 k = PyList_GET_ITEM(keys, i); 757 if (PyUnicode_Check(k)) { 758 k_bytes = PyUnicode_AsEncodedString(k, NULL, NULL); 759 if (k_bytes == NULL) { 760 *(int*)retval = -1; 761 return; 762 } 763#if PY_MAJOR_VERSION == 2 764 } else if (PyString_Check(k)) { 765 k_bytes = k; Py_INCREF(k_bytes); 766#endif 767 } else { 768 Py_DECREF(keys); 769 PyErr_Format(PyExc_TypeError, 770 "%s() keywords must be strings", 771 Py_TYPE(self)->tp_name); 772 *(int*)retval = -1; 773 return; 774 } 775 776 777 off = LOCATE_MEMBER(Py_TYPE(self), 778 PyBytes_AS_STRING(k_bytes)); 779 if (off == -1) { 780 PyErr_Format(PyExc_TypeError, 781 "no keyword argument: %s", 782 PyBytes_AS_STRING(k_bytes)); 783 Py_DECREF(k_bytes); 784 Py_DECREF(keys); 785 *(int*)retval = -1; 786 return; 787 } 788 789 if (off <= setUntil) { 790 PyErr_Format(PyExc_TypeError, 791 "%s() got multiple values for keyword " 792 "argument '%s'", 793 Py_TYPE(self)->tp_name, 794 PyBytes_AS_STRING(k_bytes)); 795 Py_DECREF(k_bytes); 796 Py_DECREF(keys); 797 *(int*)retval = -1; 798 return; 799 } 800 Py_DECREF(k_bytes); 801 802 member = Py_TYPE(self)->tp_members + off; 803 v = PyDict_GetItem(kwds, k); 804 SET_FIELD(self, member, v); 805 } 806 Py_DECREF(keys); 807 } 808 809 *(int*)retval = 0; 810 return; 811} 812 813static initproc 814make_init(const char* typestr) 815{ 816static ffi_cif* init_cif = NULL; 817 ffi_closure* cl = NULL; 818 ffi_status rv; 819 820 if (init_cif == NULL) { 821 PyObjCMethodSignature* signature; 822 signature = PyObjCMethodSignature_FromSignature("i^v^v^v", YES); 823 init_cif = PyObjCFFI_CIFForSignature(signature); 824 Py_DECREF(signature); 825 if (init_cif == NULL) { 826 return NULL; 827 } 828 } 829 830 cl = PyObjC_malloc_closure(); 831 if (cl == NULL) { 832 return NULL; 833 } 834 835 rv = ffi_prep_closure(cl, init_cif, struct_init, (char*)typestr); 836 if (rv != FFI_OK) { 837 PyObjC_free_closure(cl); 838 PyErr_Format(PyExc_RuntimeError, 839 "Cannot create FFI closure: %d", rv); 840 return NULL; 841 } 842 843 return (initproc)cl; 844} 845 846 847 848static long 849struct_hash(PyObject* self) 850{ 851 PyErr_Format(PyExc_TypeError, "%s objects are unhashable", 852 Py_TYPE(self)->tp_name); 853 return -1; 854} 855 856static PyObject* 857struct_richcompare(PyObject* self, PyObject* other, int op) 858{ 859 Py_ssize_t self_len, other_len, i, len; 860 int cmp; 861 PyObject* self_cur; 862 PyObject* other_cur; 863 864 if (!PySequence_Check(other)) { 865 if (op == Py_EQ) { 866 Py_INCREF(Py_False); 867 return Py_False; 868 } else if (op == Py_NE) { 869 Py_INCREF(Py_True); 870 return Py_True; 871 } else { 872 PyErr_Format(PyExc_TypeError, 873 "Cannot compare instances of %s and %s", 874 Py_TYPE(self)->tp_name, 875 Py_TYPE(other)->tp_name); 876 return NULL; 877 } 878 } 879 880 self_len = struct_sq_length(self); 881 other_len = PySequence_Length(other); 882 len = self_len; 883 if (other_len < len) { 884 len = other_len; 885 } 886 887 if (self_len != other_len && (op == Py_EQ || op == Py_NE)){ 888 /* Shortcut comparison for non-equals lengths */ 889 if (op == Py_EQ) { 890 Py_INCREF(Py_False); 891 return Py_False; 892 } else { 893 Py_INCREF(Py_True); 894 return Py_True; 895 } 896 } 897 898 for (i = 0; i < len; i ++) { 899 int k; 900 901 self_cur = GET_FIELD(self, Py_TYPE(self)->tp_members+i); 902 other_cur = PySequence_GetItem(other, i); 903 if (other_cur == NULL) return NULL; 904 905 k = PyObject_RichCompareBool(self_cur, other_cur, Py_EQ); 906 if (k < 0) { 907 Py_DECREF(other_cur); 908 return NULL; 909 } 910 911 if (!k) { 912 /* Not equal, result is the comparison of the last 913 * item, we can do better for '==' and '!='. 914 */ 915 PyObject* v; 916 917 if (op == Py_EQ) { 918 Py_INCREF(Py_False); 919 return Py_False; 920 } else if (op == Py_NE) { 921 Py_INCREF(Py_True); 922 return Py_True; 923 } 924 v = PyObject_RichCompare(self_cur, other_cur, op); 925 Py_DECREF(other_cur); 926 return v; 927 } 928 Py_DECREF(other_cur); 929 } 930 931 /* All items are equal, compare using sizes */ 932 switch (op) { 933 case Py_LT: cmp = self_len < other_len; break; 934 case Py_LE: cmp = self_len <= other_len; break; 935 case Py_EQ: cmp = self_len == other_len; break; 936 case Py_NE: cmp = self_len != other_len; break; 937 case Py_GE: cmp = self_len >= other_len; break; 938 case Py_GT: cmp = self_len > other_len; break; 939 default: 940 /* Should never happen */ 941 PyErr_SetString(PyExc_TypeError, "Invalid comparion"); 942 return NULL; 943 } 944 if (cmp) { 945 Py_INCREF(Py_True); 946 return Py_True; 947 } else { 948 Py_INCREF(Py_False); 949 return Py_False; 950 } 951} 952 953static int 954struct_traverse(PyObject* self, visitproc visit, void* arg) 955{ 956 PyMemberDef* member; 957 PyObject* v; 958 int err; 959 960 for (member = Py_TYPE(self)->tp_members; 961 member && member->name; member++) { 962 v = GET_FIELD(self, member); 963 if (v == NULL) continue; 964 err = visit(v, arg); 965 if (err) return err; 966 } 967 return 0; 968} 969 970static int 971struct_clear(PyObject* self) 972{ 973 PyMemberDef* member; 974 975 for (member = Py_TYPE(self)->tp_members; 976 member && member->name; member++) { 977 SET_FIELD(self, member, NULL); 978 } 979 return 0; 980} 981 982 983 984static PyObject* 985struct_repr(PyObject* self) 986{ 987 Py_ssize_t i, len; 988 PyObject* cur; 989 PyMemberDef* member; 990 991 len = struct_sq_length(self); 992 if (len == 0) { 993 return PyText_FromFormat("<%s>", 994 Py_TYPE(self)->tp_name); 995 } 996 997 i = Py_ReprEnter(self); 998 if (i < 0) { 999 return NULL; 1000 } else if (i != 0) { 1001 /* Self-recursive struct */ 1002 return PyText_FromFormat("<%s ...>", 1003 Py_TYPE(self)->tp_name); 1004 } 1005 1006 cur = PyText_FromFormat("<%s", Py_TYPE(self)->tp_name); 1007 1008 member = Py_TYPE(self)->tp_members; 1009 while (member->name != NULL) { 1010 PyObject* v; 1011 1012 PyText_Append(&cur, 1013 PyText_FromFormat(" %s=", member->name)); 1014 if (cur == NULL) goto done; 1015 1016 v = GET_FIELD(self, member); 1017 1018 PyText_Append(&cur, PyObject_Repr(v)); 1019 if (cur == NULL) goto done; 1020 member++; 1021 } 1022 1023 PyText_Append(&cur, PyText_FromString(">")); 1024 1025done: 1026 Py_ReprLeave(self); 1027 return cur; 1028} 1029 1030struct StructTypeObject { 1031 PyTypeObject base; 1032 Py_ssize_t pack; /* struct packing, -1 for default packing */ 1033}; 1034 1035/* 1036 * A template for the type object 1037 */ 1038static struct StructTypeObject StructTemplate_Type = { 1039 { 1040 PyVarObject_HEAD_INIT(NULL, 0) 1041 "objc.StructTemplate", /* tp_name */ 1042 sizeof (PyObject*), /* tp_basicsize */ 1043 0, /* tp_itemsize */ 1044 1045 /* methods */ 1046 struct_dealloc, /* tp_dealloc */ 1047 0, /* tp_print */ 1048 0, /* tp_getattr */ 1049 0, /* tp_setattr */ 1050 0, /* tp_compare */ 1051 struct_repr, /* tp_repr */ 1052 0, /* tp_as_number */ 1053 &struct_as_sequence, /* tp_as_sequence */ 1054 &struct_as_mapping, /* tp_as_mapping */ 1055 struct_hash, /* tp_hash */ 1056 0, /* tp_call */ 1057 0, /* tp_str */ 1058 PyObject_GenericGetAttr, /* tp_getattro */ 1059 struct_setattro, /* tp_setattro */ 1060 0, /* tp_as_buffer */ 1061 Py_TPFLAGS_DEFAULT 1062#if PY_MAJOR_VERSION == 2 1063 | Py_TPFLAGS_HAVE_RICHCOMPARE 1064#endif 1065 | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 1066 0, /* tp_doc */ 1067 struct_traverse, /* tp_traverse */ 1068 struct_clear, /* tp_clear */ 1069 struct_richcompare, /* tp_richcompare */ 1070 0, /* tp_weaklistoffset */ 1071 0, /* tp_iter */ 1072 0, /* tp_iternext */ 1073 struct_methods, /* tp_methods */ 1074 0, /* tp_members */ 1075 0, /* tp_getset */ 1076 0, /* tp_base */ 1077 0, /* tp_dict */ 1078 0, /* tp_descr_get */ 1079 0, /* tp_descr_set */ 1080 0, /* tp_dictoffset */ 1081 0, /* tp_init */ 1082 0, /* tp_alloc */ 1083 struct_new, /* tp_new */ 1084 0, /* tp_free */ 1085 0, /* tp_is_gc */ 1086 0, /* tp_bases */ 1087 0, /* tp_mro */ 1088 0, /* tp_cache */ 1089 0, /* tp_subclasses */ 1090 0, /* tp_weaklist */ 1091 0 /* tp_del */ 1092#if PY_VERSION_HEX >= 0x02060000 1093 , 0 /* tp_version_tag */ 1094#endif 1095 }, 1096 -1 1097}; 1098 1099PyObject* 1100PyObjC_MakeStructType( 1101 const char* name, 1102 const char* doc, 1103 initproc tpinit, 1104 Py_ssize_t numFields, 1105 const char** fieldnames, 1106 const char* typestr, 1107 Py_ssize_t pack) 1108{ 1109 struct StructTypeObject* result; 1110 PyMemberDef* members; 1111 PyObject* fields; 1112 Py_ssize_t i; 1113 1114 fields = PyTuple_New(numFields); 1115 if (fields == NULL) { 1116 return NULL; 1117 } 1118 1119 members = PyMem_Malloc(sizeof(PyMemberDef) * (numFields+1)); 1120 if (members == NULL) { 1121 Py_DECREF(fields); 1122 PyErr_NoMemory(); 1123 return NULL; 1124 } 1125 for (i = 0; i < numFields; i++) { 1126 PyObject* nm = PyText_FromString(fieldnames[i]); 1127 if (nm == NULL) { 1128 Py_DECREF(fields); 1129 PyMem_Free(members); 1130 return NULL; 1131 } 1132 PyTuple_SET_ITEM(fields, i, nm); nm = NULL; 1133 members[i].name = (char*)fieldnames[i]; 1134 members[i].type = T_OBJECT; 1135 members[i].offset = sizeof(PyObject) + i*sizeof(PyObject*); 1136 members[i].flags = 0; /* A read-write field */ 1137 members[i].doc = NULL; 1138 1139 } 1140 members[numFields].name = NULL; 1141 1142 result = PyMem_Malloc(sizeof(struct StructTypeObject)); 1143 if (result == NULL) { 1144 Py_DECREF(fields); 1145 PyMem_Free(members); 1146 PyErr_NoMemory(); 1147 return NULL; 1148 } 1149 1150 *result = StructTemplate_Type; 1151 result->base.tp_name = (char*)name; 1152 result->base.tp_doc = (char*)doc; 1153 result->base.tp_dict = PyDict_New(); 1154 if (result->base.tp_dict == NULL) { 1155 Py_DECREF(fields); 1156 PyMem_Free(members); 1157 PyMem_Free(result); 1158 return NULL; 1159 } 1160 Py_REFCNT(result) = 1; 1161 result->base.tp_members = members; 1162 result->base.tp_basicsize = sizeof(PyObject) + numFields*sizeof(PyObject*); 1163 if (PyDict_SetItemString(result->base.tp_dict, "_fields", fields)==-1){ 1164 Py_DECREF(fields); 1165 PyMem_Free(members); 1166 PyMem_Free(result); 1167 return NULL; 1168 } 1169 Py_CLEAR(fields); 1170 1171 if (tpinit) { 1172 result->base.tp_init = tpinit; 1173 } else { 1174 result->base.tp_init = make_init(typestr); 1175 if (result->base.tp_init == NULL) { 1176 PyMem_Free(members); 1177 PyMem_Free(result); 1178 return NULL; 1179 } 1180 } 1181 1182 /* XXX: Add _fields to tp_dict (NamedTuple interface */ 1183 1184 result->pack = pack; 1185 1186 if (PyType_Ready((PyTypeObject*)result) == -1) { 1187 /* Is freeing save? */ 1188 PyMem_Free(result); 1189 PyMem_Free(members); 1190 return NULL; 1191 } 1192 return (PyObject*)result; 1193} 1194 1195/* 1196 * This is the start of PyObjC specific code 1197 */ 1198 1199static PyObject* structRegistry = NULL; 1200 1201PyObject* 1202PyObjC_CreateRegisteredStruct(const char* signature, Py_ssize_t len, const char** objc_encoding, Py_ssize_t* ppack) 1203{ 1204 PyTypeObject* type; 1205 PyObject* result; 1206 PyObject* v; 1207 PyMemberDef* member; 1208 1209 if (structRegistry == NULL) return NULL; 1210 1211 if (ppack != NULL) { 1212 *ppack = -1; 1213 } 1214 1215 v = PyText_FromStringAndSize(signature, len); 1216 type = (PyTypeObject*)PyDict_GetItem(structRegistry, v); 1217 Py_DECREF(v); 1218 if (type == NULL) { 1219 PyErr_Clear(); 1220 return NULL; 1221 } 1222 1223 member = type->tp_members; 1224 1225 result = PyObject_GC_New(PyObject, type); 1226 if (result == NULL) { 1227 PyErr_Clear(); 1228 return NULL; 1229 } 1230 1231 while (member && member->name) { 1232 if (member->type != T_OBJECT) { 1233 member++; 1234 continue; 1235 } 1236 *((PyObject**)(((char*)result) + member->offset)) = NULL; 1237 member++; 1238 } 1239 1240 PyObject_GC_Track(result); 1241 1242 if (objc_encoding) { 1243 PyObject* typestr = PyDict_GetItemString(type->tp_dict, "__typestr__"); 1244 if (typestr != NULL) { 1245 *objc_encoding = PyBytes_AsString(typestr); 1246 } else { 1247 *objc_encoding = signature; 1248 } 1249 } 1250 if (ppack != NULL) { 1251 *ppack = ((struct StructTypeObject*)type)->pack; 1252 } 1253 return result; 1254} 1255 1256 1257PyObject* 1258PyObjC_RegisterStructType( 1259 const char* signature, 1260 const char* name, 1261 const char* doc, 1262 initproc tpinit, 1263 Py_ssize_t numFields, 1264 const char** fieldnames, 1265 Py_ssize_t pack) 1266{ 1267 PyObject* structType; 1268 PyObject* v; 1269 int r; 1270 int freeNames = 0; 1271 1272 if (numFields == -1) { 1273 /* XXX: extract me into a seperate function, 1274 * and improve error checking/recovery. 1275 */ 1276 /* Don't use fieldnames, but extract the names 1277 * from the type signature. 1278 */ 1279 const char* sigcur = signature; 1280 const char* fieldstart; 1281 1282 if (*sigcur != _C_STRUCT_B) { 1283 PyErr_SetString(PyExc_ValueError, "invalid signature: not a struct encoding"); 1284 return NULL; 1285 } 1286 1287 1288 while (*sigcur && *sigcur != _C_STRUCT_E && *sigcur != '=') sigcur++; 1289 1290 if (!*sigcur || *sigcur == _C_STRUCT_E) { 1291 PyErr_SetString(PyExc_ValueError, "invalid signature: not a complete struct encoding"); 1292 return NULL; 1293 } 1294 1295 fieldstart = ++sigcur; 1296 numFields = 0; 1297 1298 while (*sigcur != _C_STRUCT_E) { 1299 numFields ++; 1300 if (*sigcur == '"') { 1301 sigcur++; 1302 sigcur = strchr(sigcur, '"'); 1303 if (sigcur == NULL) { 1304 PyErr_SetString(PyExc_ValueError, "invalid signature: embedded field name without end"); 1305 return NULL; 1306 } 1307 sigcur++; 1308 } else { 1309 PyErr_SetString(PyExc_ValueError, "invalid signature: not all fields have an embedded name"); 1310 return NULL; 1311 } 1312 if (*sigcur == _C_STRUCT_E) break; 1313 sigcur = PyObjCRT_NextField(sigcur); 1314 if (sigcur == NULL) { 1315 return NULL; 1316 } 1317 } 1318 1319 fieldnames = PyMem_Malloc((numFields + 1) * sizeof(char*)); 1320 numFields = 0; 1321 1322 sigcur = fieldstart; 1323 while (*sigcur != _C_STRUCT_E) { 1324 if (*sigcur == '"') { 1325 char* end; 1326 sigcur++; 1327 end = strchr(sigcur, '"'); 1328 1329 if (end == NULL) { 1330 PyErr_SetString(PyExc_ValueError, "invalid signature: embedded field name without end"); 1331 return NULL; 1332 } 1333 fieldnames[numFields] = PyMem_Malloc(end - sigcur + 1); 1334 memcpy((char*)fieldnames[numFields], sigcur, end-sigcur); 1335 ((char*)fieldnames[numFields])[end-sigcur] = '\0'; 1336 sigcur = end + 1; 1337 } 1338 numFields ++; 1339 sigcur = PyObjCRT_NextField(sigcur); 1340 } 1341 fieldnames[numFields] = NULL; 1342 freeNames = 1; 1343 1344 /* 1345 * The signature string still contains embedded field names, 1346 * remove those. 1347 */ 1348 char* sigtmp = PyMem_Malloc(strlen(signature)+20); 1349 if (sigtmp == NULL) { 1350 PyErr_NoMemory(); 1351 return NULL; 1352 } 1353 if (PyObjCRT_RemoveFieldNames(sigtmp, signature) == NULL) { 1354 PyMem_Free(sigtmp); 1355 return NULL; 1356 } 1357 signature = sigtmp; 1358 } 1359 1360 1361 structType = PyObjC_MakeStructType(name, doc, tpinit, 1362 numFields, fieldnames, signature, pack); 1363 if (structType == NULL) { 1364 if (freeNames) { 1365 int i; 1366 PyMem_Free((char*)signature); 1367 for (i = 0; i < numFields; i++) { 1368 PyMem_Free((char*)fieldnames[i]); 1369 } 1370 PyMem_Free(fieldnames); 1371 } 1372 return NULL; 1373 } 1374 1375 v = PyBytes_FromString(signature); 1376 if (v == NULL) { 1377 Py_DECREF(structType); 1378 return NULL; 1379 } 1380 1381 r = PyDict_SetItemString(((PyTypeObject*)structType)->tp_dict, "__typestr__", v); 1382 Py_DECREF(v); 1383 if (r == -1) { 1384 Py_DECREF(structType); 1385 return NULL; 1386 } 1387 1388 if (pack != -1) { 1389 /* Store custom struct packing as an attribute of the type 1390 * object, to be able to fetch it when depythonifying the object. 1391 * 1392 * XXX: Need a cleaner method for doing this. 1393 */ 1394 v = Py_BuildValue(Py_ARG_SIZE_T, pack); 1395 if (v == NULL) { 1396 Py_DECREF(structType); 1397 return NULL; 1398 } 1399 r = PyDict_SetItemString(((PyTypeObject*)structType)->tp_dict, "__struct_pack__", v); 1400 Py_DECREF(v); 1401 if (v == NULL) { 1402 Py_DECREF(structType); 1403 return NULL; 1404 } 1405 } 1406 1407 if (structRegistry == NULL) { 1408 structRegistry = PyDict_New(); 1409 if (structRegistry == NULL) { 1410 /* This leaks some memory, but we cannot safely 1411 * deallocate the type 1412 */ 1413 return NULL; 1414 } 1415 } 1416 1417 r = PyDict_SetItemString(structRegistry, signature, structType); 1418 if (r == -1) { 1419 /* This leaks some memory, but we cannot safely 1420 * deallocate the type 1421 */ 1422 return NULL; 1423 } 1424 1425 /* Register again using the typecode used in the ObjC runtime */ 1426 PyObjC_RemoveInternalTypeCodes((char*)signature); 1427 r = PyDict_SetItemString(structRegistry, signature, structType); 1428 if (r == -1) { 1429 return NULL; 1430 } 1431 1432 return structType; 1433} 1434 1435int 1436PyObjC_RegisterStructAlias(const char* signature, PyObject* structType) 1437{ 1438 char buf[1024]; 1439 int r; 1440 1441 if (strlen(signature) > 1023) { 1442 PyErr_SetString(PyExc_ValueError, "typestr too long"); 1443 return -1; 1444 } 1445 if (PyObjCRT_RemoveFieldNames(buf, signature) == NULL) { 1446 return -1; 1447 } 1448 1449 if (structRegistry == NULL) { 1450 structRegistry = PyDict_New(); 1451 if (structRegistry == NULL) { 1452 return -1; 1453 } 1454 } 1455 1456 r = PyDict_SetItemString(structRegistry, buf, structType); 1457 if (r == -1) { 1458 return -1; 1459 } 1460 1461 /* Register again using the typecode used in the ObjC runtime */ 1462 PyObjC_RemoveInternalTypeCodes(buf); 1463 r = PyDict_SetItemString(structRegistry, buf, structType); 1464 if (r == -1) { 1465 return -1; 1466 } 1467 1468 return 0; 1469} 1470