1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2011 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 #include "sal/config.h" 29 30 #include <vector> 31 32 #include "boost/noncopyable.hpp" 33 #include "com/sun/star/uno/Reference.hxx" 34 #include "com/sun/star/uno/RuntimeException.hpp" 35 #include "com/sun/star/uno/Sequence.hxx" 36 #include "com/sun/star/uno/XInterface.hpp" 37 #include "cppu/unotype.hxx" 38 #include "osl/diagnose.h" 39 #include "rtl/byteseq.hxx" 40 #include "rtl/string.hxx" 41 #include "rtl/textcvt.h" 42 #include "rtl/textenc.h" 43 #include "rtl/ustring.h" 44 #include "rtl/ustring.hxx" 45 #include "sal/types.h" 46 #include "typelib/typeclass.h" 47 #include "typelib/typedescription.h" 48 #include "typelib/typedescription.hxx" 49 #include "uno/dispatcher.hxx" 50 51 #include "binaryany.hxx" 52 #include "bridge.hxx" 53 #include "cache.hxx" 54 #include "lessoperators.hxx" 55 #include "marshal.hxx" 56 57 namespace binaryurp { 58 59 namespace { 60 61 namespace css = com::sun::star; 62 63 void write64(std::vector< unsigned char > * buffer, sal_uInt64 value) { 64 Marshal::write8(buffer, value >> 56); 65 Marshal::write8(buffer, (value >> 48) & 0xFF); 66 Marshal::write8(buffer, (value >> 40) & 0xFF); 67 Marshal::write8(buffer, (value >> 32) & 0xFF); 68 Marshal::write8(buffer, (value >> 24) & 0xFF); 69 Marshal::write8(buffer, (value >> 16) & 0xFF); 70 Marshal::write8(buffer, (value >> 8) & 0xFF); 71 Marshal::write8(buffer, value & 0xFF); 72 } 73 74 void writeCompressed(std::vector< unsigned char > * buffer, sal_uInt32 value) { 75 if (value < 0xFF) { 76 Marshal::write8(buffer, static_cast< sal_uInt8 >(value)); 77 } else { 78 Marshal::write8(buffer, 0xFF); 79 Marshal::write32(buffer, value); 80 } 81 } 82 83 void writeString( 84 std::vector< unsigned char > * buffer, rtl::OUString const & value) 85 { 86 OSL_ASSERT(buffer != 0); 87 rtl::OString v; 88 if (!value.convertToString( 89 &v, RTL_TEXTENCODING_UTF8, 90 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | 91 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) 92 { 93 throw css::uno::RuntimeException( 94 rtl::OUString( 95 RTL_CONSTASCII_USTRINGPARAM( 96 "UNO string contains invalid UTF-16 sequence")), 97 css::uno::Reference< css::uno::XInterface >()); 98 } 99 writeCompressed(buffer, static_cast< sal_uInt32 >(v.getLength())); 100 buffer->insert(buffer->end(), v.getStr(), v.getStr() + v.getLength()); 101 } 102 103 } 104 105 Marshal::Marshal(rtl::Reference< Bridge > const & bridge, WriterState & state): 106 bridge_(bridge), state_(state) 107 { 108 OSL_ASSERT(bridge.is()); 109 } 110 111 Marshal::~Marshal() {} 112 113 void Marshal::write8(std::vector< unsigned char > * buffer, sal_uInt8 value) { 114 OSL_ASSERT(buffer != 0); 115 buffer->push_back(value); 116 } 117 118 void Marshal::write16(std::vector< unsigned char > * buffer, sal_uInt16 value) { 119 write8(buffer, value >> 8); 120 write8(buffer, value & 0xFF); 121 } 122 123 void Marshal::write32(std::vector< unsigned char > * buffer, sal_uInt32 value) { 124 write8(buffer, value >> 24); 125 write8(buffer, (value >> 16) & 0xFF); 126 write8(buffer, (value >> 8) & 0xFF); 127 write8(buffer, value & 0xFF); 128 } 129 130 void Marshal::writeValue( 131 std::vector< unsigned char > * buffer, 132 css::uno::TypeDescription const & type, BinaryAny const & value) 133 { 134 OSL_ASSERT( 135 type.is() && 136 (type.get()->eTypeClass == typelib_TypeClass_ANY || 137 value.getType().equals(type))); 138 writeValue(buffer, type, value.getValue(type)); 139 } 140 141 void Marshal::writeType( 142 std::vector< unsigned char > * buffer, 143 css::uno::TypeDescription const & value) 144 { 145 value.makeComplete(); 146 OSL_ASSERT(value.is()); 147 typelib_TypeClass tc = value.get()->eTypeClass; 148 if (tc <= typelib_TypeClass_ANY) { 149 write8(buffer, static_cast< sal_uInt8 >(tc)); 150 } else { 151 bool found; 152 sal_uInt16 idx = state_.typeCache.add(value, &found); 153 if (found) { 154 write8(buffer, static_cast< sal_uInt8 >(tc)); 155 write16(buffer, idx); 156 } else { 157 write8(buffer, static_cast< sal_uInt8 >(tc) | 0x80); 158 write16(buffer, idx); 159 writeString(buffer, rtl::OUString(value.get()->pTypeName)); 160 } 161 } 162 } 163 164 void Marshal::writeOid( 165 std::vector< unsigned char > * buffer, rtl::OUString const & oid) 166 { 167 bool found; 168 sal_uInt16 idx; 169 if (oid.getLength() == 0) { 170 found = true; 171 idx = cache::ignore; 172 } else { 173 idx = state_.oidCache.add(oid, &found); 174 } 175 if (found) { 176 write8(buffer, 0); 177 } else { 178 writeString(buffer, oid); 179 } 180 write16(buffer, idx); 181 } 182 183 void Marshal::writeTid( 184 std::vector< unsigned char > * buffer, rtl::ByteSequence const & tid) 185 { 186 bool found; 187 sal_uInt16 idx = state_.tidCache.add(tid, &found); 188 if (found) { 189 write8(buffer, 0); 190 } else { 191 sal_Sequence * p = tid.getHandle(); 192 writeValue( 193 buffer, 194 css::uno::TypeDescription( 195 cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get()), &p); 196 } 197 write16(buffer, idx); 198 } 199 200 void Marshal::writeValue( 201 std::vector< unsigned char > * buffer, 202 css::uno::TypeDescription const & type, void const * value) 203 { 204 OSL_ASSERT(buffer != 0 && type.is()); 205 type.makeComplete(); 206 switch (type.get()->eTypeClass) { 207 case typelib_TypeClass_VOID: 208 break; 209 case typelib_TypeClass_BOOLEAN: 210 OSL_ASSERT(*static_cast< sal_uInt8 const * >(value) <= 1); 211 // fall through 212 case typelib_TypeClass_BYTE: 213 write8(buffer, *static_cast< sal_uInt8 const * >(value)); 214 break; 215 case typelib_TypeClass_SHORT: 216 case typelib_TypeClass_UNSIGNED_SHORT: 217 case typelib_TypeClass_CHAR: 218 write16(buffer, *static_cast< sal_uInt16 const * >(value)); 219 break; 220 case typelib_TypeClass_LONG: 221 case typelib_TypeClass_UNSIGNED_LONG: 222 case typelib_TypeClass_FLOAT: 223 case typelib_TypeClass_ENUM: 224 write32(buffer, *static_cast< sal_uInt32 const * >(value)); 225 break; 226 case typelib_TypeClass_HYPER: 227 case typelib_TypeClass_UNSIGNED_HYPER: 228 case typelib_TypeClass_DOUBLE: 229 write64(buffer, *static_cast< sal_uInt64 const * >(value)); 230 break; 231 case typelib_TypeClass_STRING: 232 writeString( 233 buffer, 234 rtl::OUString(*static_cast< rtl_uString * const * >(value))); 235 break; 236 case typelib_TypeClass_TYPE: 237 writeType( 238 buffer, 239 css::uno::TypeDescription( 240 *static_cast< typelib_TypeDescriptionReference * const * >( 241 value))); 242 break; 243 case typelib_TypeClass_ANY: 244 { 245 uno_Any const * p = static_cast< uno_Any const * >(value); 246 css::uno::TypeDescription t(p->pType); 247 writeType(buffer, t); 248 writeValue(buffer, t, p->pData); 249 break; 250 } 251 case typelib_TypeClass_SEQUENCE: 252 { 253 sal_Sequence * p = *static_cast< sal_Sequence * const * >(value); 254 writeCompressed(buffer, static_cast< sal_uInt32 >(p->nElements)); 255 css::uno::TypeDescription ctd( 256 reinterpret_cast< typelib_IndirectTypeDescription * >( 257 type.get())-> 258 pType); 259 OSL_ASSERT(ctd.is()); 260 if (ctd.get()->eTypeClass == typelib_TypeClass_BYTE) { 261 buffer->insert( 262 buffer->end(), p->elements, p->elements + p->nElements); 263 } else { 264 for (sal_Int32 i = 0; i != p->nElements; ++i) { 265 writeValue(buffer, ctd, p->elements + i * ctd.get()->nSize); 266 } 267 } 268 break; 269 } 270 case typelib_TypeClass_STRUCT: 271 case typelib_TypeClass_EXCEPTION: 272 writeMemberValues(buffer, type, value); 273 break; 274 case typelib_TypeClass_INTERFACE: 275 writeOid( 276 buffer, 277 bridge_->registerOutgoingInterface( 278 css::uno::UnoInterfaceReference( 279 *static_cast< uno_Interface * const * >(value)), 280 type)); 281 break; 282 default: 283 OSL_ASSERT(false); // this cannot happen 284 break; 285 } 286 } 287 288 void Marshal::writeMemberValues( 289 std::vector< unsigned char > * buffer, 290 css::uno::TypeDescription const & type, void const * aggregateValue) 291 { 292 OSL_ASSERT( 293 type.is() && 294 (type.get()->eTypeClass == typelib_TypeClass_STRUCT || 295 type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) && 296 aggregateValue != 0); 297 type.makeComplete(); 298 typelib_CompoundTypeDescription * ctd = 299 reinterpret_cast< typelib_CompoundTypeDescription * >(type.get()); 300 if (ctd->pBaseTypeDescription != 0) { 301 writeMemberValues( 302 buffer, 303 css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase), 304 aggregateValue); 305 } 306 for (sal_Int32 i = 0; i != ctd->nMembers; ++i) { 307 writeValue( 308 buffer, css::uno::TypeDescription(ctd->ppTypeRefs[i]), 309 (static_cast< char const * >(aggregateValue) + 310 ctd->pMemberOffsets[i])); 311 } 312 } 313 314 } 315