Browse Source

updated doxy of merge()
made number parser use strol/d
added 'support' for numbers of the form '.1'
IntElement now contains long int instead of int



git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac172@2345 e5f2f494-b856-4b98-b285-d166d9295462

Jelte Jansen 15 years ago
parent
commit
fb3488a5b0
4 changed files with 50 additions and 82 deletions
  1. 29 66
      src/lib/cc/data.cc
  2. 16 11
      src/lib/cc/data.h
  3. 2 2
      src/lib/cc/data_unittests.cc
  4. 3 3
      src/lib/cc/session.cc

+ 29 - 66
src/lib/cc/data.cc

@@ -63,7 +63,7 @@ Element::toWire(std::ostream& ss)
 // installed files we define the methods here.
 //
 bool
-Element::getValue(int& t UNUSED_PARAM) {
+Element::getValue(long int& t UNUSED_PARAM) {
     return false;
 }
 
@@ -93,7 +93,7 @@ Element::getValue(std::map<std::string, ElementPtr>& t UNUSED_PARAM) {
 }
 
 bool
-Element::setValue(const int v UNUSED_PARAM) {
+Element::setValue(const long int v UNUSED_PARAM) {
     return false;
 }
 
@@ -209,7 +209,7 @@ Element::create() {
 }
 
 ElementPtr
-Element::create(const int i) {
+Element::create(const long int i) {
     return ElementPtr(new IntElement(i));
 }
 
@@ -344,19 +344,15 @@ word_from_stringstream(std::istream &in, int& pos) {
     return ss.str();
 }
 
-inline int
-count_chars_i(int i) {
-    int result = 1;
-    if (i < 0) {
-        i = -i;
-        // account for the '-' symbol
-        result += 1;
-    }
-    while (i > 10) {
-        ++result;
-        i = i / 10;
+static std::string
+number_from_stringstream(std::istream &in, int& pos) {
+    std::stringstream ss;
+    while (isdigit(in.peek()) || in.peek() == '+' || in.peek() == '-' ||
+           in.peek() == '.' || in.peek() == 'e' || in.peek() == 'E') {
+        ss << (char) in.get();
     }
-    return result;
+    pos += ss.str().size();
+    return ss.str();
 }
 
 // Should we change from IntElement and DoubleElement to NumberElement
@@ -364,61 +360,30 @@ count_chars_i(int i) {
 // value is larger than an int can handle)
 ElementPtr
 from_stringstream_number(std::istream &in, int &pos) {
-    int i = 0;
+    long int i = 0;
     double d = 0.0;
     bool is_double = false;
+    char *endptr;
 
-    in >> i;
-    pos += count_chars_i(i);
-    if (in.fail()) {
-        isc_throw(JSONError, "Bad integer or overflow");
-    }
-    if (in.peek() == '.') {
-        int d_i = 0;
+    std::string number = number_from_stringstream(in, pos);
+
+    i = strtol(number.c_str(), &endptr, 10);
+    if (*endptr != '\0') {
+        d = strtod(number.c_str(), &endptr);
         is_double = true;
-        in.get();
-        pos++;
-        in >> d_i;
-        if (in.fail()) {
-            isc_throw(JSONError, "Bad real or overflow");
-        }
-        d = (double)d_i / 10;
-        while (d > 1.0) {
-            d = d / 10;
-        }
-        if (i < 0) {
-            d = - d;
-        }
-        d += i;
-        pos += count_chars_i(d_i);
-    }
-    if (in.peek() == 'e' || in.peek() == 'E') {
-        int e;
-        double p;
-        in.get();
-        pos++;
-        in >> e;
-        if (in.fail()) {
-            isc_throw(JSONError, "Bad exponent or overflow");
-        }
-        pos += count_chars_i(e);
-        p = pow(10, e);
-        if (p == HUGE_VAL) {
-            isc_throw(JSONError, "Bad exponent or overflow");
-        }
-        if (is_double) {
-            d = d * p;
+        if (*endptr != '\0') {
+            isc_throw(JSONError, std::string("Bad number: ") + number);
         } else {
-            if (p > 1.0) {
-                i = i * p;
-            } else {
-                // negative exponent, so type becomes a double
-                is_double = true;
-                d = i * p;
+            if (d == HUGE_VAL) {
+                isc_throw(JSONError, std::string("Number overflow: ") + number);
             }
         }
+    } else {
+        if (i == LONG_MAX || i == LONG_MIN) {
+            isc_throw(JSONError, std::string("Number overflow: ") + number);
+        }
     }
-
+    
     if (is_double) {
         return Element::create(d);
     } else {
@@ -595,11 +560,9 @@ Element::fromJSON(std::istream &in, const std::string& file, int& line, int& pos
             case '9':
             case '0':
             case '-':
-                in.putback(c);
-                element = from_stringstream_number(in, pos);
-                el_read = true;
-                break;
             case '+':
+            case '.':
+                in.putback(c);
                 element = from_stringstream_number(in, pos);
                 el_read = true;
                 break;

+ 16 - 11
src/lib/cc/data.h

@@ -126,7 +126,7 @@ public:
     /// If you want an exception-safe getter method, use
     /// getValue() below
     //@{
-    virtual int intValue() { isc_throw(TypeError, "intValue() called on non-integer Element"); };
+    virtual long int intValue() { isc_throw(TypeError, "intValue() called on non-integer Element"); };
     virtual double doubleValue() { isc_throw(TypeError, "doubleValue() called on non-double Element"); };
     virtual bool boolValue() { isc_throw(TypeError, "boolValue() called on non-Bool Element"); };
     virtual std::string stringValue() { isc_throw(TypeError, "stringValue() called on non-string Element"); };
@@ -143,7 +143,7 @@ public:
     /// data to the given reference and returning true
     ///
     //@{
-    virtual bool getValue(int& t);
+    virtual bool getValue(long int& t);
     virtual bool getValue(double& t);
     virtual bool getValue(bool& t);
     virtual bool getValue(std::string& t);
@@ -159,7 +159,7 @@ public:
     /// is of the correct type
     ///
     //@{
-    virtual bool setValue(const int v);
+    virtual bool setValue(const long int v);
     virtual bool setValue(const double v);
     virtual bool setValue(const bool t);
     virtual bool setValue(const std::string& v);
@@ -264,7 +264,8 @@ public:
     /// represents an empty value, and is created with Element::create())
     //@{
     static ElementPtr create();
-    static ElementPtr create(const int i);
+    static ElementPtr create(const long int i);
+    static ElementPtr create(const int i) { return create(static_cast<long int>(i)); };
     static ElementPtr create(const double d);
     static ElementPtr create(const bool b);
     static ElementPtr create(const std::string& s);
@@ -360,15 +361,15 @@ public:
 };
 
 class IntElement : public Element {
-    int i;
+    long int i;
 
 public:
-    IntElement(int v) : Element(integer), i(v) { };
-    int intValue() { return i; }
+    IntElement(long int v) : Element(integer), i(v) { };
+    long int intValue() { return i; }
     using Element::getValue;
-    bool getValue(int& t) { t = i; return true; };
+    bool getValue(long int& t) { t = i; return true; };
     using Element::setValue;
-    bool setValue(const int v) { i = v; return true; };
+    bool setValue(const long int v) { i = v; return true; };
     void toJSON(std::ostream& ss);
     bool equals(ElementPtr other);
 };
@@ -499,8 +500,12 @@ void removeIdentical(ElementPtr a, const ElementPtr b);
 /// MapElements.
 /// Every string,value pair in other is copied into element
 /// (the ElementPtr of value is copied, this is not a new object)
-/// Unless the value is an empty ElementPtr, in which case the
-/// whole key is removed from element.
+/// Unless the value is a NullElement, in which case the
+/// key is removed from element, rather than setting the value to
+/// the given NullElement.
+/// This way, we can remove values from for instance maps with
+/// configuration data (which would then result in reverting back
+/// to the default).
 /// Raises a TypeError if either ElementPtr is not a MapElement
 void merge(ElementPtr element, const ElementPtr other);
 

+ 2 - 2
src/lib/cc/data_unittests.cc

@@ -135,6 +135,7 @@ TEST(Element, from_and_to_json) {
     EXPECT_EQ("100", Element::fromJSON("+1e2")->str());
     EXPECT_EQ("-100", Element::fromJSON("-1e2")->str());
     EXPECT_EQ("0.01", Element::fromJSON("1e-2")->str());
+    EXPECT_EQ("0.01", Element::fromJSON(".01")->str());
     EXPECT_EQ("-0.01", Element::fromJSON("-1e-2")->str());
     EXPECT_EQ("1.2", Element::fromJSON("1.2")->str());
     EXPECT_EQ("1", Element::fromJSON("1.0")->str());
@@ -153,7 +154,6 @@ TEST(Element, from_and_to_json) {
 
     // number overflows
     EXPECT_THROW(Element::fromJSON("12345678901234567890")->str(), JSONError);
-    EXPECT_THROW(Element::fromJSON("1.12345678901234567890")->str(), JSONError);
     EXPECT_THROW(Element::fromJSON("1.1e12345678901234567890")->str(), JSONError);
     EXPECT_THROW(Element::fromJSON("1e12345678901234567890")->str(), JSONError);
     EXPECT_THROW(Element::fromJSON("1e50000")->str(), JSONError);
@@ -164,7 +164,7 @@ TEST(Element, create_and_value_throws) {
     // this test checks whether elements throw exceptions if the
     // incorrect type is requested
     ElementPtr el;
-    int i;
+    long int i;
     double d;
     bool b;
     std::string s("asdf");

+ 3 - 3
src/lib/cc/session.cc

@@ -66,7 +66,7 @@ public:
     virtual void readData(void* data, size_t datalen) = 0;
     virtual void startRead(boost::function<void()> user_handler) = 0;
     
-    int sequence_; // the next sequence number to use
+    long int sequence_; // the next sequence number to use
     std::string lname_;
     ElementPtr queue_;
 };
@@ -458,7 +458,7 @@ Session::group_sendmsg(ElementPtr msg, std::string group,
                        std::string instance, std::string to)
 {
     ElementPtr env = Element::createMap();
-    int nseq = ++impl_->sequence_;
+    long int nseq = ++impl_->sequence_;
     
     env->set("type", Element::create("send"));
     env->set("from", Element::create(impl_->lname_));
@@ -482,7 +482,7 @@ Session::group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
 int
 Session::reply(ElementPtr& envelope, ElementPtr& newmsg) {
     ElementPtr env = Element::createMap();
-    int nseq = ++impl_->sequence_;
+    long int nseq = ++impl_->sequence_;
     
     env->set("type", Element::create("send"));
     env->set("from", Element::create(impl_->lname_));