blob: 84fd15015b438aa7bf988cb5b132704060408e09 [file] [log] [blame]
/*
* Copyright (C) 2015, The Android Open Source Project
*
* Licensed 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "generate_cpp.h"
#include "parse_helpers.h"
#include <cctype>
#include <memory>
#include <random>
#include <string>
#include "aidl_language.h"
#include "ast_cpp.h"
#include "code_writer.h"
#include "logging.h"
using std::string;
using std::unique_ptr;
using std::vector;
namespace android {
namespace aidl {
namespace internals {
string StrippedLiteral(const buffer_type& buffer) {
std::string i_name = buffer.Literal();
string c_name;
if (i_name.length() >= 2 && i_name[0] == 'I' && isupper(i_name[1]))
c_name = i_name.substr(1);
else
c_name = i_name;
return c_name;
}
string GetCPPType(type_type *type) {
string lit = type->type.Literal();
if (lit == "int")
return "int32_t";
else if (lit == "long")
return "int64_t";
else
LOG(FATAL) << "Type not yet supported";
return "int";
}
string GetCPPVarDec(type_type* type, string name,
int direction) {
return GetCPPType(type) + ((OUT_PARAMETER & direction) ? "* " : " ") +
name + type->Brackets();
}
unique_ptr<CppDocument> BuildClientSource(interface_type* parsed_doc) {
unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}};
return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}};
}
unique_ptr<CppDocument> BuildServerSource(interface_type* parsed_doc) {
unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}};
return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}};
}
unique_ptr<CppDocument> BuildInterfaceSource(interface_type* parsed_doc) {
unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}};
return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}};
}
unique_ptr<CppDocument> BuildClientHeader(interface_type* parsed_doc) {
string i_name = parsed_doc->name.Literal();
string c_name = StrippedLiteral(parsed_doc->name);
string bp_name = "Bp" + c_name;
unique_ptr<CppMacroOrConstructorDeclaration> constructor{
new CppMacroOrConstructorDeclaration(bp_name, {}, false, false)};
unique_ptr<CppMacroOrConstructorDeclaration> destructor{
new CppMacroOrConstructorDeclaration("~" + bp_name, {}, false, false)};
vector<unique_ptr<CppDeclaration>> publics;
publics.push_back(std::move(constructor));
publics.push_back(std::move(destructor));
for (interface_item_type *item = parsed_doc->interface_items;
item;
item = item->next) {
if (item->item_type != METHOD_TYPE) {
LOG(FATAL) << "Unknown interface item type";
return nullptr;
}
method_type *m_item = (method_type *)item;
string method_name = m_item->name.Literal();
string return_arg = GetCPPVarDec(&m_item->type, "_aidl_return",
OUT_PARAMETER);
vector<string> args;
for (const std::unique_ptr<AidlArgument>& arg : *m_item->args)
args.push_back(GetCPPVarDec(&arg->type, arg->name.Literal(),
convert_direction(arg->direction.data)));
args.push_back(return_arg);
unique_ptr<CppDeclaration> meth {
new CppMethodDeclaration("android::status_t", method_name,
args, false, true)
};
publics.push_back(std::move(meth));
}
unique_ptr<CppClassDeclaration> bp_class{
new CppClassDeclaration{bp_name,
"public android::BpInterface<" + i_name + ">",
std::move(publics),
{}
}};
vector<unique_ptr<CppDeclaration>> bp_class_vec;
bp_class_vec.push_back(std::move(bp_class));
unique_ptr<CppNamespace> ns {new CppNamespace{"android", std::move(bp_class_vec)}};
unique_ptr<CppDocument> bp_header{new CppHeader{bp_name + "_H",
{"binder/IBinder.h",
"binder/IInterface.h",
"utils/Errors.h",
i_name + ".h"},
std::move(ns) }};
return bp_header;
}
unique_ptr<CppDocument> BuildServerHeader(interface_type* parsed_doc) {
string i_name = parsed_doc->name.Literal();;
string c_name = StrippedLiteral(parsed_doc->name);
string bn_name = "Bn" + c_name;
unique_ptr<CppDeclaration> on_transact{
new CppMethodDeclaration("android::status_t", "onTransact",
{ "uint32_t code",
"const android::Parcel& data",
"android::Parcel* reply",
"uint32_t flags = 0"
})};
std::vector<unique_ptr<CppDeclaration>> publics;
publics.push_back(std::move(on_transact));
unique_ptr<CppClassDeclaration> bn_class{
new CppClassDeclaration{bn_name,
"public android::BnInterface<" + i_name + ">",
std::move(publics),
{}
}};
std::vector<unique_ptr<CppDeclaration>> declarations;
declarations.push_back(std::move(bn_class));
unique_ptr<CppNamespace> ns{new CppNamespace{"android", std::move(declarations)}};
unique_ptr<CppDocument> bn_header{new CppHeader{bn_name + "_H",
{"binder/IInterface.h",
i_name + ".h"},
std::move(ns) }};
return bn_header;
}
unique_ptr<CppDocument> BuildInterfaceHeader(interface_type* parsed_doc) {
unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}};
return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}};
}
bool GenerateCppForFile(const std::string& name, unique_ptr<CppDocument> doc) {
if (!doc) {
return false;
}
unique_ptr<CodeWriter> writer = GetFileWriter(name);
doc->Write(writer.get());
return true;
}
} // namespace internals
using namespace internals;
bool GenerateCpp(const CppOptions& options, interface_type* parsed_doc) {
bool success = true;
success &= GenerateCppForFile(options.ClientCppFileName(),
BuildClientSource(parsed_doc));
success &= GenerateCppForFile(options.ClientHeaderFileName(),
BuildClientHeader(parsed_doc));
success &= GenerateCppForFile(options.ServerCppFileName(),
BuildServerSource(parsed_doc));
success &= GenerateCppForFile(options.ServerHeaderFileName(),
BuildServerHeader(parsed_doc));
success &= GenerateCppForFile(options.InterfaceCppFileName(),
BuildInterfaceSource(parsed_doc));
success &= GenerateCppForFile(options.InterfaceHeaderFileName(),
BuildInterfaceHeader(parsed_doc));
return success;
}
} // namespace android
} // namespace aidl