Bump version to 24.04.3.4
[LibreOffice.git] / unoidl / source / legacyprovider.cxx
blob9299ae7ce04616a63fe0f151b09aa46d61408bac
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <sal/config.h>
12 #include <cassert>
13 #include <utility>
14 #include <vector>
16 #include <registry/reader.hxx>
17 #include <registry/registry.hxx>
18 #include <registry/regtype.h>
19 #include <rtl/ref.hxx>
20 #include <rtl/ustring.hxx>
21 #include <sal/types.h>
22 #include <unoidl/unoidl.hxx>
24 #include "legacyprovider.hxx"
26 namespace unoidl::detail {
28 namespace {
30 std::vector< OUString > translateAnnotations(std::u16string_view documentation) {
31 std::vector< OUString > ans;
32 if (documentation.find(u"@deprecated") != std::u16string_view::npos) {
33 //TODO: this check is somewhat crude
34 ans.push_back("deprecated");
36 return ans;
39 ConstantValue translateConstantValue(
40 RegistryKey & key, RTConstValue const & value)
42 switch (value.m_type) {
43 case RT_TYPE_BOOL:
44 return ConstantValue(value.m_value.aBool);
45 case RT_TYPE_BYTE:
46 return ConstantValue(value.m_value.aByte);
47 case RT_TYPE_INT16:
48 return ConstantValue(value.m_value.aShort);
49 case RT_TYPE_UINT16:
50 return ConstantValue(value.m_value.aUShort);
51 case RT_TYPE_INT32:
52 return ConstantValue(value.m_value.aLong);
53 case RT_TYPE_UINT32:
54 return ConstantValue(value.m_value.aULong);
55 case RT_TYPE_INT64:
56 return ConstantValue(value.m_value.aHyper);
57 case RT_TYPE_UINT64:
58 return ConstantValue(value.m_value.aUHyper);
59 case RT_TYPE_FLOAT:
60 return ConstantValue(value.m_value.aFloat);
61 case RT_TYPE_DOUBLE:
62 return ConstantValue(value.m_value.aDouble);
63 default:
64 throw FileFormatException(
65 key.getRegistryName(),
66 ("legacy format: unexpected type " + OUString::number(value.m_type)
67 + " of value of a field of constant group with key "
68 + key.getName()));
72 rtl::Reference< Entity > readEntity(
73 rtl::Reference< Manager > const & manager, RegistryKey & ucr,
74 RegistryKey & key, OUString const & path, bool probe);
76 class Cursor: public MapCursor {
77 public:
78 Cursor(
79 rtl::Reference< Manager > manager, RegistryKey const & ucr,
80 RegistryKey const & key);
82 private:
83 virtual ~Cursor() noexcept override {}
85 virtual rtl::Reference< Entity > getNext(OUString * name) override;
87 rtl::Reference< Manager > manager_;
88 RegistryKey ucr_;
89 RegistryKey key_;
90 OUString prefix_;
91 RegistryKeyNames names_;
92 sal_uInt32 index_;
95 Cursor::Cursor(
96 rtl::Reference< Manager > manager, RegistryKey const & ucr,
97 RegistryKey const & key):
98 manager_(std::move(manager)), ucr_(ucr), key_(key), index_(0)
100 if (!ucr_.isValid())
101 return;
103 prefix_ = key_.getName();
104 if (!prefix_.endsWith("/")) {
105 prefix_ += "/";
107 RegError e = key_.getKeyNames("", names_);
108 if (e != RegError::NO_ERROR) {
109 throw FileFormatException(
110 key_.getRegistryName(),
111 ("legacy format: cannot get sub-key names of " + key_.getName()
112 + ": " + OUString::number(static_cast<int>(e))));
116 rtl::Reference< Entity > Cursor::getNext(OUString * name) {
117 assert(name != nullptr);
118 rtl::Reference< Entity > ent;
119 if (index_ != names_.getLength()) {
120 OUString path(names_.getElement(index_));
121 assert(path.match(prefix_));
122 *name = path.copy(prefix_.getLength());
123 ent = readEntity(manager_, ucr_, key_, *name, false);
124 assert(ent.is());
125 ++index_;
127 return ent;
130 class Module: public ModuleEntity {
131 public:
132 Module(
133 rtl::Reference< Manager > manager, RegistryKey const & ucr,
134 RegistryKey const & key):
135 manager_(std::move(manager)), ucr_(ucr), key_(key)
138 private:
139 virtual ~Module() noexcept override {}
141 virtual std::vector< OUString > getMemberNames() const override;
143 virtual rtl::Reference< MapCursor > createCursor() const override
144 { return new Cursor(manager_, ucr_, key_); }
146 rtl::Reference< Manager > manager_;
147 RegistryKey ucr_;
148 mutable RegistryKey key_;
151 std::vector< OUString > Module::getMemberNames() const {
152 RegistryKeyNames names;
153 RegError e = key_.getKeyNames("", names);
154 if (e != RegError::NO_ERROR) {
155 throw FileFormatException(
156 key_.getRegistryName(),
157 ("legacy format: cannot get sub-key names of " + key_.getName()
158 + ": " + OUString::number(static_cast<int>(e))));
160 std::vector< OUString > ns;
161 for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
162 ns.push_back(names.getElement(i));
164 return ns;
167 typereg::Reader getReader(RegistryKey & key, std::vector< char > * buffer) {
168 assert(buffer != nullptr);
169 RegValueType type;
170 sal_uInt32 size;
171 RegError e = key.getValueInfo("", &type, &size);
172 if (e != RegError::NO_ERROR) {
173 throw FileFormatException(
174 key.getRegistryName(),
175 ("legacy format: cannot get value info about key " + key.getName()
176 + ": " + OUString::number(static_cast<int>(e))));
178 if (type != RegValueType::BINARY) {
179 throw FileFormatException(
180 key.getRegistryName(),
181 ("legacy format: unexpected value type " + OUString::number(static_cast<int>(type))
182 + " of key " + key.getName()));
184 if (size == 0
185 /*TODO: || size > std::numeric_limits< std::vector< char >::size_type >::max() */)
187 throw FileFormatException(
188 key.getRegistryName(),
189 ("legacy format: bad binary value size " + OUString::number(size)
190 + " of key " + key.getName()));
192 buffer->resize(static_cast< std::vector< char >::size_type >(size));
193 e = key.getValue("", buffer->data());
194 if (e != RegError::NO_ERROR) {
195 throw FileFormatException(
196 key.getRegistryName(),
197 ("legacy format: cannot get binary value of key " + key.getName()
198 + ": " + OUString::number(static_cast<int>(e))));
200 typereg::Reader reader(buffer->data(), size);
201 if (!reader.isValid()) {
202 throw FileFormatException(
203 key.getRegistryName(),
204 "legacy format: malformed binary value of key " + key.getName());
206 return reader;
209 rtl::Reference< Entity > readEntity(
210 rtl::Reference< Manager > const & manager, RegistryKey & ucr,
211 RegistryKey & key, OUString const & path, bool probe)
213 assert(manager.is());
214 RegistryKey sub;
215 RegError e = key.openKey(path, sub);
216 switch (e) {
217 case RegError::NO_ERROR:
218 break;
219 case RegError::KEY_NOT_EXISTS:
220 if (probe) {
221 return rtl::Reference< Entity >();
223 [[fallthrough]];
224 default:
225 throw FileFormatException(
226 key.getRegistryName(),
227 ("legacy format: cannot open sub-key " + path + " of "
228 + key.getName() + ": " + OUString::number(static_cast<int>(e))));
230 std::vector< char > buf;
231 typereg::Reader reader(getReader(sub, &buf));
232 switch (reader.getTypeClass()) {
233 case RT_TYPE_INTERFACE:
235 std::vector< AnnotatedReference > mandBases;
236 sal_uInt16 n = reader.getSuperTypeCount();
237 for (sal_uInt16 j = 0; j != n; ++j) {
238 mandBases.emplace_back(
239 reader.getSuperTypeName(j).replace('/', '.'),
240 std::vector< OUString >());
242 std::vector< AnnotatedReference > optBases;
243 n = reader.getReferenceCount();
244 for (sal_uInt16 j = 0; j != n; ++j) {
245 optBases.emplace_back(
246 reader.getReferenceTypeName(j).replace('/', '.'),
247 translateAnnotations(reader.getReferenceDocumentation(j)));
249 sal_uInt16 methodCount = reader.getMethodCount();
250 std::vector< InterfaceTypeEntity::Attribute > attrs;
251 n = reader.getFieldCount(); // attributes
252 for (sal_uInt16 j = 0; j != n; ++j) {
253 OUString attrName(reader.getFieldName(j));
254 std::vector< OUString > getExcs;
255 std::vector< OUString > setExcs;
256 for (sal_uInt16 k = 0; k != methodCount; ++k) {
257 if (reader.getMethodName(k) == attrName) {
258 switch (reader.getMethodFlags(k)) {
259 case RTMethodMode::ATTRIBUTE_GET:
261 sal_uInt16 m
262 = reader.getMethodExceptionCount(k);
263 // cid#1213376 unhelpfully warns about an
264 // untrusted loop bound here:
265 // coverity[tainted_data] - trusted data source
266 for (sal_uInt16 l = 0; l != m; ++l) {
267 getExcs.push_back(
268 reader.getMethodExceptionTypeName(k, l).
269 replace('/', '.'));
271 break;
273 case RTMethodMode::ATTRIBUTE_SET:
275 sal_uInt16 m
276 = reader.getMethodExceptionCount(k);
277 // cid#1213376 unhelpfully warns about an
278 // untrusted loop bound here:
279 // coverity[tainted_data] - trusted data source
280 for (sal_uInt16 l = 0; l != m; ++l) {
281 setExcs.push_back(
282 reader.getMethodExceptionTypeName(k, l).
283 replace('/', '.'));
285 break;
287 default:
288 throw FileFormatException(
289 key.getRegistryName(),
290 ("legacy format: method and attribute with same"
291 " name " + attrName
292 + " in interface type with key "
293 + sub.getName()));
297 RTFieldAccess flags = reader.getFieldFlags(j);
298 attrs.emplace_back(
299 attrName, reader.getFieldTypeName(j).replace('/', '.'),
300 bool(flags & RTFieldAccess::BOUND),
301 bool(flags & RTFieldAccess::READONLY), std::move(getExcs), std::move(setExcs),
302 translateAnnotations(reader.getFieldDocumentation(j)));
304 std::vector< InterfaceTypeEntity::Method > meths;
305 meths.reserve(methodCount);
306 for (sal_uInt16 j = 0; j != methodCount; ++j) {
307 RTMethodMode flags = reader.getMethodFlags(j);
308 if (flags != RTMethodMode::ATTRIBUTE_GET
309 && flags != RTMethodMode::ATTRIBUTE_SET)
311 std::vector< InterfaceTypeEntity::Method::Parameter >
312 params;
313 sal_uInt16 m = reader.getMethodParameterCount(j);
314 // cid#1213376 unhelpfully warns about an untrusted loop
315 // bound here:
316 // coverity[tainted_data] - trusted data source
317 for (sal_uInt16 k = 0; k != m; ++k) {
318 RTParamMode mode = reader.getMethodParameterFlags(j, k);
319 InterfaceTypeEntity::Method::Parameter::Direction dir;
320 switch (mode) {
321 case RT_PARAM_IN:
322 dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
323 break;
324 case RT_PARAM_OUT:
325 dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT;
326 break;
327 case RT_PARAM_INOUT:
328 dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT;
329 break;
330 default:
331 throw FileFormatException(
332 key.getRegistryName(),
333 ("legacy format: unexpected mode "
334 + OUString::number(mode) + " of parameter "
335 + reader.getMethodParameterName(j, k)
336 + " of method " + reader.getMethodName(j)
337 + " in interface type with key "
338 + sub.getName()));
340 params.emplace_back(
341 reader.getMethodParameterName(j, k),
342 (reader.getMethodParameterTypeName(j, k).
343 replace('/', '.')),
344 dir);
346 std::vector< OUString > excs;
347 m = reader.getMethodExceptionCount(j);
348 // cid#1213376 unhelpfully warns about an untrusted loop
349 // bound here:
350 // coverity[tainted_data] - trusted data source
351 for (sal_uInt16 k = 0; k != m; ++k) {
352 excs.push_back(
353 reader.getMethodExceptionTypeName(j, k).replace(
354 '/', '.'));
356 meths.emplace_back(
357 reader.getMethodName(j),
358 reader.getMethodReturnTypeName(j).replace('/', '.'),
359 std::move(params), std::move(excs),
360 translateAnnotations(
361 reader.getMethodDocumentation(j)));
364 return new InterfaceTypeEntity(
365 reader.isPublished(), std::move(mandBases), std::move(optBases), std::move(attrs), std::move(meths),
366 translateAnnotations(reader.getDocumentation()));
368 case RT_TYPE_MODULE:
369 return new Module(manager, ucr, sub);
370 case RT_TYPE_STRUCT:
372 sal_uInt16 n = reader.getReferenceCount();
373 if (n == 0) {
374 OUString base;
375 switch (reader.getSuperTypeCount()) {
376 case 0:
377 break;
378 case 1:
379 base = reader.getSuperTypeName(0).replace('/', '.');
380 break;
381 default:
382 throw FileFormatException(
383 key.getRegistryName(),
384 ("legacy format: unexpected number "
385 + OUString::number(reader.getSuperTypeCount())
386 + " of super-types of plain struct type with key "
387 + sub.getName()));
389 std::vector< PlainStructTypeEntity::Member > mems;
390 n = reader.getFieldCount();
391 for (sal_uInt16 j = 0; j != n; ++j) {
392 mems.emplace_back(
393 reader.getFieldName(j),
394 reader.getFieldTypeName(j).replace('/', '.'),
395 translateAnnotations(reader.getFieldDocumentation(j)));
397 return new PlainStructTypeEntity(
398 reader.isPublished(), base, std::move(mems),
399 translateAnnotations(reader.getDocumentation()));
400 } else {
401 if (reader.getSuperTypeCount() != 0) {
402 throw FileFormatException(
403 key.getRegistryName(),
404 ("legacy format: unexpected number "
405 + OUString::number(reader.getSuperTypeCount())
406 + " of super-types of polymorphic struct type template"
407 " with key " + sub.getName()));
409 std::vector< OUString > params;
410 for (sal_uInt16 j = 0; j != n; ++j) {
411 params.push_back(
412 reader.getReferenceTypeName(j).replace('/', '.'));
414 std::vector< PolymorphicStructTypeTemplateEntity::Member > mems;
415 n = reader.getFieldCount();
416 for (sal_uInt16 j = 0; j != n; ++j) {
417 mems.emplace_back(
418 reader.getFieldName(j),
419 reader.getFieldTypeName(j).replace('/', '.'),
420 bool(
421 reader.getFieldFlags(j)
422 & RTFieldAccess::PARAMETERIZED_TYPE),
423 translateAnnotations(reader.getFieldDocumentation(j)));
425 return new PolymorphicStructTypeTemplateEntity(
426 reader.isPublished(), std::move(params), std::move(mems),
427 translateAnnotations(reader.getDocumentation()));
430 case RT_TYPE_ENUM:
432 std::vector< EnumTypeEntity::Member > mems;
433 sal_uInt16 n = reader.getFieldCount();
434 for (sal_uInt16 j = 0; j != n; ++j) {
435 RTConstValue v(reader.getFieldValue(j));
436 if (v.m_type != RT_TYPE_INT32) {
437 throw FileFormatException(
438 key.getRegistryName(),
439 ("legacy format: unexpected type "
440 + OUString::number(v.m_type) + " of value of field "
441 + reader.getFieldName(j) + " of enum type with key "
442 + sub.getName()));
444 mems.emplace_back(
445 reader.getFieldName(j), v.m_value.aLong,
446 translateAnnotations(reader.getFieldDocumentation(j)));
449 return new EnumTypeEntity(
450 reader.isPublished(), std::move(mems),
451 translateAnnotations(reader.getDocumentation()));
453 case RT_TYPE_EXCEPTION:
455 OUString base;
456 switch (reader.getSuperTypeCount()) {
457 case 0:
458 break;
459 case 1:
460 base = reader.getSuperTypeName(0).replace('/', '.');
461 break;
462 default:
463 throw FileFormatException(
464 key.getRegistryName(),
465 ("legacy format: unexpected number "
466 + OUString::number(reader.getSuperTypeCount())
467 + " of super-types of exception type with key "
468 + sub.getName()));
470 std::vector< ExceptionTypeEntity::Member > mems;
471 sal_uInt16 n = reader.getFieldCount();
472 for (sal_uInt16 j = 0; j != n; ++j) {
473 mems.emplace_back(
474 reader.getFieldName(j),
475 reader.getFieldTypeName(j).replace('/', '.'),
476 translateAnnotations(reader.getFieldDocumentation(j)));
478 return new ExceptionTypeEntity(
479 reader.isPublished(), base, std::move(mems),
480 translateAnnotations(reader.getDocumentation()));
482 case RT_TYPE_TYPEDEF:
483 if (reader.getSuperTypeCount() != 1) {
484 throw FileFormatException(
485 key.getRegistryName(),
486 ("legacy format: unexpected number "
487 + OUString::number(reader.getSuperTypeCount())
488 + " of super-types of typedef with key " + sub.getName()));
490 return new TypedefEntity(
491 reader.isPublished(), reader.getSuperTypeName(0).replace('/', '.'),
492 translateAnnotations(reader.getDocumentation()));
493 case RT_TYPE_SERVICE:
494 switch (reader.getSuperTypeCount()) {
495 case 0:
497 std::vector< AnnotatedReference > mandServs;
498 std::vector< AnnotatedReference > optServs;
499 std::vector< AnnotatedReference > mandIfcs;
500 std::vector< AnnotatedReference > optIfcs;
501 sal_uInt16 n = reader.getReferenceCount();
502 for (sal_uInt16 j = 0; j != n; ++j) {
503 AnnotatedReference base{
504 reader.getReferenceTypeName(j).replace('/', '.'),
505 translateAnnotations(
506 reader.getReferenceDocumentation(j))};
507 switch (reader.getReferenceSort(j)) {
508 case RTReferenceType::EXPORTS:
509 if (!(reader.getReferenceFlags(j) & RTFieldAccess::OPTIONAL))
511 mandServs.push_back(base);
512 } else {
513 optServs.push_back(base);
515 break;
516 case RTReferenceType::SUPPORTS:
517 if (!(reader.getReferenceFlags(j) & RTFieldAccess::OPTIONAL))
519 mandIfcs.push_back(base);
520 } else {
521 optIfcs.push_back(base);
523 break;
524 default:
525 throw FileFormatException(
526 key.getRegistryName(),
527 ("legacy format: unexpected mode "
528 + OUString::number(static_cast<int>(reader.getReferenceSort(j)))
529 + " of reference " + reader.getReferenceTypeName(j)
530 + " in service with key " + sub.getName()));
533 std::vector< AccumulationBasedServiceEntity::Property > props;
534 n = reader.getFieldCount();
535 for (sal_uInt16 j = 0; j != n; ++j) {
536 RTFieldAccess acc = reader.getFieldFlags(j);
537 int attrs = 0;
538 if (acc & RTFieldAccess::READONLY) {
539 attrs |= AccumulationBasedServiceEntity::Property::
540 ATTRIBUTE_READ_ONLY;
542 if (acc & RTFieldAccess::OPTIONAL) {
543 attrs |= AccumulationBasedServiceEntity::Property::
544 ATTRIBUTE_OPTIONAL;
546 if (acc & RTFieldAccess::MAYBEVOID) {
547 attrs |= AccumulationBasedServiceEntity::Property::
548 ATTRIBUTE_MAYBE_VOID;
550 if (acc & RTFieldAccess::BOUND) {
551 attrs |= AccumulationBasedServiceEntity::Property::
552 ATTRIBUTE_BOUND;
554 if (acc & RTFieldAccess::CONSTRAINED) {
555 attrs |= AccumulationBasedServiceEntity::Property::
556 ATTRIBUTE_CONSTRAINED;
558 if (acc & RTFieldAccess::TRANSIENT) {
559 attrs |= AccumulationBasedServiceEntity::Property::
560 ATTRIBUTE_TRANSIENT;
562 if (acc & RTFieldAccess::MAYBEAMBIGUOUS) {
563 attrs |= AccumulationBasedServiceEntity::Property::
564 ATTRIBUTE_MAYBE_AMBIGUOUS;
566 if (acc & RTFieldAccess::MAYBEDEFAULT) {
567 attrs |= AccumulationBasedServiceEntity::Property::
568 ATTRIBUTE_MAYBE_DEFAULT;
570 if (acc & RTFieldAccess::REMOVABLE) {
571 attrs |= AccumulationBasedServiceEntity::Property::
572 ATTRIBUTE_REMOVABLE;
574 props.emplace_back(
575 reader.getFieldName(j),
576 reader.getFieldTypeName(j).replace('/', '.'),
577 static_cast<
578 AccumulationBasedServiceEntity::Property::
579 Attributes >(attrs),
580 translateAnnotations(reader.getFieldDocumentation(j)));
582 return new AccumulationBasedServiceEntity(
583 reader.isPublished(), std::move(mandServs), std::move(optServs), std::move(mandIfcs),
584 std::move(optIfcs), std::move(props),
585 translateAnnotations(reader.getDocumentation()));
587 case 1:
589 std::vector< SingleInterfaceBasedServiceEntity::Constructor >
590 ctors;
591 sal_uInt16 n = reader.getMethodCount();
592 if (n == 1 && reader.getMethodFlags(0) == RTMethodMode::TWOWAY
593 && reader.getMethodName(0).isEmpty()
594 && reader.getMethodReturnTypeName(0) == "void"
595 && reader.getMethodParameterCount(0) == 0
596 && reader.getMethodExceptionCount(0) == 0)
598 ctors.push_back(
599 SingleInterfaceBasedServiceEntity::Constructor());
600 } else {
601 for (sal_uInt16 j = 0; j != n; ++j) {
602 if (reader.getMethodFlags(j) != RTMethodMode::TWOWAY) {
603 throw FileFormatException(
604 key.getRegistryName(),
605 ("legacy format: unexpected mode "
606 + OUString::number(static_cast<int>(reader.getMethodFlags(j)))
607 + " of constructor " + reader.getMethodName(j)
608 + " in service with key " + sub.getName()));
610 std::vector<
611 SingleInterfaceBasedServiceEntity::Constructor::
612 Parameter > params;
613 sal_uInt16 m = reader.getMethodParameterCount(j);
614 // cid#1213376 unhelpfully warns about an untrusted
615 // loop bound here:
616 // coverity[tainted_data] - trusted data source
617 for (sal_uInt16 k = 0; k != m; ++k) {
618 RTParamMode mode
619 = reader.getMethodParameterFlags(j, k);
620 if ((mode & ~RT_PARAM_REST) != RT_PARAM_IN) {
621 throw FileFormatException(
622 key.getRegistryName(),
623 ("legacy format: unexpected mode "
624 + OUString::number(mode)
625 + " of parameter "
626 + reader.getMethodParameterName(j, k)
627 + " of constructor "
628 + reader.getMethodName(j)
629 + " in service with key "
630 + sub.getName()));
632 if ((mode & RT_PARAM_REST) != 0
633 && (m != 1
634 || ((reader.getMethodParameterTypeName(
635 j, 0))
636 != "any")))
638 throw FileFormatException(
639 key.getRegistryName(),
640 ("legacy format: bad rest parameter "
641 + reader.getMethodParameterName(j, k)
642 + " of constructor "
643 + reader.getMethodName(j)
644 + " in service with key "
645 + sub.getName()));
647 params.emplace_back(
648 reader.getMethodParameterName(j, k),
649 (reader.getMethodParameterTypeName(j, k).
650 replace('/', '.')),
651 (mode & RT_PARAM_REST) != 0);
653 std::vector< OUString > excs;
654 m = reader.getMethodExceptionCount(j);
655 // cid#1213376 unhelpfully warns about an untrusted
656 // loop bound here:
657 // coverity[tainted_data] - trusted data source
658 for (sal_uInt16 k = 0; k != m; ++k) {
659 excs.push_back(
660 reader.getMethodExceptionTypeName(j, k).replace(
661 '/', '.'));
663 ctors.push_back(
664 SingleInterfaceBasedServiceEntity::Constructor(
665 reader.getMethodName(j), std::move(params), std::move(excs),
666 translateAnnotations(
667 reader.getMethodDocumentation(j))));
670 return new SingleInterfaceBasedServiceEntity(
671 reader.isPublished(),
672 reader.getSuperTypeName(0).replace('/', '.'), std::move(ctors),
673 translateAnnotations(reader.getDocumentation()));
675 default:
676 throw FileFormatException(
677 key.getRegistryName(),
678 ("legacy format: unexpected number "
679 + OUString::number(reader.getSuperTypeCount())
680 + " of super-types of service with key " + sub.getName()));
682 case RT_TYPE_SINGLETON:
684 if (reader.getSuperTypeCount() != 1) {
685 throw FileFormatException(
686 key.getRegistryName(),
687 ("legacy format: unexpected number "
688 + OUString::number(reader.getSuperTypeCount())
689 + " of super-types of singleton with key "
690 + sub.getName()));
692 OUString basePath(reader.getSuperTypeName(0));
693 OUString baseName(basePath.replace('/', '.'));
694 bool newStyle;
695 rtl::Reference< Entity > base(manager->findEntity(baseName));
696 if (base.is()) {
697 switch (base->getSort()) {
698 case Entity::SORT_INTERFACE_TYPE:
699 newStyle = true;
700 break;
701 case Entity::SORT_ACCUMULATION_BASED_SERVICE:
702 newStyle = false;
703 break;
704 default:
705 throw FileFormatException(
706 key.getRegistryName(),
707 ("legacy format: unexpected sort "
708 + OUString::number(base->getSort()) + " of base "
709 + baseName + " of singleton with key "
710 + sub.getName()));
712 } else {
713 RegistryKey key2;
714 e = ucr.openKey(basePath, key2);
715 switch (e) {
716 case RegError::NO_ERROR:
717 break;
718 case RegError::KEY_NOT_EXISTS:
719 throw FileFormatException(
720 key.getRegistryName(),
721 ("legacy format: unknown super-type " + basePath
722 + " of super-type with key " + sub.getName()));
723 default:
724 throw FileFormatException(
725 key.getRegistryName(),
726 ("legacy format: cannot open ucr sub-key " + basePath
727 + ": " + OUString::number(static_cast<int>(e))));
729 std::vector< char > buf2;
730 typereg::Reader reader2(getReader(key2, &buf2));
731 switch (reader2.getTypeClass()) {
732 case RT_TYPE_INTERFACE:
733 newStyle = true;
734 break;
735 case RT_TYPE_SERVICE:
736 newStyle = false;
737 break;
738 default:
739 throw FileFormatException(
740 key.getRegistryName(),
741 ("legacy format: unexpected type class "
742 + OUString::number(reader2.getTypeClass())
743 + " of super-type with key " + key2.getName()
744 + " of singleton with key " + sub.getName()));
747 return newStyle
748 ? rtl::Reference< Entity >(
749 new InterfaceBasedSingletonEntity(
750 reader.isPublished(), baseName,
751 translateAnnotations(reader.getDocumentation())))
752 : rtl::Reference< Entity >(
753 new ServiceBasedSingletonEntity(
754 reader.isPublished(), baseName,
755 translateAnnotations(reader.getDocumentation())));
757 case RT_TYPE_CONSTANTS:
759 std::vector< ConstantGroupEntity::Member > mems;
760 sal_uInt16 n = reader.getFieldCount();
761 for (sal_uInt16 j = 0; j != n; ++j) {
762 mems.emplace_back(
763 reader.getFieldName(j),
764 translateConstantValue(sub, reader.getFieldValue(j)),
765 translateAnnotations(reader.getFieldDocumentation(j)));
767 return new ConstantGroupEntity(
768 reader.isPublished(), std::move(mems),
769 translateAnnotations(reader.getDocumentation()));
771 default:
772 throw FileFormatException(
773 key.getRegistryName(),
774 ("legacy format: unexpected type class "
775 + OUString::number(reader.getTypeClass()) + " of key "
776 + sub.getName()));
782 LegacyProvider::LegacyProvider(Manager & manager, OUString const & uri):
783 manager_(manager)
785 Registry reg;
786 RegError e = reg.open(uri, RegAccessMode::READONLY);
787 switch (e) {
788 case RegError::NO_ERROR:
789 break;
790 case RegError::REGISTRY_NOT_EXISTS:
791 throw NoSuchFileException(uri);
792 default:
793 throw FileFormatException(
794 uri, "cannot open legacy file: " + OUString::number(static_cast<int>(e)));
796 RegistryKey root;
797 e = reg.openRootKey(root);
798 if (e != RegError::NO_ERROR) {
799 throw FileFormatException(
800 uri, "legacy format: cannot open root key: " + OUString::number(static_cast<int>(e)));
802 e = root.openKey("UCR", ucr_);
803 switch (e) {
804 case RegError::NO_ERROR:
805 case RegError::KEY_NOT_EXISTS: // such effectively empty files exist in the wild
806 break;
807 default:
808 throw FileFormatException(
809 uri, "legacy format: cannot open UCR key: " + OUString::number(static_cast<int>(e)));
813 rtl::Reference< MapCursor > LegacyProvider::createRootCursor() const {
814 return new Cursor(&manager_, ucr_, ucr_);
817 rtl::Reference< Entity > LegacyProvider::findEntity(OUString const & name)
818 const
820 return ucr_.isValid()
821 ? readEntity(&manager_, ucr_, ucr_, name.replace('.', '/'), true)
822 : rtl::Reference< Entity >();
825 LegacyProvider::~LegacyProvider() noexcept {}
829 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */