Skip to content

Commit

Permalink
AVRO-3995 [C++] Requires C++17 to compile Avro (#2949)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerrit0 authored Jun 13, 2024
1 parent 072b51f commit 1a348b2
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 103 deletions.
4 changes: 4 additions & 0 deletions lang/c++/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ if (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
endif()

if (CMAKE_CXX_STANDARD LESS 17)
message(FATAL_ERROR "Avro requires at least C++17")
endif()

set(CMAKE_CXX_STANDARD_REQUIRED ON)

if (APPLE)
Expand Down
4 changes: 2 additions & 2 deletions lang/c++/MainPage.dox
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ One should be able to build Avro C++ on (1) any UNIX flavor including cygwin for

In order to build Avro C++, one needs the following:
<ul>
<li>A C++ compiler and runtime libraries.
<li>A C++17 or later compiler and runtime libraries.
<li>Boost library version 1.38 or later. Apart from the header-only libraries of Boost, Avro C++ requires filesystem, iostreams, system and program_options libraries. Please see <a href="https://www.boost.org/">https://www.boost.org</a> or your platform's documentation for details on how to set up Boost for your platform.
<li>CMake build tool version 2.6 or later. Please see <a href="https://www.cmake.org">https://www.cmake.org</a> or your platform's documentation for details on how to set up CMake for your system.
<li>CMake build tool version 3.5 or later. Please see <a href="https://www.cmake.org">https://www.cmake.org</a> or your platform's documentation for details on how to set up CMake for your system.
<li>Python. If not already present, please consult your platform-specific documentation on how to install Python on your system.
</ul>

Expand Down
4 changes: 2 additions & 2 deletions lang/c++/README
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ INSTRUCTIONS

Pre-requisites:

To compile requires boost headers, the boost regex library and the fmt library. Optionally, it requires Snappy compression library. If Snappy is available, it builds support for Snappy compression and skips it otherwise. (Please see your OS-specific instructions on how to install Boost and Snappy for your OS).
To compile requires boost headers. Optionally, it requires Snappy compression library. If Snappy is available, it builds support for Snappy compression and skips it otherwise. (Please see your OS-specific instructions on how to install Boost and Snappy for your OS).

To build one requires cmake 3.5 or later and a compiler which supports at least C++17.
To build one requires cmake 3.5 or later and a compiler supporting C++17 or later.

To generate a Makefile under Unix, MacOS (using GNU) or Cygwin use:

Expand Down
61 changes: 7 additions & 54 deletions lang/c++/api/GenericDatum.hh
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,12 @@
#ifndef avro_GenericDatum_hh__
#define avro_GenericDatum_hh__

#include <any>
#include <cstdint>
#include <map>
#include <string>
#include <vector>

#if __cplusplus >= 201703L
#include <any>
#else
#include "boost/any.hpp"
#endif

#include "LogicalType.hh"
#include "Node.hh"
#include "ValidSchema.hh"
Expand Down Expand Up @@ -62,11 +57,7 @@ class AVRO_DECL GenericDatum {
protected:
Type type_;
LogicalType logicalType_;
#if __cplusplus >= 201703L
std::any value_;
#else
boost::any value_;
#endif

explicit GenericDatum(Type t)
: type_(t), logicalType_(LogicalType::NONE) {}
Expand Down Expand Up @@ -192,11 +183,7 @@ public:
template<typename T>
GenericDatum(const NodePtr &schema, const T &v) : type_(schema->type()), logicalType_(schema->logicalType()) {
init(schema);
#if __cplusplus >= 201703L
*std::any_cast<T>(&value_) = v;
#else
*boost::any_cast<T>(&value_) = v;
#endif
}

/**
Expand Down Expand Up @@ -539,67 +526,33 @@ public:
};

inline Type GenericDatum::type() const {
return (type_ == AVRO_UNION) ?
#if __cplusplus >= 201703L
std::any_cast<GenericUnion>(&value_)->datum().type()
:
#else
boost::any_cast<GenericUnion>(&value_)->datum().type()
:
#endif
type_;
return (type_ == AVRO_UNION) ? std::any_cast<GenericUnion>(&value_)->datum().type()
: type_;
}

inline LogicalType GenericDatum::logicalType() const {
return (type_ == AVRO_UNION) ?
#if __cplusplus >= 201703L
std::any_cast<GenericUnion>(&value_)->datum().logicalType()
:
#else
boost::any_cast<GenericUnion>(&value_)->datum().logicalType()
:
#endif
logicalType_;
return (type_ == AVRO_UNION) ? std::any_cast<GenericUnion>(&value_)->datum().logicalType()
: logicalType_;
}

template<typename T>
T &GenericDatum::value() {
return (type_ == AVRO_UNION) ?
#if __cplusplus >= 201703L
std::any_cast<GenericUnion>(&value_)->datum().value<T>()
return (type_ == AVRO_UNION) ? std::any_cast<GenericUnion>(&value_)->datum().value<T>()
: *std::any_cast<T>(&value_);
#else
boost::any_cast<GenericUnion>(&value_)->datum().value<T>()
: *boost::any_cast<T>(&value_);
#endif
}

template<typename T>
const T &GenericDatum::value() const {
return (type_ == AVRO_UNION) ?
#if __cplusplus >= 201703L
std::any_cast<GenericUnion>(&value_)->datum().value<T>()
return (type_ == AVRO_UNION) ? std::any_cast<GenericUnion>(&value_)->datum().value<T>()
: *std::any_cast<T>(&value_);
#else
boost::any_cast<GenericUnion>(&value_)->datum().value<T>()
: *boost::any_cast<T>(&value_);
#endif
}

inline size_t GenericDatum::unionBranch() const {
#if __cplusplus >= 201703L
return std::any_cast<GenericUnion>(&value_)->currentBranch();
#else
return boost::any_cast<GenericUnion>(&value_)->currentBranch();
#endif
}

inline void GenericDatum::selectBranch(size_t branch) {
#if __cplusplus >= 201703L
std::any_cast<GenericUnion>(&value_)->selectBranch(branch);
#else
boost::any_cast<GenericUnion>(&value_)->selectBranch(branch);
#endif
}

} // namespace avro
Expand Down
72 changes: 27 additions & 45 deletions lang/c++/impl/avrogencpp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
#include <boost/random/mersenne_twister.hpp>
#include <utility>

#include <boost/algorithm/string_regex.hpp>

#include "Compiler.hh"
#include "NodeImpl.hh"
#include "ValidSchema.hh"
Expand Down Expand Up @@ -78,8 +76,6 @@ class CodeGen {
const std::string headerFile_;
const std::string includePrefix_;
const bool noUnion_;
const bool useCpp17_;
std::string anyNs;
const std::string guardString_;
boost::mt19937 random_;

Expand Down Expand Up @@ -110,16 +106,11 @@ class CodeGen {
CodeGen(std::ostream &os, std::string ns,
std::string schemaFile, std::string headerFile,
std::string guardString,
std::string includePrefix, bool noUnion, bool useCpp17) : unionNumber_(0), os_(os), inNamespace_(false), ns_(std::move(ns)),
schemaFile_(std::move(schemaFile)), headerFile_(std::move(headerFile)),
includePrefix_(std::move(includePrefix)), noUnion_(noUnion), useCpp17_(useCpp17),
guardString_(std::move(guardString)),
random_(static_cast<uint32_t>(::time(nullptr))) {
#if __cplusplus >= 201703L
anyNs = "std";
#else
anyNs = (useCpp17) ? "std" : "boost";
#endif
std::string includePrefix, bool noUnion) : unionNumber_(0), os_(os), inNamespace_(false), ns_(std::move(ns)),
schemaFile_(std::move(schemaFile)), headerFile_(std::move(headerFile)),
includePrefix_(std::move(includePrefix)), noUnion_(noUnion),
guardString_(std::move(guardString)),
random_(static_cast<uint32_t>(::time(nullptr))) {
}

void generate(const ValidSchema &schema);
Expand Down Expand Up @@ -322,7 +313,7 @@ string CodeGen::unionName() {

static void generateGetterAndSetter(ostream &os,
const string &structName, const string &type, const string &name,
size_t idx, const std::string &anyNs) {
size_t idx) {
string sn = " " + structName + "::";

os << "inline\n";
Expand All @@ -332,7 +323,7 @@ static void generateGetterAndSetter(ostream &os,
<< " throw avro::Exception(\"Invalid type for "
<< "union " << structName << "\");\n"
<< " }\n"
<< " return " << anyNs << "::any_cast<" << type << " >(value_);\n"
<< " return std::any_cast<" << type << " >(value_);\n"
<< "}\n\n";

os << "inline\n"
Expand Down Expand Up @@ -389,7 +380,7 @@ string CodeGen::generateUnionType(const NodePtr &n) {
os_ << "struct " << result << " {\n"
<< "private:\n"
<< " size_t idx_;\n"
<< " " << anyNs << "::any value_;\n"
<< " std::any value_;\n"
<< "public:\n"
<< " size_t idx() const { return idx_; }\n";

Expand All @@ -401,7 +392,7 @@ string CodeGen::generateUnionType(const NodePtr &n) {
<< " }\n"
<< " void set_null() {\n"
<< " idx_ = " << i << ";\n"
<< " value_ = " << anyNs << "::any();\n"
<< " value_ = std::any();\n"
<< " }\n";
} else {
const string &type = types[i];
Expand Down Expand Up @@ -728,28 +719,15 @@ void CodeGen::generate(const ValidSchema &schema) {
os_ << "#ifndef " << h << "\n";
os_ << "#define " << h << "\n\n\n";

os_ << "#include <sstream>\n";
#if __cplusplus >= 201703L
os_ << "#include <any>\n";
#else
if (useCpp17_)
os_ << "#include <any>\n";
else
os_ << "#include \"boost/any.hpp\"\n";
#endif
os_ << "#include \"" << includePrefix_ << "Specific.hh\"\n"
os_ << "#include <sstream>\n"
<< "#include <any>\n"
<< "#include \"" << includePrefix_ << "Specific.hh\"\n"
<< "#include \"" << includePrefix_ << "Encoder.hh\"\n"
<< "#include \"" << includePrefix_ << "Decoder.hh\"\n"
<< "\n";

vector<string> nsVector;
if (!ns_.empty()) {
boost::algorithm::split_regex(nsVector, ns_, boost::regex("::"));
for (vector<string>::const_iterator it =
nsVector.begin();
it != nsVector.end(); ++it) {
os_ << "namespace " << *it << " {\n";
}
os_ << "namespace " << ns_ << " {\n";
inNamespace_ = true;
}

Expand All @@ -760,7 +738,7 @@ void CodeGen::generate(const ValidSchema &schema) {
pendingGettersAndSetters.begin();
it != pendingGettersAndSetters.end(); ++it) {
generateGetterAndSetter(os_, it->structName, it->type, it->name,
it->idx, anyNs);
it->idx);
}

for (vector<PendingConstructor>::const_iterator it =
Expand All @@ -772,11 +750,7 @@ void CodeGen::generate(const ValidSchema &schema) {

if (!ns_.empty()) {
inNamespace_ = false;
for (vector<string>::const_iterator it =
nsVector.begin();
it != nsVector.end(); ++it) {
os_ << "}\n";
}
os_ << "}\n";
}

os_ << "namespace avro {\n";
Expand Down Expand Up @@ -822,7 +796,16 @@ int main(int argc, char **argv) {
const string NO_UNION_TYPEDEF("no-union-typedef");

po::options_description desc("Allowed options");
desc.add_options()("help,h", "produce help message")("version,V", "produce version information")("include-prefix,p", po::value<string>()->default_value("avro"), "prefix for include headers, - for none, default: avro")("no-union-typedef,U", "do not generate typedefs for unions in records")("namespace,n", po::value<string>(), "set namespace for generated code")("cpp17", "use c++17 instead of boost")("input,i", po::value<string>(), "input file")("output,o", po::value<string>(), "output file to generate");
// clang-format off
desc.add_options()
("help,h", "produce help message")
("version,V", "produce version information")
("include-prefix,p", po::value<string>()->default_value("avro"), "prefix for include headers, - for none, default: avro")
("no-union-typedef,U", "do not generate typedefs for unions in records")
("namespace,n", po::value<string>(), "set namespace for generated code")
("input,i", po::value<string>(), "input file")
("output,o", po::value<string>(), "output file to generate");
// clang-format on

po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
Expand All @@ -848,7 +831,6 @@ int main(int argc, char **argv) {
string inf = vm.count(IN_FILE) > 0 ? vm[IN_FILE].as<string>() : string();
string incPrefix = vm[INCLUDE_PREFIX].as<string>();
bool noUnion = vm.count(NO_UNION_TYPEDEF) != 0;
bool useCpp17 = vm.count("cpp17") != 0;

if (incPrefix == "-") {
incPrefix.clear();
Expand All @@ -869,9 +851,9 @@ int main(int argc, char **argv) {
if (!outf.empty()) {
string g = readGuard(outf);
ofstream out(outf.c_str());
CodeGen(out, ns, inf, outf, g, incPrefix, noUnion, useCpp17).generate(schema);
CodeGen(out, ns, inf, outf, g, incPrefix, noUnion).generate(schema);
} else {
CodeGen(std::cout, ns, inf, outf, "", incPrefix, noUnion, useCpp17).generate(schema);
CodeGen(std::cout, ns, inf, outf, "", incPrefix, noUnion).generate(schema);
}
return 0;
} catch (std::exception &e) {
Expand Down

0 comments on commit 1a348b2

Please sign in to comment.