(root)/
Python-3.11.7/
Python/
structmember.c
       1  
       2  /* Map C struct members to Python object attributes */
       3  
       4  #include "Python.h"
       5  #include "structmember.h"         // PyMemberDef
       6  
       7  PyObject *
       8  PyMember_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  
     104  int
     105  PyMember_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  }