1 //-----------------------------------------------------------------------------
2 //
3 // Copyright (c) 1998 - 2007, The Regents of the University of California
4 // Produced at the Lawrence Livermore National Laboratory
5 // All rights reserved.
6 //
7 // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The
8 // full copyright notice is contained in the file COPYRIGHT located at the root
9 // of the PyCXX distribution.
10 //
11 // Redistribution  and  use  in  source  and  binary  forms,  with  or  without
12 // modification, are permitted provided that the following conditions are met:
13 //
14 //  - Redistributions of  source code must  retain the above  copyright notice,
15 //    this list of conditions and the disclaimer below.
16 //  - Redistributions in binary form must reproduce the above copyright notice,
17 //    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
18 //    documentation and/or materials provided with the distribution.
19 //  - Neither the name of the UC/LLNL nor  the names of its contributors may be
20 //    used to  endorse or  promote products derived from  this software without
21 //    specific prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
24 // AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
25 // IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
26 // ARE  DISCLAIMED.  IN  NO  EVENT  SHALL  THE  REGENTS  OF  THE  UNIVERSITY OF
27 // CALIFORNIA, THE U.S.  DEPARTMENT  OF  ENERGY OR CONTRIBUTORS BE  LIABLE  FOR
28 // ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR CONSEQUENTIAL
29 // DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
30 // SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
31 // CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
32 // LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
33 // OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
34 // DAMAGE.
35 //
36 //-----------------------------------------------------------------------------
37 
38 #ifndef __CXX_PythonType__h
39 #define __CXX_PythonType__h
40 
41 #if defined( Py_LIMITED_API )
42 #include <unordered_map>
43 #endif
44 
45 namespace Py
46 {
47     class PythonType
48     {
49     public:
50         // if you define one sequence method you must define
51         // all of them except the assigns
52 
53         PythonType( size_t base_size, int itemsize, const char *default_name );
54         virtual ~PythonType();
55 
56         const char *getName() const;
57         const char *getDoc() const;
58 
59         PyTypeObject *type_object() const;
60         PythonType &name( const char *nam );
61         PythonType &doc( const char *d );
62 
63         PythonType &supportClass( void );
64 #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7
65         PythonType &supportPrint( void );
66 #endif
67         PythonType &supportGetattr( void );
68         PythonType &supportSetattr( void );
69         PythonType &supportGetattro( void );
70         PythonType &supportSetattro( void );
71 #ifdef PYCXX_PYTHON_2TO3
72         PythonType &supportCompare( void );
73 #endif
74         PythonType &supportRichCompare( void );
75         PythonType &supportRepr( void );
76         PythonType &supportStr( void );
77         PythonType &supportHash( void );
78         PythonType &supportCall( void );
79 
80 #define B( n ) (1<<(n))
81         enum {
82             support_iter_iter =                 B(0),
83             support_iter_iternext =             B(1)
84         };
85         PythonType &supportIter( int methods_to_support=
86                         support_iter_iter |
87                         support_iter_iternext );
88 
89         enum {
90             support_sequence_length =           B(0),
91             support_sequence_repeat =           B(1),
92             support_sequence_item =             B(2),
93             support_sequence_slice =            B(3),
94             support_sequence_concat =           B(4),
95             support_sequence_ass_item =         B(5),
96             support_sequence_ass_slice =        B(6),
97             support_sequence_inplace_concat =   B(7),
98             support_sequence_inplace_repeat =   B(8),
99             support_sequence_contains =         B(9)
100         };
101         PythonType &supportSequenceType( int methods_to_support=
102                         support_sequence_length |
103                         support_sequence_repeat |
104                         support_sequence_item |
105                         support_sequence_slice |
106                         support_sequence_concat
107                         );
108 
109         enum {
110             support_mapping_length =            B(0),
111             support_mapping_subscript =         B(1),
112             support_mapping_ass_subscript =     B(2)
113         };
114         PythonType &supportMappingType( int methods_to_support=
115                         support_mapping_length |
116                         support_mapping_subscript
117                         );
118 
119         enum {
120             support_number_add =                B(0),
121             support_number_subtract =           B(1),
122             support_number_multiply =           B(2),
123             support_number_remainder =          B(3),
124             support_number_divmod =             B(4),
125             support_number_power =              B(5),
126             support_number_negative =           B(6),
127             support_number_positive =           B(7),
128             support_number_absolute =           B(8),
129             support_number_invert =             B(9),
130             support_number_lshift =             B(10),
131             support_number_rshift =             B(11),
132             support_number_and =                B(12),
133             support_number_xor =                B(13),
134             support_number_or =                 B(14),
135             support_number_int =                B(15),
136             support_number_float =              B(16),
137             support_number_floor_divide =       B(17),
138             support_number_true_divide =        B(18),
139             support_number_index =              B(19),
140 #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
141             support_number_matrix_multiply =    B(20),
142 #endif
143 
144             // start a new bit mask for inplace that avoid using more then 32 bits in methods_to_support
145             support_number_inplace_floor_divide = B(0),
146             support_number_inplace_true_divide = B(1),
147             support_number_inplace_add =        B(2),
148             support_number_inplace_subtract =   B(3),
149             support_number_inplace_multiply =   B(4),
150             support_number_inplace_remainder =  B(5),
151             support_number_inplace_power =      B(6),
152             support_number_inplace_lshift =     B(7),
153             support_number_inplace_rshift =     B(8),
154             support_number_inplace_and =        B(9),
155             support_number_inplace_xor =        B(10),
156             support_number_inplace_or =         B(11)
157 #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
158             ,
159             support_number_inplace_matrix_multiply = B(12)
160 #endif
161         };
162         PythonType &supportNumberType(
163             int methods_to_support=
164                 support_number_add |
165                 support_number_subtract |
166                 support_number_multiply |
167                 support_number_remainder |
168                 support_number_divmod |
169                 support_number_power |
170                 support_number_negative |
171                 support_number_positive |
172                 support_number_absolute |
173                 support_number_invert |
174                 support_number_lshift |
175                 support_number_rshift |
176                 support_number_and |
177                 support_number_xor |
178                 support_number_or |
179                 support_number_int |
180                 support_number_float,
181             int inplace_methods_to_support=0
182             );
183 
184 #if !defined( Py_LIMITED_API )
185         enum {
186             support_buffer_getbuffer =          B(0),
187             support_buffer_releasebuffer =      B(1)
188         };
189         PythonType &supportBufferType( int methods_to_support=
190                     support_buffer_getbuffer |
191                     support_buffer_releasebuffer
192                     );
193 #endif
194 #undef B
195 
196         PythonType &set_tp_dealloc( void (*tp_dealloc)( PyObject * ) );
197         PythonType &set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) );
198         PythonType &set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) );
199         PythonType &set_methods( PyMethodDef *methods );
200 
201         // call once all support functions have been called to ready the type
202         bool readyType();
203 
204     protected:
205 #if defined( Py_LIMITED_API )
206         std::unordered_map<int, void*>  slots;
207         PyType_Spec                     *spec;
208         PyTypeObject                    *tp_object;
209 #else
210         PyTypeObject            *table;
211         PySequenceMethods       *sequence_table;
212         PyMappingMethods        *mapping_table;
213         PyNumberMethods         *number_table;
214         PyBufferProcs           *buffer_table;
215 #endif
216 
217     private:
218         //
219         // prevent the compiler generating these unwanted functions
220         //
221         PythonType( const PythonType &tb );     // unimplemented
222         void operator=( const PythonType &t );  // unimplemented
223 
224     };
225 
226 } // Namespace Py
227 
228 // End of __CXX_PythonType__h
229 #endif
230