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