home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Python / structmember.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  5.0 KB  |  246 lines

  1.  
  2. /* Map C struct members to Python object attributes */
  3.  
  4. #include "Python.h"
  5.  
  6. #include "structmember.h"
  7.  
  8. static PyObject *
  9. listmembers(struct memberlist *mlist)
  10. {
  11.     int i, n;
  12.     PyObject *v;
  13.     for (n = 0; mlist[n].name != NULL; n++)
  14.         ;
  15.     v = PyList_New(n);
  16.     if (v != NULL) {
  17.         for (i = 0; i < n; i++)
  18.             PyList_SetItem(v, i,
  19.                        PyString_FromString(mlist[i].name));
  20.         if (PyErr_Occurred()) {
  21.             Py_DECREF(v);
  22.             v = NULL;
  23.         }
  24.         else {
  25.             PyList_Sort(v);
  26.         }
  27.     }
  28.     return v;
  29. }
  30.  
  31. PyObject *
  32. PyMember_Get(char *addr, struct memberlist *mlist, char *name)
  33. {
  34.     struct memberlist *l;
  35.     
  36.     if (strcmp(name, "__members__") == 0)
  37.         return listmembers(mlist);
  38.     for (l = mlist; l->name != NULL; l++) {
  39.         if (strcmp(l->name, name) == 0) {
  40.             PyObject *v;
  41.             addr += l->offset;
  42.             switch (l->type) {
  43.             case T_BYTE:
  44.                 v = PyInt_FromLong((long)
  45.                          (((*(char*)addr & 0xff)
  46.                            ^ 0x80) - 0x80));
  47.                 break;
  48.             case T_UBYTE:
  49.                 v = PyInt_FromLong((long) *(char*)addr & 0xff);
  50.                 break;
  51.             case T_SHORT:
  52.                 v = PyInt_FromLong((long) *(short*)addr);
  53.                 break;
  54.             case T_USHORT:
  55.                 v = PyInt_FromLong((long)
  56.                          *(unsigned short*)addr);
  57.                 break;
  58.             case T_INT:
  59.                 v = PyInt_FromLong((long) *(int*)addr);
  60.                 break;
  61.             case T_UINT:
  62.                 v = PyInt_FromLong((long)
  63.                            *(unsigned int*)addr);
  64.                 break;
  65.             case T_LONG:
  66.                 v = PyInt_FromLong(*(long*)addr);
  67.                 break;
  68.             case T_ULONG:
  69.                 v = PyLong_FromDouble((double)
  70.                            *(unsigned long*)addr);
  71.                 break;
  72.             case T_FLOAT:
  73.                 v = PyFloat_FromDouble((double)*(float*)addr);
  74.                 break;
  75.             case T_DOUBLE:
  76.                 v = PyFloat_FromDouble(*(double*)addr);
  77.                 break;
  78.             case T_STRING:
  79.                 if (*(char**)addr == NULL) {
  80.                     Py_INCREF(Py_None);
  81.                     v = Py_None;
  82.                 }
  83.                 else
  84.                     v = PyString_FromString(*(char**)addr);
  85.                 break;
  86.             case T_STRING_INPLACE:
  87.                 v = PyString_FromString((char*)addr);
  88.                 break;
  89. #ifdef macintosh
  90.             case T_PSTRING:
  91.                 if (*(char**)addr == NULL) {
  92.                     Py_INCREF(Py_None);
  93.                     v = Py_None;
  94.                 }
  95.                 else
  96.                     v = PyString_FromStringAndSize(
  97.                         (*(char**)addr)+1,
  98.                         **(unsigned char**)addr);
  99.                 break;
  100.             case T_PSTRING_INPLACE:
  101.                 v = PyString_FromStringAndSize(
  102.                     ((char*)addr)+1,
  103.                     *(unsigned char*)addr);
  104.                 break;
  105. #endif /* macintosh */
  106.             case T_CHAR:
  107.                 v = PyString_FromStringAndSize((char*)addr, 1);
  108.                 break;
  109.             case T_OBJECT:
  110.                 v = *(PyObject **)addr;
  111.                 if (v == NULL)
  112.                     v = Py_None;
  113.                 Py_INCREF(v);
  114.                 break;
  115.             default:
  116.                 PyErr_SetString(PyExc_SystemError,
  117.                         "bad memberlist type");
  118.                 v = NULL;
  119.             }
  120.             return v;
  121.         }
  122.     }
  123.     
  124.     PyErr_SetString(PyExc_AttributeError, name);
  125.     return NULL;
  126. }
  127.  
  128. int
  129. PyMember_Set(char *addr, struct memberlist *mlist, char *name, PyObject *v)
  130. {
  131.     struct memberlist *l;
  132.     PyObject *oldv;
  133.     
  134.     for (l = mlist; l->name != NULL; l++) {
  135.         if (strcmp(l->name, name) == 0) {
  136. #ifdef macintosh
  137.             if (l->readonly || l->type == T_STRING ||
  138.                 l->type == T_PSTRING)
  139.             {
  140. #else
  141.             if (l->readonly || l->type == T_STRING ) {
  142. #endif /* macintosh */
  143.                 PyErr_SetString(PyExc_TypeError,
  144.                         "readonly attribute");
  145.                 return -1;
  146.             }
  147.             if (v == NULL && l->type != T_OBJECT) {
  148.                 PyErr_SetString(PyExc_TypeError,
  149.                   "can't delete numeric/char attribute");
  150.                 return -1;
  151.             }
  152.             addr += l->offset;
  153.             switch (l->type) {
  154.             case T_BYTE:
  155.             case T_UBYTE:
  156.                 if (!PyInt_Check(v)) {
  157.                     PyErr_BadArgument();
  158.                     return -1;
  159.                 }
  160.                 *(char*)addr = (char) PyInt_AsLong(v);
  161.                 break;
  162.             case T_SHORT:
  163.             case T_USHORT:
  164.                 if (!PyInt_Check(v)) {
  165.                     PyErr_BadArgument();
  166.                     return -1;
  167.                 }
  168.                 *(short*)addr = (short) PyInt_AsLong(v);
  169.                 break;
  170.             case T_UINT:
  171.             case T_INT:
  172.                 if (!PyInt_Check(v)) {
  173.                     PyErr_BadArgument();
  174.                     return -1;
  175.                 }
  176.                 *(int*)addr = (int) PyInt_AsLong(v);
  177.                 break;
  178.             case T_LONG:
  179.                 if (!PyInt_Check(v)) {
  180.                     PyErr_BadArgument();
  181.                     return -1;
  182.                 }
  183.                 *(long*)addr = PyInt_AsLong(v);
  184.                 break;
  185.             case T_ULONG:
  186.                 if (PyInt_Check(v))
  187.                     *(long*)addr = PyInt_AsLong(v);
  188.                 else if (PyLong_Check(v))
  189.                     *(long*)addr = PyLong_AsLong(v);
  190.                 else {
  191.                     PyErr_BadArgument();
  192.                     return -1;
  193.                 }
  194.                 break;
  195.             case T_FLOAT:
  196.                 if (PyInt_Check(v))
  197.                     *(float*)addr =
  198.                         (float) PyInt_AsLong(v);
  199.                 else if (PyFloat_Check(v))
  200.                     *(float*)addr =
  201.                         (float) PyFloat_AsDouble(v);
  202.                 else {
  203.                     PyErr_BadArgument();
  204.                     return -1;
  205.                 }
  206.                 break;
  207.             case T_DOUBLE:
  208.                 if (PyInt_Check(v))
  209.                     *(double*)addr =
  210.                         (double) PyInt_AsLong(v);
  211.                 else if (PyFloat_Check(v))
  212.                     *(double*)addr = PyFloat_AsDouble(v);
  213.                 else {
  214.                     PyErr_BadArgument();
  215.                     return -1;
  216.                 }
  217.                 break;
  218.             case T_OBJECT:
  219.                 Py_XINCREF(v);
  220.                 oldv = *(PyObject **)addr;
  221.                 *(PyObject **)addr = v;
  222.                 Py_XDECREF(oldv);
  223.                 break;
  224.             case T_CHAR:
  225.                 if (PyString_Check(v) &&
  226.                     PyString_Size(v) == 1) {
  227.                     *(char*)addr =
  228.                         PyString_AsString(v)[0];
  229.                 }
  230.                 else {
  231.                     PyErr_BadArgument();
  232.                     return -1;
  233.                 }
  234.             default:
  235.                 PyErr_SetString(PyExc_SystemError,
  236.                         "bad memberlist type");
  237.                 return -1;
  238.             }
  239.             return 0;
  240.         }
  241.     }
  242.     
  243.     PyErr_SetString(PyExc_AttributeError, name);
  244.     return -1;
  245. }
  246.