chiark / gitweb /
Add 'pyke/' from commit '6c2569879c220eeac35957cdba9a043e8a5ea9ed'
[mLib-python] / pyke / pyke-mLib.c
1 /* -*-c-*-
2  *
3  * Pyke: the Python Kit for Extensions, mLib integration
4  *
5  * (c) 2019 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Pyke: the Python Kit for Extensions.
11  *
12  * Pyke is free software: you can redistribute it and/or modify it under
13  * the terms of the GNU General Public License as published by the Free
14  * Software Foundation; either version 2 of the License, or (at your
15  * option) any later version.
16  *
17  * Pyke is distributed in the hope that it will be useful, but WITHOUT
18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20  * for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Pyke.  If not, write to the Free Software Foundation, Inc.,
24  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /*----- Header files ------------------------------------------------------*/
28
29 #include "pyke-mLib.h"
30
31 /* #undef HAVE_LONG_LONG */
32
33 /*----- Conversions -------------------------------------------------------*/
34
35 #ifndef HAVE_LONG_LONG
36 static PyObject *i32 = 0;
37 static int init_i32(void)
38   { if (!i32 && (i32 = PyInt_FromLong(32)) == 0) return (-1); return (0); }
39 #endif
40
41 PyObject *getk64(kludge64 u)
42 {
43 #ifdef HAVE_LONG_LONG
44   return (PyLong_FromUnsignedLongLong(GET64(unsigned PY_LONG_LONG, u)));
45 #else
46   PyObject *i = 0, *j = 0, *t;
47   PyObject *rc = 0;
48
49   if (init_i32()) goto end;
50   if ((i = PyLong_FromUnsignedLong(HI64(u))) == 0) goto end;
51   if ((t = PyNumber_InPlaceLshift(i, i32)) == 0) goto end;
52   Py_DECREF(i); i = t;
53   if ((j = PyLong_FromUnsignedLong(LO64(u))) == 0) goto end;
54   if ((t = PyNumber_InPlaceOr(i, j)) == 0) goto end;
55 #  ifdef PY2
56   Py_DECREF(i); i = t;
57   if ((t = PyNumber_Int(i)) == 0) goto end;
58 #  endif
59   rc = t;
60 end:
61   Py_XDECREF(i);
62   Py_XDECREF(j);
63   return (rc);
64 #endif
65 }
66
67 #ifdef HAVE_UINT64
68 #  define CONVu64(n) do {                                               \
69      kludge64 k;                                                        \
70      uint64 t;                                                          \
71      if (!convk64(o, &k)) goto end;                                     \
72      t = GET64(uint64, k);                                              \
73      if (t > MASK##n) OVFERR("out of range");                           \
74      *p = t;                                                            \
75    } while (0)
76 #else
77 #  define CONVu64(n) assert(!"shouldn't be possible")
78 #endif
79
80 #define CONVU_(n)                                                       \
81   int convu##n(PyObject *o, void *pp)                                   \
82   {                                                                     \
83     unsigned long u;                                                    \
84     uint##n *p = pp;                                                    \
85                                                                         \
86     if (MASK##n > ULONG_MAX)                                            \
87       CONVu64(n);                                                       \
88     else {                                                              \
89       if (!convulong(o, &u)) goto end;                                  \
90       if (u > MASK##n) OVFERR("out of range");                          \
91       *p = u;                                                           \
92     }                                                                   \
93     return (1);                                                         \
94   end:                                                                  \
95     return (0);                                                         \
96   }
97 DOUINTSZ(CONVU_)
98
99 int convk64(PyObject *o, void *pp)
100 {
101   PyObject *i = 0;
102   int rc = 0;
103 #if HAVE_LONG_LONG
104   unsigned PY_LONG_LONG t;
105 #else
106   PyObject *t;
107   uint32 lo, hi;
108 #endif
109
110 #if HAVE_LONG_LONG
111   if ((i = PyNumber_Long(o)) == 0) goto end;
112   t = PyLong_AsUnsignedLongLong(i);
113   if (t == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) goto end;
114   ASSIGN64(*(kludge64 *)pp, t);
115 #else
116   if (init_i32()) goto end;
117   if ((i = PyNumber_Int(o)) == 0) goto end;
118   lo = PyInt_AsUnsignedLongMask(i);
119   if ((t = PyNumber_InPlaceRshift(i, i32)) == 0) goto end;
120   Py_DECREF(i); i = t;
121   hi = PyInt_AsUnsignedLongMask(i);
122   if ((t = PyNumber_InPlaceRshift(i, i32)) == 0) goto end;
123   Py_DECREF(i); i = t;
124   if (PyObject_IsTrue(i)) OVFERR("out of range");
125   SET64(*(kludge64 *)pp, hi, lo);
126 #endif
127   rc = 1;
128
129 end:
130   Py_XDECREF(i);
131   return (rc);
132 }
133
134 /*----- That's all, folks -------------------------------------------------*/