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