Everything builds and works again.
[fail.git] / src / services / python / basic_types.h
blob238f3894bbc9db4ac1d15ce80a00cb9d065e6f42
1 #ifndef AWFUL_PYTHON_BASIC_TYPES_H
2 #define AWFUL_PYTHON_BASIC_TYPES_H
4 namespace awful { namespace PythonImpl
5 {
6 template< typename category, typename T > struct TypeConverter
8 };
10 // No overflow checking for now because I'm lazy.
11 struct IntegerTypeConverter
13 static bool CheckType_nothrow( PyObject* pPyObj_ )
15 return PyInt_Check( pPyObj_ ) || PyLong_Check( pPyObj_ );
19 template< typename T > struct SignedIntegerTypeConverter : public IntegerTypeConverter
21 static void ConvertFromPython_nocheck( PyObject* pPyObj_, T& Dest_ )
23 if( PyInt_Check( pPyObj_ ) )
24 Dest_ = PyInt_AS_LONG( pPyObj_ );
25 else
26 Dest_ = PyLong_AsLongLong( pPyObj_ );
29 static void ConvertFromPython( PyObject* pPyObj_, T& Dest_ )
31 if( !CheckType_nothrow( pPyObj_ ) )
32 throw Error::TypeMismatch();
34 ConvertFromPython_nocheck( pPyObj_, Dest_ );
37 static PyObject* ConvertToPython( T Value_ )
39 return PyLong_FromLongLong( Value_ );
43 template< typename T > struct UnsignedIntegerTypeConverter : public IntegerTypeConverter
45 static void ConvertFromPython_nocheck( PyObject* pPyObj_, T& Dest_ )
47 if( PyInt_Check( pPyObj_ ) )
48 Dest_ = PyInt_AS_LONG( pPyObj_ );
49 else
50 Dest_ = PyLong_AsUnsignedLongLong( pPyObj_ );
53 static void ConvertFromPython( PyObject* pPyObj_, T& Dest_ )
55 if( !CheckType_nothrow( pPyObj_ ) )
56 throw Error::TypeMismatch();
58 ConvertFromPython_nocheck( pPyObj_, Dest_ );
61 static PyObject* ConvertToPython( T Value_ )
63 return PyLong_FromUnsignedLongLong( Value_ );
67 template<> struct TypeConverter< NormalType, uint8_t > : public UnsignedIntegerTypeConverter< uint8_t > {};
68 template<> struct TypeConverter< NormalType, int8_t > : public SignedIntegerTypeConverter< int8_t > {};
70 template<> struct TypeConverter< NormalType, uint16_t > : public UnsignedIntegerTypeConverter< uint16_t > {};
71 template<> struct TypeConverter< NormalType, int16_t > : public SignedIntegerTypeConverter< int16_t > {};
73 template<> struct TypeConverter< NormalType, uint32_t > : public UnsignedIntegerTypeConverter< uint32_t > {};
74 template<> struct TypeConverter< NormalType, int32_t > : public SignedIntegerTypeConverter< int32_t > {};
76 template<> struct TypeConverter< NormalType, uint64_t > : public UnsignedIntegerTypeConverter< uint64_t > {};
77 template<> struct TypeConverter< NormalType, int64_t > : public SignedIntegerTypeConverter< int64_t > {};
79 template< typename enum_type > struct TypeConverter< EnumType, enum_type > :
80 public SignedIntegerTypeConverter< int32_t >
82 typedef SignedIntegerTypeConverter< int32_t > base;
84 static void ConvertFromPython_nocheck( PyObject* pPyObj_, enum_type& Dest_ )
86 int32_t val;
87 base::ConvertFromPython_nocheck( pPyObj_, val );
88 Dest_ = static_cast< enum_type >( val );
91 static void ConvertFromPython( PyObject* pPyObj_, enum_type& Dest_ )
93 int32_t val;
94 base::ConvertFromPython( pPyObj_, val );
95 Dest_ = static_cast< enum_type >( val );
98 static PyObject* ConvertToPython( enum_type Value_ )
100 return base::ConvertToPython( Value_ );
104 // float
105 template<> struct TypeConverter< NormalType, float >
107 static bool CheckType_nothrow( PyObject* pPyObj_ )
109 return !!PyFloat_Check( pPyObj_ );
112 static void ConvertFromPython_nocheck( PyObject* pPyObj_, float& Dest_ )
114 Dest_ = PyFloat_AS_DOUBLE( pPyObj_ );
117 static void ConvertFromPython( PyObject* pPyObj_, float& Dest_ )
119 if( !CheckType_nothrow( pPyObj_ ) )
120 throw Error::TypeMismatch();
122 ConvertFromPython_nocheck( pPyObj_, Dest_ );
125 static PyObject* ConvertToPython( float Value_ )
127 return PyFloat_FromDouble( Value_ );
131 // bool
132 template<> struct TypeConverter< NormalType, bool >
134 static bool CheckType_nothrow( PyObject* pPyObj_ )
136 return !!PyBool_Check( pPyObj_ );
139 static void ConvertFromPython_nocheck( PyObject* pPyObj_, bool& Dest_ )
141 // FOR FUCKS SAKE
142 // Every single python developer is a fucking brainless eat-shitting moron
143 // "warning: dereferencing type-punned pointer will break strict-aliasing rules"
144 // because those shitty Py_True/Py_False macros do retarded casting, and there is
145 // of course no way to test a boolean value without using these.
147 // And of course, it all comes from the incredibly stupid decision of python
148 // to implement numeric values as objects, and share their instances. So instead of
149 // carrying around a boolean value (1 byte), they lug around a pointer and need to
150 // update reference counters for those numeric values. And they have to be dereferenced
151 // anytime the actual numeric value is needed.
153 // So they make the common use cases slower for the sake of the rare use case
154 // where you need to consider an integer as an object. They could have implemented
155 // native types directly passed around by values, with automatic boxing/unboxing
156 // into an object of the corresponding numeric class when needed, but I guess it's way
157 // too clever for them.
159 // Anyway, if I want my stuff to build without warnings (which I of course do) I can either:
161 // - disable this warning (which I won't because it's useful to avoid
162 // accidentaly writing retarded code, but I guess that if the python
163 // fucktards did this, they wouldn't be able to figure out how to code
164 // anything at all)
166 // - use a pragma to disable this warning just here (non-portable, and it doesn't seem
167 // to work for that particular warning)
169 // - fuck their shitty macros and do it by hand with some workaround, and because
170 // I then don't use the python API properly anymore (funny how in the world of
171 // python, properly means "with a disgusting compilation warning"), things
172 // will probably break down somehow in the future if they decide to break
173 // binary compatilibty.
175 // The gene pool would be so much improved if everyone intentionally choosing
176 // to use python for any purpose whatsoever, as well as anyone having anything
177 // to do with its development would suddenly choke and die.
179 // Option 2 failed, so I'm going for option 3. If you're here because you
180 // have a version of python above 2.5 and it fails to build/work, now you
181 // know why.
183 //Dest_ = ( pPyObj_ != Py_True );
184 Dest_ = ( pPyObj_ == static_cast< PyObject* >( static_cast< void* >( &_Py_TrueStruct ) ) );
187 static void ConvertFromPython( PyObject* pPyObj_, bool& Dest_ )
189 if( !CheckType_nothrow( pPyObj_ ) )
190 throw Error::TypeMismatch();
192 ConvertFromPython_nocheck( pPyObj_, Dest_ );
195 static PyObject* ConvertToPython( const bool& Value_ )
197 return PyBool_FromLong( Value_ );
201 // string
202 template<> struct TypeConverter< NormalType, std::string >
204 static bool CheckType_nothrow( PyObject* pPyObj_ )
206 return !!PyString_Check( pPyObj_ );
209 static void ConvertFromPython_nocheck( PyObject* pPyObj_, std::string& Dest_ )
211 Dest_ = PyString_AsString( pPyObj_ );
214 static void ConvertFromPython( PyObject* pPyObj_, std::string& Dest_ )
216 if( !CheckType_nothrow( pPyObj_ ) )
217 throw Error::TypeMismatch();
219 ConvertFromPython_nocheck( pPyObj_, Dest_ );
222 static PyObject* ConvertToPython( const std::string& Value_ )
224 return PyString_FromString( Value_.c_str() );
228 // Dummy type converters for all STL container types for now
229 template< typename C, typename T > struct TypeConverter< MonadicType< C >, T >
231 static bool CheckType_nothrow( PyObject* pPyObj_ ) { return false; }
232 static void ConvertFromPython_nocheck( PyObject* pPyObj_, T& Dest_ ) {}
233 static void ConvertFromPython( PyObject* pPyObj_, T& Dest_ ) {}
234 static PyObject* ConvertToPython( const T& Value_ ) { Py_RETURN_NONE; }
237 template< typename C1, typename C2, typename T > struct TypeConverter< DyadicType< C1, C2 >, T >
239 static bool CheckType_nothrow( PyObject* pPyObj_ ) { return false; }
240 static void ConvertFromPython_nocheck( PyObject* pPyObj_, T& Dest_ ) {}
241 static void ConvertFromPython( PyObject* pPyObj_, T& Dest_ ) {}
242 static PyObject* ConvertToPython( const T& Value_ ) { Py_RETURN_NONE; }
245 template<> struct TypeConverter< NormalType, DynamicBuffer >
247 static bool CheckType_nothrow( PyObject* pPyObj_ ) { return false; }
248 static void ConvertFromPython_nocheck( PyObject* pPyObj_, DynamicBuffer& Dest_ ) {}
249 static void ConvertFromPython( PyObject* pPyObj_, DynamicBuffer& Dest_ ) {}
250 static PyObject* ConvertToPython( const DynamicBuffer& Value_ ) { Py_RETURN_NONE; }
253 // TODO: all other types
256 #endif