From: Andrei Pavel Date: Wed, 26 Apr 2023 12:44:33 +0000 (+0300) Subject: [#2658] add BigIntElement X-Git-Tag: Kea-2.3.8~133 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e79feea5f60d942466e1ad41d9c58504949f8cfa;p=thirdparty%2Fkea.git [#2658] add BigIntElement BigIntElement is modelled as an int128_t, following the precedent of signed integer of int64_t from IntElement. --- diff --git a/src/lib/cc/data.cc b/src/lib/cc/data.cc index 2df39abf48..2f69f27a8c 100644 --- a/src/lib/cc/data.cc +++ b/src/lib/cc/data.cc @@ -101,6 +101,11 @@ Element::setValue(const long long int) { return (false); } +bool +Element::setValue(isc::util::int128_t const&) { + return (false); +} + bool Element::setValue(const double) { return (false); @@ -247,6 +252,11 @@ Element::create(const long long int i, const Position& pos) { return (ElementPtr(new IntElement(static_cast(i), pos))); } +ElementPtr +Element::create(const isc::util::int128_t& i, const Position& pos) { + return (ElementPtr(new BigIntElement(i, pos))); +} + ElementPtr Element::create(const int i, const Position& pos) { return (create(static_cast(i), pos)); @@ -622,6 +632,8 @@ Element::typeToName(Element::types type) { switch (type) { case Element::integer: return (std::string("integer")); + case Element::bigint: + return (std::string("bigint")); case Element::real: return (std::string("real")); case Element::boolean: @@ -645,6 +657,8 @@ Element::types Element::nameToType(const std::string& type_name) { if (type_name == "integer") { return (Element::integer); + } else if (type_name == "bigint") { + return (Element::bigint); } else if (type_name == "real") { return (Element::real); } else if (type_name == "boolean") { @@ -801,6 +815,11 @@ IntElement::toJSON(std::ostream& ss) const { ss << intValue(); } +void +BigIntElement::toJSON(std::ostream& ss) const { + ss << bigIntValue(); +} + void DoubleElement::toJSON(std::ostream& ss) const { // The default output for doubles nicely drops off trailing @@ -981,8 +1000,24 @@ MapElement::find(const std::string& id, ConstElementPtr& t) const { bool IntElement::equals(const Element& other) const { - return (other.getType() == Element::integer) && - (i == other.intValue()); + // Let's not be very picky with constraining the integer types to be the + // same. Equality is sometimes checked from high-up in the Element hierarcy. + // That is a context which, most of the time, does not have information on + // the type of integers stored on Elements lower in the hierarchy. So it + // would be difficult to differentiate between the integer types. + return (other.getType() == Element::integer && i == other.intValue()) || + (other.getType() == Element::bigint && i == other.bigIntValue()); +} + +bool +BigIntElement::equals(const Element& other) const { + // Let's not be very picky with constraining the integer types to be the + // same. Equality is sometimes checked from high-up in the Element hierarcy. + // That is a context which, most of the time, does not have information on + // the type of integers stored on Elements lower in the hierarchy. So it + // would be difficult to differentiate between the integer types. + return (other.getType() == Element::bigint && i_ == other.bigIntValue()) || + (other.getType() == Element::integer && i_ == other.intValue()); } bool diff --git a/src/lib/cc/data.h b/src/lib/cc/data.h index 916ad3f106..6e29f2fbf2 100644 --- a/src/lib/cc/data.h +++ b/src/lib/cc/data.h @@ -7,6 +7,8 @@ #ifndef ISC_DATA_H #define ISC_DATA_H 1 +#include + #include #include #include @@ -126,9 +128,25 @@ public: return (position); } - // any is a special type used in list specifications, specifying - // that the elements can be of any type - enum types { integer, real, boolean, null, string, list, map, any }; + /// @brief The types that an Element can hold + /// + /// Some of these types need to match their associated integer from the + /// parameter_data_type database table, so let the enums be explicitly + /// mapped to integers, to reduce the chance of messing up. + /// + /// any is a special type used in list specifications, specifying that the + /// elements can be of any type. + enum types { + integer = 0, + real = 1, + boolean = 2, + null = 3, + string = 4, + bigint = 5, + list = 6, + map = 7, + any = 8, + }; private: // technically the type could be omitted; is it useful? @@ -214,6 +232,9 @@ public: //@{ virtual int64_t intValue() const { throwTypeError("intValue() called on non-integer Element"); }; + virtual isc::util::int128_t bigIntValue() const { + throwTypeError("bigIntValue() called on non-big-integer Element"); + } virtual double doubleValue() const { throwTypeError("doubleValue() called on non-double Element"); }; virtual bool boolValue() const @@ -258,6 +279,7 @@ public: /// long long int, long int and int. //@{ virtual bool setValue(const long long int v); + virtual bool setValue(const isc::util::int128_t& v); bool setValue(const long int i) { return (setValue(static_cast(i))); }; bool setValue(const int i) { return (setValue(static_cast(i))); }; virtual bool setValue(const double v); @@ -376,6 +398,8 @@ public: static ElementPtr create(const Position& pos = ZERO_POSITION()); static ElementPtr create(const long long int i, const Position& pos = ZERO_POSITION()); + static ElementPtr create(const isc::util::int128_t& i, + const Position& pos = ZERO_POSITION()); static ElementPtr create(const int i, const Position& pos = ZERO_POSITION()); static ElementPtr create(const long int i, @@ -601,6 +625,45 @@ public: bool equals(const Element& other) const; }; +/// @brief Wrapper over int128_t +class BigIntElement : public Element { + using int128_t = isc::util::int128_t; + using Element::getValue; + using Element::setValue; + +public: + /// @brief Constructor + BigIntElement(const int128_t& v, const Position& pos = ZERO_POSITION()) + : Element(bigint, pos), i_(v) { + } + + /// @brief Retrieve the underlying big integer value. + /// + /// @return the underlying value + int128_t bigIntValue() const override { + return (i_); + } + + /// @brief Sets the underlying big integer value. + /// + /// @return true for no reason + bool setValue(const int128_t& v) override { + i_ = v; + return (true); + } + + /// @brief Converts the Element to JSON format and appends it to the given + /// stringstream. + void toJSON(std::ostream& ss) const override; + + /// @brief Checks whether the other Element has the same type and value. + bool equals(const Element& other) const override; + +private: + /// @brief the underlying stored value + int128_t i_; +}; + class DoubleElement : public Element { double d; diff --git a/src/lib/cc/tests/data_unittests.cc b/src/lib/cc/tests/data_unittests.cc index 5aed9a4d78..196b565ff2 100644 --- a/src/lib/cc/tests/data_unittests.cc +++ b/src/lib/cc/tests/data_unittests.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2022 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2009-2023 Internet Systems Consortium, Inc. ("ISC") // // 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 @@ -55,6 +55,7 @@ TEST(Element, type) { TEST(Element, TypeNameConversion) { EXPECT_EQ(Element::integer, Element::nameToType("integer")); + EXPECT_EQ(Element::bigint, Element::nameToType("bigint")); EXPECT_EQ(Element::real, Element::nameToType("real")); EXPECT_EQ(Element::boolean, Element::nameToType("boolean")); EXPECT_EQ(Element::string, Element::nameToType("string")); @@ -65,6 +66,7 @@ TEST(Element, TypeNameConversion) { EXPECT_THROW(Element::nameToType("somethingunknown"), TypeError); EXPECT_EQ("integer", Element::typeToName(Element::integer)); + EXPECT_EQ("bigint", Element::typeToName(Element::bigint)); EXPECT_EQ("real", Element::typeToName(Element::real)); EXPECT_EQ("boolean", Element::typeToName(Element::boolean)); EXPECT_EQ("string", Element::typeToName(Element::string));