xref: /trunk/main/pyuno/source/module/pyuno_type.cxx (revision c83c60c7e6aac8747783658329758074eef3eb8c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #include "pyuno_impl.hxx"
24 
25 #include <rtl/ustrbuf.hxx>
26 #include <rtl/strbuf.hxx>
27 
28 #include <typelib/typedescription.hxx>
29 
30 using rtl::OString;
31 using rtl::OUString;
32 using rtl::OUStringBuffer;
33 using rtl::OUStringToOString;
34 using rtl::OStringBuffer;
35 
36 using com::sun::star::uno::TypeClass;
37 using com::sun::star::uno::Type;
38 using com::sun::star::uno::RuntimeException;
39 using com::sun::star::uno::Any;
40 using com::sun::star::uno::XInterface;
41 using com::sun::star::uno::Reference;
42 using com::sun::star::uno::TypeDescription;
43 
44 #define USTR_ASCII(x) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
45 namespace pyuno
46 {
typeClassToString(TypeClass t)47 const char *typeClassToString( TypeClass t )
48 {
49     const char * ret = 0;
50     switch (t)
51     {
52     case com::sun::star::uno::TypeClass_VOID:
53         ret = "VOID"; break;
54     case com::sun::star::uno::TypeClass_CHAR:
55         ret = "CHAR"; break;
56     case com::sun::star::uno::TypeClass_BOOLEAN:
57         ret = "BOOLEAN"; break;
58     case com::sun::star::uno::TypeClass_BYTE:
59         ret = "BYTE"; break;
60     case com::sun::star::uno::TypeClass_SHORT:
61         ret = "SHORT"; break;
62     case com::sun::star::uno::TypeClass_UNSIGNED_SHORT:
63         ret = "UNSIGNED_SHORT"; break;
64     case com::sun::star::uno::TypeClass_LONG:
65         ret = "LONG"; break;
66     case com::sun::star::uno::TypeClass_UNSIGNED_LONG:
67         ret = "UNSIGNED_LONG"; break;
68     case com::sun::star::uno::TypeClass_HYPER:
69         ret = "HYPER"; break;
70     case com::sun::star::uno::TypeClass_UNSIGNED_HYPER:
71         ret = "UNSIGNED_HYPER"; break;
72     case com::sun::star::uno::TypeClass_FLOAT:
73         ret = "FLOAT"; break;
74     case com::sun::star::uno::TypeClass_DOUBLE:
75         ret = "DOUBLE"; break;
76     case com::sun::star::uno::TypeClass_STRING:
77         ret = "STRING"; break;
78     case com::sun::star::uno::TypeClass_TYPE:
79         ret = "TYPE"; break;
80     case com::sun::star::uno::TypeClass_ANY:
81         ret = "ANY";break;
82     case com::sun::star::uno::TypeClass_ENUM:
83         ret = "ENUM";break;
84     case com::sun::star::uno::TypeClass_STRUCT:
85         ret = "STRUCT"; break;
86     case com::sun::star::uno::TypeClass_EXCEPTION:
87         ret = "EXCEPTION"; break;
88     case com::sun::star::uno::TypeClass_SEQUENCE:
89         ret = "SEQUENCE"; break;
90     case com::sun::star::uno::TypeClass_INTERFACE:
91         ret = "INTERFACE"; break;
92     case com::sun::star::uno::TypeClass_TYPEDEF:
93         ret = "TYPEDEF"; break;
94     case com::sun::star::uno::TypeClass_UNION:
95         ret = "UNION"; break;
96     case com::sun::star::uno::TypeClass_ARRAY:
97         ret = "ARRAY"; break;
98     case com::sun::star::uno::TypeClass_SERVICE:
99         ret = "SERVICE"; break;
100     case com::sun::star::uno::TypeClass_MODULE:
101         ret = "MODULE"; break;
102     case com::sun::star::uno::TypeClass_INTERFACE_METHOD:
103         ret = "INTERFACE_METHOD"; break;
104     case com::sun::star::uno::TypeClass_INTERFACE_ATTRIBUTE:
105         ret = "INTERFACE_ATTRIBUTE"; break;
106     default:
107         ret = "UNKNOWN"; break;
108     }
109     return ret;
110 }
111 
getClass(const Runtime & r,const char * name)112 static PyRef getClass( const Runtime & r , const char * name)
113 {
114     return PyRef( PyDict_GetItemString( r.getImpl()->cargo->getUnoModule().get(), (char*) name ) );
115 }
116 
getTypeClass(const Runtime & r)117 PyRef getTypeClass( const Runtime & r )
118 {
119     return getClass( r , "Type" );
120 }
121 
getEnumClass(const Runtime & r)122 PyRef getEnumClass( const Runtime & r )
123 {
124     return getClass( r , "Enum" );
125 }
126 
getCharClass(const Runtime & r)127 PyRef getCharClass( const Runtime & r )
128 {
129     return getClass( r , "Char" );
130 }
131 
getByteSequenceClass(const Runtime & r)132 PyRef getByteSequenceClass( const Runtime & r )
133 {
134     return getClass( r , "ByteSequence" );
135 }
136 
getAnyClass(const Runtime & r)137 PyRef getAnyClass( const Runtime & r )
138 {
139     return getClass( r , "Any" );
140 }
141 
142 
PyChar2Unicode(PyObject * obj)143 sal_Unicode PyChar2Unicode( PyObject *obj ) throw ( RuntimeException )
144 {
145     PyRef value( PyObject_GetAttrString( obj, const_cast< char * >("value") ), SAL_NO_ACQUIRE );
146     if( ! PyUnicode_Check( value.get() ) )
147     {
148         throw RuntimeException(
149             USTR_ASCII( "attribute value of uno.Char is not a unicode string" ),
150             Reference< XInterface > () );
151     }
152 
153 #if PY_VERSION_HEX >= 0x030C0000
154     if( PyUnicode_GetLength( value.get() ) < 1 )
155 #else
156     if( PyUnicode_GetSize( value.get() ) < 1 )
157 #endif
158     {
159         throw RuntimeException(
160             USTR_ASCII( "uno.Char contains an empty unicode string" ),
161             Reference< XInterface > () );
162     }
163 #if PY_VERSION_HEX >= 0x03030000
164     sal_Unicode c = (sal_Unicode)PyUnicode_ReadChar( value.get(), 0 );
165 #else
166     sal_Unicode c = (sal_Unicode)PyUnicode_AsUnicode( value.get() )[0];
167 #endif
168     return c;
169 }
170 
PyEnum2Enum(PyObject * obj)171 Any PyEnum2Enum( PyObject *obj ) throw ( RuntimeException )
172 {
173     Any ret;
174     PyRef typeName( PyObject_GetAttrString( obj,const_cast< char * >("typeName") ), SAL_NO_ACQUIRE);
175     PyRef value( PyObject_GetAttrString( obj, const_cast< char * >("value") ), SAL_NO_ACQUIRE);
176     if( !PYSTR_CHECK( typeName.get() ) || ! PYSTR_CHECK( value.get() ) )
177     {
178         throw RuntimeException(
179             USTR_ASCII( "attributes typeName and/or value of uno.Enum are not strings" ),
180             Reference< XInterface > () );
181     }
182 
183     OUString strTypeName( pyString2ustring( typeName.get() ) );
184     OUString strValue( pyString2ustring( value.get() ) );
185 
186     TypeDescription desc( strTypeName );
187     if( desc.is() )
188     {
189         if(desc.get()->eTypeClass != typelib_TypeClass_ENUM )
190         {
191             OUStringBuffer buf;
192             buf.appendAscii( "pyuno.checkEnum: " ).append( strTypeName ).appendAscii( " is a " );
193             buf.appendAscii(
194                 typeClassToString( (com::sun::star::uno::TypeClass) desc.get()->eTypeClass));
195             buf.appendAscii( ", expected ENUM" );
196             throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface>  () );
197         }
198 
199         desc.makeComplete();
200 
201         typelib_EnumTypeDescription *pEnumDesc = (typelib_EnumTypeDescription*) desc.get();
202         int i = 0;
203         for( i = 0; i < pEnumDesc->nEnumValues ; i ++ )
204         {
205             if( (*((OUString *)&pEnumDesc->ppEnumNames[i])).compareTo( strValue ) == 0 )
206             {
207                 break;
208             }
209         }
210         if( i == pEnumDesc->nEnumValues )
211         {
212             OUStringBuffer buf;
213             buf.appendAscii( "value " ).append( strValue ).appendAscii( " is unknown in enum " );
214             buf.append( strTypeName );
215             throw RuntimeException( buf.makeStringAndClear(), Reference<XInterface> () );
216         }
217         ret = Any( &pEnumDesc->pEnumValues[i], desc.get()->pWeakRef );
218     }
219     else
220     {
221         OUStringBuffer buf;
222         buf.appendAscii( "enum " ).append( strTypeName ).appendAscii( " is unknown" );
223         throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface>  () );
224     }
225     return ret;
226 }
227 
228 
PyType2Type(PyObject * o)229 Type PyType2Type( PyObject * o ) throw(RuntimeException )
230 {
231     PyRef pyName( PyObject_GetAttrString( o, const_cast< char * >("typeName") ), SAL_NO_ACQUIRE);
232     if( !PYSTR_CHECK( pyName.get() ) )
233     {
234         throw RuntimeException(
235             USTR_ASCII( "type object does not have typeName property" ),
236             Reference< XInterface > () );
237     }
238 
239     PyRef pyTC( PyObject_GetAttrString( o, const_cast< char * >("typeClass") ), SAL_NO_ACQUIRE );
240     Any enumValue = PyEnum2Enum( pyTC.get() );
241 
242     OUString name( pyString2ustring( pyName.get() ) );
243     TypeDescription desc( name );
244     if( ! desc.is() )
245     {
246         OUStringBuffer buf;
247         buf.appendAscii( "type " ).append(name).appendAscii( " is unknown" );
248         throw RuntimeException(
249             buf.makeStringAndClear(), Reference< XInterface > () );
250     }
251     if( desc.get()->eTypeClass != (typelib_TypeClass) *(sal_Int32*)enumValue.getValue() )
252     {
253         OUStringBuffer buf;
254         buf.appendAscii( "pyuno.checkType: " ).append(name).appendAscii( " is a " );
255         buf.appendAscii( typeClassToString( (TypeClass) desc.get()->eTypeClass) );
256         buf.appendAscii( ", but type got construct with typeclass " );
257         buf.appendAscii( typeClassToString( (TypeClass) *(sal_Int32*)enumValue.getValue() ) );
258         throw RuntimeException(
259             buf.makeStringAndClear(), Reference< XInterface > () );
260     }
261     return desc.get()->pWeakRef;
262 }
263 
importToGlobal(PyObject * str,PyObject * dict,PyObject * target)264 PyObject *importToGlobal(PyObject *str, PyObject *dict, PyObject *target)
265 {
266     // maybe a constant ?
267     PyObject *ret = 0;
268     OUString name = pyString2ustring(str);
269     try
270     {
271         Runtime runtime;
272         TypeDescription desc(name );
273         desc.makeComplete();
274         if( desc.is() )
275         {
276             com::sun::star::uno::TypeClass tc =
277                 (com::sun::star::uno::TypeClass)desc.get()->eTypeClass;
278 
279             PyRef typesModule( PyDict_GetItemString( dict, "unotypes" ) );
280             if( ! typesModule.is() || ! PyModule_Check( typesModule.get() ))
281             {
282                 typesModule = PyRef( PyModule_New( const_cast< char * >("unotypes") ), SAL_NO_ACQUIRE );
283                 Py_INCREF( typesModule.get() );
284                 PyDict_SetItemString( dict, "unotypes" , typesModule.get() );
285             }
286 #if PY_VERSION_HEX >= 0x03030000
287             const char *targetName = PyUnicode_AsUTF8( target );
288             const char *typeName = PyUnicode_AsUTF8( str );
289 #elif PY_MAJOR_VERSION > 3
290             PyRef pUtf8( PyUnicode_AsUTF8String( target ), SAL_NO_ACQUIRE );
291             const char *targetName = PyBytes_AsString( pUtf8.get() );
292             PyRef pTypeName( PyUnicode_AsUTF8String( str ), SAL_NO_ACQUIRE );
293             const char *typeName = PyBytes_AsString( pTypeName.get() );
294 #else
295             /*const*/ char *targetName = PyBytes_AsString( target );
296             const char *typeName = PyBytes_AsString( str );
297 #endif
298             PyModule_AddObject(
299                 typesModule.get(),
300                 targetName,
301                 PyUNO_Type_new( typeName, tc, runtime ) );
302 
303             if( com::sun::star::uno::TypeClass_EXCEPTION == tc ||
304                 com::sun::star::uno::TypeClass_STRUCT    == tc )
305             {
306                 PyRef exc = getClass( name, runtime );
307                 PyDict_SetItem( dict, target, exc.getAcquired() );
308             }
309             else if( com::sun::star::uno::TypeClass_ENUM == tc )
310             {
311                 // introduce all enums into the dictionary !
312                 typelib_EnumTypeDescription *pDesc =
313                     (typelib_EnumTypeDescription *) desc.get();
314                 for( int i = 0 ; i < pDesc->nEnumValues; i ++ )
315                 {
316                     OString enumElementName(
317                         OUStringToOString( pDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US) );
318 #if PY_VERSION_HEX >= 0x03030000
319                     const char *name = PyUnicode_AsUTF8(str);
320 #elif PY_MAJOR_VERSION > 3
321                     PyRef *pUtf8( PyUnicode_AsUTF8String( str ), SAL_NO_ACQUIRE );
322                     const char *name = PyBytes_AsString( pUtf8.get() );
323 #else
324                     const char *name = PyBytes_AsString(str);
325 #endif
326                     PyDict_SetItemString(
327                         dict, (char*)enumElementName.getStr(),
328                         PyUNO_Enum_new(name, enumElementName.getStr(), runtime ) );
329                 }
330             }
331             Py_INCREF( Py_None );
332             ret = Py_None;
333         }
334         else
335         {
336             Any a = runtime.getImpl()->cargo->xTdMgr->getByHierarchicalName(name);
337             if(a.hasValue())
338             {
339                 PyRef constant = runtime.any2PyObject( a );
340                 if( constant.is() )
341                 {
342                     Py_INCREF( constant.get() );
343                     PyDict_SetItem( dict, target , constant.get());
344                     ret = constant.get();
345                 }
346                 else
347                 {
348                     OUStringBuffer buf;
349                     buf.appendAscii( "constant " ).append(pyString2ustring(str)).appendAscii(  " unknown" );
350                     PyErr_SetString(
351                         PyExc_RuntimeError,
352                         OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_UTF8).getStr() );
353                 }
354             }
355             else
356             {
357                 OUStringBuffer buf;
358                 buf.appendAscii( "pyuno.imp unknown type " );
359                 buf.append( name );
360                 PyErr_SetString(
361                     PyExc_RuntimeError,
362                     OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US).getStr() );
363             }
364         }
365     }
366     catch( com::sun::star::container::NoSuchElementException & )
367     {
368         OUStringBuffer buf;
369         buf.appendAscii( "pyuno.imp unknown type " );
370         buf.append( name );
371         PyErr_SetString(
372             PyExc_RuntimeError,
373             OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US).getStr() );
374     }
375     catch( com::sun::star::script::CannotConvertException & e )
376     {
377         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
378     }
379     catch( com::sun::star::lang::IllegalArgumentException & e )
380     {
381         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
382     }
383     catch( RuntimeException &e )
384     {
385         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ));
386     }
387     return ret;
388 }
389 
callCtor(const Runtime & r,const char * clazz,const PyRef & args)390 static PyObject* callCtor( const Runtime &r , const char * clazz, const PyRef & args )
391 {
392     PyRef code( PyDict_GetItemString( r.getImpl()->cargo->getUnoModule().get(), (char*)clazz ) );
393     if( ! code.is() )
394     {
395         OStringBuffer buf;
396         buf.append( "couldn't access uno." );
397         buf.append( clazz );
398         PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
399         return NULL;
400     }
401     PyRef instance( PyObject_CallObject( code.get(), args.get()  ), SAL_NO_ACQUIRE);
402     Py_XINCREF( instance.get() );
403     return instance.get();
404 
405 }
406 
407 
PyUNO_Enum_new(const char * enumBase,const char * enumValue,const Runtime & r)408 PyObject *PyUNO_Enum_new( const char *enumBase, const char *enumValue, const Runtime &r )
409 {
410     PyRef args( PyTuple_New( 2 ), SAL_NO_ACQUIRE );
411     PyTuple_SetItem( args.get() , 0 , PYSTR_FROMSTR( enumBase ) );
412     PyTuple_SetItem( args.get() , 1 , PYSTR_FROMSTR( enumValue ) );
413 
414     return callCtor( r, "Enum" , args );
415 }
416 
417 
PyUNO_Type_new(const char * typeName,TypeClass t,const Runtime & r)418 PyObject* PyUNO_Type_new (const char *typeName , TypeClass t , const Runtime &r )
419 {
420     // retrieve type object
421     PyRef args( PyTuple_New( 2 ), SAL_NO_ACQUIRE );
422 
423     PyTuple_SetItem( args.get() , 0 , PYSTR_FROMSTR( typeName ) );
424     PyObject *typeClass = PyUNO_Enum_new( "com.sun.star.uno.TypeClass" , typeClassToString(t), r );
425     if( ! typeClass )
426         return NULL;
427     PyTuple_SetItem( args.get() , 1 , typeClass);
428 
429     return callCtor( r, "Type" , args );
430 }
431 
PyUNO_char_new(sal_Unicode val,const Runtime & r)432 PyObject* PyUNO_char_new ( sal_Unicode val , const Runtime &r )
433 {
434     // retrieve type object
435     PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
436 
437 #if PY_VERSION_HEX >= 0x03030000
438     Py_UCS2 u[1];
439     u[0] = val;
440     PyTuple_SetItem( args.get(), 0, PyUnicode_FromKindAndData( PyUnicode_2BYTE_KIND, u, 1 ) );
441 #else
442     Py_UNICODE u[2];
443     u[0] = val;
444     u[1] = 0;
445     PyTuple_SetItem( args.get() , 0 , PyUnicode_FromUnicode( u ,1) );
446 #endif
447 
448     return callCtor( r, "Char" , args );
449 }
450 
PyUNO_ByteSequence_new(const com::sun::star::uno::Sequence<sal_Int8> & byteSequence,const Runtime & r)451 PyObject *PyUNO_ByteSequence_new(
452     const com::sun::star::uno::Sequence< sal_Int8 > &byteSequence, const Runtime &r )
453 {
454     PyRef str(
455         PyBytes_FromStringAndSize( (char*)byteSequence.getConstArray(), byteSequence.getLength()),
456         SAL_NO_ACQUIRE );
457     PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
458     PyTuple_SetItem( args.get() , 0 , str.getAcquired() );
459     return callCtor( r, "ByteSequence" , args );
460 
461 }
462 }
463