/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
using com::sun::star::uno::Sequence; using com::sun::star::uno::Reference; using com::sun::star::uno::XInterface; using com::sun::star::uno::Any; using com::sun::star::uno::UNO_QUERY; using com::sun::star::uno::Type; using com::sun::star::uno::TypeClass; using com::sun::star::uno::TypeDescription; using com::sun::star::uno::RuntimeException; using com::sun::star::uno::Exception; using com::sun::star::lang::XSingleServiceFactory; using com::sun::star::lang::XServiceInfo; using com::sun::star::lang::XTypeProvider; using com::sun::star::lang::XUnoTunnel; using com::sun::star::script::XInvocation2; using com::sun::star::container::XEnumeration; using com::sun::star::container::XEnumerationAccess; using com::sun::star::container::XIndexAccess; using com::sun::star::container::XIndexContainer; using com::sun::star::container::XIndexReplace; using com::sun::star::container::XNameAccess; using com::sun::star::container::XNameContainer; using com::sun::star::container::XNameReplace;
TYPELIB_DANGER_RELEASE( pTypeDescr ); break;
} case typelib_TypeClass_BOOLEAN: if (*static_cast<sal_Bool const *>(pVal))
buf.append( "true" ); else
buf.append( "false" ); break; case typelib_TypeClass_CHAR:
buf.append( "\'"
+ OUStringChar(*static_cast<sal_Unicode const *>(pVal) )
+ "\'" ); break; case typelib_TypeClass_FLOAT:
buf.append( *static_cast<floatconst *>(pVal) ); break; case typelib_TypeClass_DOUBLE:
buf.append( *static_cast<doubleconst *>(pVal) ); break; case typelib_TypeClass_BYTE:
buf.append( "0x" +
OUString::number( static_cast<sal_Int32>(*static_cast<sal_Int8 const *>(pVal)), 16 )); break; case typelib_TypeClass_SHORT:
buf.append( "0x" +
OUString::number( static_cast<sal_Int32>(*static_cast<sal_Int16 const *>(pVal)), 16 )); break; case typelib_TypeClass_UNSIGNED_SHORT:
buf.append( "0x" +
OUString::number( static_cast<sal_Int32>(*static_cast<sal_uInt16 const *>(pVal)), 16 )); break; case typelib_TypeClass_LONG:
buf.append( "0x" +
OUString::number( *static_cast<sal_Int32 const *>(pVal), 16 )); break; case typelib_TypeClass_UNSIGNED_LONG:
buf.append( "0x" +
OUString::number( static_cast<sal_Int64>(*static_cast<sal_uInt32 const *>(pVal)), 16 )); break; case typelib_TypeClass_HYPER: case typelib_TypeClass_UNSIGNED_HYPER:
buf.append( "0x" ); #ifdefined(__GNUC__) && defined(SPARC) // I guess this really should check if there are strict alignment // requirements, not just "GCC on SPARC".
{
sal_Int64 aVal;
*(sal_Int32 *)&aVal = *(sal_Int32 *)pVal;
*((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1);
buf.append( aVal, 16 );
} #else
buf.append( *static_cast<sal_Int64 const *>(pVal), 16 ); #endif break;
case typelib_TypeClass_VOID: case typelib_TypeClass_UNKNOWN: case typelib_TypeClass_SERVICE: case typelib_TypeClass_MODULE: default:
buf.append( '?' );
}
return buf.makeStringAndClear();
}
static sal_Int32 lcl_PyNumber_AsSal_Int32( PyObject *pObj )
{ // Check object is an index
PyRef rIndex( PyNumber_Index( pObj ), SAL_NO_ACQUIRE ); if ( !rIndex.is() ) return -1;
// Convert Python number to platform long, then check actual value against // bounds of sal_Int32 int nOverflow; long nResult = PyLong_AsLongAndOverflow( pObj, &nOverflow ); if ( nOverflow || nResult > SAL_MAX_INT32 || nResult < SAL_MIN_INT32) {
PyErr_SetString( PyExc_IndexError, "Python int too large to convert to UNO long" ); return -1;
}
// Py_hash_t is not necessarily the same size as a pointer, but this is not // important for hashing - it just has to return the same value each time return sal::static_int_cast< Py_hash_t >( reinterpret_cast< sal_IntPtr > (
*static_cast<void * const *>(me->members->wrappedObject.getValue()) ) );
// If both XIndexContainer and XNameContainer are implemented, it is // assumed that getCount() gives the same result as the number of names // returned by getElementNames(), or the user may be surprised.
// For XIndexContainer
Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY ); if ( xIndexAccess.is() )
{ return xIndexAccess->getCount();
}
// For XNameContainer // Not terribly efficient - get the count of all the names
Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY ); if ( xNameAccess.is() )
{ return xNameAccess->getElementNames().getLength();
}
return -1;
}
staticint PyUNO_bool( PyObject* self )
{
PyUNO* me = reinterpret_cast<PyUNO*>(self);
try
{ int nLen = lcl_detach_getLength( me ); if (nLen >= 0) return nLen == 0 ? 0 : 1;
// Anything which doesn't have members is a scalar object and therefore true return 1;
} catch( const css::uno::RuntimeException &e )
{
raisePyExceptionWithAny( css::uno::Any( e ) );
}
// If the object is an XIndexAccess and/or XNameAccess, but the // key passed wasn't suitable, give a TypeError which specifically // describes this
Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY ); if ( xIndexAccess.is() || xNameAccess.is() )
{
PyErr_SetString( PyExc_TypeError, "subscription with invalid type" ); return nullptr;
}
PyErr_SetString( PyExc_TypeError, "object is not subscriptable" );
} catch( const css::lang::IndexOutOfBoundsException & )
{
PyErr_SetString( PyExc_IndexError, "index out of range" );
} catch( const css::container::NoSuchElementException & )
{
PyErr_SetString( PyExc_KeyError, "key not found" );
} catch( const css::script::CannotConvertException &e )
{
raisePyExceptionWithAny( css::uno::Any( e ) );
} catch( const css::lang::IllegalArgumentException &e )
{
raisePyExceptionWithAny( css::uno::Any( e ) );
} catch( const css::lang::WrappedTargetException &e )
{
raisePyExceptionWithAny( css::uno::Any( e ) );
} catch( const css::uno::RuntimeException &e )
{
raisePyExceptionWithAny( css::uno::Any( e ) );
}
Any aValue; if ( pValue != nullptr )
{
isTuple = PyTuple_Check( pValue );
try
{
aValue = runtime.pyObject2Any( pValue );
} catch ( const css::uno::RuntimeException & )
{ // TODO pyObject2Any can't convert e.g. dicts but only throws // RuntimeException on failure. Fixing this will require an audit of // all the rest of PyUNO throw css::script::CannotConvertException();
}
}
// XIndexReplace replace by index if ( (pValue != nullptr) && xIndexReplace.is() )
{ if ( isTuple )
{ // Apply type specialisation to ensure the correct kind of sequence is passed
Type aType = xIndexReplace->getElementType();
aValue = runtime.getImpl()->cargo->xTypeConverter->convertTo( aValue, aType );
}
sal_Int32 nCur, i;
sal_Int32 nMax = ::std::max( nSliceLength, nTupleLength ); for ( nCur = nStart, i = 0; i < nMax; nCur += nStep, i++ )
{ if ( i < nTupleLength )
{
PyRef rItem = PyTuple_GetItem( pValue, i ); bool isTuple = PyTuple_Check( rItem.get() );
Any aItem; try
{
aItem = runtime.pyObject2Any( rItem.get() );
} catch ( const css::uno::RuntimeException & )
{ // TODO pyObject2Any can't convert e.g. dicts but only throws // RuntimeException on failure. Fixing this will require an audit of // all the rest of PyUNO throw css::script::CannotConvertException();
}
{
PyThreadDetach antiguard;
if ( isTuple )
{ // Apply type specialisation to ensure the correct kind of sequence is passed
Type aType = xIndexReplace->getElementType();
aItem = runtime.getImpl()->cargo->xTypeConverter->convertTo( aItem, aType );
}
Any aValue; if ( pValue != nullptr)
{
isTuple = PyTuple_Check( pValue ); try
{
aValue = runtime.pyObject2Any( pValue );
} catch( const css::uno::RuntimeException & )
{ // TODO pyObject2Any can't convert e.g. dicts but only throws // RuntimeException on failure. Fixing this will require an audit of // all the rest of PyUNO throw css::script::CannotConvertException();
}
}
if ( xNameReplace.is() )
{ if ( isTuple && aValue.hasValue() )
{ // Apply type specialisation to ensure the correct kind of sequence is passed
Type aType = xNameReplace->getElementType();
aValue = runtime.getImpl()->cargo->xTypeConverter->convertTo( aValue, aType );
}
// XIndexAccess iterator if ( xIndexAccess.is() )
{ // We'd like to be able to use PySeqIter_New() here, but we're not // allowed to because we also implement the mapping protocol return PyUNO_list_iterator_new( xIndexAccess );
}
// XNameAccess iterator if (xNameAccess.is())
{ // There's no generic mapping iterator, but we can cobble our own // together using PySeqIter_New()
Runtime runtime;
Any aRet;
try
{
Any aValue; try
{
aValue = runtime.pyObject2Any( pKey );
} catch( const css::uno::RuntimeException & )
{ // TODO pyObject2Any can't convert e.g. dicts but only throws // RuntimeException on failure. Fixing this will require an audit of // all the rest of PyUNO throw css::script::CannotConvertException();
}
// XNameAccess is tried first, because checking key presence is much more // useful for objects which implement both XIndexAccess and XNameAccess
// For XNameAccess if ( PyUnicode_Check( pKey ) )
{
OUString sKey;
aValue >>= sKey;
Reference< XNameAccess > xNameAccess;
PyUNO* me = reinterpret_cast<PyUNO*>(self); if (strcmp (name, "__dict__") == 0)
{
Py_INCREF (Py_TYPE(me)->tp_dict); return Py_TYPE(me)->tp_dict;
} if (strcmp (name, "__class__") == 0)
{
Py_INCREF (Py_None); return Py_None;
}
PyObject *pRet = PyObject_GenericGetAttr( self, PyUnicode_FromString( name ) ); if( pRet ) return pRet;
PyErr_Clear();
OUString attrName( OUString::createFromAscii( name ) ); //We need to find out if it's a method... bool isMethod;
{
PyThreadDetach antiguard;
isMethod = me->members->xInvocation->hasMethod (attrName);
} if (isMethod)
{ //Create a callable object to invoke this...
PyRef ret = PyUNO_callable_new (
me->members->xInvocation,
attrName);
Py_XINCREF( ret.get() ); return ret.get();
}
//or a property bool isProperty;
Any anyRet;
{
PyThreadDetach antiguard;
isProperty = me->members->xInvocation->hasProperty ( attrName); if (isProperty)
{ //Return the value of the property
anyRet = me->members->xInvocation->getValue (attrName);
}
} if (isProperty)
{
PyRef ret = runtime.any2PyObject(anyRet);
Py_XINCREF( ret.get() ); return ret.get();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.