From 19501fc00ff1f18ecf9c65baf670dc92c0b64891 Mon Sep 17 00:00:00 2001 From: Mikhail Koviazin Date: Mon, 29 Apr 2024 16:44:38 +0300 Subject: [PATCH] [AVRO-3967] Replace boost::format with fmt library (#2832) * Replace boost::format with fmt library This reduces the binary size quite significantly and doesn't require an addtitional object creation during exception throwing. * cmake: get fmt with FetchContent * cmake: always use fmt-header-only --- .github/workflows/test-lang-c++-ARM.yml | 2 +- .github/workflows/test-lang-c++.yml | 2 +- lang/c++/CMakeLists.txt | 13 ++++++++- lang/c++/api/Exception.hh | 8 +++--- lang/c++/api/Node.hh | 9 ++++++- lang/c++/api/NodeImpl.hh | 6 ++--- lang/c++/api/Stream.hh | 1 + lang/c++/api/Types.hh | 8 ++++++ lang/c++/api/Validator.hh | 8 ++---- lang/c++/impl/BinaryDecoder.cc | 8 +++--- lang/c++/impl/Compiler.cc | 35 ++++++++++++------------- lang/c++/impl/DataFile.cc | 12 ++++----- lang/c++/impl/FileStream.cc | 18 ++++++------- lang/c++/impl/Generic.cc | 6 ++--- lang/c++/impl/GenericDatum.cc | 2 +- lang/c++/impl/LogicalType.cc | 4 +-- lang/c++/impl/Node.cc | 9 +++---- lang/c++/impl/NodeImpl.cc | 4 +-- lang/c++/impl/ValidSchema.cc | 7 ++--- lang/c++/impl/Validator.cc | 5 ++-- lang/c++/impl/json/JsonDom.cc | 6 +---- lang/c++/impl/json/JsonIO.cc | 26 +++++------------- lang/c++/impl/json/JsonIO.hh | 2 +- lang/c++/impl/parsing/JsonCodec.cc | 6 ++--- 24 files changed, 103 insertions(+), 104 deletions(-) diff --git a/.github/workflows/test-lang-c++-ARM.yml b/.github/workflows/test-lang-c++-ARM.yml index d27b6a5c568..f101eaeb2b5 100644 --- a/.github/workflows/test-lang-c++-ARM.yml +++ b/.github/workflows/test-lang-c++-ARM.yml @@ -44,7 +44,7 @@ jobs: - name: Install dependencies run: | sudo apt-get update -q - sudo apt-get install -q -y gcc g++ libboost-all-dev cmake + sudo apt-get install -q -y gcc g++ libboost-all-dev libfmt-dev cmake - name: Build run: | diff --git a/.github/workflows/test-lang-c++.yml b/.github/workflows/test-lang-c++.yml index 5747a0da361..3035aa66c91 100644 --- a/.github/workflows/test-lang-c++.yml +++ b/.github/workflows/test-lang-c++.yml @@ -39,7 +39,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Dependencies - run: sudo apt update && sudo apt-get install -qqy cppcheck libboost-all-dev libsnappy-dev cmake + run: sudo apt update && sudo apt-get install -qqy cppcheck libboost-all-dev libsnappy-dev libfmt-dev cmake - name: Clean run: ./build.sh clean diff --git a/lang/c++/CMakeLists.txt b/lang/c++/CMakeLists.txt index f6520329afe..a3ff655d9e8 100644 --- a/lang/c++/CMakeLists.txt +++ b/lang/c++/CMakeLists.txt @@ -78,6 +78,16 @@ endif () find_package (Boost 1.38 REQUIRED COMPONENTS filesystem iostreams program_options regex system) +include(FetchContent) +FetchContent_Declare( + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG 10.2.1 + GIT_PROGRESS TRUE + USES_TERMINAL_DOWNLOAD TRUE +) +FetchContent_MakeAvailable(fmt) + find_package(Snappy) if (SNAPPY_FOUND) set(SNAPPY_PKG libsnappy) @@ -121,6 +131,7 @@ set_property (TARGET avrocpp add_library (avrocpp_s STATIC ${AVRO_SOURCE_FILES}) target_include_directories(avrocpp_s PRIVATE ${SNAPPY_INCLUDE_DIR}) +target_link_libraries(avrocpp_s fmt::fmt-header-only) set_property (TARGET avrocpp avrocpp_s APPEND PROPERTY COMPILE_DEFINITIONS AVRO_SOURCE) @@ -131,7 +142,7 @@ set_target_properties (avrocpp PROPERTIES set_target_properties (avrocpp_s PROPERTIES VERSION ${AVRO_VERSION_MAJOR}.${AVRO_VERSION_MINOR}.${AVRO_VERSION_PATCH}) -target_link_libraries (avrocpp ${Boost_LIBRARIES} ${SNAPPY_LIBRARIES}) +target_link_libraries (avrocpp ${Boost_LIBRARIES} ${SNAPPY_LIBRARIES} fmt::fmt-header-only) target_include_directories(avrocpp PRIVATE ${SNAPPY_INCLUDE_DIR}) add_executable (precompile test/precompile.cc) diff --git a/lang/c++/api/Exception.hh b/lang/c++/api/Exception.hh index 691869bed8c..91c7a556f70 100644 --- a/lang/c++/api/Exception.hh +++ b/lang/c++/api/Exception.hh @@ -20,19 +20,21 @@ #define avro_Exception_hh__ #include "Config.hh" -#include #include +#include namespace avro { /// Wrapper for std::runtime_error that provides convenience constructor -/// for boost::format objects +/// for formatted messages class AVRO_DECL Exception : public virtual std::runtime_error { public: explicit Exception(const std::string &msg) : std::runtime_error(msg) {} - explicit Exception(const boost::format &msg) : std::runtime_error(boost::str(msg)) {} + template + Exception(fmt::format_string fmt, Args&&... args) + : std::runtime_error(fmt::format(fmt, std::forward(args)...) ) {} }; } // namespace avro diff --git a/lang/c++/api/Node.hh b/lang/c++/api/Node.hh index 0b8f2269cd1..f4dff17397b 100644 --- a/lang/c++/api/Node.hh +++ b/lang/c++/api/Node.hh @@ -144,7 +144,7 @@ public: virtual size_t leaves() const = 0; virtual const NodePtr &leafAt(size_t index) const = 0; virtual const GenericDatum &defaultValueAt(size_t index) { - throw Exception(boost::format("No default value at: %1%") % index); + throw Exception("No default value at: {}", index); } void addName(const std::string &name) { @@ -216,4 +216,11 @@ inline std::ostream &operator<<(std::ostream &os, const avro::Node &n) { } } // namespace std +template <> struct fmt::formatter : fmt::formatter { + template + auto format(const avro::Name &n, FormatContext &ctx) { + return fmt::formatter::format(n.fullname(), ctx); + } +}; + #endif diff --git a/lang/c++/api/NodeImpl.hh b/lang/c++/api/NodeImpl.hh index 8372a3887cf..1845c6e5213 100644 --- a/lang/c++/api/NodeImpl.hh +++ b/lang/c++/api/NodeImpl.hh @@ -129,7 +129,7 @@ protected: void doAddName(const std::string &name) override { if (!nameIndex_.add(name, leafNameAttributes_.size())) { - throw Exception(boost::format("Cannot add duplicate name: %1%") % name); + throw Exception("Cannot add duplicate name: {}", name); } leafNameAttributes_.add(name); } @@ -280,7 +280,7 @@ public: NodePtr getNode() const { NodePtr node = actualNode_.lock(); if (!node) { - throw Exception(boost::format("Could not follow symbol %1%") % name()); + throw Exception("Could not follow symbol {}", name()); } return node; } @@ -345,7 +345,7 @@ public: NodeEnum(const HasName &name, const LeafNames &symbols) : NodeImplEnum(AVRO_ENUM, name, NoLeaves(), symbols, NoAttributes(), NoSize()) { for (size_t i = 0; i < leafNameAttributes_.size(); ++i) { if (!nameIndex_.add(leafNameAttributes_.get(i), i)) { - throw Exception(boost::format("Cannot add duplicate enum: %1%") % leafNameAttributes_.get(i)); + throw Exception("Cannot add duplicate enum: {}", leafNameAttributes_.get(i)); } } } diff --git a/lang/c++/api/Stream.hh b/lang/c++/api/Stream.hh index fe2c97ee2dd..81448d26d02 100644 --- a/lang/c++/api/Stream.hh +++ b/lang/c++/api/Stream.hh @@ -22,6 +22,7 @@ #include #include #include +#include #include "boost/utility.hpp" diff --git a/lang/c++/api/Types.hh b/lang/c++/api/Types.hh index e3296ae0d00..e7903d864a1 100644 --- a/lang/c++/api/Types.hh +++ b/lang/c++/api/Types.hh @@ -20,6 +20,7 @@ #define avro_Types_hh__ #include +#include #include "Config.hh" @@ -109,4 +110,11 @@ std::ostream &operator<<(std::ostream &os, const Null &null); } // namespace avro +template <> struct fmt::formatter : fmt::formatter { + template + auto format(avro::Type t, FormatContext &ctx) { + return fmt::formatter::format(avro::toString(t), ctx); + } +}; + #endif diff --git a/lang/c++/api/Validator.hh b/lang/c++/api/Validator.hh index ab5d068df0b..d7f6aecc1ad 100644 --- a/lang/c++/api/Validator.hh +++ b/lang/c++/api/Validator.hh @@ -88,18 +88,14 @@ public: void checkTypeExpected(Type type) { if (!typeIsExpected(type)) { - throw Exception( - boost::format("Type %1% does not match schema %2%") - % type % nextType_); + throw Exception("Type {} does not match schema {}", type, nextType_); } advance(); } void checkFixedSizeExpected(int size) { if (nextSizeExpected() != size) { - throw Exception( - boost::format("Wrong size for fixed, got %1%, expected %2%") - % size % nextSizeExpected()); + throw Exception("Wrong size for fixed, got {}, expected {}", size, nextSizeExpected()); } checkTypeExpected(AVRO_FIXED); } diff --git a/lang/c++/impl/BinaryDecoder.cc b/lang/c++/impl/BinaryDecoder.cc index 248b503342a..a970d605207 100644 --- a/lang/c++/impl/BinaryDecoder.cc +++ b/lang/c++/impl/BinaryDecoder.cc @@ -74,14 +74,13 @@ bool BinaryDecoder::decodeBool() { } else if (v == 1) { return true; } - throw Exception(boost::format("Invalid value for bool: %1%") % v); + throw Exception("Invalid value for bool: {}", v); } int32_t BinaryDecoder::decodeInt() { auto val = doDecodeLong(); if (val < INT32_MIN || val > INT32_MAX) { - throw Exception( - boost::format("Value out of range for Avro int: %1%") % val); + throw Exception("Value out of range for Avro int: {}", val); } return static_cast(val); } @@ -105,8 +104,7 @@ double BinaryDecoder::decodeDouble() { size_t BinaryDecoder::doDecodeLength() { ssize_t len = decodeInt(); if (len < 0) { - throw Exception( - boost::format("Cannot have negative length: %1%") % len); + throw Exception("Cannot have negative length: {}", len); } return len; } diff --git a/lang/c++/impl/Compiler.cc b/lang/c++/impl/Compiler.cc index f46de055e36..fb0fe32d50c 100644 --- a/lang/c++/impl/Compiler.cc +++ b/lang/c++/impl/Compiler.cc @@ -96,7 +96,7 @@ static NodePtr makeNode(const string &t, SymbolTable &st, const string &ns) { if (it != st.end()) { return NodePtr(new NodeSymbolic(asSingleAttribute(n), it->second)); } - throw Exception(boost::format("Unknown type: %1%") % n.fullname()); + throw Exception("Unknown type: {}", n); } /** Returns "true" if the field is in the container */ @@ -112,7 +112,7 @@ json::Object::const_iterator findField(const Entity &e, template void ensureType(const Entity &e, const string &name) { if (e.type() != json::type_traits::type()) { - throw Exception(boost::format("Json field \"%1%\" is not a %2%: %3%") % name % json::type_traits::name() % e.toString()); + throw Exception("Json field \"{}\" is not a {}: {}", name, json::type_traits::name(), e.toString()); } } @@ -158,9 +158,9 @@ struct Field { static void assertType(const Entity &e, EntityType et) { if (e.type() != et) { - throw Exception(boost::format("Unexpected type for default value: " - "Expected %1%, but found %2% in line %3%") - % json::typeToString(et) % json::typeToString(e.type()) % e.line()); + throw Exception( + "Unexpected type for default value: Expected {}, but found {} in line {}", + json::typeToString(et), json::typeToString(e.type()), e.line()); } } @@ -219,9 +219,9 @@ static GenericDatum makeGenericDatum(NodePtr n, for (size_t i = 0; i < n->leaves(); ++i) { auto it = v.find(n->nameAt(i)); if (it == v.end()) { - throw Exception(boost::format( - "No value found in default for %1%") - % n->nameAt(i)); + throw Exception( + "No value found in default for {}", + n->nameAt(i)); } result.setFieldAt(i, makeGenericDatum(n->leafAt(i), it->second, st)); @@ -259,7 +259,7 @@ static GenericDatum makeGenericDatum(NodePtr n, case AVRO_FIXED: assertType(e, json::EntityType::String); return GenericDatum(n, GenericFixed(n, toBin(e.bytesValue()))); - default: throw Exception(boost::format("Unknown type: %1%") % t); + default: throw Exception("Unknown type: {}", t); } } @@ -380,7 +380,7 @@ static NodePtr makeEnumNode(const Entity &e, concepts::MultiAttribute symbols; for (const auto &it : v) { if (it.type() != json::EntityType::String) { - throw Exception(boost::format("Enum symbol not a string: %1%") % it.toString()); + throw Exception("Enum symbol not a string: {}", it.toString()); } symbols.add(it.stringValue()); } @@ -395,7 +395,7 @@ static NodePtr makeFixedNode(const Entity &e, const Name &name, const Object &m) { int v = static_cast(getLongField(e, m, "size")); if (v <= 0) { - throw Exception(boost::format("Size for fixed is not positive: %1%") % e.toString()); + throw Exception("Size for fixed is not positive: {}", e.toString()); } NodePtr node = NodePtr(new NodeFixed(asSingleAttribute(name), asSingleAttribute(v))); @@ -438,9 +438,9 @@ static Name getName(const Entity &e, const Object &m, const string &ns) { auto it = m.find("namespace"); if (it != m.end()) { if (it->second.type() != json::type_traits::type()) { - throw Exception(boost::format( - "Json field \"%1%\" is not a %2%: %3%") - % "namespace" % json::type_traits::name() % it->second.toString()); + throw Exception( + "Json field \"namespace\" is not a string: {}", + it->second.toString()); } result = Name(name, it->second.stringValue()); } else { @@ -500,8 +500,7 @@ static NodePtr makeNode(const Entity &e, const Object &m, return result; } - throw Exception(boost::format("Unknown type definition: %1%") - % e.toString()); + throw Exception("Unknown type definition: %1%", e.toString()); } static NodePtr makeNode(const Entity &e, const Array &m, @@ -518,13 +517,13 @@ static NodePtr makeNode(const json::Entity &e, SymbolTable &st, const string &ns case json::EntityType::String: return makeNode(e.stringValue(), st, ns); case json::EntityType::Obj: return makeNode(e, e.objectValue(), st, ns); case json::EntityType::Arr: return makeNode(e, e.arrayValue(), st, ns); - default: throw Exception(boost::format("Invalid Avro type: %1%") % e.toString()); + default: throw Exception("Invalid Avro type: {}", e.toString()); } } json::Object::const_iterator findField(const Entity &e, const Object &m, const string &fieldName) { auto it = m.find(fieldName); if (it == m.end()) { - throw Exception(boost::format("Missing Json field \"%1%\": %2%") % fieldName % e.toString()); + throw Exception("Missing Json field \"{}\": {}", fieldName, e.toString()); } else { return it; } diff --git a/lang/c++/impl/DataFile.cc b/lang/c++/impl/DataFile.cc index e58bc4f99b4..eab417f80bc 100644 --- a/lang/c++/impl/DataFile.cc +++ b/lang/c++/impl/DataFile.cc @@ -93,9 +93,9 @@ DataFileWriterBase::DataFileWriterBase(std::unique_ptr outputStrea void DataFileWriterBase::init(const ValidSchema &schema, size_t syncInterval, const Codec &codec) { if (syncInterval < minSyncInterval || syncInterval > maxSyncInterval) { - throw Exception(boost::format("Invalid sync interval: %1%. " - "Should be between %2% and %3%") - % syncInterval % minSyncInterval % maxSyncInterval); + throw Exception( + "Invalid sync interval: {}. Should be between {} and {}", + syncInterval, minSyncInterval, maxSyncInterval); } setMetadata(AVRO_CODEC_KEY, AVRO_NULL_CODEC); @@ -108,7 +108,7 @@ void DataFileWriterBase::init(const ValidSchema &schema, size_t syncInterval, co setMetadata(AVRO_CODEC_KEY, AVRO_SNAPPY_CODEC); #endif } else { - throw Exception(boost::format("Unknown codec: %1%") % codec); + throw Exception("Unknown codec: {}", int(codec)); } setMetadata(AVRO_SCHEMA_KEY, schema.toJson(false)); @@ -412,8 +412,8 @@ void DataFileReaderBase::readDataBlock() { uint32_t c = crc(); if (checksum != c) { throw Exception( - boost::format("Checksum did not match for Snappy compression: Expected: %1%, computed: %2%") % checksum - % c); + "Checksum did not match for Snappy compression: Expected: {}, computed: {}", + checksum, c); } os_.reset(new boost::iostreams::filtering_istream()); os_->push( diff --git a/lang/c++/impl/FileStream.cc b/lang/c++/impl/FileStream.cc index 17926af9d7d..ccfb441514c 100644 --- a/lang/c++/impl/FileStream.cc +++ b/lang/c++/impl/FileStream.cc @@ -51,7 +51,7 @@ struct FileBufferCopyIn : public BufferCopyIn { HANDLE h_; explicit FileBufferCopyIn(const char *filename) : h_(::CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) { if (h_ == INVALID_HANDLE_VALUE) { - throw Exception(boost::format("Cannot open file: %1%") % ::GetLastError()); + throw Exception("Cannot open file: {}", ::GetLastError()); } } @@ -61,14 +61,14 @@ struct FileBufferCopyIn : public BufferCopyIn { void seek(size_t len) override { if (::SetFilePointer(h_, len, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR) { - throw Exception(boost::format("Cannot skip file: %1%") % ::GetLastError()); + throw Exception("Cannot skip file: {}", ::GetLastError()); } } bool read(uint8_t *b, size_t toRead, size_t &actual) override { DWORD dw = 0; if (!::ReadFile(h_, b, toRead, &dw, NULL)) { - throw Exception(boost::format("Cannot read file: %1%") % ::GetLastError()); + throw Exception("Cannot read file: {}", ::GetLastError()); } actual = static_cast(dw); return actual != 0; @@ -78,7 +78,7 @@ struct FileBufferCopyIn : public BufferCopyIn { explicit FileBufferCopyIn(const char *filename) : fd_(open(filename, O_RDONLY | O_BINARY)) { if (fd_ < 0) { - throw Exception(boost::format("Cannot open file: %1%") % ::strerror(errno)); + throw Exception("Cannot open file: {}", strerror(errno)); } } @@ -89,7 +89,7 @@ struct FileBufferCopyIn : public BufferCopyIn { void seek(size_t len) final { off_t r = ::lseek(fd_, len, SEEK_CUR); if (r == static_cast(-1)) { - throw Exception(boost::format("Cannot skip file: %1%") % strerror(errno)); + throw Exception("Cannot skip file: {}", strerror(errno)); } } @@ -234,7 +234,7 @@ struct FileBufferCopyOut : public BufferCopyOut { HANDLE h_; explicit FileBufferCopyOut(const char *filename) : h_(::CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) { if (h_ == INVALID_HANDLE_VALUE) { - throw Exception(boost::format("Cannot open file: %1%") % ::GetLastError()); + throw Exception("Cannot open file: {}", ::GetLastError()); } } @@ -246,7 +246,7 @@ struct FileBufferCopyOut : public BufferCopyOut { while (len > 0) { DWORD dw = 0; if (!::WriteFile(h_, b, len, &dw, NULL)) { - throw Exception(boost::format("Cannot read file: %1%") % ::GetLastError()); + throw Exception("Cannot read file: {}", ::GetLastError()); } b += dw; len -= dw; @@ -258,7 +258,7 @@ struct FileBufferCopyOut : public BufferCopyOut { explicit FileBufferCopyOut(const char *filename) : fd_(::open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644)) { if (fd_ < 0) { - throw Exception(boost::format("Cannot open file: %1%") % ::strerror(errno)); + throw Exception("Cannot open file: {}", ::strerror(errno)); } } @@ -268,7 +268,7 @@ struct FileBufferCopyOut : public BufferCopyOut { void write(const uint8_t *b, size_t len) final { if (::write(fd_, b, len) < 0) { - throw Exception(boost::format("Cannot write file: %1%") % ::strerror(errno)); + throw Exception("Cannot write file: {}", ::strerror(errno)); } } #endif diff --git a/lang/c++/impl/Generic.cc b/lang/c++/impl/Generic.cc index 6e0436ae344..1535c604be7 100644 --- a/lang/c++/impl/Generic.cc +++ b/lang/c++/impl/Generic.cc @@ -29,7 +29,7 @@ typedef vector bytes; void GenericContainer::assertType(const NodePtr &schema, Type type) { if (schema->type() != type) { - throw Exception(boost::format("Schema type %1 expected %2") % toString(schema->type()) % toString(type)); + throw Exception("Schema type {} expected {}", schema->type(), type); } } @@ -129,7 +129,7 @@ void GenericReader::read(GenericDatum &datum, Decoder &d, bool isResolving) { } } break; default: - throw Exception(boost::format("Unknown schema type %1%") % toString(datum.type())); + throw Exception("Unknown schema type {}", datum.type()); } } @@ -217,7 +217,7 @@ void GenericWriter::write(const GenericDatum &datum, Encoder &e) { e.mapEnd(); } break; default: - throw Exception(boost::format("Unknown schema type %1%") % toString(datum.type())); + throw Exception("Unknown schema type {}", datum.type()); } } diff --git a/lang/c++/impl/GenericDatum.cc b/lang/c++/impl/GenericDatum.cc index 7b2bf93bca9..49700a927f5 100644 --- a/lang/c++/impl/GenericDatum.cc +++ b/lang/c++/impl/GenericDatum.cc @@ -83,7 +83,7 @@ void GenericDatum::init(const NodePtr &schema) { value_ = GenericUnion(sc); break; default: - throw Exception(boost::format("Unknown schema type %1%") % toString(type_)); + throw Exception("Unknown schema type {}", toString(type_)); } } diff --git a/lang/c++/impl/LogicalType.cc b/lang/c++/impl/LogicalType.cc index 1aa24bf20de..988eed56dde 100644 --- a/lang/c++/impl/LogicalType.cc +++ b/lang/c++/impl/LogicalType.cc @@ -33,7 +33,7 @@ void LogicalType::setPrecision(int precision) { throw Exception("Only logical type DECIMAL can have precision"); } if (precision <= 0) { - throw Exception(boost::format("Precision cannot be: %1%") % precision); + throw Exception("Precision cannot be: {}", precision); } precision_ = precision; } @@ -43,7 +43,7 @@ void LogicalType::setScale(int scale) { throw Exception("Only logical type DECIMAL can have scale"); } if (scale < 0) { - throw Exception(boost::format("Scale cannot be: %1%") % scale); + throw Exception("Scale cannot be: {}", scale); } scale_ = scale; } diff --git a/lang/c++/impl/Node.cc b/lang/c++/impl/Node.cc index 56ad1044beb..0c97a90256e 100644 --- a/lang/c++/impl/Node.cc +++ b/lang/c++/impl/Node.cc @@ -149,11 +149,10 @@ void Node::setLogicalType(LogicalType logicalType) { long maxPrecision = floor(log10(2.0) * (8.0 * fixedSize() - 1)); if (logicalType.precision() > maxPrecision) { throw Exception( - boost::format( - "DECIMAL precision %1% is too large for the " - "FIXED type of size %2%, precision cannot be " - "larger than %3%") - % logicalType.precision() % fixedSize() % maxPrecision); + "DECIMAL precision {} is too large for the " + "FIXED type of size {}, precision cannot be " + "larger than {}", + logicalType.precision(), fixedSize(), maxPrecision); } } if (logicalType.scale() > logicalType.precision()) { diff --git a/lang/c++/impl/NodeImpl.cc b/lang/c++/impl/NodeImpl.cc index 3d1f80a955c..bcfc28947bc 100644 --- a/lang/c++/impl/NodeImpl.cc +++ b/lang/c++/impl/NodeImpl.cc @@ -482,13 +482,13 @@ NodeRecord::NodeRecord(const HasName &name, const HasDoc &doc, const MultiLeaves for (size_t i = 0; i < leafNameAttributes_.size(); ++i) { if (!nameIndex_.add(leafNameAttributes_.get(i), i)) { - throw Exception(boost::format("Cannot add duplicate field: %1%") % leafNameAttributes_.get(i)); + throw Exception("Cannot add duplicate field: {}", leafNameAttributes_.get(i)); } if (!fieldsAliases_.empty()) { for (const auto &alias : fieldsAliases_[i]) { if (!nameIndex_.add(alias, i)) { - throw Exception(boost::format("Cannot add duplicate field: %1%") % alias); + throw Exception("Cannot add duplicate field: {}", alias); } } } diff --git a/lang/c++/impl/ValidSchema.cc b/lang/c++/impl/ValidSchema.cc index 1356d844897..d99d7e24198 100644 --- a/lang/c++/impl/ValidSchema.cc +++ b/lang/c++/impl/ValidSchema.cc @@ -16,7 +16,6 @@ * limitations under the License. */ -#include #include #include #include @@ -25,7 +24,6 @@ #include "Schema.hh" #include "ValidSchema.hh" -using boost::format; using std::make_pair; using std::ostringstream; using std::shared_ptr; @@ -37,8 +35,7 @@ using SymbolMap = std::map; static bool validate(const NodePtr &node, SymbolMap &symbolMap) { if (!node->isValid()) { - throw Exception(format("Schema is invalid, due to bad node of type %1%") - % node->type()); + throw Exception("Schema is invalid, due to bad node of type {}", node->type()); } if (node->hasName()) { @@ -51,7 +48,7 @@ static bool validate(const NodePtr &node, SymbolMap &symbolMap) { if (node->type() == AVRO_SYMBOLIC) { if (!found) { - throw Exception(format("Symbolic name \"%1%\" is unknown") % node->name()); + throw Exception("Symbolic name \"{}\" is unknown", node->name()); } shared_ptr symNode = diff --git a/lang/c++/impl/Validator.cc b/lang/c++/impl/Validator.cc index 3cd4e9e499e..d4cda11e269 100644 --- a/lang/c++/impl/Validator.cc +++ b/lang/c++/impl/Validator.cc @@ -105,9 +105,8 @@ void Validator::unionAdvance() { setupOperation(node->leafAt(static_cast(count_))); } else { throw Exception( - boost::format("Union selection out of range, got %1%," - " expecting 0-%2%") - % count_ % (node->leaves() - 1)); + "Union selection out of range, got {}, expecting 0-{}", + count_, node->leaves() - 1); } } } diff --git a/lang/c++/impl/json/JsonDom.cc b/lang/c++/impl/json/JsonDom.cc index 5bffda2559c..c2696d827ad 100644 --- a/lang/c++/impl/json/JsonDom.cc +++ b/lang/c++/impl/json/JsonDom.cc @@ -25,9 +25,6 @@ #include "JsonIO.hh" #include "Stream.hh" -using boost::format; -using std::string; - namespace avro { namespace json { const char *typeToString(EntityType t) { @@ -142,8 +139,7 @@ void writeEntity(JsonGenerator &g, const Entity &n) { void Entity::ensureType(EntityType type) const { if (type_ != type) { - format msg = format("Invalid type. Expected \"%1%\" actual %2%") % typeToString(type) % typeToString(type_); - throw Exception(msg); + throw Exception("Invalid type. Expected \"{}\" actual {}", typeToString(type), typeToString(type_)); } } diff --git a/lang/c++/impl/json/JsonIO.cc b/lang/c++/impl/json/JsonIO.cc index d30d1fded49..dad12c5549a 100644 --- a/lang/c++/impl/json/JsonIO.cc +++ b/lang/c++/impl/json/JsonIO.cc @@ -339,7 +339,7 @@ string JsonParser::decodeString(const string &s, bool binary) { } else if (c >= 'A' && c <= 'F') { n += c - 'A' + 10; } else { - throw Exception(boost::format( "Invalid hex character: %1%") % c); + throw Exception("Invalid hex character: {}", c); } } return n; @@ -375,9 +375,7 @@ string JsonParser::decodeString(const string &s, bool binary) { uint32_t n = unicodeParse(); if (binary) { if (n > 0xff) { - throw Exception(boost::format( - "Invalid byte for binary: %1%%2%") - % ch % string(startSeq, ++it)); + throw Exception("Invalid byte for binary: {}{}", ch, string(startSeq, ++it)); } else { result.push_back(n); continue; @@ -386,27 +384,19 @@ string JsonParser::decodeString(const string &s, bool binary) { if (n >= 0xd800 && n < 0xdc00) { ch = readNextByte(); if (ch != '\\') { - throw Exception(boost::format( - "Invalid unicode sequence: %1%") - % string(startSeq, it)); + throw Exception("Invalid unicode sequence: {}", string(startSeq, it)); } ch = readNextByte(); if (ch != 'u' && ch != 'U') { - throw Exception(boost::format( - "Invalid unicode sequence: %1%") - % string(startSeq, it)); + throw Exception("Invalid unicode sequence: {}", string(startSeq, it)); } uint32_t m = unicodeParse(); if (m < 0xdc00 || m > 0xdfff) { - throw Exception(boost::format( - "Invalid unicode sequence: %1%") - % string(startSeq, it)); + throw Exception("Invalid unicode sequence: {}", string(startSeq, it)); } n = 0x10000 + (((n - 0xd800) << 10) | (m - 0xdc00)); } else if (n >= 0xdc00 && n < 0xdfff) { - throw Exception(boost::format( - "Invalid unicode sequence: %1%") - % string(startSeq, it)); + throw Exception("Invalid unicode sequence: {}", string(startSeq, it)); } if (n < 0x80) { result.push_back(n); @@ -423,9 +413,7 @@ string JsonParser::decodeString(const string &s, bool binary) { result.push_back(((n >> 6) & 0x3f) | 0x80); result.push_back((n & 0x3f) | 0x80); } else { - throw Exception(boost::format( - "Invalid unicode value: %1%%2%") - % n % string(startSeq, ++it)); + throw Exception("Invalid unicode value: {}{}", n, string(startSeq, ++it)); } } continue; diff --git a/lang/c++/impl/json/JsonIO.hh b/lang/c++/impl/json/JsonIO.hh index 447c0b0df32..4e3b2c115c8 100644 --- a/lang/c++/impl/json/JsonIO.hh +++ b/lang/c++/impl/json/JsonIO.hh @@ -277,7 +277,7 @@ class AVRO_DECL JsonGenerator { escapeUnicode16(((c >> 10) & 0x3ff) | 0xd800); escapeUnicode16((c & 0x3ff) | 0xdc00); } else { - throw Exception(boost::format("Invalid code-point: %1%") % c); + throw Exception("Invalid code-point: {}", c); } } void doEncodeString(const char *b, size_t len, bool binary) { diff --git a/lang/c++/impl/parsing/JsonCodec.cc b/lang/c++/impl/parsing/JsonCodec.cc index a33fd39fd73..84b366606f9 100644 --- a/lang/c++/impl/parsing/JsonCodec.cc +++ b/lang/c++/impl/parsing/JsonCodec.cc @@ -162,8 +162,7 @@ class JsonDecoderHandler { case Symbol::Kind::Field: expectToken(in_, JsonParser::Token::String); if (s.extra() != in_.stringValue()) { - throw Exception(boost::format("Incorrect field: expected \"%1%\" but got \"%2%\".") % - s.extra() % in_.stringValue()); + throw Exception(R"(Incorrect field: expected "{}" but got "{}".)", s.extra(), in_.stringValue()); } break; default: @@ -241,8 +240,7 @@ int32_t JsonDecoder

::decodeInt() { expect(JsonParser::Token::Long); int64_t result = in_.longValue(); if (result < INT32_MIN || result > INT32_MAX) { - throw Exception(boost::format("Value out of range for Avro int: %1%") - % result); + throw Exception("Value out of range for Avro int: {}", result); } return static_cast(result); }