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
write64(std::vector<unsigned char> * buffer,sal_uInt64 value)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
writeCompressed(std::vector<unsigned char> * buffer,sal_uInt32 value)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
writeString(std::vector<unsigned char> * buffer,rtl::OUString const & value)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
Marshal(rtl::Reference<Bridge> const & bridge,WriterState & state)101 Marshal::Marshal(rtl::Reference< Bridge > const & bridge, WriterState & state):
102 bridge_(bridge), state_(state)
103 {
104 OSL_ASSERT(bridge.is());
105 }
106
~Marshal()107 Marshal::~Marshal() {}
108
write8(std::vector<unsigned char> * buffer,sal_uInt8 value)109 void Marshal::write8(std::vector< unsigned char > * buffer, sal_uInt8 value) {
110 OSL_ASSERT(buffer != 0);
111 buffer->push_back(value);
112 }
113
write16(std::vector<unsigned char> * buffer,sal_uInt16 value)114 void Marshal::write16(std::vector< unsigned char > * buffer, sal_uInt16 value) {
115 write8(buffer, value >> 8);
116 write8(buffer, value & 0xFF);
117 }
118
write32(std::vector<unsigned char> * buffer,sal_uInt32 value)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
writeValue(std::vector<unsigned char> * buffer,css::uno::TypeDescription const & type,BinaryAny const & value)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
writeType(std::vector<unsigned char> * buffer,css::uno::TypeDescription const & value)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
writeOid(std::vector<unsigned char> * buffer,rtl::OUString const & oid)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.isEmpty() ) {
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
writeTid(std::vector<unsigned char> * buffer,rtl::ByteSequence const & tid)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
writeValue(std::vector<unsigned char> * buffer,css::uno::TypeDescription const & type,void const * value)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
writeMemberValues(std::vector<unsigned char> * buffer,css::uno::TypeDescription const & type,void const * aggregateValue)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