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