1/* 2 * Some utility functions... 3 * 4 * TODO: Documentation 5 */ 6 7#include "pyobjc.h" 8 9#import <Foundation/Foundation.h> 10 11PyObject* PyObjCExc_Error; 12PyObject* PyObjCExc_NoSuchClassError; 13PyObject* PyObjCExc_InternalError; 14PyObject* PyObjCExc_UnInitDeallocWarning; 15PyObject* PyObjCExc_ObjCRevivalWarning; 16PyObject* PyObjCExc_LockError; 17PyObject* PyObjCExc_BadPrototypeError; 18 19 20 21int 22PyObjCUtil_Init(PyObject* module) 23{ 24#define NEW_EXC(identifier, name, base_class) \ 25 identifier = PyErr_NewException("objc."name, base_class, NULL); \ 26 if (identifier == NULL) return -1; \ 27 Py_INCREF(identifier); \ 28 if (PyModule_AddObject(module, name, identifier) < 0) return -1; 29 30 NEW_EXC(PyObjCExc_Error, "error", NULL); 31 NEW_EXC(PyObjCExc_NoSuchClassError, "nosuchclass_error", PyObjCExc_Error); 32 NEW_EXC(PyObjCExc_InternalError, "internal_error", PyObjCExc_Error); 33 NEW_EXC(PyObjCExc_UnInitDeallocWarning, "UninitializedDeallocWarning", PyExc_Warning); 34 NEW_EXC(PyObjCExc_ObjCRevivalWarning, "RevivedObjectiveCObjectWarning", PyExc_Warning); 35 NEW_EXC(PyObjCExc_LockError, "LockError", PyObjCExc_Error); 36 NEW_EXC(PyObjCExc_BadPrototypeError, "BadPrototypeError", PyObjCExc_Error); 37 38 return 0; 39} 40 41static PyObject* 42ObjCErr_PyExcForName(const char* value) 43{ 44 /* XXX: This table should be changeable from python */ 45 if (strcmp(value, "NSRangeException") == 0) { 46 return PyExc_IndexError; 47 } else if (strcmp(value, "NSInvalidArgumentException") == 0) { 48 return PyExc_ValueError; 49 } else if (strcmp(value, "NSMallocException") == 0) { 50 return PyExc_MemoryError; 51 } else if (strcmp(value, "NSUnknownKeyException") == 0) { 52 return PyExc_KeyError; 53 } 54 55 return PyObjCExc_Error; 56} 57 58 59void 60PyObjCErr_FromObjC(NSException* localException) 61{ 62 NSDictionary* userInfo; 63 PyObject* dict; 64 PyObject* exception; 65 PyObject* v; 66 PyObject* buf; 67 PyObject* exc_type; 68 PyObject* exc_value; 69 PyObject* exc_traceback; 70 PyObject* c_localException_name; 71 PyObject* c_localException_reason; 72 NSObject* t; 73 74 PyGILState_STATE state; 75 76 state = PyGILState_Ensure(); 77 78 if (![localException isKindOfClass:[NSException class]]) { 79 /* We caught some random objects as the exception, so the minimal possible 80 */ 81 PyErr_SetString(PyObjCExc_Error, "non-NSException object caught"); 82 83 PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); 84 if (!exc_value || !PyObject_IsInstance(exc_value, exc_type)) { 85 PyErr_NormalizeException(&exc_type, &exc_value, &exc_traceback); 86 } 87 88 PyObject* exc = PyObjC_IdToPython(localException); 89 if (exc == NULL) { 90 PyErr_Clear(); 91 } else { 92 PyObject_SetAttrString(exc_value, "_pyobjc_exc_", exc); 93 } 94 Py_DECREF(exc); exc = NULL; 95 PyErr_Restore(exc_type, exc_value, exc_traceback); 96 PyGILState_Release(state); 97 return; 98 } 99 100 exception = ObjCErr_PyExcForName([[localException name] UTF8String]); 101 102 userInfo = [localException userInfo]; 103 if (userInfo) { 104 id val; 105 106 val = [userInfo objectForKey:@"__pyobjc_exc_type__"]; 107 if (val) { 108 exc_type = [val pyObject]; 109 exc_value = [[userInfo objectForKey:@"__pyobjc_exc_value__"] pyObject]; 110 exc_traceback = [[userInfo objectForKey:@"__pyobjc_exc_traceback__"] pyObject]; 111 112 /* -pyObject returns a borrowed reference and 113 * PyErr_Restore steals one from us. 114 */ 115 Py_INCREF(exc_type); 116 Py_XINCREF(exc_value); 117 Py_XINCREF(exc_traceback); 118 119 PyErr_Restore(exc_type, exc_value, exc_traceback); 120 PyGILState_Release(state); 121 return; 122 } 123 } 124 125 t = [localException name]; 126 c_localException_name = pythonify_c_value(@encode(NSObject*), &t); 127 if (c_localException_name == NULL) { 128 return; 129 } 130 131 t = [localException reason]; 132 c_localException_reason = pythonify_c_value(@encode(NSObject*), &t); 133 if (c_localException_reason == NULL) { 134 Py_DECREF(c_localException_name); 135 return; 136 } 137 138 dict = PyDict_New(); 139 if (dict == NULL) { 140 Py_DECREF(c_localException_name); 141 Py_DECREF(c_localException_reason); 142 return; 143 } 144 PyDict_SetItemString(dict, "name", c_localException_name); 145 Py_DECREF(c_localException_name); 146 147 PyDict_SetItemString(dict, "reason", c_localException_reason); 148 Py_DECREF(c_localException_reason); 149 if (userInfo) { 150 v = PyObjCObject_New(userInfo, PyObjCObject_kDEFAULT, YES); 151 if (v != NULL) { 152 PyDict_SetItemString(dict, "userInfo", v); 153 Py_DECREF(v); 154 } else { 155 PyErr_Clear(); 156 } 157 } else { 158 PyDict_SetItemString(dict, "userInfo", Py_None); 159 } 160 161#if 0 162 /* build the description as a NSString to maintain the highest 163 * fidelity. 164 * This code is disabled because the base exception class doesn't 165 * like unicode arguments, that will wreak havoc when converting the 166 * exception to text, which in turn makes it impossible to find out 167 * what the exception actually was without poking in the PyObjC 168 * specific fields. 169 */ 170 NSString* description = [NSString stringWithFormat:@"%@ - %@", 171 [localException name], [localException reason]]; 172 if (description == nil) { 173 PyErr_SetString(exception, "<<<UNKNOWN REASON>>>"); 174 } else { 175 buf = pythonify_c_value(@encode(NSObject*), &description); 176 if (buf == NULL) { 177 Py_DECREF(dict); 178 PyGILState_Release(state); 179 return; 180 } 181 } 182#else 183 buf = PyString_FromFormat("%s - %s", 184 [[localException name] UTF8String], 185 [[localException reason] UTF8String]); 186 PyErr_SetObject(exception, buf); 187#endif 188 PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); 189 if (!exc_value || !PyObject_IsInstance(exc_value, exc_type)) { 190 PyErr_NormalizeException(&exc_type, &exc_value, &exc_traceback); 191 } 192 193 PyObject_SetAttrString(exc_value, "_pyobjc_info_", dict); 194 Py_DECREF(dict); dict = NULL; 195 PyObject_SetAttrString(exc_value, "name", c_localException_name); 196 PyErr_Restore(exc_type, exc_value, exc_traceback); 197 PyGILState_Release(state); 198} 199 200void 201PyObjCErr_ToObjC(void) 202{ 203 PyObjCErr_ToObjCWithGILState(NULL); 204} 205 206 207NSException* 208PyObjCErr_AsExc(void) 209{ 210 PyObject* exc_type; 211 PyObject* exc_value; 212 PyObject* exc_traceback; 213 PyObject* args; 214 PyObject* repr; 215 PyObject* typerepr; 216 NSException* val; 217 NSMutableDictionary* userInfo; 218 219 PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); 220 if (exc_type == NULL) { 221 return nil; 222 } 223 224 PyErr_NormalizeException(&exc_type, &exc_value, &exc_traceback); 225 226 args = PyObject_GetAttrString(exc_value, "_pyobjc_exc_"); 227 if (args == NULL) { 228 PyErr_Clear(); 229 } else { 230 return PyObjC_PythonToId(args); 231 } 232 233 args = PyObject_GetAttrString(exc_value, "_pyobjc_info_"); 234 if (args == NULL) { 235 PyErr_Clear(); 236 } else { 237 /* This may be an exception that started out in 238 * Objective-C code. 239 */ 240 PyObject* v; 241 NSString* reason = NULL; 242 NSString* name = NULL; 243 244 v = PyDict_GetItemString(args, "reason"); 245 if (v) { 246 if (depythonify_c_value(@encode(NSObject*), v, &reason) < 0) { 247 PyErr_Clear(); 248 } 249 } 250 251 v = PyDict_GetItemString(args, "name"); 252 if (v) { 253 if (depythonify_c_value(@encode(NSObject*), v, &name) < 0) { 254 PyErr_Clear(); 255 } 256 } 257 258 v = PyDict_GetItemString(args, "userInfo"); 259 if (v && PyObjCObject_Check(v)) { 260 userInfo = PyObjCObject_GetObject(v); 261 } else { 262 userInfo = nil; 263 PyErr_Clear(); 264 } 265 266 if (name && reason) { 267 val = [NSException exceptionWithName:name 268 reason:reason 269 userInfo:userInfo]; 270 Py_DECREF(args); 271 Py_XDECREF(exc_type); 272 Py_XDECREF(exc_value); 273 Py_XDECREF(exc_traceback); 274 275 return val; 276 } 277 } 278 279 repr = PyObject_Str(exc_value); 280 typerepr = PyObject_Str(exc_type); 281 userInfo = [NSMutableDictionary dictionaryWithCapacity: 3]; 282 [userInfo setObject: 283 [OC_PythonObject newWithObject:exc_type] 284 forKey:@"__pyobjc_exc_type__"]; 285 if (exc_value != NULL) 286 [userInfo setObject: 287 [OC_PythonObject newWithObject:exc_value] 288 forKey:@"__pyobjc_exc_value__"]; 289 if (exc_traceback != NULL) 290 [userInfo setObject: 291 [OC_PythonObject newWithObject:exc_traceback] 292 forKey:@"__pyobjc_exc_traceback__"]; 293 294 val = [NSException 295 exceptionWithName:@"OC_PythonException" 296 reason:[NSString stringWithFormat:@"%s: %s", PyString_AS_STRING(typerepr), PyString_AS_STRING(repr)] 297 userInfo:userInfo]; 298 299 Py_DECREF(typerepr); 300 Py_DECREF(repr); 301 302 if (PyObjC_VerboseLevel) { 303 PyErr_Restore(exc_type, exc_value , exc_traceback); 304 NSLog(@"PyObjC: Converting exception to Objective-C:"); 305 PyErr_Print(); 306 } else { 307 Py_DECREF(exc_type); 308 Py_XDECREF(exc_value); 309 Py_XDECREF(exc_traceback); 310 } 311 return val; 312} 313 314void 315PyObjCErr_ToObjCWithGILState(PyGILState_STATE* state) 316{ 317 NSException* exc = PyObjCErr_AsExc(); 318 319 if (state) { 320 PyGILState_Release(*state); 321 } 322 [exc raise]; 323} 324 325 326char* 327PyObjCUtil_Strdup(const char* value) 328{ 329 Py_ssize_t len; 330 char* result; 331 332 len = strlen(value); 333 result = PyMem_Malloc(len+1); 334 if (result == NULL) return NULL; 335 336 memcpy(result, value, len); 337 result[len] = 0; 338 return result; 339} 340 341 342NSMapTableKeyCallBacks PyObjCUtil_PointerKeyCallBacks = { 343 NULL, 344 NULL, 345 NULL, 346 NULL, 347 NULL, 348 NULL, 349}; 350 351NSMapTableValueCallBacks PyObjCUtil_PointerValueCallBacks = { 352 NULL, 353 NULL, 354 NULL, 355}; 356 357static void 358nsmaptable_objc_retain(NSMapTable *table __attribute__((__unused__)), const void *datum) { 359 CFRetain((id)datum); 360} 361 362static void 363nsmaptable_objc_release(NSMapTable *table __attribute__((__unused__)), void *datum) { 364 CFRelease((id)datum); 365} 366 367NSMapTableKeyCallBacks PyObjCUtil_ObjCIdentityKeyCallBacks = { 368 NULL, 369 NULL, 370 &nsmaptable_objc_retain, 371 &nsmaptable_objc_release, 372 NULL, 373 NULL, 374}; 375 376NSMapTableValueCallBacks PyObjCUtil_ObjCValueCallBacks = { 377 &nsmaptable_objc_retain, 378 &nsmaptable_objc_release, 379 NULL // generic description 380}; 381 382 383#define SHOULD_FREE 1 384#define SHOULD_IGNORE 2 385 386void 387PyObjC_FreeCArray(int code, void* array) 388{ 389 if (code == SHOULD_FREE) { 390 PyMem_Free(array); 391 } 392} 393 394static PyTypeObject* array_type = NULL; 395 396static inline PyTypeObject* 397fetch_array_type(void) 398{ 399 PyObject* mod; 400 PyObject* name; 401 402 if (array_type != NULL) return array_type; 403 404 name = PyString_FromString("array"); 405 if (name == NULL) { 406 return NULL; 407 } 408 409 mod = PyImport_Import(name); 410 Py_DECREF(name); 411 if (mod == NULL) { 412 return NULL; 413 } 414 415 array_type = (PyTypeObject*)PyObject_GetAttrString(mod, "ArrayType"); 416 Py_DECREF(mod); 417 if (array_type == NULL) { 418 return NULL; 419 } 420 421 /* XXX: check if array_type is realy a type! */ 422 423 return array_type; 424} 425 426#define array_check(obj) PyObject_TypeCheck(obj, fetch_array_type()) 427 428static char 429array_typestr(PyObject* array) 430{ 431 PyObject* typecode; 432 char res; 433 434 typecode = PyObject_GetAttrString(array, "typecode"); 435 if (typecode == NULL) { 436 return '\0'; 437 } 438 439 if (!PyString_Check(typecode)) { 440 PyErr_SetString(PyExc_TypeError, "typecode not a string"); 441 return '\0'; 442 } 443 444 switch (*PyString_AS_STRING(typecode)) { 445 case 'c': res = _C_CHR; break; 446 case 'b': res = _C_CHR; break; 447 case 'B': res = _C_UCHR; break; 448 case 'u': res = _C_SHT; break; 449 case 'h': res = _C_SHT; break; 450 case 'H': res = _C_USHT; break; 451 case 'i': res = _C_INT; break; 452 case 'I': res = _C_UINT; break; 453 case 'l': res = _C_LNG; break; 454 case 'L': res = _C_ULNG; break; 455 case 'f': res = _C_FLT; break; 456 case 'd': res = _C_DBL; break; 457 default: 458 PyErr_SetString(PyExc_TypeError, "unsupported typecode"); 459 res = '\0'; 460 } 461 Py_DECREF(typecode); 462 463 return res; 464} 465 466static int 467buffer_get(BOOL writable, PyObject* obj, void** bufptr, Py_ssize_t* sizeptr) 468{ 469 if (writable) { 470 return PyObject_AsWriteBuffer(obj, bufptr, sizeptr); 471 } else { 472 return PyObject_AsReadBuffer(obj, (const void**)bufptr, sizeptr); 473 } 474} 475 476static char struct_elem_code(const char* typestr); 477 478static char 479array_elem_code(const char* typestr) 480{ 481 char res = '\0'; 482 char tmp; 483 484 if (*typestr++ != _C_ARY_B) { 485 return '\0'; 486 } 487 while (isdigit(*typestr)) typestr++; 488 489 if (*typestr == _C_ARY_E) { 490 return '\0'; 491 } 492 493 while (typestr && *typestr != _C_ARY_E) { 494 switch(*typestr) { 495 case _C_ARY_B: 496 tmp = array_elem_code(typestr); 497 if (tmp == '\0') return '\0'; 498 if (res == '\0') { 499 res = tmp; 500 } else if (tmp != res) { 501 return '\0'; 502 } 503 break; 504 case _C_STRUCT_B: 505 tmp = struct_elem_code(typestr); 506 if (tmp == '\0') return '\0'; 507 if (res == '\0') { 508 res = tmp; 509 } else if (tmp != res) { 510 return '\0'; 511 } 512 break; 513 default: 514 if (res != '\0' && *typestr != res) return '\0'; 515 res = *typestr; 516 } 517 518 typestr = PyObjCRT_SkipTypeSpec(typestr); 519 } 520 return res; 521} 522 523static char 524struct_elem_code(const char* typestr) 525{ 526 char res = '\0'; 527 char tmp; 528 529 if (*typestr++ != _C_STRUCT_B) { 530 return '\0'; 531 } 532 533 while (*typestr != '=' && *typestr != _C_STRUCT_E) { 534 typestr++; 535 } 536 537 if (*typestr == _C_STRUCT_E) { 538 return '\0'; 539 } 540 typestr++; 541 542 while (typestr && *typestr != _C_STRUCT_E) { 543 switch(*typestr) { 544 case _C_ARY_B: 545 tmp = array_elem_code(typestr); 546 if (tmp == '\0') return '\0'; 547 if (res == '\0') { 548 res = tmp; 549 } else if (tmp != res) { 550 return '\0'; 551 } 552 break; 553 case _C_STRUCT_B: 554 tmp = struct_elem_code(typestr); 555 if (tmp == '\0') return '\0'; 556 if (res == '\0') { 557 res = tmp; 558 } else if (tmp != res) { 559 return '\0'; 560 } 561 break; 562 default: 563 if (res != '\0' && *typestr != res) return '\0'; 564 res = *typestr; 565 } 566 567 typestr = PyObjCRT_SkipTypeSpec(typestr); 568 } 569 return res; 570} 571 572static BOOL 573code_compatible(char array_code, char type_code) 574{ 575 if (array_code == type_code) { 576 return YES; 577 } 578 switch (type_code) { 579 case _C_NSBOOL: 580 return (array_code == _C_CHR) || (array_code == _C_UCHR); 581 case _C_CHAR_AS_INT: 582 return (array_code == _C_CHR) || (array_code == _C_UCHR); 583 case _C_CHAR_AS_TEXT: 584 return (array_code == _C_CHR); 585 case _C_UNICHAR: 586 return (array_code == _C_SHT); 587 } 588 return NO; 589} 590 591 592/* 593 * Convert a Python object to an array of 'elementType'. The array should 594 * contain 'pythonCount' elements, Py_None or NULL is accepted and will result 595 * in converting the entire Python sequence. 596 * 597 * The pythonList should either be a python sequence with appropriate entries, 598 * an array.array whose element-types match the element-types of the 599 * 'elementType' or an appropriatly typed and shaped numeric array. 600 * 601 * XXX: Numeric arrays are not yet supported. 602 * XXX: Unicode arrays are not yet support (_C_UNICHAR) 603 */ 604int 605PyObjC_PythonToCArray( 606 BOOL writable, BOOL exactSize, 607 const char* elementType, 608 PyObject* pythonList, 609 void** array, 610 Py_ssize_t* size, 611 PyObject** bufobj) 612{ 613 Py_ssize_t eltsize = PyObjCRT_SizeOfType(elementType); 614 Py_ssize_t i; 615 int r; 616 617 618 if (eltsize == -1) { 619 return -1; 620 } 621 622 if ((eltsize == 1 || eltsize == 0) && 623 !(*elementType == _C_NSBOOL || *elementType == _C_BOOL || *elementType == _C_CHAR_AS_INT)) { 624 /* A simple byte-array */ 625 /* Note: PyUnicode is explicitly excluded because it 626 * implemenents the character buffer interface giving access 627 * to the raw implementation. That's almost always not want 628 * you want. 629 */ 630 char* buf; 631 Py_ssize_t bufsize; 632 int have_buffer; 633 634 if (PyUnicode_Check(pythonList)) { 635 PyErr_Format(PyExc_TypeError, 636 "Expecting byte-buffer, got %s", 637 pythonList->ob_type->tp_name); 638 return -1; 639 } 640 641 642 have_buffer = buffer_get(writable, pythonList, (void**)&buf, &bufsize); 643 if (have_buffer == -1) { 644 if (writable) { 645 /* Ensure that the expected semantics still work 646 * when the passed in buffer is read-only 647 */ 648 if (buffer_get(NO, pythonList, (void**)&buf, &bufsize) == -1) { 649 return -1; 650 } 651 652 if (size == NULL || *size == -1) { 653 *array = PyMem_Malloc(bufsize); 654 if (*array == NULL) { 655 return -1; 656 } 657 memcpy(*array, buf, bufsize); 658 } else { 659 if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) { 660 PyErr_Format(PyExc_ValueError, 661 "Requesting buffer of %"PY_FORMAT_SIZE_T"d, have buffer " 662 "of %"PY_FORMAT_SIZE_T"d", *size, bufsize); 663 return -1; 664 } 665 *array = PyMem_Malloc(*size); 666 if (*array == NULL) { 667 return -1; 668 } 669 memcpy(*array, buf, *size); 670 } 671 return SHOULD_FREE; 672 } 673 } 674 675 if (have_buffer != -1) { 676 if (size == NULL) { 677 *array = buf; 678 *bufobj = pythonList; 679 Py_INCREF(pythonList); 680 681 } else if (*size == -1) { 682 *array = buf; 683 *size = bufsize; 684 *bufobj = pythonList; 685 Py_INCREF(pythonList); 686 687 } else { 688 if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) { 689 PyErr_Format(PyExc_ValueError, 690 "Requesting buffer of %"PY_FORMAT_SIZE_T"d, have buffer " 691 "of %"PY_FORMAT_SIZE_T"d", *size, bufsize); 692 return -1; 693 } 694 *array = buf; 695 *bufobj = pythonList; 696 Py_INCREF(pythonList); 697 } 698 return SHOULD_IGNORE; 699 } 700 701 PyErr_Clear(); 702 } 703 704 if (*elementType == _C_UNICHAR && PyUnicode_Check(pythonList)) { 705 Py_ssize_t bufsize = PyUnicode_GetSize(pythonList); 706 707 if (*size == -1) { 708 *size = bufsize; 709 } else if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) { 710 PyErr_Format(PyExc_ValueError, 711 "Requesting unicode buffer of %"PY_FORMAT_SIZE_T"d, have unicode buffer " 712 "of %"PY_FORMAT_SIZE_T"d", *size, bufsize); 713 return -1; 714 } 715 716 if (writable) { 717 *array = PyMem_Malloc(*size * sizeof(UniChar)); 718 memcpy(*array, PyUnicode_AsUnicode(pythonList), *size * sizeof(UniChar)); 719 return SHOULD_FREE; 720 } else { 721 *array = PyUnicode_AsUnicode(pythonList); 722 *bufobj = pythonList; 723 Py_INCREF(pythonList); 724 return SHOULD_IGNORE; 725 } 726 727 } else if (*elementType == _C_UNICHAR && PyString_Check(pythonList)) { 728 PyObject* u = PyUnicode_Decode( 729 PyString_AsString(pythonList), 730 PyString_Size(pythonList), 731 NULL, NULL); 732 if (u == NULL) { 733 return -1; 734 } 735 736 Py_ssize_t bufsize = PyUnicode_GetSize(u); 737 738 if (*size == -1) { 739 *size = bufsize; 740 } else if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) { 741 PyErr_Format(PyExc_ValueError, 742 "Requesting unicode buffer of %"PY_FORMAT_SIZE_T"d, have unicode buffer " 743 "of %"PY_FORMAT_SIZE_T"d", *size, bufsize); 744 Py_DECREF(u); 745 return -1; 746 } 747 748 if (writable) { 749 *array = PyMem_Malloc(*size * sizeof(UniChar)); 750 memcpy(*array, PyUnicode_AsUnicode(u), *size * sizeof(UniChar)); 751 Py_DECREF(u); 752 return SHOULD_FREE; 753 } else { 754 *array = PyUnicode_AsUnicode(u); 755 *bufobj = u; 756 return SHOULD_IGNORE; 757 } 758 } 759 760 761 /* A more complex array */ 762 763#if PY_VERSION_HEX >= 0x02060000 764 if (PyObject_CheckBuffer(pythonList)) { 765 /* An object that implements the new-style buffer interface. 766 * Use the buffer interface description to check if the buffer 767 * type is compatible with what we expect. 768 * 769 * Specifically: 770 * - If the C code expects an array of basic types: 771 * the buffer must be a single-dimensional array of 772 * a compatible type. 773 * - If the C code expects and array of structures: 774 * The python array must be two dimensional, one row 775 * in the python array corresponds to one struct "instance" 776 * - If the C code expects a multi-dimensional array: 777 * the python buffer must have a compatible dimension. 778 * 779 * The array must be large enough and mustn't contain holes 780 * in the fragment that gets used by us. 781 */ 782 783 } 784 785#endif 786 787 if (array_check(pythonList)) { 788 /* An array.array. Only convert if the typestr describes an 789 * simple type of the same type as the array, or a struct/array 790 * containing only elements of the type of the array. 791 */ 792 char* buf; 793 Py_ssize_t bufsize; 794 char code = array_typestr(pythonList); 795 if (code_compatible(code, *elementType)) { 796 /* Simple array, ok */ 797 } else if (*elementType == _C_ARY_B) { 798 /* Array of arrays, 'code' must be the same as the 799 * element-type of the array. 800 */ 801 if (!code_compatible(code, array_elem_code(elementType))) { 802 PyErr_Format(PyExc_ValueError, 803 "type mismatch between array.array " 804 "of %c and and C array of %s", 805 code, elementType); 806 return -1; 807 } 808 809 } else if (*elementType == _C_STRUCT_B) { 810 /* Array of structs, 'code' must be the same as the 811 * the field-types of the structs (that is, the struct 812 * must contain one or more fields of type 'code'). 813 */ 814 if (!code_compatible(code, struct_elem_code(elementType))) { 815 PyErr_Format(PyExc_ValueError, 816 "type mismatch between array.array " 817 "of %c and and C array of %s", 818 code, elementType); 819 return -1; 820 } 821 } else { 822 PyErr_Format(PyExc_ValueError, 823 "type mismatch between array.array " 824 "of %c and and C array of %s", 825 code, elementType); 826 return -1; 827 } 828 829 if (buffer_get(writable, pythonList, (void**)&buf, &bufsize) == -1) { 830 return -1; 831 } 832 if ((bufsize % eltsize) != 0) { 833 PyErr_SetString(PyExc_ValueError, 834 "Badly shaped array.array"); 835 return -1; 836 } 837 838 *array = buf; 839 840 if (size == NULL) { 841 /* pass */ 842 843 } else if (*size == -1) { 844 *size = bufsize / eltsize; 845 846 } else { 847 bufsize /= eltsize; 848 849 if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) { 850 PyErr_Format(PyExc_ValueError, 851 "Requesting buffer of %"PY_FORMAT_SIZE_T"d, have buffer " 852 "of %"PY_FORMAT_SIZE_T"d", *size, bufsize); 853 return -1; 854 } 855 *array = buf; 856 } 857 *bufobj = pythonList; 858 Py_INCREF(pythonList); 859 return SHOULD_IGNORE; 860 861#ifdef PyObjC_ENABLE_NUMARRAY 862 863# error "Please implement Numarray/Numeric support" 864 865 } else if (...){ 866 /* TODO: Convert the numeric array (or return a pointer to it's 867 * data), but only if it is the right type: 868 * - If typestr is a basic type, the array must be a 1D array 869 * of that type 870 * - If typestr is a structured type, the array must be a 2D 871 * array where rows match the structured type 872 * 873 * XXX: I have no idea if this is feasable, not having used 874 * numarray/numeric myself. 875 */ 876#endif /* PyObjC_ENABLE_NUMARRAY */ 877 } else { 878 Py_ssize_t seqlen; 879 Py_ssize_t pycount; 880 881 if (*elementType == _C_NSBOOL) { 882 if (PyString_Check(pythonList)) { 883 PyErr_Format(PyExc_ValueError, "Need array of BOOL, got string"); 884 return -1; 885 } 886 } else if (*elementType == _C_CHAR_AS_INT) { 887 if (PyString_Check(pythonList)) { 888 PyErr_Format(PyExc_ValueError, "Need array of small integers, got string"); 889 return -1; 890 } 891 } 892 PyObject* seq = PySequence_Fast(pythonList, 893 "converting to a C array"); 894 if (seq == NULL) { 895 return -1; 896 } 897 898 seqlen = PySequence_Fast_GET_SIZE(seq); 899 if (size == NULL || *size == -1) { 900 pycount = seqlen; 901 } else { 902 pycount = *size; 903 } 904 905 if ((exactSize && seqlen != pycount) || (!exactSize && seqlen < pycount)) { 906 Py_DECREF(seq); 907 PyErr_Format(PyExc_ValueError, 908 "too few values (%"PY_FORMAT_SIZE_T"d) expecting at " 909 "least %"PY_FORMAT_SIZE_T"d", seqlen, pycount); 910 return -1; 911 } 912 *array = PyMem_Malloc(eltsize * pycount); 913 if (*array == NULL) { 914 Py_DECREF(seq); 915 PyErr_NoMemory(); 916 return -1; 917 } 918 if (size) { 919 *size = pycount; 920 } 921 *bufobj = NULL; 922 923 for (i = 0; i < pycount; i++) { 924 PyObject* item = PySequence_Fast_GET_ITEM(seq, i); 925 926 r = depythonify_c_value(elementType, item, 927 ((char*)*array)+(i*eltsize)); 928 if (r == -1) { 929 Py_DECREF(seq); 930 PyMem_Free(*array); *array = NULL; 931 return -1; 932 } 933 } 934 return SHOULD_FREE; 935 } 936 937} 938 939 940PyObject* 941PyObjC_CArrayToPython( 942 const char* elementType, 943 void* array, 944 Py_ssize_t size) 945{ 946 PyObject* result; 947 Py_ssize_t i; 948 Py_ssize_t eltsize; 949 950 eltsize = PyObjCRT_SizeOfType(elementType); 951 if (eltsize == -1) { 952 return NULL; 953 } 954 955 956 if (eltsize == 1 || eltsize == 0) { 957 if (*elementType != _C_NSBOOL && *elementType != _C_BOOL && *elementType != _C_CHAR_AS_INT) { 958 /* Special case for buffer-like objects */ 959 return PyString_FromStringAndSize(array, size); 960 } 961 } 962 963 if (*elementType == _C_UNICHAR) { 964#if defined(PyObjC_UNICODE_FAST_PATH) 965 result = PyUnicode_FromUnicode((Py_UNICODE*)array, size); 966#else 967# error "Sorry, Wide Unicode builds not supported at the moment" 968#endif 969 return result; 970 } 971 972 result = PyTuple_New(size); 973 if (result == NULL) { 974 return NULL; 975 } 976 977 978 for (i = 0; i < size; i++) { 979 PyObject* elt = pythonify_c_value(elementType, array); 980 if (elt == NULL) { 981 Py_DECREF(result); 982 return NULL; 983 } 984 985 PyTuple_SET_ITEM(result, i, elt); 986 array = ((char*)array) + eltsize; 987 } 988 989 return result; 990} 991 992int 993PyObjC_IsPythonKeyword(const char* word) 994{ 995 /* 996 * We cheat a little: this list only contains those keywords that 997 * are actually used in Cocoa. 998 * 999 * XXX: If we ever add the complete list here we should optimize 1000 * this function. 1001 */ 1002 static const char* keywords[] = { 1003 "class", 1004 "raise", 1005 NULL 1006 }; 1007 const char** cur; 1008 1009 for (cur = keywords; *cur != NULL; cur++) { 1010 if (strcmp(word, *cur) == 0) { 1011 return 1; 1012 } 1013 } 1014 return 0; 1015} 1016 1017int 1018PyObjCRT_SimplifySignature(char* signature, char* buf, size_t buflen) 1019{ 1020 char* cur; 1021 char* end; 1022 char* next; 1023 1024 cur = signature; 1025 *buf = '\0'; 1026 1027 while (*cur != '\0') { 1028 next = end = (char*)PyObjCRT_SkipTypeSpec(cur); 1029 end -= 1; 1030 while (end != cur && isdigit(*end)) { 1031 end --; 1032 } 1033 end++; 1034 1035 if ((size_t)(end - cur) > buflen) { 1036 return -1; 1037 } 1038 1039 memcpy(buf, cur, end-cur); 1040 buflen -= (end-cur); 1041 buf += (end-cur); 1042 *buf = '\0'; 1043 cur = next; 1044 } 1045 return 0; 1046} 1047 1048int 1049PyObjCObject_Convert(PyObject* object, void* pvar) 1050{ 1051 int r; 1052 r = depythonify_c_value(@encode(id), object, (id*)pvar); 1053 if (r == -1) { 1054 return 0; 1055 } else { 1056 return 1; 1057 } 1058} 1059 1060int 1061PyObjC_ConvertBOOL(PyObject* object, void* pvar) 1062{ 1063 BOOL* pbool = (BOOL*)pvar; 1064 1065 if (PyObject_IsTrue(object)) { 1066 *pbool = YES; 1067 } else { 1068 *pbool = NO; 1069 } 1070 1071 return 1; 1072} 1073 1074int 1075PyObjC_ConvertChar(PyObject* object, void* pvar) 1076{ 1077 char* pchar = (char*)pvar; 1078 1079 if (!PyString_Check(object)) { 1080 PyErr_SetString(PyExc_TypeError, "Expecting string of len 1"); 1081 return 0; 1082 } 1083 1084 if (PyString_Size(object) != 1) { 1085 PyErr_SetString(PyExc_TypeError, "Expecting string of len 1"); 1086 return 0; 1087 } 1088 1089 *pchar = *PyString_AsString(object); 1090 return 1; 1091} 1092 1093int 1094PyObjCSelector_Convert(PyObject* object, void* pvar) 1095{ 1096 int r; 1097 1098 if (object == Py_None) { 1099 *(SEL*)pvar = NULL; 1100 return 1; 1101 } 1102 if (PyObjCSelector_Check(object)) { 1103 *(SEL*)pvar = PyObjCSelector_GetSelector(object); 1104 return 1; 1105 } 1106 if (!PyString_Check(object)) { 1107 PyErr_SetString(PyExc_TypeError, "Expected string"); 1108 return 0; 1109 } 1110 1111 r = depythonify_c_value(@encode(SEL), object, pvar); 1112 if (r == -1) { 1113 return 0; 1114 } 1115 return 1; 1116} 1117 1118int 1119PyObjCClass_Convert(PyObject* object, void* pvar) 1120{ 1121 if (!PyObjCClass_Check(object)) { 1122 PyErr_SetString(PyExc_TypeError, "Expected objective-C class"); 1123 return 0; 1124 } 1125 1126 *(Class*)pvar = PyObjCClass_GetClass(object); 1127 if (*(Class*)pvar == NULL) return 0; 1128 return 1; 1129} 1130 1131 1132PyObject* 1133PyObjC_CArrayToPython2( 1134 const char* elementType, 1135 void* array, 1136 Py_ssize_t size, 1137 bool alreadyRetained, 1138 bool alreadyCFRetained) 1139{ 1140 PyObject* result; 1141 Py_ssize_t i; 1142 Py_ssize_t eltsize; 1143 1144 if (size == -1) { 1145 size = 0; 1146 } 1147 1148 eltsize = PyObjCRT_SizeOfType(elementType); 1149 if (eltsize == -1) { 1150 return NULL; 1151 } 1152 1153 if (eltsize == 1 || eltsize == 0) { 1154 if (*elementType != _C_NSBOOL && *elementType != _C_BOOL && *elementType != _C_CHAR_AS_INT) { 1155 /* Special case for buffer-like objects */ 1156 return PyString_FromStringAndSize(array, size); 1157 } 1158 } 1159 if (*elementType == _C_UNICHAR) { 1160#if defined(PyObjC_UNICODE_FAST_PATH) 1161 result = PyUnicode_FromUnicode((Py_UNICODE*)array, size); 1162#else 1163# error "Sorry, Wide Unicode builds not supported at the moment" 1164#endif 1165 return result; 1166 } 1167 1168 result = PyTuple_New(size); 1169 if (result == NULL) { 1170 return NULL; 1171 } 1172 1173 1174 for (i = 0; i < size; i++) { 1175 PyObject* elt = pythonify_c_value(elementType, array); 1176 if (elt == NULL) { 1177 Py_DECREF(result); 1178 return NULL; 1179 } 1180 1181 if (alreadyRetained) { 1182 [*(id*)array release]; 1183 } else if (alreadyCFRetained) { 1184 CFRelease(*(id*)array); 1185 } 1186 1187 PyTuple_SET_ITEM(result, i, elt); 1188 array = ((char*)array) + eltsize; 1189 } 1190 1191 return result; 1192} 1193