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 3494 : void write64(std::vector< unsigned char > * buffer, sal_uInt64 value) {
54 3494 : Marshal::write8(buffer, value >> 56);
55 3494 : Marshal::write8(buffer, (value >> 48) & 0xFF);
56 3494 : Marshal::write8(buffer, (value >> 40) & 0xFF);
57 3494 : Marshal::write8(buffer, (value >> 32) & 0xFF);
58 3494 : Marshal::write8(buffer, (value >> 24) & 0xFF);
59 3494 : Marshal::write8(buffer, (value >> 16) & 0xFF);
60 3494 : Marshal::write8(buffer, (value >> 8) & 0xFF);
61 3494 : Marshal::write8(buffer, value & 0xFF);
62 3494 : }
63 :
64 289595 : void writeCompressed(std::vector< unsigned char > * buffer, sal_uInt32 value) {
65 289595 : if (value < 0xFF) {
66 289529 : Marshal::write8(buffer, static_cast< sal_uInt8 >(value));
67 : } else {
68 66 : Marshal::write8(buffer, 0xFF);
69 66 : Marshal::write32(buffer, value);
70 : }
71 289595 : }
72 :
73 269186 : void writeString(
74 : std::vector< unsigned char > * buffer, OUString const & value)
75 : {
76 : assert(buffer != 0);
77 269186 : OString v;
78 269186 : if (!value.convertToString(
79 : &v, RTL_TEXTENCODING_UTF8,
80 : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
81 269186 : RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
82 : {
83 : throw css::uno::RuntimeException(
84 0 : "UNO string contains invalid UTF-16 sequence");
85 : }
86 269186 : writeCompressed(buffer, static_cast< sal_uInt32 >(v.getLength()));
87 269186 : buffer->insert(buffer->end(), v.getStr(), v.getStr() + v.getLength());
88 269186 : }
89 :
90 : }
91 :
92 102 : Marshal::Marshal(rtl::Reference< Bridge > const & bridge, WriterState & state):
93 102 : bridge_(bridge), state_(state)
94 : {
95 : assert(bridge.is());
96 102 : }
97 :
98 102 : Marshal::~Marshal() {}
99 :
100 6260344 : void Marshal::write8(std::vector< unsigned char > * buffer, sal_uInt8 value) {
101 : assert(buffer != 0);
102 6260344 : buffer->push_back(value);
103 6260344 : }
104 :
105 469493 : void Marshal::write16(std::vector< unsigned char > * buffer, sal_uInt16 value) {
106 469493 : write8(buffer, value >> 8);
107 469493 : write8(buffer, value & 0xFF);
108 469493 : }
109 :
110 1003978 : void Marshal::write32(std::vector< unsigned char > * buffer, sal_uInt32 value) {
111 1003978 : write8(buffer, value >> 24);
112 1003978 : write8(buffer, (value >> 16) & 0xFF);
113 1003978 : write8(buffer, (value >> 8) & 0xFF);
114 1003978 : write8(buffer, value & 0xFF);
115 1003978 : }
116 :
117 417857 : void Marshal::writeValue(
118 : std::vector< unsigned char > * buffer,
119 : css::uno::TypeDescription const & type, BinaryAny const & value)
120 : {
121 : assert(
122 : type.is() &&
123 : (type.get()->eTypeClass == typelib_TypeClass_ANY ||
124 : value.getType().equals(type)));
125 417857 : writeValue(buffer, type, value.getValue(type));
126 417857 : }
127 :
128 313795 : void Marshal::writeType(
129 : std::vector< unsigned char > * buffer,
130 : css::uno::TypeDescription const & value)
131 : {
132 313795 : value.makeComplete();
133 : assert(value.is());
134 313795 : typelib_TypeClass tc = value.get()->eTypeClass;
135 313795 : if (tc <= typelib_TypeClass_ANY) {
136 222467 : write8(buffer, static_cast< sal_uInt8 >(tc));
137 : } else {
138 : bool found;
139 91328 : sal_uInt16 idx = state_.typeCache.add(value, &found);
140 91328 : if (found) {
141 88046 : write8(buffer, static_cast< sal_uInt8 >(tc));
142 88046 : write16(buffer, idx);
143 : } else {
144 3282 : write8(buffer, static_cast< sal_uInt8 >(tc) | 0x80);
145 3282 : write16(buffer, idx);
146 3282 : writeString(buffer, OUString(value.get()->pTypeName));
147 : }
148 : }
149 313795 : }
150 :
151 173896 : void Marshal::writeOid(
152 : std::vector< unsigned char > * buffer, OUString const & oid)
153 : {
154 : bool found;
155 : sal_uInt16 idx;
156 173896 : if ( oid.isEmpty() ) {
157 16956 : found = true;
158 16956 : idx = cache::ignore;
159 : } else {
160 156940 : idx = state_.oidCache.add(oid, &found);
161 : }
162 173896 : if (found) {
163 102225 : write8(buffer, 0);
164 : } else {
165 71671 : writeString(buffer, oid);
166 : }
167 173896 : write16(buffer, idx);
168 173896 : }
169 :
170 12616 : void Marshal::writeTid(
171 : std::vector< unsigned char > * buffer, rtl::ByteSequence const & tid)
172 : {
173 : bool found;
174 12616 : sal_uInt16 idx = state_.tidCache.add(tid, &found);
175 12616 : if (found) {
176 12233 : write8(buffer, 0);
177 : } else {
178 383 : sal_Sequence * p = tid.getHandle();
179 : writeValue(
180 : buffer,
181 : css::uno::TypeDescription(
182 383 : cppu::UnoType< css::uno::Sequence< sal_Int8 > >::get()), &p);
183 : }
184 12616 : write16(buffer, idx);
185 12616 : }
186 :
187 1355637 : void Marshal::writeValue(
188 : std::vector< unsigned char > * buffer,
189 : css::uno::TypeDescription const & type, void const * value)
190 : {
191 : assert(buffer != 0 && type.is());
192 1355637 : type.makeComplete();
193 1355637 : switch (type.get()->eTypeClass) {
194 : case typelib_TypeClass_VOID:
195 72148 : break;
196 : case typelib_TypeClass_BOOLEAN:
197 : assert(*static_cast< sal_uInt8 const * >(value) <= 1);
198 : // fall through
199 : case typelib_TypeClass_BYTE:
200 132369 : write8(buffer, *static_cast< sal_uInt8 const * >(value));
201 132369 : break;
202 : case typelib_TypeClass_SHORT:
203 : case typelib_TypeClass_UNSIGNED_SHORT:
204 : case typelib_TypeClass_CHAR:
205 191653 : write16(buffer, *static_cast< sal_uInt16 const * >(value));
206 191653 : break;
207 : case typelib_TypeClass_LONG:
208 : case typelib_TypeClass_UNSIGNED_LONG:
209 : case typelib_TypeClass_FLOAT:
210 : case typelib_TypeClass_ENUM:
211 171934 : write32(buffer, *static_cast< sal_uInt32 const * >(value));
212 171934 : break;
213 : case typelib_TypeClass_HYPER:
214 : case typelib_TypeClass_UNSIGNED_HYPER:
215 : case typelib_TypeClass_DOUBLE:
216 3494 : write64(buffer, *static_cast< sal_uInt64 const * >(value));
217 3494 : break;
218 : case typelib_TypeClass_STRING:
219 : writeString(
220 : buffer,
221 194233 : OUString(*static_cast< rtl_uString * const * >(value)));
222 194233 : break;
223 : case typelib_TypeClass_TYPE:
224 : writeType(
225 : buffer,
226 : css::uno::TypeDescription(
227 : *static_cast< typelib_TypeDescriptionReference * const * >(
228 41270 : value)));
229 41270 : break;
230 : case typelib_TypeClass_ANY:
231 : {
232 268931 : uno_Any const * p = static_cast< uno_Any const * >(value);
233 268931 : css::uno::TypeDescription t(p->pType);
234 268931 : writeType(buffer, t);
235 268931 : writeValue(buffer, t, p->pData);
236 268931 : break;
237 : }
238 : case typelib_TypeClass_SEQUENCE:
239 : {
240 20409 : sal_Sequence * p = *static_cast< sal_Sequence * const * >(value);
241 20409 : writeCompressed(buffer, static_cast< sal_uInt32 >(p->nElements));
242 : css::uno::TypeDescription ctd(
243 : reinterpret_cast< typelib_IndirectTypeDescription * >(
244 20409 : type.get())->
245 20409 : pType);
246 : assert(ctd.is());
247 20409 : if (ctd.get()->eTypeClass == typelib_TypeClass_BYTE) {
248 : buffer->insert(
249 625 : buffer->end(), p->elements, p->elements + p->nElements);
250 : } else {
251 222318 : for (sal_Int32 i = 0; i != p->nElements; ++i) {
252 202534 : writeValue(buffer, ctd, p->elements + i * ctd.get()->nSize);
253 : }
254 : }
255 20409 : break;
256 : }
257 : case typelib_TypeClass_STRUCT:
258 : case typelib_TypeClass_EXCEPTION:
259 89834 : writeMemberValues(buffer, type, value);
260 89834 : break;
261 : case typelib_TypeClass_INTERFACE:
262 : writeOid(
263 : buffer,
264 : bridge_->registerOutgoingInterface(
265 : css::uno::UnoInterfaceReference(
266 : *static_cast< uno_Interface * const * >(value)),
267 169362 : type));
268 169362 : break;
269 : default:
270 : assert(false); // this cannot happen
271 0 : break;
272 : }
273 1355637 : }
274 :
275 104291 : void Marshal::writeMemberValues(
276 : std::vector< unsigned char > * buffer,
277 : css::uno::TypeDescription const & type, void const * aggregateValue)
278 : {
279 : assert(
280 : type.is() &&
281 : (type.get()->eTypeClass == typelib_TypeClass_STRUCT ||
282 : type.get()->eTypeClass == typelib_TypeClass_EXCEPTION) &&
283 : aggregateValue != 0);
284 104291 : type.makeComplete();
285 : typelib_CompoundTypeDescription * ctd =
286 104291 : reinterpret_cast< typelib_CompoundTypeDescription * >(type.get());
287 104291 : if (ctd->pBaseTypeDescription != 0) {
288 : writeMemberValues(
289 : buffer,
290 : css::uno::TypeDescription(&ctd->pBaseTypeDescription->aBase),
291 14457 : aggregateValue);
292 : }
293 570223 : for (sal_Int32 i = 0; i != ctd->nMembers; ++i) {
294 : writeValue(
295 465932 : buffer, css::uno::TypeDescription(ctd->ppTypeRefs[i]),
296 465932 : (static_cast< char const * >(aggregateValue) +
297 931864 : ctd->pMemberOffsets[i]));
298 : }
299 104291 : }
300 :
301 : }
302 :
303 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|