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