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