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_CLEAR(exc); 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 if ([[localException reason] UTF8String]) { 184 buf = PyText_FromFormat("%s - %s", 185 [[localException name] UTF8String], 186 [[localException reason] UTF8String]); 187 } else { 188 buf = PyText_FromFormat("%s", 189 [[localException name] UTF8String]); 190 } 191 PyErr_SetObject(exception, buf); 192#endif 193 PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); 194 if (!exc_value || !PyObject_IsInstance(exc_value, exc_type)) { 195 PyErr_NormalizeException(&exc_type, &exc_value, &exc_traceback); 196 } 197 198 PyObject_SetAttrString(exc_value, "_pyobjc_info_", dict); 199 Py_DECREF(dict); dict = NULL; 200 PyObject_SetAttrString(exc_value, "name", c_localException_name); 201 PyErr_Restore(exc_type, exc_value, exc_traceback); 202 PyGILState_Release(state); 203} 204 205void 206PyObjCErr_ToObjC(void) 207{ 208 PyObjCErr_ToObjCWithGILState(NULL); 209} 210 211 212NSException* 213PyObjCErr_AsExc(void) 214{ 215 PyObject* exc_type; 216 PyObject* exc_value; 217 PyObject* exc_traceback; 218 PyObject* args; 219 PyObject* repr; 220 PyObject* typerepr; 221 NSException* val; 222 NSMutableDictionary* userInfo; 223 224 PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); 225 if (exc_type == NULL) { 226 return nil; 227 } 228 229 PyErr_NormalizeException(&exc_type, &exc_value, &exc_traceback); 230 231 args = PyObject_GetAttrString(exc_value, "_pyobjc_exc_"); 232 if (args == NULL) { 233 PyErr_Clear(); 234 } else { 235 id result; 236 237 if (depythonify_c_value(@encode(id), args, &result) == -1) { 238 abort(); 239 } 240 return result; 241 } 242 243 args = PyObject_GetAttrString(exc_value, "_pyobjc_info_"); 244 if (args == NULL) { 245 PyErr_Clear(); 246 } else { 247 /* This may be an exception that started out in 248 * Objective-C code. 249 */ 250 PyObject* v; 251 NSString* reason = NULL; 252 NSString* name = NULL; 253 254 v = PyDict_GetItemString(args, "reason"); 255 if (v) { 256 if (depythonify_c_value(@encode(NSObject*), v, &reason) < 0) { 257 PyErr_Clear(); 258 } 259 } 260 261 v = PyDict_GetItemString(args, "name"); 262 if (v) { 263 if (depythonify_c_value(@encode(NSObject*), v, &name) < 0) { 264 PyErr_Clear(); 265 } 266 } 267 268 v = PyDict_GetItemString(args, "userInfo"); 269 if (v && PyObjCObject_Check(v)) { 270 userInfo = PyObjCObject_GetObject(v); 271 } else { 272 userInfo = nil; 273 PyErr_Clear(); 274 } 275 276 if (name && reason) { 277 val = [NSException exceptionWithName:name 278 reason:reason 279 userInfo:userInfo]; 280 Py_DECREF(args); 281 Py_XDECREF(exc_type); 282 Py_XDECREF(exc_value); 283 Py_XDECREF(exc_traceback); 284 285 return val; 286 } 287 } 288 289 repr = PyObject_Str(exc_value); 290 typerepr = PyObject_Str(exc_type); 291 userInfo = [NSMutableDictionary dictionaryWithCapacity: 3]; 292 [userInfo setObject: 293 [[[OC_PythonObject alloc] initWithObject:exc_type] autorelease] 294 forKey:@"__pyobjc_exc_type__"]; 295 if (exc_value != NULL) 296 [userInfo setObject: 297 [[[OC_PythonObject alloc] initWithObject:exc_value] autorelease] 298 forKey:@"__pyobjc_exc_value__"]; 299 if (exc_traceback != NULL) 300 [userInfo setObject: 301 [[[OC_PythonObject alloc] initWithObject:exc_traceback] autorelease] 302 forKey:@"__pyobjc_exc_traceback__"]; 303 304 val = [NSException 305 exceptionWithName:@"OC_PythonException" 306 reason:[NSString stringWithFormat:@"%@: %@", typerepr?PyObjC_PythonToId(typerepr):NULL, repr?PyObjC_PythonToId(repr):NULL] 307 userInfo:userInfo]; 308 309 Py_XDECREF(typerepr); 310 Py_XDECREF(repr); 311 312 if (PyObjC_VerboseLevel) { 313 PyErr_Restore(exc_type, exc_value , exc_traceback); 314 NSLog(@"PyObjC: Converting exception to Objective-C:"); 315 PyErr_Print(); 316 } else { 317 Py_DECREF(exc_type); 318 Py_XDECREF(exc_value); 319 Py_XDECREF(exc_traceback); 320 } 321 return val; 322} 323 324void 325PyObjCErr_ToObjCWithGILState(PyGILState_STATE* state) 326{ 327 NSException* exc = PyObjCErr_AsExc(); 328 329 if (state) { 330 PyGILState_Release(*state); 331 } 332 [exc raise]; 333} 334 335 336char* 337PyObjCUtil_Strdup(const char* value) 338{ 339 Py_ssize_t len; 340 char* result; 341 342 len = strlen(value); 343 result = PyMem_Malloc(len+1); 344 if (result == NULL) return NULL; 345 346 memcpy(result, value, len); 347 result[len] = 0; 348 return result; 349} 350 351 352NSMapTableKeyCallBacks PyObjCUtil_PointerKeyCallBacks = { 353 NULL, 354 NULL, 355 NULL, 356 NULL, 357 NULL, 358 NULL, 359}; 360 361NSMapTableValueCallBacks PyObjCUtil_PointerValueCallBacks = { 362 NULL, 363 NULL, 364 NULL, 365}; 366 367static void 368nsmaptable_objc_retain(NSMapTable *table __attribute__((__unused__)), const void *datum) { 369 CFRetain((id)datum); 370} 371 372static void 373nsmaptable_objc_release(NSMapTable *table __attribute__((__unused__)), void *datum) { 374 CFRelease((id)datum); 375} 376 377NSMapTableKeyCallBacks PyObjCUtil_ObjCIdentityKeyCallBacks = { 378 NULL, 379 NULL, 380 &nsmaptable_objc_retain, 381 &nsmaptable_objc_release, 382 NULL, 383 NULL, 384}; 385 386NSMapTableValueCallBacks PyObjCUtil_ObjCValueCallBacks = { 387 &nsmaptable_objc_retain, 388 &nsmaptable_objc_release, 389 NULL // generic description 390}; 391 392 393#define SHOULD_FREE 1 394#define SHOULD_IGNORE 2 395 396void 397PyObjC_FreeCArray(int code, void* array) 398{ 399 if (code == SHOULD_FREE) { 400 PyMem_Free(array); 401 } 402} 403 404static PyTypeObject* array_type = NULL; 405 406static inline PyTypeObject* 407fetch_array_type(void) 408{ 409 PyObject* mod; 410 PyObject* name; 411 412 if (array_type != NULL) return array_type; 413 414 name = PyText_FromString("array"); 415 if (name == NULL) { 416 return NULL; 417 } 418 419 mod = PyImport_Import(name); 420 Py_DECREF(name); 421 if (mod == NULL) { 422 return NULL; 423 } 424 425 array_type = (PyTypeObject*)PyObject_GetAttrString(mod, "ArrayType"); 426 Py_DECREF(mod); 427 if (array_type == NULL) { 428 return NULL; 429 } 430 431 /* XXX: check if array_type is realy a type! */ 432 433 return array_type; 434} 435 436#define array_check(obj) PyObject_TypeCheck(obj, fetch_array_type()) 437 438static char 439array_typestr(PyObject* array) 440{ 441 PyObject* typecode; 442 PyObject* bytes; 443 char res; 444 445 typecode = PyObject_GetAttrString(array, "typecode"); 446 if (typecode == NULL) { 447 return '\0'; 448 } 449 450 if (PyUnicode_Check(typecode)) { 451 bytes = PyUnicode_AsEncodedString(typecode, NULL, NULL); 452 if (bytes == NULL) { 453 return '\0'; 454 } 455#if PY_MAJOR_VERSION == 2 456 } else if (PyString_Check(typecode)) { 457 bytes = typecode; Py_INCREF(bytes); 458#endif 459 } else { 460 PyErr_SetString(PyExc_TypeError, "typecode not a string"); 461 return '\0'; 462 } 463 464 switch (*PyBytes_AS_STRING(bytes)) { 465 case 'c': res = _C_CHR; break; 466 case 'b': res = _C_CHR; break; 467 case 'B': res = _C_UCHR; break; 468 case 'u': res = _C_SHT; break; 469 case 'h': res = _C_SHT; break; 470 case 'H': res = _C_USHT; break; 471 case 'i': res = _C_INT; break; 472 case 'I': res = _C_UINT; break; 473 case 'l': res = _C_LNG; break; 474 case 'L': res = _C_ULNG; break; 475 case 'f': res = _C_FLT; break; 476 case 'd': res = _C_DBL; break; 477 default: 478 PyErr_SetString(PyExc_TypeError, "unsupported typecode"); 479 res = '\0'; 480 } 481 Py_DECREF(typecode); 482 Py_DECREF(bytes); 483 484 return res; 485} 486 487static int 488buffer_get(BOOL writable, PyObject* obj, void** bufptr, Py_ssize_t* sizeptr) 489{ 490 if (writable) { 491 return PyObject_AsWriteBuffer(obj, bufptr, sizeptr); 492 } else { 493 return PyObject_AsReadBuffer(obj, (const void**)bufptr, sizeptr); 494 } 495} 496 497static char struct_elem_code(const char* typestr); 498 499static char 500array_elem_code(const char* typestr) 501{ 502 char res = '\0'; 503 char tmp; 504 505 if (*typestr++ != _C_ARY_B) { 506 return '\0'; 507 } 508 while (isdigit(*typestr)) typestr++; 509 510 if (*typestr == _C_ARY_E) { 511 return '\0'; 512 } 513 514 while (typestr && *typestr != _C_ARY_E) { 515 switch(*typestr) { 516 case _C_ARY_B: 517 tmp = array_elem_code(typestr); 518 if (tmp == '\0') return '\0'; 519 if (res == '\0') { 520 res = tmp; 521 } else if (tmp != res) { 522 return '\0'; 523 } 524 break; 525 case _C_STRUCT_B: 526 tmp = struct_elem_code(typestr); 527 if (tmp == '\0') return '\0'; 528 if (res == '\0') { 529 res = tmp; 530 } else if (tmp != res) { 531 return '\0'; 532 } 533 break; 534 default: 535 if (res != '\0' && *typestr != res) return '\0'; 536 res = *typestr; 537 } 538 539 typestr = PyObjCRT_SkipTypeSpec(typestr); 540 } 541 return res; 542} 543 544static char 545struct_elem_code(const char* typestr) 546{ 547 char res = '\0'; 548 char tmp; 549 550 if (*typestr++ != _C_STRUCT_B) { 551 return '\0'; 552 } 553 554 while (*typestr != '=' && *typestr != _C_STRUCT_E) { 555 typestr++; 556 } 557 558 if (*typestr == _C_STRUCT_E) { 559 return '\0'; 560 } 561 typestr++; 562 563 while (typestr && *typestr != _C_STRUCT_E) { 564 switch(*typestr) { 565 case _C_ARY_B: 566 tmp = array_elem_code(typestr); 567 if (tmp == '\0') return '\0'; 568 if (res == '\0') { 569 res = tmp; 570 } else if (tmp != res) { 571 return '\0'; 572 } 573 break; 574 case _C_STRUCT_B: 575 tmp = struct_elem_code(typestr); 576 if (tmp == '\0') return '\0'; 577 if (res == '\0') { 578 res = tmp; 579 } else if (tmp != res) { 580 return '\0'; 581 } 582 break; 583 default: 584 if (res != '\0' && *typestr != res) return '\0'; 585 res = *typestr; 586 } 587 588 typestr = PyObjCRT_SkipTypeSpec(typestr); 589 } 590 return res; 591} 592 593static BOOL 594code_compatible(char array_code, char type_code) 595{ 596 if (array_code == type_code) { 597 return YES; 598 } 599 switch (type_code) { 600 case _C_LNG_LNG: 601#ifdef __LP64__ 602 /* fall through */ 603#else 604 return NO; 605#endif 606 case _C_LNG: 607 return (array_code == 'l') 608#ifndef __LP64__ 609 || (array_code == 'i') 610#endif 611 ; 612 case _C_ULNG_LNG: 613#ifdef __LP64__ 614 /* fall through */ 615#else 616 return NO; 617#endif 618 case _C_ULNG: 619 return (array_code == 'L') 620#ifndef __LP64__ 621 || (array_code == 'I') 622#endif 623 ; 624 625 case _C_INT: 626 return (array_code == 'i') 627#ifndef __LP64__ 628 || (array_code == 'l') 629#endif 630 ; 631 case _C_UINT: 632 return (array_code == 'I') 633#ifndef __LP64__ 634 || (array_code == 'L') 635#endif 636 ; 637 638 case _C_NSBOOL: 639 return (array_code == _C_CHR) || (array_code == _C_UCHR); 640 case _C_CHAR_AS_INT: 641 return (array_code == _C_CHR) || (array_code == _C_UCHR); 642 case _C_CHAR_AS_TEXT: 643 return (array_code == _C_CHR); 644 case _C_UNICHAR: 645 return (array_code == _C_SHT); 646 } 647 return NO; 648} 649 650 651/* 652 * Convert a Python object to an array of 'elementType'. The array should 653 * contain 'pythonCount' elements, Py_None or NULL is accepted and will result 654 * in converting the entire Python sequence. 655 * 656 * The pythonList should either be a python sequence with appropriate entries, 657 * an array.array whose element-types match the element-types of the 658 * 'elementType' or an appropriatly typed and shaped numeric array. 659 * 660 * XXX: Numeric arrays are not yet supported. 661 * XXX: Unicode arrays are not yet support (_C_UNICHAR) 662 */ 663int 664PyObjC_PythonToCArray( 665 BOOL writable, BOOL exactSize, 666 const char* elementType, 667 PyObject* pythonList, 668 void** array, 669 Py_ssize_t* size, 670 PyObject** bufobj) 671{ 672 Py_ssize_t eltsize = PyObjCRT_SizeOfType(elementType); 673 Py_ssize_t i; 674 int r; 675 676 677 if (eltsize == -1) { 678 return -1; 679 } 680 681 if ((eltsize == 1 || eltsize == 0) && 682 !(*elementType == _C_NSBOOL || *elementType == _C_BOOL || *elementType == _C_CHAR_AS_INT)) { 683 /* A simple byte-array */ 684 /* Note: PyUnicode is explicitly excluded because it 685 * implemenents the character buffer interface giving access 686 * to the raw implementation. That's almost always not want 687 * you want. 688 */ 689 char* buf; 690 Py_ssize_t bufsize; 691 int have_buffer; 692 693 if (PyUnicode_Check(pythonList)) { 694 PyErr_Format(PyExc_TypeError, 695 "Expecting byte-buffer, got %s", 696 Py_TYPE(pythonList)->tp_name); 697 return -1; 698 } 699 700 701 have_buffer = buffer_get(writable, pythonList, (void**)&buf, &bufsize); 702 if (have_buffer == -1) { 703 if (writable) { 704 /* Ensure that the expected semantics still work 705 * when the passed in buffer is read-only 706 */ 707 if (buffer_get(NO, pythonList, (void**)&buf, &bufsize) == -1) { 708 return -1; 709 } 710 711 if (size == NULL || *size == -1) { 712 *array = PyMem_Malloc(bufsize); 713 if (*array == NULL) { 714 return -1; 715 } 716 memcpy(*array, buf, bufsize); 717 } else { 718 if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) { 719 PyErr_Format(PyExc_ValueError, 720 "Requesting buffer of %"PY_FORMAT_SIZE_T"d, have buffer " 721 "of %"PY_FORMAT_SIZE_T"d", *size, bufsize); 722 return -1; 723 } 724 *array = PyMem_Malloc(*size); 725 if (*array == NULL) { 726 return -1; 727 } 728 memcpy(*array, buf, *size); 729 } 730 return SHOULD_FREE; 731 } 732 } 733 734 if (have_buffer != -1) { 735 if (size == NULL) { 736 *array = buf; 737 *bufobj = pythonList; 738 Py_INCREF(pythonList); 739 740 } else if (*size == -1) { 741 *array = buf; 742 *size = bufsize; 743 *bufobj = pythonList; 744 Py_INCREF(pythonList); 745 746 } else { 747 if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) { 748 PyErr_Format(PyExc_ValueError, 749 "Requesting buffer of %"PY_FORMAT_SIZE_T"d, have buffer " 750 "of %"PY_FORMAT_SIZE_T"d", *size, bufsize); 751 return -1; 752 } 753 *array = buf; 754 *bufobj = pythonList; 755 Py_INCREF(pythonList); 756 } 757 return SHOULD_IGNORE; 758 } 759 760 PyErr_Clear(); 761 } 762 763 if (*elementType == _C_UNICHAR && PyUnicode_Check(pythonList)) { 764 Py_ssize_t bufsize = PyUnicode_GetSize(pythonList); 765 766 if (*size == -1) { 767 *size = bufsize; 768 } else if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) { 769 PyErr_Format(PyExc_ValueError, 770 "Requesting unicode buffer of %"PY_FORMAT_SIZE_T"d, have unicode buffer " 771 "of %"PY_FORMAT_SIZE_T"d", *size, bufsize); 772 return -1; 773 } 774 775 if (writable) { 776 *array = PyMem_Malloc(*size * sizeof(UniChar)); 777 memcpy(*array, PyUnicode_AsUnicode(pythonList), *size * sizeof(UniChar)); 778 return SHOULD_FREE; 779 } else { 780 *array = PyUnicode_AsUnicode(pythonList); 781 *bufobj = pythonList; 782 Py_INCREF(pythonList); 783 return SHOULD_IGNORE; 784 } 785#if PY_MAJOR_VERSION == 2 786 } else if (*elementType == _C_UNICHAR && PyString_Check(pythonList)) { 787 PyObject* u = PyUnicode_Decode( 788 PyString_AsString(pythonList), 789 PyString_Size(pythonList), 790 NULL, NULL); 791 if (u == NULL) { 792 return -1; 793 } 794 795 Py_ssize_t bufsize = PyUnicode_GetSize(u); 796 797 if (*size == -1) { 798 *size = bufsize; 799 } else if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) { 800 PyErr_Format(PyExc_ValueError, 801 "Requesting unicode buffer of %"PY_FORMAT_SIZE_T"d, have unicode buffer " 802 "of %"PY_FORMAT_SIZE_T"d", *size, bufsize); 803 Py_DECREF(u); 804 return -1; 805 } 806 807 if (writable) { 808 *array = PyMem_Malloc(*size * sizeof(UniChar)); 809 memcpy(*array, PyUnicode_AsUnicode(u), *size * sizeof(UniChar)); 810 Py_DECREF(u); 811 return SHOULD_FREE; 812 } else { 813 *array = PyUnicode_AsUnicode(u); 814 *bufobj = u; 815 return SHOULD_IGNORE; 816 } 817#endif 818 } 819 820 /* A more complex array */ 821 822#if PY_VERSION_HEX >= 0x02060000 823 if (PyObject_CheckBuffer(pythonList)) { 824 /* An object that implements the new-style buffer interface. 825 * Use the buffer interface description to check if the buffer 826 * type is compatible with what we expect. 827 * 828 * Specifically: 829 * - If the C code expects an array of basic types: 830 * the buffer must be a single-dimensional array of 831 * a compatible type. 832 * - If the C code expects and array of structures: 833 * The python array must be two dimensional, one row 834 * in the python array corresponds to one struct "instance" 835 * - If the C code expects a multi-dimensional array: 836 * the python buffer must have a compatible dimension. 837 * 838 * The array must be large enough and mustn't contain holes 839 * in the fragment that gets used by us. 840 */ 841 842 } 843 844#endif 845 if (array_check(pythonList)) { 846 /* An array.array. Only convert if the typestr describes an 847 * simple type of the same type as the array, or a struct/array 848 * containing only elements of the type of the array. 849 */ 850 char* buf; 851 Py_ssize_t bufsize; 852 char code = array_typestr(pythonList); 853 if (code_compatible(code, *elementType)) { 854 /* Simple array, ok */ 855 } else if (*elementType == _C_ARY_B) { 856 /* Array of arrays, 'code' must be the same as the 857 * element-type of the array. 858 */ 859 if (!code_compatible(code, array_elem_code(elementType))) { 860 PyErr_Format(PyExc_ValueError, 861 "type mismatch between array.array " 862 "of %c and and C array of %s", 863 code, elementType); 864 return -1; 865 } 866 867 } else if (*elementType == _C_STRUCT_B) { 868 /* Array of structs, 'code' must be the same as the 869 * the field-types of the structs (that is, the struct 870 * must contain one or more fields of type 'code'). 871 */ 872 if (!code_compatible(code, struct_elem_code(elementType))) { 873 PyErr_Format(PyExc_ValueError, 874 "type mismatch between array.array " 875 "of %c and and C array of %s", 876 code, elementType); 877 return -1; 878 } 879 } else { 880 PyErr_Format(PyExc_ValueError, 881 "type mismatch between array.array " 882 "of %c and and C array of %s", 883 code, elementType); 884 return -1; 885 } 886 887 if (buffer_get(writable, pythonList, (void**)&buf, &bufsize) == -1) { 888 return -1; 889 } 890 891 assert(eltsize != 0); 892 if ((bufsize % eltsize) != 0) { 893 PyErr_SetString(PyExc_ValueError, 894 "Badly shaped array.array"); 895 return -1; 896 } 897 898 *array = buf; 899 900 if (size == NULL) { 901 /* pass */ 902 903 } else if (*size == -1) { 904 *size = bufsize / eltsize; 905 906 } else { 907 bufsize /= eltsize; 908 909 if ((exactSize && *size != bufsize) || (!exactSize && *size > bufsize)) { 910 PyErr_Format(PyExc_ValueError, 911 "Requesting buffer of %"PY_FORMAT_SIZE_T"d, have buffer " 912 "of %"PY_FORMAT_SIZE_T"d", *size, bufsize); 913 return -1; 914 } 915 *array = buf; 916 } 917 *bufobj = pythonList; 918 Py_INCREF(pythonList); 919 return SHOULD_IGNORE; 920 921#ifdef PyObjC_ENABLE_NUMARRAY 922 923# error "Please implement Numarray/Numeric support" 924 925 } else if (...){ 926 /* TODO: Convert the numeric array (or return a pointer to it's 927 * data), but only if it is the right type: 928 * - If typestr is a basic type, the array must be a 1D array 929 * of that type 930 * - If typestr is a structured type, the array must be a 2D 931 * array where rows match the structured type 932 * 933 * XXX: I have no idea if this is feasable, not having used 934 * numarray/numeric myself. 935 */ 936#endif /* PyObjC_ENABLE_NUMARRAY */ 937 } else { 938 Py_ssize_t seqlen; 939 Py_ssize_t pycount; 940 941 if (*elementType == _C_NSBOOL) { 942 if (PyBytes_Check(pythonList)) { 943 PyErr_Format(PyExc_ValueError, "Need array of BOOL, got byte string"); 944 return -1; 945 } 946 } else if (*elementType == _C_CHAR_AS_INT) { 947 if (PyBytes_Check(pythonList)) { 948 PyErr_Format(PyExc_ValueError, "Need array of small integers, got byte string"); 949 return -1; 950 } 951 } 952 PyObject* seq = PySequence_Fast(pythonList, 953 "converting to a C array"); 954 if (seq == NULL) { 955 return -1; 956 } 957 958 seqlen = PySequence_Fast_GET_SIZE(seq); 959 if (size == NULL || *size == -1) { 960 pycount = seqlen; 961 } else { 962 pycount = *size; 963 } 964 965 if ((exactSize && seqlen != pycount) || (!exactSize && seqlen < pycount)) { 966 Py_DECREF(seq); 967 PyErr_Format(PyExc_ValueError, 968 "too few values (%"PY_FORMAT_SIZE_T"d) expecting at " 969 "least %"PY_FORMAT_SIZE_T"d", seqlen, pycount); 970 return -1; 971 } 972 *array = PyMem_Malloc(eltsize * pycount); 973 if (*array == NULL) { 974 Py_DECREF(seq); 975 PyErr_NoMemory(); 976 return -1; 977 } 978 if (size) { 979 *size = pycount; 980 } 981 *bufobj = NULL; 982 983 for (i = 0; i < pycount; i++) { 984 PyObject* item = PySequence_Fast_GET_ITEM(seq, i); 985 986 r = depythonify_c_value(elementType, item, 987 ((char*)*array)+(i*eltsize)); 988 if (r == -1) { 989 Py_DECREF(seq); 990 PyMem_Free(*array); *array = NULL; 991 return -1; 992 } 993 } 994 return SHOULD_FREE; 995 } 996 997} 998 999 1000PyObject* 1001PyObjC_CArrayToPython( 1002 const char* elementType, 1003 void* array, 1004 Py_ssize_t size) 1005{ 1006 PyObject* result; 1007 Py_ssize_t i; 1008 Py_ssize_t eltsize; 1009 1010 eltsize = PyObjCRT_SizeOfType(elementType); 1011 if (eltsize == -1) { 1012 return NULL; 1013 } 1014 1015 1016 if (eltsize == 1 || eltsize == 0) { 1017 if (*elementType == _C_CHAR_AS_TEXT) { 1018 return PyBytes_FromStringAndSize(array, size); 1019 } 1020 if (*elementType != _C_NSBOOL && *elementType != _C_BOOL && *elementType != _C_CHAR_AS_INT) { 1021 /* Special case for buffer-like objects */ 1022 return PyBytes_FromStringAndSize(array, size); 1023 } 1024 } 1025 1026 if (*elementType == _C_UNICHAR) { 1027#if defined(PyObjC_UNICODE_FAST_PATH) 1028 result = PyUnicode_FromUnicode((Py_UNICODE*)array, size); 1029#else 1030# error "Sorry, Wide Unicode builds not supported at the moment" 1031#endif 1032 return result; 1033 } 1034 1035 result = PyTuple_New(size); 1036 if (result == NULL) { 1037 return NULL; 1038 } 1039 1040 1041 for (i = 0; i < size; i++) { 1042 PyObject* elt = pythonify_c_value(elementType, array); 1043 if (elt == NULL) { 1044 Py_DECREF(result); 1045 return NULL; 1046 } 1047 1048 PyTuple_SET_ITEM(result, i, elt); 1049 array = ((char*)array) + eltsize; 1050 } 1051 1052 return result; 1053} 1054 1055int 1056PyObjC_IsPythonKeyword(const char* word) 1057{ 1058 /* 1059 * We cheat a little: this list only contains those keywords that 1060 * are actually used in Cocoa. 1061 * 1062 * XXX: If we ever add the complete list here we should optimize 1063 * this function. 1064 */ 1065 static const char* keywords[] = { 1066 "class", 1067 "raise", 1068 NULL 1069 }; 1070 const char** cur; 1071 1072 for (cur = keywords; *cur != NULL; cur++) { 1073 if (strcmp(word, *cur) == 0) { 1074 return 1; 1075 } 1076 } 1077 return 0; 1078} 1079 1080int 1081PyObjCRT_SimplifySignature(char* signature, char* buf, size_t buflen) 1082{ 1083 char* cur; 1084 char* end; 1085 char* next; 1086 1087 cur = signature; 1088 *buf = '\0'; 1089 1090 while (*cur != '\0') { 1091 next = end = (char*)PyObjCRT_SkipTypeSpec(cur); 1092 end -= 1; 1093 while (end != cur && isdigit(*end)) { 1094 end --; 1095 } 1096 end++; 1097 1098 if ((size_t)(end - cur) > buflen) { 1099 return -1; 1100 } 1101 1102 memcpy(buf, cur, end-cur); 1103 buflen -= (end-cur); 1104 buf += (end-cur); 1105 *buf = '\0'; 1106 cur = next; 1107 } 1108 return 0; 1109} 1110 1111 1112PyObject* 1113PyObjC_CArrayToPython2( 1114 const char* elementType, 1115 void* array, 1116 Py_ssize_t size, 1117 bool alreadyRetained, 1118 bool alreadyCFRetained) 1119{ 1120 PyObject* result; 1121 Py_ssize_t i; 1122 Py_ssize_t eltsize; 1123 1124 if (size == -1) { 1125 size = 0; 1126 } 1127 1128 eltsize = PyObjCRT_SizeOfType(elementType); 1129 if (eltsize == -1) { 1130 return NULL; 1131 } 1132 1133 if (eltsize == 1 || eltsize == 0) { 1134 if (*elementType == _C_CHAR_AS_TEXT) { 1135 return PyBytes_FromStringAndSize(array, size); 1136 } 1137 if (*elementType != _C_NSBOOL && *elementType != _C_BOOL && *elementType != _C_CHAR_AS_INT) { 1138 /* Special case for buffer-like objects */ 1139 return PyBytes_FromStringAndSize(array, size); 1140 } 1141 } 1142 if (*elementType == _C_UNICHAR) { 1143#if defined(PyObjC_UNICODE_FAST_PATH) 1144 result = PyUnicode_FromUnicode((Py_UNICODE*)array, size); 1145#else 1146# error "Sorry, Wide Unicode builds not supported at the moment" 1147#endif 1148 return result; 1149 } 1150 1151 result = PyTuple_New(size); 1152 if (result == NULL) { 1153 return NULL; 1154 } 1155 1156 1157 for (i = 0; i < size; i++) { 1158 PyObject* elt = pythonify_c_value(elementType, array); 1159 if (elt == NULL) { 1160 Py_DECREF(result); 1161 return NULL; 1162 } 1163 1164 if (alreadyRetained) { 1165 [*(id*)array release]; 1166 } else if (alreadyCFRetained) { 1167 CFRelease(*(id*)array); 1168 } 1169 1170 PyTuple_SET_ITEM(result, i, elt); 1171 array = ((char*)array) + eltsize; 1172 } 1173 1174 return result; 1175} 1176 1177int 1178PyObjCObject_Convert(PyObject* object, void* pvar) 1179{ 1180 int r; 1181 r = depythonify_c_value(@encode(id), object, (id*)pvar); 1182 if (r == -1) { 1183 return 0; 1184 } else { 1185 return 1; 1186 } 1187} 1188 1189int 1190PyObjCClass_Convert(PyObject* object, void* pvar) 1191{ 1192 if (!PyObjCClass_Check(object)) { 1193 PyErr_SetString(PyExc_TypeError, "Expected objective-C class"); 1194 return 0; 1195 } 1196 1197 *(Class*)pvar = PyObjCClass_GetClass(object); 1198 if (*(Class*)pvar == NULL) return 0; 1199 return 1; 1200} 1201 1202int PyObjC_is_ascii_string(PyObject* unicode_string, const char* ascii_string) 1203{ 1204 size_t uni_sz = PyUnicode_GetSize(unicode_string); 1205 size_t i; 1206 Py_UNICODE* code_points = PyUnicode_AsUnicode(unicode_string); 1207 1208 if (code_points == NULL) { 1209 PyErr_Clear(); 1210 return 0; 1211 } 1212 1213 for (i = 0; i < uni_sz; i++) { 1214 if (code_points[i] != (Py_UNICODE)ascii_string[i]) { 1215 return 0; 1216 } else if (ascii_string[i] == '\0') { 1217 return 0; 1218 } 1219 } 1220 if (ascii_string[i] != '\0') { 1221 return 0; 1222 } 1223 return 1; 1224} 1225 1226int PyObjC_is_ascii_prefix(PyObject* unicode_string, const char* ascii_string, size_t n) 1227{ 1228 size_t uni_sz = PyUnicode_GetSize(unicode_string); 1229 size_t i; 1230 Py_UNICODE* code_points = PyUnicode_AsUnicode(unicode_string); 1231 1232 if (code_points == NULL) { 1233 PyErr_Clear(); 1234 return 0; 1235 } 1236 1237 for (i = 0; i < uni_sz && i < n; i++) { 1238 if (code_points[i] != (Py_UNICODE)ascii_string[i]) { 1239 return 0; 1240 } else if (ascii_string[i] == '\0') { 1241 return 0; 1242 } 1243 } 1244 return 1; 1245} 1246 1247PyObject* 1248PyObjC_ImportName(const char* name) 1249{ 1250 PyObject* py_name; 1251 PyObject* mod; 1252 char* c = strrchr(name, '.'); 1253 1254 if (c == NULL) { 1255 /* Toplevel module */ 1256 py_name = PyText_FromString(name); 1257 mod = PyImport_Import(py_name); 1258 Py_DECREF(py_name); 1259 return mod; 1260 } else { 1261 py_name = PyText_FromStringAndSize(name, c - name); 1262 mod = PyImport_Import(py_name); 1263 Py_DECREF(py_name); 1264 if (mod == NULL) { 1265 return NULL; 1266 } 1267 1268 PyObject* v = PyObject_GetAttrString(mod, c + 1); 1269 Py_DECREF(mod); 1270 return v; 1271 } 1272} 1273