1//-------------------------------------------------------------------------- 2// Name: src/arrays.sip 3// Purpose: Implements a %MappedType for wxArrayString and wxArrayInt 4// 5// Author: Robin Dunn 6// 7// Created: 2-Sept-2011 8// Copyright: (c) 2011-2018 by Total Control Software 9// Licence: wxWindows license 10//-------------------------------------------------------------------------- 11 12 13// Some SIP MappedTypes that automatically convert Python lists of 14// strings/ints to and from wxArrayString/wxArrayInt. 15 16// TODO: SWitch to iterator protocol APIs 17 18//-------------------------------------------------------------------------- 19 20%MappedType wxArrayString 21{ 22 %ConvertToTypeCode 23 // Code to test a PyObject for compatibility 24 // Verify that the object is a sequence, but not bytes or unicode 25 if (!sipIsErr) { 26 return (PySequence_Check(sipPy) && 27 !(PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))); 28 } 29 30 31 // Code to create a new wxArrayString and convert a compatible PyObject 32 wxArrayString *array = new wxArrayString; 33 Py_ssize_t i, len = PySequence_Length(sipPy); 34 for (i=0; i<len; i++) { 35 PyObject* item = PySequence_GetItem(sipPy, i); 36 37 // Ensure each item is a bytes or string/unicode object 38 if ( !PyBytes_Check(item) && !PyUnicode_Check(item) ) { 39 // raise a TypeError if not 40 PyErr_Format(PyExc_TypeError, 41 "Item at index %zd has type '%s' but a sequence of bytes or strings is expected", 42 i, sipPyTypeName(Py_TYPE(item))); 43 delete array; 44 Py_DECREF(item); 45 *sipIsErr = 1; 46 return 0; 47 } 48 49 // if it's a string object convert it to unicode first, assuming utf-8 50 if (PyBytes_Check(item)) { 51 Py_DECREF(item); 52 item = PyUnicode_FromEncodedObject(item, "utf-8", "strict"); 53 if (PyErr_Occurred()) { 54 *sipIsErr = 1; 55 delete array; 56 Py_DECREF(item); 57 return 0; 58 } 59 } 60 PyErr_Clear(); 61 wxString string; 62 size_t len = PyUnicode_GET_SIZE(item); 63 if (len) { 64 wxPyUnicode_AsWideChar(item, wxStringBuffer(string, len), len); 65 } 66 if (PyErr_Occurred()) { 67 *sipIsErr = 1; 68 delete array; 69 Py_DECREF(item); 70 return 0; 71 } 72 array->Add(string); 73 Py_DECREF(item); 74 } 75 *sipCppPtr = array; 76 return sipGetState(sipTransferObj); 77 %End 78 79 80 %ConvertFromTypeCode 81 // Code to convert a wxArrayString to a Python list of strings. 82 PyObject* list = PyList_New(0); 83 for (size_t i=0; i < sipCpp->GetCount(); i++) { 84 PyObject* str = wx2PyString(sipCpp->Item(i)); 85 PyList_Append(list, str); 86 Py_DECREF(str); 87 } 88 return list; 89 %End 90 91}; 92 93 94// Used just for unittesting the MappedType code, it can be removed later 95%ModuleCode 96wxArrayString testArrayStringTypemap(const wxArrayString& arr) 97{ 98 wxArrayString local = arr; // force a copy 99 return local; 100} 101%End 102wxArrayString testArrayStringTypemap(const wxArrayString& arr); 103 104 105//-------------------------------------------------------------------------- 106 107%MappedType wxArrayInt 108{ 109 %ConvertToTypeCode 110 // Code to test a PyObject for compatibility 111 if (!sipIsErr) { 112 return (PySequence_Check(sipPy) && 113 !(PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))); 114 } 115 116 // Code to create a new wxArrayInt and convert a compatible PyObject 117 wxArrayInt *array = new wxArrayInt; 118 Py_ssize_t i, len = PySequence_Length(sipPy); 119 for (i=0; i<len; i++) { 120 PyObject* item = PySequence_GetItem(sipPy, i); 121 122 // Ensure each item is a number object 123 if ( !PyNumber_Check(item) ) { 124 // raise a TypeError if not 125 PyErr_Format(PyExc_TypeError, 126 "Item at index %zd has type '%s' but a sequence of numbers is expected", 127 i, sipPyTypeName(Py_TYPE(item))); 128 delete array; 129 Py_DECREF(item); 130 *sipIsErr = 1; 131 return 0; 132 } 133 134 // Convert to Integer 135 PyObject* number = wxPyNumber_Int(item); 136 if (PyErr_Occurred()) { 137 *sipIsErr = 1; 138 delete array; 139 Py_DECREF(item); 140 return 0; 141 } 142 // And add it to the array 143 array->Add(wxPyInt_AS_LONG(number)); 144 Py_DECREF(item); 145 Py_DECREF(number); 146 } 147 *sipCppPtr = array; 148 return sipGetState(sipTransferObj); 149 %End 150 151 152 %ConvertFromTypeCode 153 // Code to convert a wxArrayInt to a Python list of integers. 154 PyObject* list = PyList_New(0); 155 for (size_t i=0; i < sipCpp->GetCount(); i++) { 156 PyObject* number = wxPyInt_FromLong(sipCpp->Item(i)); 157 PyList_Append(list, number); 158 Py_DECREF(number); 159 } 160 return list; 161 %End 162 163}; 164 165 166// Used just for unittesting the MappedType code, it can be removed later 167%ModuleCode 168wxArrayInt testArrayIntTypemap(const wxArrayInt& arr) 169{ 170 wxArrayInt local = arr; // force a copy 171 return local; 172} 173%End 174wxArrayInt testArrayIntTypemap(const wxArrayInt& arr); 175 176 177//-------------------------------------------------------------------------- 178 179 180%MappedType wxArrayDouble 181{ 182 %ConvertToTypeCode 183 // Code to test a PyObject for compatibility 184 if (!sipIsErr) { 185 return (PySequence_Check(sipPy) && 186 !(PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))); 187 } 188 189 // Code to create a new wxArrayDouble and convert a compatible PyObject 190 wxArrayDouble *array = new wxArrayDouble; 191 Py_ssize_t i, len = PySequence_Length(sipPy); 192 for (i=0; i<len; i++) { 193 PyObject* item = PySequence_GetItem(sipPy, i); 194 195 // Ensure each item is a number object 196 if ( !PyNumber_Check(item) ) { 197 // raise a TypeError if not 198 PyErr_Format(PyExc_TypeError, 199 "Item at index %zd has type '%s' but a sequence of numbers is expected", 200 i, sipPyTypeName(Py_TYPE(item))); 201 delete array; 202 Py_DECREF(item); 203 *sipIsErr = 1; 204 return 0; 205 } 206 207 // Convert to a Float 208 PyObject* number = PyNumber_Float(item); 209 if (PyErr_Occurred()) { 210 *sipIsErr = 1; 211 delete array; 212 Py_DECREF(item); 213 return 0; 214 } 215 // And add it to the array 216 array->Add(PyFloat_AS_DOUBLE(number)); 217 Py_DECREF(item); 218 Py_DECREF(number); 219 } 220 *sipCppPtr = array; 221 return sipGetState(sipTransferObj); 222 %End 223 224 225 %ConvertFromTypeCode 226 // Code to convert a wxArrayDouble to a Python list of floating point values. 227 PyObject* list = PyList_New(0); 228 for (size_t i=0; i < sipCpp->GetCount(); i++) { 229 PyObject* number = PyFloat_FromDouble(sipCpp->Item(i)); 230 PyList_Append(list, number); 231 Py_DECREF(number); 232 } 233 return list; 234 %End 235 236}; 237 238 239// Used just for unittesting the MappedType code, it can be removed later 240%ModuleCode 241wxArrayDouble testArrayDoubleTypemap(const wxArrayDouble& arr) 242{ 243 wxArrayDouble local = arr; // force a copy 244 return local; 245} 246%End 247wxArrayDouble testArrayDoubleTypemap(const wxArrayDouble& arr); 248 249//-------------------------------------------------------------------------- 250