Ver Fonte

Fix double precision
Fix error message length increased

isundil há 9 anos atrás
pai
commit
fafa56dc7d

+ 5 - 0
include/config.h

@@ -0,0 +1,5 @@
+
+#ifndef  ERROR_HISTORY_LEN
+# define ERROR_HISTORY_LEN 45
+#endif //ERROR_HISTORY_LEN
+

+ 7 - 6
include/jsonException.hh

@@ -1,6 +1,7 @@
 #pragma once
 
 #include <exception>
+#include "config.h"
 #include "wrappedBuffer.hpp"
 
 class EofException: public std::exception
@@ -9,39 +10,39 @@ class EofException: public std::exception
 class JsonException: public std::exception
 {
     public:
-        JsonException(const std::string &what, unsigned long long offset, WrappedBuffer<char> &buf);
+        JsonException(const std::string &what, unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &buf);
 
         std::string getHistory() const;
         const char *what() const noexcept;
 
     protected:
         const unsigned long long offset;
-        const WrappedBuffer<char> history;
+        const WrappedBuffer<char, ERROR_HISTORY_LEN> history;
         const std::string _what;
 };
 
 class JsonNotJsonException: public JsonException
 {
     public:
-        JsonNotJsonException(unsigned long long offet, WrappedBuffer<char> &h);
+        JsonNotJsonException(unsigned long long offet, WrappedBuffer<char, ERROR_HISTORY_LEN> &h);
 };
 
 class JsonUnexpectedException: public JsonException
 {
     public:
-        JsonUnexpectedException(const char expected, unsigned long long offset, WrappedBuffer<char> &h);
+        JsonUnexpectedException(const char expected, unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &h);
 };
 
 class JsonFormatException: public JsonException
 {
     public:
-        JsonFormatException(unsigned long long offset, WrappedBuffer<char> &h);
+        JsonFormatException(unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &h);
 };
 
 class JsonEscapedException: public JsonException
 {
     public:
-        JsonEscapedException(char c, unsigned long long offset, WrappedBuffer<char> &h);
+        JsonEscapedException(char c, unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &h);
 
     protected:
         const char c;

+ 3 - 2
include/jsonObject.hh

@@ -1,5 +1,6 @@
 #pragma once
 
+#include "config.h"
 #include "jsonContainer.hh"
 #include "jsonObjectEntry.hh"
 #include "jsonException.hh"
@@ -24,13 +25,13 @@ class JSonObject: public JSonContainer
     class DoubleKeyException: public JsonException
     {
         public:
-            DoubleKeyException(unsigned long long offset, const std::string &key, WrappedBuffer<char> &buf);
+            DoubleKeyException(unsigned long long offset, const std::string &key, WrappedBuffer<char, ERROR_HISTORY_LEN> &buf);
     };
 
     class NotAKeyException: public JsonException
     {
         public:
-            NotAKeyException(unsigned long long offset, WrappedBuffer<char> &buf);
+            NotAKeyException(unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &buf);
     };
 };
 

+ 6 - 1
include/streamConsumer.hh

@@ -1,6 +1,7 @@
 #pragma once
 
 #include <istream>
+#include "config.h"
 #include "jsonObject.hh"
 #include "jsonArray.hh"
 #include "jsonPrimitive.hh"
@@ -29,6 +30,10 @@ class StreamConsumer
         std::istream &stream;
         JSonElement *root;
 
-        WrappedBuffer<char> history;
+        WrappedBuffer<char, ERROR_HISTORY_LEN> history;
+
+    private:
+        static float _stof(const std::string &);
+        static float _stof(const char *);
 };
 

+ 5 - 5
src/jsonException.cpp

@@ -1,22 +1,22 @@
 #include <string>
 #include "jsonException.hh"
 
-JsonException::JsonException(const std::string &wh, unsigned long long pos, WrappedBuffer<char> &h): offset(pos), history(h), _what(wh)
+JsonException::JsonException(const std::string &wh, unsigned long long pos, WrappedBuffer<char, ERROR_HISTORY_LEN> &h): offset(pos), history(h), _what(wh)
 { }
 
-JsonFormatException::JsonFormatException(unsigned long long pos, WrappedBuffer<char> &h):
+JsonFormatException::JsonFormatException(unsigned long long pos, WrappedBuffer<char, ERROR_HISTORY_LEN> &h):
     JsonException("invalid value", pos, h)
 { }
 
-JsonNotJsonException::JsonNotJsonException(unsigned long long pos, WrappedBuffer<char> &h):
+JsonNotJsonException::JsonNotJsonException(unsigned long long pos, WrappedBuffer<char, ERROR_HISTORY_LEN> &h):
     JsonException("expected json entry, got token", pos, h)
 { }
 
-JsonEscapedException::JsonEscapedException(char ch, unsigned long long pos, WrappedBuffer<char> &h):
+JsonEscapedException::JsonEscapedException(char ch, unsigned long long pos, WrappedBuffer<char, ERROR_HISTORY_LEN> &h):
     JsonException("unexpected escaped char " +c, pos, h), c(ch)
 { }
 
-JsonUnexpectedException::JsonUnexpectedException(const char expected, unsigned long long offset, WrappedBuffer<char> &h): JsonException("expected " +expected, offset, h)
+JsonUnexpectedException::JsonUnexpectedException(const char expected, unsigned long long offset, WrappedBuffer<char, ERROR_HISTORY_LEN> &h): JsonException("expected " +expected, offset, h)
 { }
 
 std::string JsonException::getHistory() const

+ 2 - 2
src/jsonObject.cpp

@@ -62,12 +62,12 @@ std::string JSonObject::stringify() const
     return "{ }";
 }
 
-JSonObject::DoubleKeyException::DoubleKeyException(unsigned long long pos, const std::string &key, WrappedBuffer<char> &buf):
+JSonObject::DoubleKeyException::DoubleKeyException(unsigned long long pos, const std::string &key, WrappedBuffer<char, ERROR_HISTORY_LEN> &buf):
     JsonException("Unexpected double key " +key +" for object", pos, buf)
 {
 }
 
-JSonObject::NotAKeyException::NotAKeyException(unsigned long long pos, WrappedBuffer<char> &buf):
+JSonObject::NotAKeyException::NotAKeyException(unsigned long long pos, WrappedBuffer<char, ERROR_HISTORY_LEN> &buf):
     JsonException("expected string key for object", pos, buf)
 { }
 

+ 2 - 2
src/jsonPrimitive.cpp

@@ -1,6 +1,6 @@
 #include "jsonPrimitive.hh"
 
-template<> JSonPrimitive<float>::~JSonPrimitive() {}
+template<> JSonPrimitive<double>::~JSonPrimitive() {}
 template<> JSonPrimitive<bool>::~JSonPrimitive() {}
 template<> JSonPrimitive<int>::~JSonPrimitive() {}
 template<> JSonPrimitive<long long>::~JSonPrimitive() {}
@@ -11,7 +11,7 @@ template<> std::string JSonPrimitive<std::string>::stringify() const
     return value;
 }
 
-template<> std::string JSonPrimitive<float>::stringify() const
+template<> std::string JSonPrimitive<double>::stringify() const
 {
     return std::to_string(value);
 }

+ 14 - 6
src/streamConsumer.cpp

@@ -1,4 +1,5 @@
 #include <iostream>
+#include <sstream>
 #include "jsonException.hh"
 #include "jsonElement.hh"
 #include "streamConsumer.hh"
@@ -111,7 +112,7 @@ JSonElement *StreamConsumer::consumeToken(JSonContainer *parent, std::string &bu
     bool inString = false;
     bool inBool = false;
     bool inNumber = false;
-    bool numberIsFloat = false;
+    bool numberIsDouble = false;
 
     while (stream.good())
     {
@@ -165,17 +166,24 @@ JSonElement *StreamConsumer::consumeToken(JSonContainer *parent, std::string &bu
         {
             if (c >= '0' && c <= '9')
                 buf += c;
-            else if (c == '.' && !numberIsFloat)
+            else if (c == '.' && !numberIsDouble)
             {
-                numberIsFloat = true;
+                numberIsDouble = true;
                 buf += c;
             }
             else
             {
                 history.pop_back();
                 stream.unget();
-                if (numberIsFloat)
-                    return new JSonPrimitive<float>(parent, std::stof(buf));
+                if (numberIsDouble)
+                {
+                    try {
+                        return new JSonPrimitive<double>(parent, atof(buf.c_str()));
+                    } catch (std::runtime_error &e)
+                    {
+                        throw JsonFormatException(stream.tellg(), history);
+                    }
+                }
                 try
                 {
                     return new JSonPrimitive<int>(parent, std::stoi(buf));
@@ -204,7 +212,7 @@ JSonElement *StreamConsumer::consumeToken(JSonContainer *parent, std::string &bu
                 buf = c;
                 return nullptr;
             }
-            else if ((c >= '0' && c <= '9') || c == '.')
+            else if ((c >= '0' && c <= '9') || c == '.' || c == '-')
             {
                 buf = c;
                 inNumber = true;

+ 18 - 10
test/src/main.cpp

@@ -17,7 +17,7 @@ StreamConsumer *toJson(std::string str)
 void checkArray()
 {
     //Check array
-    StreamConsumer *root = toJson("[true, 42, \"coucou\", 12.34, false]");
+    StreamConsumer *root = toJson("[true, 42, \"coucou\", 12.34, false, -12, -12.42]");
     JSonArray *arr = dynamic_cast<JSonArray *>(root->getRoot());
     assert(arr != nullptr);
     JSonArray::const_iterator it = arr->cbegin();
@@ -30,11 +30,18 @@ void checkArray()
     assert((dynamic_cast<JSonPrimitive<std::string> *> (*it)) != nullptr);
     assert(((JSonPrimitive<std::string> *)(*it))->getValue() == "coucou");
     it++;
-    assert((dynamic_cast<JSonPrimitive<float> *> (*it)) != nullptr);
-    assert(((JSonPrimitive<float> *)(*it))->getValue() == 12.34f);
+    assert((dynamic_cast<JSonPrimitive<double> *> (*it)) != nullptr);
+    assert(((JSonPrimitive<double> *)(*it))->getValue() == 12.34);
     it++;
     assert((dynamic_cast<JSonPrimitive<bool> *> (*it)) != nullptr);
     assert(((JSonPrimitive<bool> *)(*it))->getValue() == false);
+    it++;
+    assert((dynamic_cast<JSonPrimitive<int> *> (*it)) != nullptr);
+    assert(((JSonPrimitive<int> *)(*it))->getValue() == -12);
+    it++;
+    assert((dynamic_cast<JSonPrimitive<double> *> (*it)) != nullptr);
+    double value = ((JSonPrimitive<double> *)(*it))->getValue();
+    assert(value == -12.42);
     delete root;
 }
 
@@ -54,7 +61,8 @@ void checkTypes()
     assert(dynamic_cast<JSonPrimitive<int> *>(root->getRoot()) != nullptr);
     delete root;
     root = toJson("42.2");
-    assert(dynamic_cast<JSonPrimitive<float> *>(root->getRoot()) != nullptr);
+    assert(dynamic_cast<JSonPrimitive<double> *>(root->getRoot()) != nullptr);
+    assert((((JSonPrimitive<double> *)(root->getRoot()))->getValue()) == 42.2);
     delete root;
     root = toJson(std::to_string((long long)LLONG_MAX));
     assert(dynamic_cast<JSonPrimitive<long long> *>(root->getRoot()) != nullptr);
@@ -67,7 +75,7 @@ void checkTypes()
 void checkObject()
 {
     //Check Obj
-    StreamConsumer *root = toJson("{\"bool\":true, \"int\":42, \"str\":\"coucou\", \"float\":12.34, \"arrayOfInt\":[1, 2, 3, 4.5]}");
+    StreamConsumer *root = toJson("{\"bool\":true, \"int\":42, \"str\":\"coucou\", \"double\":12.34, \"arrayOfInt\":[1, 2, 3, 4.5]}");
     assert(dynamic_cast<JSonObject *>(root->getRoot()) != nullptr);
     assert(((JSonObject *)(root->getRoot()))->size() == 5);
     const JSonElement *tmp = ((JSonObject *)(root->getRoot()))->get("bool");
@@ -79,9 +87,9 @@ void checkObject()
     tmp = ((JSonObject *)(root->getRoot()))->get("str");
     assert((dynamic_cast<const JSonPrimitive<std::string> *> (tmp)) != nullptr);
     assert((dynamic_cast<const JSonPrimitive<std::string> *> (tmp))->getValue() == "coucou");
-    tmp = ((JSonObject *)(root->getRoot()))->get("float");
-    assert((dynamic_cast<const JSonPrimitive<float> *> (tmp)) != nullptr);
-    assert((dynamic_cast<const JSonPrimitive<float> *> (tmp))->getValue() == 12.34f);
+    tmp = ((JSonObject *)(root->getRoot()))->get("double");
+    assert((dynamic_cast<const JSonPrimitive<double> *> (tmp)) != nullptr);
+    assert((dynamic_cast<const JSonPrimitive<double> *> (tmp))->getValue() == 12.34);
     tmp = ((JSonObject *)(root->getRoot()))->get("arrayOfInt");
     const JSonArray *arr2 = dynamic_cast<const JSonArray *> (tmp);
     assert(arr2 != nullptr);
@@ -96,8 +104,8 @@ void checkObject()
     assert((dynamic_cast<JSonPrimitive<int> *> (*it)) != nullptr);
     assert(((JSonPrimitive<int> *)(*it))->getValue() == 3);
     it++;
-    assert((dynamic_cast<JSonPrimitive<float> *> (*it)) != nullptr);
-    assert(((JSonPrimitive<float> *)(*it))->getValue() == 4.5f);
+    assert((dynamic_cast<JSonPrimitive<double> *> (*it)) != nullptr);
+    assert(((JSonPrimitive<double> *)(*it))->getValue() == 4.5);
     delete root;
 }