]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2658] add BigIntElement
authorAndrei Pavel <andrei@isc.org>
Wed, 26 Apr 2023 12:44:33 +0000 (15:44 +0300)
committerAndrei Pavel <andrei@isc.org>
Wed, 17 May 2023 16:09:38 +0000 (19:09 +0300)
BigIntElement is modelled as an int128_t, following the precedent of
signed integer of int64_t from IntElement.

src/lib/cc/data.cc
src/lib/cc/data.h
src/lib/cc/tests/data_unittests.cc

index 2df39abf4875606641f28492499f59be9f377529..2f69f27a8cbd6b7dd943bcb90e292c4e31276508 100644 (file)
@@ -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<int64_t>(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<long long int>(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
index 916ad3f10676e8cfbb21a97a1bc2f8707ca0ca53..6e29f2fbf202fb1485c3166b1aa1b51a36982b37 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef ISC_DATA_H
 #define ISC_DATA_H 1
 
+#include <util/bigints.h>
+
 #include <iostream>
 #include <map>
 #include <stdexcept>
@@ -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<long long int>(i))); };
     bool setValue(const int i) { return (setValue(static_cast<long long int>(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;
 
index 5aed9a4d78b1bed51164b6b75f3d2a162e215b16..196b565ff22595cbe6e9f347170cd8b0c2c8d00f 100644 (file)
@@ -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));