xref: /trunk/main/pyuno/source/module/pyuno_type.cxx (revision 27dee00ef8b391d4d520b7edb65b4093b02f83ed)
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( PyUnicode_GetLength( value.get() ) < 1 )
154     {
155         throw RuntimeException(
156             USTR_ASCII( "uno.Char contains an empty unicode string" ),
157             Reference< XInterface > () );
158     }
159     sal_Unicode c = (sal_Unicode)PyUnicode_ReadChar( value.get(), 0 );
160     return c;
161 }
162 
PyEnum2Enum(PyObject * obj)163 Any PyEnum2Enum( PyObject *obj ) throw ( RuntimeException )
164 {
165     Any ret;
166     PyRef typeName( PyObject_GetAttrString( obj,const_cast< char * >("typeName") ), SAL_NO_ACQUIRE);
167     PyRef value( PyObject_GetAttrString( obj, const_cast< char * >("value") ), SAL_NO_ACQUIRE);
168     if( !PYSTR_CHECK( typeName.get() ) || ! PYSTR_CHECK( value.get() ) )
169     {
170         throw RuntimeException(
171             USTR_ASCII( "attributes typeName and/or value of uno.Enum are not strings" ),
172             Reference< XInterface > () );
173     }
174 
175     OUString strTypeName( pyString2ustring( typeName.get() ) );
176     OUString strValue( pyString2ustring( value.get() ) );
177 
178     TypeDescription desc( strTypeName );
179     if( desc.is() )
180     {
181         if(desc.get()->eTypeClass != typelib_TypeClass_ENUM )
182         {
183             OUStringBuffer buf;
184             buf.appendAscii( "pyuno.checkEnum: " ).append( strTypeName ).appendAscii( " is a " );
185             buf.appendAscii(
186                 typeClassToString( (com::sun::star::uno::TypeClass) desc.get()->eTypeClass));
187             buf.appendAscii( ", expected ENUM" );
188             throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface>  () );
189         }
190 
191         desc.makeComplete();
192 
193         typelib_EnumTypeDescription *pEnumDesc = (typelib_EnumTypeDescription*) desc.get();
194         int i = 0;
195         for( i = 0; i < pEnumDesc->nEnumValues ; i ++ )
196         {
197             if( (*((OUString *)&pEnumDesc->ppEnumNames[i])).compareTo( strValue ) == 0 )
198             {
199                 break;
200             }
201         }
202         if( i == pEnumDesc->nEnumValues )
203         {
204             OUStringBuffer buf;
205             buf.appendAscii( "value " ).append( strValue ).appendAscii( " is unknown in enum " );
206             buf.append( strTypeName );
207             throw RuntimeException( buf.makeStringAndClear(), Reference<XInterface> () );
208         }
209         ret = Any( &pEnumDesc->pEnumValues[i], desc.get()->pWeakRef );
210     }
211     else
212     {
213         OUStringBuffer buf;
214         buf.appendAscii( "enum " ).append( strTypeName ).appendAscii( " is unknown" );
215         throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface>  () );
216     }
217     return ret;
218 }
219 
220 
PyType2Type(PyObject * o)221 Type PyType2Type( PyObject * o ) throw(RuntimeException )
222 {
223     PyRef pyName( PyObject_GetAttrString( o, const_cast< char * >("typeName") ), SAL_NO_ACQUIRE);
224     if( !PYSTR_CHECK( pyName.get() ) )
225     {
226         throw RuntimeException(
227             USTR_ASCII( "type object does not have typeName property" ),
228             Reference< XInterface > () );
229     }
230 
231     PyRef pyTC( PyObject_GetAttrString( o, const_cast< char * >("typeClass") ), SAL_NO_ACQUIRE );
232     Any enumValue = PyEnum2Enum( pyTC.get() );
233 
234     OUString name( pyString2ustring( pyName.get() ) );
235     TypeDescription desc( name );
236     if( ! desc.is() )
237     {
238         OUStringBuffer buf;
239         buf.appendAscii( "type " ).append(name).appendAscii( " is unknown" );
240         throw RuntimeException(
241             buf.makeStringAndClear(), Reference< XInterface > () );
242     }
243     if( desc.get()->eTypeClass != (typelib_TypeClass) *(sal_Int32*)enumValue.getValue() )
244     {
245         OUStringBuffer buf;
246         buf.appendAscii( "pyuno.checkType: " ).append(name).appendAscii( " is a " );
247         buf.appendAscii( typeClassToString( (TypeClass) desc.get()->eTypeClass) );
248         buf.appendAscii( ", but type got construct with typeclass " );
249         buf.appendAscii( typeClassToString( (TypeClass) *(sal_Int32*)enumValue.getValue() ) );
250         throw RuntimeException(
251             buf.makeStringAndClear(), Reference< XInterface > () );
252     }
253     return desc.get()->pWeakRef;
254 }
255 
importToGlobal(PyObject * str,PyObject * dict,PyObject * target)256 PyObject *importToGlobal(PyObject *str, PyObject *dict, PyObject *target)
257 {
258     // maybe a constant ?
259     PyObject *ret = 0;
260     OUString name = pyString2ustring(str);
261     try
262     {
263         Runtime runtime;
264         TypeDescription desc(name );
265         desc.makeComplete();
266         if( desc.is() )
267         {
268             com::sun::star::uno::TypeClass tc =
269                 (com::sun::star::uno::TypeClass)desc.get()->eTypeClass;
270 
271             PyRef typesModule( PyDict_GetItemString( dict, "unotypes" ) );
272             if( ! typesModule.is() || ! PyModule_Check( typesModule.get() ))
273             {
274                 typesModule = PyRef( PyModule_New( const_cast< char * >("unotypes") ), SAL_NO_ACQUIRE );
275                 Py_INCREF( typesModule.get() );
276                 PyDict_SetItemString( dict, "unotypes" , typesModule.get() );
277             }
278             const char *targetName = PyUnicode_AsUTF8( target );
279             const char *typeName = PyUnicode_AsUTF8( str );
280             PyModule_AddObject(
281                 typesModule.get(),
282                 targetName,
283                 PyUNO_Type_new( typeName, tc, runtime ) );
284 
285             if( com::sun::star::uno::TypeClass_EXCEPTION == tc ||
286                 com::sun::star::uno::TypeClass_STRUCT    == tc )
287             {
288                 PyRef exc = getClass( name, runtime );
289                 PyDict_SetItem( dict, target, exc.getAcquired() );
290             }
291             else if( com::sun::star::uno::TypeClass_ENUM == tc )
292             {
293                 // introduce all enums into the dictionary !
294                 typelib_EnumTypeDescription *pDesc =
295                     (typelib_EnumTypeDescription *) desc.get();
296                 for( int i = 0 ; i < pDesc->nEnumValues; i ++ )
297                 {
298                     OString enumElementName(
299                         OUStringToOString( pDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US) );
300                     const char *name = PyUnicode_AsUTF8(str);
301                     PyDict_SetItemString(
302                         dict, (char*)enumElementName.getStr(),
303                         PyUNO_Enum_new(name, enumElementName.getStr(), runtime ) );
304                 }
305             }
306             Py_INCREF( Py_None );
307             ret = Py_None;
308         }
309         else
310         {
311             Any a = runtime.getImpl()->cargo->xTdMgr->getByHierarchicalName(name);
312             if(a.hasValue())
313             {
314                 PyRef constant = runtime.any2PyObject( a );
315                 if( constant.is() )
316                 {
317                     Py_INCREF( constant.get() );
318                     PyDict_SetItem( dict, target , constant.get());
319                     ret = constant.get();
320                 }
321                 else
322                 {
323                     OUStringBuffer buf;
324                     buf.appendAscii( "constant " ).append(pyString2ustring(str)).appendAscii(  " unknown" );
325                     PyErr_SetString(
326                         PyExc_RuntimeError,
327                         OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_UTF8).getStr() );
328                 }
329             }
330             else
331             {
332                 OUStringBuffer buf;
333                 buf.appendAscii( "pyuno.imp unknown type " );
334                 buf.append( name );
335                 PyErr_SetString(
336                     PyExc_RuntimeError,
337                     OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US).getStr() );
338             }
339         }
340     }
341     catch( com::sun::star::container::NoSuchElementException & )
342     {
343         OUStringBuffer buf;
344         buf.appendAscii( "pyuno.imp unknown type " );
345         buf.append( name );
346         PyErr_SetString(
347             PyExc_RuntimeError,
348             OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US).getStr() );
349     }
350     catch( com::sun::star::script::CannotConvertException & e )
351     {
352         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
353     }
354     catch( com::sun::star::lang::IllegalArgumentException & e )
355     {
356         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
357     }
358     catch( RuntimeException &e )
359     {
360         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ));
361     }
362     return ret;
363 }
364 
callCtor(const Runtime & r,const char * clazz,const PyRef & args)365 static PyObject* callCtor( const Runtime &r , const char * clazz, const PyRef & args )
366 {
367     PyRef code( PyDict_GetItemString( r.getImpl()->cargo->getUnoModule().get(), (char*)clazz ) );
368     if( ! code.is() )
369     {
370         OStringBuffer buf;
371         buf.append( "couldn't access uno." );
372         buf.append( clazz );
373         PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
374         return NULL;
375     }
376     PyRef instance( PyObject_CallObject( code.get(), args.get()  ), SAL_NO_ACQUIRE);
377     Py_XINCREF( instance.get() );
378     return instance.get();
379 
380 }
381 
382 
PyUNO_Enum_new(const char * enumBase,const char * enumValue,const Runtime & r)383 PyObject *PyUNO_Enum_new( const char *enumBase, const char *enumValue, const Runtime &r )
384 {
385     PyRef args( PyTuple_New( 2 ), SAL_NO_ACQUIRE );
386     PyTuple_SetItem( args.get() , 0 , PYSTR_FROMSTR( enumBase ) );
387     PyTuple_SetItem( args.get() , 1 , PYSTR_FROMSTR( enumValue ) );
388 
389     return callCtor( r, "Enum" , args );
390 }
391 
392 
PyUNO_Type_new(const char * typeName,TypeClass t,const Runtime & r)393 PyObject* PyUNO_Type_new (const char *typeName , TypeClass t , const Runtime &r )
394 {
395     // retrieve type object
396     PyRef args( PyTuple_New( 2 ), SAL_NO_ACQUIRE );
397 
398     PyTuple_SetItem( args.get() , 0 , PYSTR_FROMSTR( typeName ) );
399     PyObject *typeClass = PyUNO_Enum_new( "com.sun.star.uno.TypeClass" , typeClassToString(t), r );
400     if( ! typeClass )
401         return NULL;
402     PyTuple_SetItem( args.get() , 1 , typeClass);
403 
404     return callCtor( r, "Type" , args );
405 }
406 
PyUNO_char_new(sal_Unicode val,const Runtime & r)407 PyObject* PyUNO_char_new ( sal_Unicode val , const Runtime &r )
408 {
409     // retrieve type object
410     PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
411 
412     Py_UCS2 u[1];
413     u[0] = val;
414     PyTuple_SetItem( args.get(), 0, PyUnicode_FromKindAndData( PyUnicode_2BYTE_KIND, u, 1 ) );
415 
416     return callCtor( r, "Char" , args );
417 }
418 
PyUNO_ByteSequence_new(const com::sun::star::uno::Sequence<sal_Int8> & byteSequence,const Runtime & r)419 PyObject *PyUNO_ByteSequence_new(
420     const com::sun::star::uno::Sequence< sal_Int8 > &byteSequence, const Runtime &r )
421 {
422     PyRef str(
423         PyBytes_FromStringAndSize( (char*)byteSequence.getConstArray(), byteSequence.getLength()),
424         SAL_NO_ACQUIRE );
425     PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
426     PyTuple_SetItem( args.get() , 0 , str.getAcquired() );
427     return callCtor( r, "ByteSequence" , args );
428 
429 }
430 }
431