Unverified Commit 4da5fec8 authored by Joseph Noir's avatar Joseph Noir Committed by GitHub

Merge pull request #31

Auto-generate to_string implementations for enums
parents 01c487f1 c18f978d
......@@ -91,6 +91,16 @@ function(pretty_yes var)
endif()
endfunction(pretty_yes)
add_executable(caf-generate-enum-strings cmake/caf-generate-enum-strings.cpp)
function(enum_to_string relative_input_file relative_output_file)
set(input "${CMAKE_CURRENT_SOURCE_DIR}/${relative_input_file}")
set(output "${CMAKE_CURRENT_BINARY_DIR}/${relative_output_file}")
add_custom_command(OUTPUT "${output}"
COMMAND caf-generate-enum-strings "${input}" "${output}"
DEPENDS caf-generate-enum-strings "${input}")
endfunction()
# -- binary and library path setup ---------------------------------------------
# Prohibit in-source builds.
......
#include <algorithm>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using std::cerr;
using std::find;
using std::find_if;
using std::string;
using std::vector;
void trim(string& str) {
auto not_space = [](char c) { return isspace(c) == 0; };
str.erase(str.begin(), find_if(str.begin(), str.end(), not_space));
str.erase(find_if(str.rbegin(), str.rend(), not_space).base(), str.end());
}
template <size_t N>
bool starts_with(const string& str, const char (&prefix)[N]) {
return str.compare(0, N - 1, prefix) == 0;
}
template <size_t N>
void drop_prefix(string& str, const char (&prefix)[N]) {
if (str.compare(0, N - 1, prefix) == 0)
str.erase(str.begin(), str.begin() + (N - 1));
}
void keep_alnum(string& str) {
auto not_alnum = [](char c) { return isalnum(c) == 0 && c != '_'; };
str.erase(find_if(str.begin(), str.end(), not_alnum), str.end());
}
int main(int argc, char** argv) {
if (argc != 3) {
cerr << "wrong number of arguments.\n"
<< "usage: " << argv[0] << "input-file output-file\n";
return EXIT_FAILURE;
}
std::ifstream in{argv[1]};
if (!in) {
cerr << "unable to open input file: " << argv[1] << '\n';
return EXIT_FAILURE;
}
vector<string> namespaces;
string enum_name;
string line;
bool is_enum_class = false;
// Locate the beginning of the enum.
for (;;) {
if (!getline(in, line)) {
cerr << "unable to locate enum in file: " << argv[1] << '\n';
return EXIT_FAILURE;
}
trim(line);
if (starts_with(line, "enum ")) {
drop_prefix(line, "enum ");
if (starts_with(line, "class ")) {
is_enum_class = true;
drop_prefix(line, "class ");
}
trim(line);
keep_alnum(line);
enum_name = line;
break;
}
if (starts_with(line, "namespace ")) {
if (line.back() == '{')
line.pop_back();
line.erase(line.begin(), find(line.begin(), line.end(), ' '));
trim(line);
namespaces.emplace_back(line);
}
}
// Sanity checking.
if (namespaces.empty()) {
cerr << "enum found outside of a namespace\n";
return EXIT_FAILURE;
}
if (enum_name.empty()) {
cerr << "empty enum name found\n";
return EXIT_FAILURE;
}
std::ofstream out{argv[2]};
if (!out) {
cerr << "unable to open output file: " << argv[1] << '\n';
return EXIT_FAILURE;
}
// Print file header.
out << "#include \"" << namespaces[0];
for (size_t i = 1; i < namespaces.size(); ++i)
out << '/' << namespaces[i];
out << '/' << enum_name << ".hpp\"\n\n"
<< "#include <string>\n\n"
<< "namespace " << namespaces[0] << " {\n";
for (size_t i = 1; i < namespaces.size(); ++i)
out << "namespace " << namespaces[i] << " {\n";
out << "\nstd::string to_string(" << enum_name << " x) {\n"
<< " switch(x) {\n"
<< " default:\n"
<< " return \"???\";\n";
// Read until hitting the closing '}'.
std::string case_label_prefix;
if (is_enum_class)
case_label_prefix = enum_name + "::";
for (;;) {
if (!getline(in, line)) {
cerr << "unable to read enum values\n";
return EXIT_FAILURE;
}
trim(line);
if (line.empty())
continue;
if (line[0] == '}')
break;
if (line[0] != '/') {
keep_alnum(line);
out << " case " << case_label_prefix << line << ":\n"
<< " return \"" << line << "\";\n";
}
}
// Done. Print file footer and exit.
out << " };\n"
<< "}\n\n";
for (auto i = namespaces.rbegin(); i != namespaces.rend(); ++i)
out << "} // namespace " << *i << '\n';
}
......@@ -5,11 +5,19 @@ project(caf_net C CXX)
# e.g., for creating proper Xcode projects
file(GLOB_RECURSE LIBCAF_NET_HDRS "caf/*.hpp")
enum_to_string("caf/net/basp/connection_state.hpp" "basp_conn_strings.cpp")
enum_to_string("caf/net/basp/ec.hpp" "basp_ec_strings.cpp")
enum_to_string("caf/net/basp/message_type.hpp" "basp_message_type_strings.cpp")
enum_to_string("caf/net/operation.hpp" "operation_strings.cpp")
# list cpp files excluding platform-dependent files
set(LIBCAF_NET_SRCS
"${CMAKE_CURRENT_BINARY_DIR}/basp_conn_strings.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/basp_ec_strings.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/basp_message_type_strings.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/operation_strings.cpp"
src/actor_proxy_impl.cpp
src/application.cpp
src/connection_state.cpp
src/convert_ip_endpoint.cpp
src/datagram_socket.cpp
src/ec.cpp
......@@ -17,7 +25,6 @@ set(LIBCAF_NET_SRCS
src/header.cpp
src/host.cpp
src/ip.cpp
src/message_type.cpp
src/multiplexer.cpp
src/net/backend/test.cpp
src/net/endpoint_manager_queue.cpp
......
......@@ -18,6 +18,8 @@
#pragma once
#include <string>
namespace caf {
namespace net {
......@@ -45,13 +47,7 @@ constexpr operation operator~(operation x) {
return static_cast<operation>(~static_cast<int>(x));
}
constexpr const char* to_string(operation x) {
return x == operation::none
? "none"
: (x == operation::read
? "read"
: (x == operation::write ? "write" : "read_write"));
}
std::string to_string(operation x);
} // namespace net
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/net/basp/connection_state.hpp"
namespace caf {
namespace net {
namespace basp {
namespace {
const char* connection_state_names[] = {
"await_handshake_header",
"await_handshake_payload",
"await_header",
"await_payload",
"shutdown",
};
} // namespace
std::string to_string(connection_state x) {
return connection_state_names[static_cast<uint8_t>(x)];
}
} // namespace basp
} // namespace net
} // namespace caf
......@@ -26,32 +26,6 @@ namespace caf {
namespace net {
namespace basp {
namespace {
string_view ec_names[] = {
"none",
"invalid_magic_number",
"unexpected_number_of_bytes",
"unexpected_payload",
"missing_payload",
"illegal_state",
"invalid_handshake",
"missing_handshake",
"unexpected_handshake",
"version_mismatch",
"unimplemented",
"app_identifiers_mismatch",
"invalid_payload",
"invalid_scheme",
};
} // namespace
std::string to_string(ec x) {
auto result = ec_names[static_cast<uint8_t>(x)];
return std::string{result.begin(), result.end()};
}
error make_error(ec x) {
return {static_cast<uint8_t>(x), atom("basp")};
}
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/net/basp/message_type.hpp"
#include "caf/string_view.hpp"
namespace caf {
namespace net {
namespace basp {
namespace {
string_view message_type_names[] = {
"handshake", "actor_message", "resolve_request", "resolve_response",
"monitor_message", "down_message", "heartbeat",
};
} // namespace
std::string to_string(message_type x) {
auto result = message_type_names[static_cast<uint8_t>(x)];
return std::string{result.begin(), result.end()};
}
} // namespace basp
} // namespace net
} // namespace caf
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment