/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sal/config.h>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <codemaker/global.hxx>
#include <codemaker/typemanager.hxx>
#include <rtl/ref.hxx>
#include <rtl/ustring.hxx>
#include <unoidl/unoidl.hxx>
TypeManager::TypeManager(): manager_(new unoidl::Manager) {}
TypeManager::~TypeManager() {}
void TypeManager::loadProvider(OUString const & uri, bool primary) {
rtl::Reference< unoidl::Provider > prov(manager_->addProvider(uri));
if (primary) {
primaryProviders_.push_back(prov);
}
}
bool TypeManager::foundAtPrimaryProvider(OUString const & name) const {
if (name.isEmpty()) {
return !primaryProviders_.empty();
}
for (const rtl::Reference< unoidl::Provider >& xProvider : primaryProviders_)
{
if (xProvider->findEntity(name).is()) {
return true;
}
}
if (!manager_->findEntity(name).is()) {
throw CannotDumpException("Unknown entity '" + name + "'");
}
return false;
}
codemaker::UnoType::Sort TypeManager::getSort(
OUString const & name, rtl::Reference< unoidl::Entity > * entity,
rtl::Reference< unoidl::MapCursor > * cursor) const
{
if (name.isEmpty()) {
if (cursor != nullptr) {
*cursor = manager_->createCursor("");
}
return codemaker::UnoType::Sort::Module;
}
if (name == "void") {
return codemaker::UnoType::Sort::Void;
}
if (name == "boolean") {
return codemaker::UnoType::Sort::Boolean;
}
if (name == "byte") {
return codemaker::UnoType::Sort::Byte;
}
if (name == "short") {
return codemaker::UnoType::Sort::Short;
}
if (name == "unsigned short") {
return codemaker::UnoType::Sort::UnsignedShort;
}
if (name == "long") {
return codemaker::UnoType::Sort::Long;
}
if (name == "unsigned long") {
return codemaker::UnoType::Sort::UnsignedLong;
}
if (name == "hyper") {
return codemaker::UnoType::Sort::Hyper;
}
if (name == "unsigned hyper") {
return codemaker::UnoType::Sort::UnsignedHyper;
}
if (name == "float") {
return codemaker::UnoType::Sort::Float;
}
if (name == "double") {
return codemaker::UnoType::Sort::Double;
}
if (name == "char") {
return codemaker::UnoType::Sort::Char;
}
if (name == "string") {
return codemaker::UnoType::Sort::String;
}
if (name == "type") {
return codemaker::UnoType::Sort::Type;
}
if (name == "any") {
return codemaker::UnoType::Sort::Any;
}
if (name.startsWith("[")) {
return codemaker::UnoType::Sort::Sequence;
}
if (name.indexOf('<') != -1) {
return codemaker::UnoType::Sort::InstantiatedPolymorphicStruct;
}
rtl::Reference< unoidl::Entity > ent(manager_->findEntity(name));
if (!ent.is()) {
throw CannotDumpException("Unknown entity '" + name + "'");
}
if (entity != nullptr) {
*entity = ent;
}
switch (ent->getSort()) {
case unoidl::Entity::SORT_MODULE:
if (cursor != nullptr) {
*cursor = manager_->createCursor(name);
}
return codemaker::UnoType::Sort::Module;
case unoidl::Entity::SORT_ENUM_TYPE:
return codemaker::UnoType::Sort::Enum;
case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
return codemaker::UnoType::Sort::PlainStruct;
case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
return codemaker::UnoType::Sort::PolymorphicStructTemplate;
case unoidl::Entity::SORT_EXCEPTION_TYPE:
return codemaker::UnoType::Sort::Exception;
case unoidl::Entity::SORT_INTERFACE_TYPE:
return codemaker::UnoType::Sort::Interface;
case unoidl::Entity::SORT_TYPEDEF:
return codemaker::UnoType::Sort::Typedef;
case unoidl::Entity::SORT_CONSTANT_GROUP:
return codemaker::UnoType::Sort::ConstantGroup;
case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
return codemaker::UnoType::Sort::SingleInterfaceBasedService;
case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
return codemaker::UnoType::Sort::AccumulationBasedService;
case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
return codemaker::UnoType::Sort::InterfaceBasedSingleton;
case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
return codemaker::UnoType::Sort::ServiceBasedSingleton;
default:
for (;;) { std::abort(); } // this cannot happen
}
}
codemaker::UnoType::Sort TypeManager::decompose(
OUString const & name, bool resolveTypedefs, OUString * nucleus,
sal_Int32 * rank, std::vector< OUString > * arguments,
rtl::Reference< unoidl::Entity > * entity) const
{
sal_Int32 k;
std::vector< OString > args;
OUString n = b2u(codemaker::UnoType::decompose(u2b(name), &k, &args));
for (;;) {
rtl::Reference< unoidl::Entity > ent;
codemaker::UnoType::Sort s = getSort(n, &ent);
if (args.empty()
!= (s != codemaker::UnoType::Sort::PolymorphicStructTemplate))
{
throw CannotDumpException(
"template arguments mismatch for \"" + n
+ "\" resolved from \"" + name + "\"");
}
switch (s) {
case codemaker::UnoType::Sort::Typedef:
if (resolveTypedefs) {
n = dynamic_cast<unoidl::TypedefEntity&>(*ent.get()).
getType();
while (n.startsWith("[]")) {
++k; //TODO: overflow
n = n.copy(std::strlen("[]"));
}
break;
}
SAL_FALLTHROUGH;
case codemaker::UnoType::Sort::Void:
case codemaker::UnoType::Sort::Boolean:
case codemaker::UnoType::Sort::Byte:
case codemaker::UnoType::Sort::Short:
case codemaker::UnoType::Sort::UnsignedShort:
case codemaker::UnoType::Sort::Long:
case codemaker::UnoType::Sort::UnsignedLong:
case codemaker::UnoType::Sort::Hyper:
case codemaker::UnoType::Sort::UnsignedHyper:
case codemaker::UnoType::Sort::Float:
case codemaker::UnoType::Sort::Double:
case codemaker::UnoType::Sort::Char:
case codemaker::UnoType::Sort::String:
case codemaker::UnoType::Sort::Type:
case codemaker::UnoType::Sort::Any:
case codemaker::UnoType::Sort::Enum:
case codemaker::UnoType::Sort::PlainStruct:
case codemaker::UnoType::Sort::Exception:
case codemaker::UnoType::Sort::Interface:
if (nucleus != nullptr) {
*nucleus = n;
}
if (rank != nullptr) {
*rank = k;
}
if (arguments != nullptr) {
arguments->clear();
}
if (entity != nullptr) {
*entity = ent;
}
return s;
case codemaker::UnoType::Sort::PolymorphicStructTemplate:
if (args.size()
!= (dynamic_cast<
unoidl::PolymorphicStructTypeTemplateEntity * >(ent.get())->
getTypeParameters().size()))
{
throw CannotDumpException(
"bad number of template arguments for \"" + n
+ "\" resolved from \"" + name + "\"");
}
if (nucleus != nullptr) {
*nucleus = n;
}
if (rank != nullptr) {
*rank = k;
}
if (arguments != nullptr) {
arguments->clear();
for (const OString& rArg : args)
{
arguments->push_back(b2u(rArg));
}
}
if (entity != nullptr) {
*entity = ent;
}
return
codemaker::UnoType::Sort::InstantiatedPolymorphicStruct;
case codemaker::UnoType::Sort::Sequence:
for (;;) std::abort(); // this cannot happen
default:
throw CannotDumpException(
"unexpected \"" + n + "\" resolved from \"" + name
+ "\"in call to TypeManager::decompose");
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V522 There might be dereferencing of a potential null pointer.