LibreOffice Module comphelper (master)  1
anytostring.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
22 #include <rtl/ustrbuf.hxx>
23 #include <typelib/typedescription.h>
24 #include <com/sun/star/lang/XServiceInfo.hpp>
25 
26 using namespace ::com::sun::star;
27 
28 namespace comphelper {
29 namespace {
30 
31 void appendTypeError(
32  OUStringBuffer & buf, typelib_TypeDescriptionReference * typeRef )
33 {
34  buf.append( "<cannot get type description of type " );
35  buf.append( OUString::unacquired( &typeRef->pTypeName ) );
36  buf.append( '>' );
37 }
38 
39 void appendChar( OUStringBuffer & buf, sal_Unicode c )
40 {
41  if (c < ' ' || c > '~') {
42  buf.append( "\\X" );
43  OUString const s(
44  OUString::number( static_cast< sal_Int32 >(c), 16 ) );
45  for ( sal_Int32 f = 4 - s.getLength(); f > 0; --f )
46  buf.append( '0' );
47  buf.append( s );
48  }
49  else {
50  buf.append( c );
51  }
52 }
53 
54 
55 void appendValue( OUStringBuffer & buf,
56  void const * val, typelib_TypeDescriptionReference * typeRef,
57  bool prependType )
58 {
59  if (typeRef->eTypeClass == typelib_TypeClass_VOID) {
60  buf.append( "void" );
61  return;
62  }
63  assert(val != nullptr);
64 
65  if (prependType &&
66  typeRef->eTypeClass != typelib_TypeClass_STRING &&
67  typeRef->eTypeClass != typelib_TypeClass_CHAR &&
68  typeRef->eTypeClass != typelib_TypeClass_BOOLEAN)
69  {
70  buf.append( '(' );
71  buf.append( OUString::unacquired( &typeRef->pTypeName ) );
72  buf.append( ") " );
73  }
74 
75  switch (typeRef->eTypeClass) {
76  case typelib_TypeClass_INTERFACE: {
77  buf.append( '@' );
78  buf.append( reinterpret_cast< sal_Int64 >(
79  *static_cast< void * const * >(val) ), 16 );
80  uno::Reference< lang::XServiceInfo > xServiceInfo(
81  *static_cast< uno::XInterface * const * >(val),
82  uno::UNO_QUERY );
83  if (xServiceInfo.is()) {
84  buf.append( " (ImplementationName = \"" );
85  buf.append( xServiceInfo->getImplementationName() );
86  buf.append( "\")" );
87  }
88  break;
89  }
90  case typelib_TypeClass_STRUCT:
91  case typelib_TypeClass_EXCEPTION: {
92  buf.append( "{ " );
93  typelib_TypeDescription * typeDescr = nullptr;
95  if (typeDescr == nullptr || !typelib_typedescription_complete( &typeDescr )) {
96  appendTypeError( buf, typeRef );
97  }
98  else {
99  typelib_CompoundTypeDescription * compType =
100  reinterpret_cast< typelib_CompoundTypeDescription * >(
101  typeDescr );
102  sal_Int32 nDescr = compType->nMembers;
103 
104  if (compType->pBaseTypeDescription) {
105  appendValue(
106  buf, val, reinterpret_cast<
107  typelib_TypeDescription * >(
108  compType->pBaseTypeDescription)->pWeakRef, false );
109  if (nDescr > 0)
110  buf.append( ", " );
111  }
112 
113  typelib_TypeDescriptionReference ** ppTypeRefs =
114  compType->ppTypeRefs;
115  sal_Int32 * memberOffsets = compType->pMemberOffsets;
116  rtl_uString ** ppMemberNames = compType->ppMemberNames;
117 
118  for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
119  {
120  buf.append( ppMemberNames[ nPos ] );
121  buf.append( " = " );
122  typelib_TypeDescription * memberType = nullptr;
123  TYPELIB_DANGER_GET( &memberType, ppTypeRefs[ nPos ] );
124  if (memberType == nullptr) {
125  appendTypeError( buf, ppTypeRefs[ nPos ] );
126  }
127  else {
128  appendValue( buf,
129  static_cast< char const * >(
130  val ) + memberOffsets[ nPos ],
131  memberType->pWeakRef, true );
132  TYPELIB_DANGER_RELEASE( memberType );
133  }
134  if (nPos < (nDescr - 1))
135  buf.append( ", " );
136  }
137  }
138  buf.append( " }" );
139  if (typeDescr != nullptr)
140  typelib_typedescription_release( typeDescr );
141  break;
142  }
143  case typelib_TypeClass_SEQUENCE: {
144  typelib_TypeDescription * typeDescr = nullptr;
145  TYPELIB_DANGER_GET( &typeDescr, typeRef );
146  if (typeDescr == nullptr) {
147  appendTypeError( buf,typeRef );
148  }
149  else {
150  typelib_TypeDescriptionReference * elementTypeRef =
151  reinterpret_cast<
152  typelib_IndirectTypeDescription * >(typeDescr)->pType;
153  typelib_TypeDescription * elementTypeDescr = nullptr;
154  TYPELIB_DANGER_GET( &elementTypeDescr, elementTypeRef );
155  if (elementTypeDescr == nullptr)
156  {
157  appendTypeError( buf, elementTypeRef );
158  }
159  else
160  {
161  sal_Int32 nElementSize = elementTypeDescr->nSize;
162  uno_Sequence * seq =
163  *static_cast< uno_Sequence * const * >(val);
164  sal_Int32 nElements = seq->nElements;
165 
166  if (nElements > 0)
167  {
168  buf.append( "{ " );
169  char const * pElements = seq->elements;
170  for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
171  {
172  appendValue(
173  buf, pElements + (nElementSize * nPos),
174  elementTypeDescr->pWeakRef, false );
175  if (nPos < (nElements - 1))
176  buf.append( ", " );
177  }
178  buf.append( " }" );
179  }
180  else
181  {
182  buf.append( "{}" );
183  }
184  TYPELIB_DANGER_RELEASE( elementTypeDescr );
185  }
186  TYPELIB_DANGER_RELEASE( typeDescr );
187  }
188  break;
189  }
190  case typelib_TypeClass_ANY: {
191  buf.append( "{ " );
192  uno_Any const * pAny = static_cast< uno_Any const * >(val);
193  appendValue( buf, pAny->pData, pAny->pType, true );
194  buf.append( " }" );
195  break;
196  }
197  case typelib_TypeClass_TYPE:
198  buf.append( (*static_cast<
199  typelib_TypeDescriptionReference * const * >(val)
200  )->pTypeName );
201  break;
202  case typelib_TypeClass_STRING: {
203  buf.append( '\"' );
204  OUString const & str = OUString::unacquired(
205  static_cast< rtl_uString * const * >(val) );
206  sal_Int32 len = str.getLength();
207  for ( sal_Int32 pos = 0; pos < len; ++pos )
208  {
209  sal_Unicode c = str[ pos ];
210  if (c == '\"')
211  buf.append( "\\\"" );
212  else if (c == '\\')
213  buf.append( "\\\\" );
214  else
215  appendChar( buf, c );
216  }
217  buf.append( '\"' );
218  break;
219  }
220  case typelib_TypeClass_ENUM: {
221  typelib_TypeDescription * typeDescr = nullptr;
223  if (typeDescr == nullptr || !typelib_typedescription_complete( &typeDescr )) {
224  appendTypeError( buf, typeRef );
225  }
226  else
227  {
228  sal_Int32 * pValues =
229  reinterpret_cast< typelib_EnumTypeDescription * >(
230  typeDescr )->pEnumValues;
231  sal_Int32 nPos = reinterpret_cast< typelib_EnumTypeDescription * >(
232  typeDescr )->nEnumValues;
233  while (nPos--)
234  {
235  if (pValues[ nPos ] == *static_cast< int const * >(val))
236  break;
237  }
238  if (nPos >= 0)
239  {
240  buf.append( reinterpret_cast< typelib_EnumTypeDescription * >(
241  typeDescr )->ppEnumNames[ nPos ] );
242  }
243  else
244  {
245  buf.append( "?unknown enum value?" );
246  }
247  }
248  if (typeDescr != nullptr)
249  typelib_typedescription_release( typeDescr );
250  break;
251  }
252  case typelib_TypeClass_BOOLEAN:
253  if (*static_cast< sal_Bool const * >(val))
254  buf.append( "true" );
255  else
256  buf.append( "false" );
257  break;
258  case typelib_TypeClass_CHAR: {
259  buf.append( '\'' );
260  sal_Unicode c = *static_cast< sal_Unicode const * >(val);
261  if (c == '\'')
262  buf.append( "\\\'" );
263  else if (c == '\\')
264  buf.append( "\\\\" );
265  else
266  appendChar( buf, c );
267  buf.append( '\'' );
268  break;
269  }
270  case typelib_TypeClass_FLOAT:
271  buf.append( *static_cast< float const * >(val) );
272  break;
273  case typelib_TypeClass_DOUBLE:
274  buf.append( *static_cast< double const * >(val) );
275  break;
276  case typelib_TypeClass_BYTE:
277  buf.append( static_cast< sal_Int32 >(
278  *static_cast< sal_Int8 const * >(val) ) );
279  break;
280  case typelib_TypeClass_SHORT:
281  buf.append( static_cast< sal_Int32 >(
282  *static_cast< sal_Int16 const * >(val) ) );
283  break;
284  case typelib_TypeClass_UNSIGNED_SHORT:
285  buf.append( static_cast< sal_Int32 >(
286  *static_cast< sal_uInt16 const * >(val) ) );
287  break;
288  case typelib_TypeClass_LONG:
289  buf.append( *static_cast< sal_Int32 const * >(val) );
290  break;
291  case typelib_TypeClass_UNSIGNED_LONG:
292  buf.append( static_cast< sal_Int64 >(
293  *static_cast< sal_uInt32 const * >(val) ) );
294  break;
295  case typelib_TypeClass_HYPER:
296  case typelib_TypeClass_UNSIGNED_HYPER:
297  buf.append( *static_cast< sal_Int64 const * >(val) );
298  break;
299 // case typelib_TypeClass_UNKNOWN:
300 // case typelib_TypeClass_SERVICE:
301 // case typelib_TypeClass_MODULE:
302  default:
303  buf.append( '?' );
304  break;
305  }
306 }
307 
308 } // anon namespace
309 
310 
311 OUString anyToString( uno::Any const & value )
312 {
313  OUStringBuffer buf;
314  appendValue( buf, value.getValue(), value.getValueTypeRef(), true );
315  return buf.makeStringAndClear();
316 }
317 
318 } // namespace comphelper
319 
320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SAL_CALL typelib_typedescriptionreference_getDescription(typelib_TypeDescription **ppRet, typelib_TypeDescriptionReference *pRef) SAL_THROW_EXTERN_C()
sal_uInt16 sal_Unicode
sal_Bool SAL_CALL typelib_typedescription_complete(typelib_TypeDescription **ppTypeDescr) SAL_THROW_EXTERN_C()
sal_Int32 nElements
struct _uno_Any uno_Any
void SAL_CALL typelib_typedescription_release(typelib_TypeDescription *pTD) SAL_THROW_EXTERN_C()
void(* f)(TrueTypeTable *)
sal_Int32 nPos
OUString anyToString(uno::Any const &value)