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