1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_comphelper.hxx" 30 31 #include "comphelper/anytostring.hxx" 32 #include "osl/diagnose.h" 33 #include "rtl/ustrbuf.hxx" 34 #include "typelib/typedescription.h" 35 #include "com/sun/star/lang/XServiceInfo.hpp" 36 37 using namespace ::com::sun::star; 38 39 namespace comphelper { 40 namespace { 41 42 void appendTypeError( 43 rtl::OUStringBuffer & buf, typelib_TypeDescriptionReference * typeRef ) 44 { 45 buf.appendAscii( 46 RTL_CONSTASCII_STRINGPARAM("<cannot get type description of type ") ); 47 buf.append( rtl::OUString::unacquired( &typeRef->pTypeName ) ); 48 buf.append( static_cast< sal_Unicode >('>') ); 49 } 50 51 inline void appendChar( rtl::OUStringBuffer & buf, sal_Unicode c ) 52 { 53 if (c < ' ' || c > '~') { 54 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\\X") ); 55 rtl::OUString const s( 56 rtl::OUString::valueOf( static_cast< sal_Int32 >(c), 16 ) ); 57 for ( sal_Int32 f = 4 - s.getLength(); f > 0; --f ) 58 buf.append( static_cast< sal_Unicode >('0') ); 59 buf.append( s ); 60 } 61 else { 62 buf.append( c ); 63 } 64 } 65 66 //------------------------------------------------------------------------------ 67 void appendValue( rtl::OUStringBuffer & buf, 68 void const * val, typelib_TypeDescriptionReference * typeRef, 69 bool prependType ) 70 { 71 if (typeRef->eTypeClass == typelib_TypeClass_VOID) { 72 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("void") ); 73 return; 74 } 75 OSL_ASSERT( val != 0 ); 76 77 if (prependType && 78 typeRef->eTypeClass != typelib_TypeClass_STRING && 79 typeRef->eTypeClass != typelib_TypeClass_CHAR && 80 typeRef->eTypeClass != typelib_TypeClass_BOOLEAN) 81 { 82 buf.append( static_cast< sal_Unicode >('(') ); 83 buf.append( rtl::OUString::unacquired( &typeRef->pTypeName ) ); 84 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(") ") ); 85 } 86 87 switch (typeRef->eTypeClass) { 88 case typelib_TypeClass_INTERFACE: { 89 buf.append( static_cast<sal_Unicode>('@') ); 90 buf.append( reinterpret_cast< sal_Int64 >( 91 *static_cast< void * const * >(val) ), 16 ); 92 uno::Reference< lang::XServiceInfo > xServiceInfo( 93 *static_cast< uno::XInterface * const * >(val), 94 uno::UNO_QUERY ); 95 if (xServiceInfo.is()) { 96 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 97 " (ImplementationName = \"") ); 98 buf.append( xServiceInfo->getImplementationName() ); 99 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); 100 } 101 break; 102 } 103 case typelib_TypeClass_STRUCT: 104 case typelib_TypeClass_EXCEPTION: { 105 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); 106 typelib_TypeDescription * typeDescr = 0; 107 typelib_typedescriptionreference_getDescription( &typeDescr, typeRef ); 108 if (typeDescr == 0 || !typelib_typedescription_complete( &typeDescr )) { 109 appendTypeError( buf, typeRef ); 110 } 111 else { 112 typelib_CompoundTypeDescription * compType = 113 reinterpret_cast< typelib_CompoundTypeDescription * >( 114 typeDescr ); 115 sal_Int32 nDescr = compType->nMembers; 116 117 if (compType->pBaseTypeDescription) { 118 appendValue( 119 buf, val, reinterpret_cast< 120 typelib_TypeDescription * >( 121 compType->pBaseTypeDescription)->pWeakRef, false ); 122 if (nDescr > 0) 123 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); 124 } 125 126 typelib_TypeDescriptionReference ** ppTypeRefs = 127 compType->ppTypeRefs; 128 sal_Int32 * memberOffsets = compType->pMemberOffsets; 129 rtl_uString ** ppMemberNames = compType->ppMemberNames; 130 131 for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos ) 132 { 133 buf.append( ppMemberNames[ nPos ] ); 134 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" = ") ); 135 typelib_TypeDescription * memberType = 0; 136 TYPELIB_DANGER_GET( &memberType, ppTypeRefs[ nPos ] ); 137 if (memberType == 0) { 138 appendTypeError( buf, ppTypeRefs[ nPos ] ); 139 } 140 else { 141 appendValue( buf, 142 static_cast< char const * >( 143 val ) + memberOffsets[ nPos ], 144 memberType->pWeakRef, true ); 145 TYPELIB_DANGER_RELEASE( memberType ); 146 } 147 if (nPos < (nDescr - 1)) 148 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); 149 } 150 } 151 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); 152 if (typeDescr != 0) 153 typelib_typedescription_release( typeDescr ); 154 break; 155 } 156 case typelib_TypeClass_SEQUENCE: { 157 typelib_TypeDescription * typeDescr = 0; 158 TYPELIB_DANGER_GET( &typeDescr, typeRef ); 159 if (typeDescr == 0) { 160 appendTypeError( buf,typeRef ); 161 } 162 else { 163 typelib_TypeDescriptionReference * elementTypeRef = 164 reinterpret_cast< 165 typelib_IndirectTypeDescription * >(typeDescr)->pType; 166 typelib_TypeDescription * elementTypeDescr = 0; 167 TYPELIB_DANGER_GET( &elementTypeDescr, elementTypeRef ); 168 if (elementTypeDescr == 0) 169 { 170 appendTypeError( buf, elementTypeRef ); 171 } 172 else 173 { 174 sal_Int32 nElementSize = elementTypeDescr->nSize; 175 uno_Sequence * seq = 176 *static_cast< uno_Sequence * const * >(val); 177 sal_Int32 nElements = seq->nElements; 178 179 if (nElements > 0) 180 { 181 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); 182 char const * pElements = seq->elements; 183 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) 184 { 185 appendValue( 186 buf, pElements + (nElementSize * nPos), 187 elementTypeDescr->pWeakRef, false ); 188 if (nPos < (nElements - 1)) 189 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); 190 } 191 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); 192 } 193 else 194 { 195 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{}") ); 196 } 197 TYPELIB_DANGER_RELEASE( elementTypeDescr ); 198 } 199 TYPELIB_DANGER_RELEASE( typeDescr ); 200 } 201 break; 202 } 203 case typelib_TypeClass_ANY: { 204 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); 205 uno_Any const * pAny = static_cast< uno_Any const * >(val); 206 appendValue( buf, pAny->pData, pAny->pType, true ); 207 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); 208 break; 209 } 210 case typelib_TypeClass_TYPE: 211 buf.append( (*reinterpret_cast< 212 typelib_TypeDescriptionReference * const * >(val) 213 )->pTypeName ); 214 break; 215 case typelib_TypeClass_STRING: { 216 buf.append( static_cast< sal_Unicode >('\"') ); 217 rtl::OUString const & str = rtl::OUString::unacquired( 218 static_cast< rtl_uString * const * >(val) ); 219 sal_Int32 len = str.getLength(); 220 for ( sal_Int32 pos = 0; pos < len; ++pos ) 221 { 222 sal_Unicode c = str[ pos ]; 223 if (c == '\"') 224 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\\\"") ); 225 else if (c == '\\') 226 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\\\\") ); 227 else 228 appendChar( buf, c ); 229 } 230 buf.append( static_cast< sal_Unicode >('\"') ); 231 break; 232 } 233 case typelib_TypeClass_ENUM: { 234 typelib_TypeDescription * typeDescr = 0; 235 typelib_typedescriptionreference_getDescription( &typeDescr, typeRef ); 236 if (typeDescr == 0 || !typelib_typedescription_complete( &typeDescr )) { 237 appendTypeError( buf, typeRef ); 238 } 239 else 240 { 241 sal_Int32 * pValues = 242 reinterpret_cast< typelib_EnumTypeDescription * >( 243 typeDescr )->pEnumValues; 244 sal_Int32 nPos = reinterpret_cast< typelib_EnumTypeDescription * >( 245 typeDescr )->nEnumValues; 246 while (nPos--) 247 { 248 if (pValues[ nPos ] == *static_cast< int const * >(val)) 249 break; 250 } 251 if (nPos >= 0) 252 { 253 buf.append( reinterpret_cast< typelib_EnumTypeDescription * >( 254 typeDescr )->ppEnumNames[ nPos ] ); 255 } 256 else 257 { 258 buf.appendAscii( 259 RTL_CONSTASCII_STRINGPARAM("?unknown enum value?") ); 260 } 261 } 262 if (typeDescr != 0) 263 typelib_typedescription_release( typeDescr ); 264 break; 265 } 266 case typelib_TypeClass_BOOLEAN: 267 if (*static_cast< sal_Bool const * >(val) != sal_False) 268 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("true") ); 269 else 270 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("false") ); 271 break; 272 case typelib_TypeClass_CHAR: { 273 buf.append( static_cast< sal_Unicode >('\'') ); 274 sal_Unicode c = *static_cast< sal_Unicode const * >(val); 275 if (c == '\'') 276 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\\\'") ); 277 else if (c == '\\') 278 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\\\\") ); 279 else 280 appendChar( buf, c ); 281 buf.append( static_cast< sal_Unicode >('\'') ); 282 break; 283 } 284 case typelib_TypeClass_FLOAT: 285 buf.append( *static_cast< float const * >(val) ); 286 break; 287 case typelib_TypeClass_DOUBLE: 288 buf.append( *static_cast< double const * >(val) ); 289 break; 290 case typelib_TypeClass_BYTE: 291 buf.append( static_cast< sal_Int32 >( 292 *static_cast< sal_Int8 const * >(val) ) ); 293 break; 294 case typelib_TypeClass_SHORT: 295 buf.append( static_cast< sal_Int32 >( 296 *static_cast< sal_Int16 const * >(val) ) ); 297 break; 298 case typelib_TypeClass_UNSIGNED_SHORT: 299 buf.append( static_cast< sal_Int32 >( 300 *static_cast< sal_uInt16 const * >(val) ) ); 301 break; 302 case typelib_TypeClass_LONG: 303 buf.append( *static_cast< sal_Int32 const * >(val) ); 304 break; 305 case typelib_TypeClass_UNSIGNED_LONG: 306 buf.append( static_cast< sal_Int64 >( 307 *static_cast< sal_uInt32 const * >(val) ) ); 308 break; 309 case typelib_TypeClass_HYPER: 310 case typelib_TypeClass_UNSIGNED_HYPER: 311 buf.append( *static_cast< sal_Int64 const * >(val) ); 312 break; 313 // case typelib_TypeClass_UNION: 314 // case typelib_TypeClass_ARRAY: 315 // case typelib_TypeClass_UNKNOWN: 316 // case typelib_TypeClass_SERVICE: 317 // case typelib_TypeClass_MODULE: 318 default: 319 buf.append( static_cast< sal_Unicode >('?') ); 320 break; 321 } 322 } 323 324 } // anon namespace 325 326 //============================================================================== 327 rtl::OUString anyToString( uno::Any const & value ) 328 { 329 rtl::OUStringBuffer buf; 330 appendValue( buf, value.getValue(), value.getValueTypeRef(), true ); 331 return buf.makeStringAndClear(); 332 } 333 334 } // namespace comphelper 335 336