1 2/* Map C struct members to Python object attributes */ 3 4#include "Python.h" 5#include "structmember.h" // PyMemberDef 6 7PyObject * 8PyMember_GetOne(const char *obj_addr, PyMemberDef *l) 9{ 10 PyObject *v; 11 12 const char* addr = obj_addr + l->offset; 13 switch (l->type) { 14 case T_BOOL: 15 v = PyBool_FromLong(*(char*)addr); 16 break; 17 case T_BYTE: 18 v = PyLong_FromLong(*(char*)addr); 19 break; 20 case T_UBYTE: 21 v = PyLong_FromUnsignedLong(*(unsigned char*)addr); 22 break; 23 case T_SHORT: 24 v = PyLong_FromLong(*(short*)addr); 25 break; 26 case T_USHORT: 27 v = PyLong_FromUnsignedLong(*(unsigned short*)addr); 28 break; 29 case T_INT: 30 v = PyLong_FromLong(*(int*)addr); 31 break; 32 case T_UINT: 33 v = PyLong_FromUnsignedLong(*(unsigned int*)addr); 34 break; 35 case T_LONG: 36 v = PyLong_FromLong(*(long*)addr); 37 break; 38 case T_ULONG: 39 v = PyLong_FromUnsignedLong(*(unsigned long*)addr); 40 break; 41 case T_PYSSIZET: 42 v = PyLong_FromSsize_t(*(Py_ssize_t*)addr); 43 break; 44 case T_FLOAT: 45 v = PyFloat_FromDouble((double)*(float*)addr); 46 break; 47 case T_DOUBLE: 48 v = PyFloat_FromDouble(*(double*)addr); 49 break; 50 case T_STRING: 51 if (*(char**)addr == NULL) { 52 Py_INCREF(Py_None); 53 v = Py_None; 54 } 55 else 56 v = PyUnicode_FromString(*(char**)addr); 57 break; 58 case T_STRING_INPLACE: 59 v = PyUnicode_FromString((char*)addr); 60 break; 61 case T_CHAR: 62 v = PyUnicode_FromStringAndSize((char*)addr, 1); 63 break; 64 case T_OBJECT: 65 v = *(PyObject **)addr; 66 if (v == NULL) 67 v = Py_None; 68 Py_INCREF(v); 69 break; 70 case T_OBJECT_EX: 71 v = *(PyObject **)addr; 72 if (v == NULL) { 73 PyObject *obj = (PyObject *)obj_addr; 74 PyTypeObject *tp = Py_TYPE(obj); 75 PyErr_Format(PyExc_AttributeError, 76 "'%.200s' object has no attribute '%s'", 77 tp->tp_name, l->name); 78 } 79 Py_XINCREF(v); 80 break; 81 case T_LONGLONG: 82 v = PyLong_FromLongLong(*(long long *)addr); 83 break; 84 case T_ULONGLONG: 85 v = PyLong_FromUnsignedLongLong(*(unsigned long long *)addr); 86 break; 87 case T_NONE: 88 v = Py_None; 89 Py_INCREF(v); 90 break; 91 default: 92 PyErr_SetString(PyExc_SystemError, "bad memberdescr type"); 93 v = NULL; 94 } 95 return v; 96} 97 98#define WARN(msg) \ 99 do { \ 100 if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \ 101 return -1; \ 102 } while (0) 103 104int 105PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) 106{ 107 PyObject *oldv; 108 109 addr += l->offset; 110 111 if ((l->flags & READONLY)) 112 { 113 PyErr_SetString(PyExc_AttributeError, "readonly attribute"); 114 return -1; 115 } 116 if (v == NULL) { 117 if (l->type == T_OBJECT_EX) { 118 /* Check if the attribute is set. */ 119 if (*(PyObject **)addr == NULL) { 120 PyErr_SetString(PyExc_AttributeError, l->name); 121 return -1; 122 } 123 } 124 else if (l->type != T_OBJECT) { 125 PyErr_SetString(PyExc_TypeError, 126 "can't delete numeric/char attribute"); 127 return -1; 128 } 129 } 130 switch (l->type) { 131 case T_BOOL:{ 132 if (!PyBool_Check(v)) { 133 PyErr_SetString(PyExc_TypeError, 134 "attribute value type must be bool"); 135 return -1; 136 } 137 if (v == Py_True) 138 *(char*)addr = (char) 1; 139 else 140 *(char*)addr = (char) 0; 141 break; 142 } 143 case T_BYTE:{ 144 long long_val = PyLong_AsLong(v); 145 if ((long_val == -1) && PyErr_Occurred()) 146 return -1; 147 *(char*)addr = (char)long_val; 148 /* XXX: For compatibility, only warn about truncations 149 for now. */ 150 if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN)) 151 WARN("Truncation of value to char"); 152 break; 153 } 154 case T_UBYTE:{ 155 long long_val = PyLong_AsLong(v); 156 if ((long_val == -1) && PyErr_Occurred()) 157 return -1; 158 *(unsigned char*)addr = (unsigned char)long_val; 159 if ((long_val > UCHAR_MAX) || (long_val < 0)) 160 WARN("Truncation of value to unsigned char"); 161 break; 162 } 163 case T_SHORT:{ 164 long long_val = PyLong_AsLong(v); 165 if ((long_val == -1) && PyErr_Occurred()) 166 return -1; 167 *(short*)addr = (short)long_val; 168 if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN)) 169 WARN("Truncation of value to short"); 170 break; 171 } 172 case T_USHORT:{ 173 long long_val = PyLong_AsLong(v); 174 if ((long_val == -1) && PyErr_Occurred()) 175 return -1; 176 *(unsigned short*)addr = (unsigned short)long_val; 177 if ((long_val > USHRT_MAX) || (long_val < 0)) 178 WARN("Truncation of value to unsigned short"); 179 break; 180 } 181 case T_INT:{ 182 long long_val = PyLong_AsLong(v); 183 if ((long_val == -1) && PyErr_Occurred()) 184 return -1; 185 *(int *)addr = (int)long_val; 186 if ((long_val > INT_MAX) || (long_val < INT_MIN)) 187 WARN("Truncation of value to int"); 188 break; 189 } 190 case T_UINT:{ 191 unsigned long ulong_val = PyLong_AsUnsignedLong(v); 192 if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) { 193 /* XXX: For compatibility, accept negative int values 194 as well. */ 195 PyErr_Clear(); 196 ulong_val = PyLong_AsLong(v); 197 if ((ulong_val == (unsigned long)-1) && 198 PyErr_Occurred()) 199 return -1; 200 *(unsigned int *)addr = (unsigned int)ulong_val; 201 WARN("Writing negative value into unsigned field"); 202 } else 203 *(unsigned int *)addr = (unsigned int)ulong_val; 204 if (ulong_val > UINT_MAX) 205 WARN("Truncation of value to unsigned int"); 206 break; 207 } 208 case T_LONG:{ 209 *(long*)addr = PyLong_AsLong(v); 210 if ((*(long*)addr == -1) && PyErr_Occurred()) 211 return -1; 212 break; 213 } 214 case T_ULONG:{ 215 *(unsigned long*)addr = PyLong_AsUnsignedLong(v); 216 if ((*(unsigned long*)addr == (unsigned long)-1) 217 && PyErr_Occurred()) { 218 /* XXX: For compatibility, accept negative int values 219 as well. */ 220 PyErr_Clear(); 221 *(unsigned long*)addr = PyLong_AsLong(v); 222 if ((*(unsigned long*)addr == (unsigned long)-1) 223 && PyErr_Occurred()) 224 return -1; 225 WARN("Writing negative value into unsigned field"); 226 } 227 break; 228 } 229 case T_PYSSIZET:{ 230 *(Py_ssize_t*)addr = PyLong_AsSsize_t(v); 231 if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1) 232 && PyErr_Occurred()) 233 return -1; 234 break; 235 } 236 case T_FLOAT:{ 237 double double_val = PyFloat_AsDouble(v); 238 if ((double_val == -1) && PyErr_Occurred()) 239 return -1; 240 *(float*)addr = (float)double_val; 241 break; 242 } 243 case T_DOUBLE: 244 *(double*)addr = PyFloat_AsDouble(v); 245 if ((*(double*)addr == -1) && PyErr_Occurred()) 246 return -1; 247 break; 248 case T_OBJECT: 249 case T_OBJECT_EX: 250 Py_XINCREF(v); 251 oldv = *(PyObject **)addr; 252 *(PyObject **)addr = v; 253 Py_XDECREF(oldv); 254 break; 255 case T_CHAR: { 256 const char *string; 257 Py_ssize_t len; 258 259 string = PyUnicode_AsUTF8AndSize(v, &len); 260 if (string == NULL || len != 1) { 261 PyErr_BadArgument(); 262 return -1; 263 } 264 *(char*)addr = string[0]; 265 break; 266 } 267 case T_STRING: 268 case T_STRING_INPLACE: 269 PyErr_SetString(PyExc_TypeError, "readonly attribute"); 270 return -1; 271 case T_LONGLONG:{ 272 long long value; 273 *(long long*)addr = value = PyLong_AsLongLong(v); 274 if ((value == -1) && PyErr_Occurred()) 275 return -1; 276 break; 277 } 278 case T_ULONGLONG:{ 279 unsigned long long value; 280 /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong 281 doesn't ??? */ 282 if (PyLong_Check(v)) 283 *(unsigned long long*)addr = value = PyLong_AsUnsignedLongLong(v); 284 else 285 *(unsigned long long*)addr = value = PyLong_AsLong(v); 286 if ((value == (unsigned long long)-1) && PyErr_Occurred()) 287 return -1; 288 break; 289 } 290 default: 291 PyErr_Format(PyExc_SystemError, 292 "bad memberdescr type for %s", l->name); 293 return -1; 294 } 295 return 0; 296} 297