Przeglądaj źródła

[refactor] JSonContainer is a list, and JSonObject contains only JSonObjectEntry

isundil 9 lat temu
rodzic
commit
01b6058a95

+ 2 - 2
CMakeLists.txt

@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 2.8)
 
-add_executable(jsonstroll src/main.cpp src/jsonContainer.cpp src/params.cpp src/curseOutput.cpp src/streamConsumer.cpp src/jsonArray.cpp src/jsonObject.cpp src/jsonElement.cpp src/jsonPrimitive.cpp src/jsonException.cpp)
-add_executable(json_test test/src/main.cpp src/jsonContainer.cpp src/params.cpp src/streamConsumer.cpp src/jsonArray.cpp src/jsonObject.cpp src/jsonElement.cpp src/jsonPrimitive.cpp src/jsonException.cpp)
+add_executable(jsonstroll src/main.cpp src/jsonContainer.cpp src/params.cpp src/curseOutput.cpp src/streamConsumer.cpp src/jsonArray.cpp src/jsonObjectEntry.cpp src/jsonObject.cpp src/jsonElement.cpp src/jsonPrimitive.cpp src/jsonException.cpp)
+add_executable(json_test test/src/main.cpp src/jsonContainer.cpp src/params.cpp src/streamConsumer.cpp src/jsonArray.cpp src/jsonObjectEntry.cpp src/jsonObject.cpp src/jsonElement.cpp src/jsonPrimitive.cpp src/jsonException.cpp)
 
 set_property(TARGET jsonstroll PROPERTY RUNTIME_OUTPUT_DIRECTORY bin)
 

+ 4 - 5
include/curseOutput.hh

@@ -3,6 +3,7 @@
 #include <fstream>
 #include <ios>
 #include <set>
+#include <list>
 #include <ncurses.h>
 
 class JSonElement;
@@ -21,7 +22,6 @@ class CurseOutput
         bool onsig(int signo);
 
     private:
-        typedef Optional<std::pair<Optional<const std::string>, const JSonElement *> > t_nextKey;
         virtual void loop();
 
     protected:
@@ -34,8 +34,8 @@ class CurseOutput
         bool redraw(std::pair<int, int> &, const std::pair<unsigned int, unsigned int> &maxWidth, const JSonElement *, const JSonContainer *);
         bool readInput();
         void getScreenSize(std::pair<unsigned int, unsigned int> &, std::pair<int, int> &) const;
-        static CurseOutput::t_nextKey findPrev(const JSonElement *);
-        static CurseOutput::t_nextKey findNext(const JSonElement *);
+        static const JSonElement* findPrev(const JSonElement *);
+        static const JSonElement* findNext(const JSonElement *);
         void checkSelection(const JSonElement *item, const JSonElement *parent, const std::pair<int, int>&);
         static unsigned int getNbLines(float nbChar, unsigned int maxWidth);
         unsigned int write(const int &x, const int &y, const JSonElement *item, unsigned int maxWidth, bool selected =false);
@@ -44,8 +44,7 @@ class CurseOutput
         unsigned int write(const int &x, const int &y, const char *item, unsigned int maxWidth, bool selected =false);
         bool writeKey(const std::string &key, std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxWidth, bool selected);
         bool writeContainer(std::pair<int, int> &, const std::pair<unsigned int, unsigned int> &maxSize, const JSonContainer *);
-        bool writeContent(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, const JSonArray * obj);
-        bool writeContent(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, const JSonObject * obj);
+        bool writeContent(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, const std::list<JSonElement *> * obj);
 
         std::set<const JSonContainer *> collapsed;
 

+ 1 - 3
include/jsonArray.hh

@@ -1,14 +1,12 @@
 #pragma once
 
-#include <list>
 #include "jsonContainer.hh"
 
-class JSonArray: public JSonContainer, public std::list<JSonElement *>
+class JSonArray: public JSonContainer
 {
     public:
         JSonArray(JSonContainer *parent);
         virtual ~JSonArray();
-        virtual unsigned int size() const;
 
         virtual JSonElement *firstChild();
         virtual const JSonElement *firstChild() const;

+ 2 - 2
include/jsonContainer.hh

@@ -1,13 +1,13 @@
 #pragma once
 
+#include <list>
 #include "jsonElement.hh"
 
-class JSonContainer: public JSonElement
+class JSonContainer: public JSonElement, public std::list<JSonElement*>
 {
     public:
         JSonContainer(JSonContainer *parent);
         virtual ~JSonContainer();
-        virtual unsigned int size() const =0;
         virtual JSonElement *firstChild() =0;
         virtual const JSonElement *firstChild() const =0;
 };

+ 3 - 5
include/jsonObject.hh

@@ -1,18 +1,16 @@
 #pragma once
 
-#include <map>
 #include "jsonContainer.hh"
+#include "jsonObjectEntry.hh"
 
-template<typename T> class JSonPrimitive;
-
-class JSonObject: public JSonContainer, public std::map<std::string, JSonElement*>
+class JSonObject: public JSonContainer
 {
     public:
         JSonObject(JSonContainer *parent);
         virtual ~JSonObject();
 
         void push(const std::string &key, JSonElement *child);
-        virtual unsigned int size() const;
+        JSonObject::const_iterator find(const std::string &key) const;
         bool contains(const std::string &) const;
 
         virtual JSonElement *firstChild();

+ 23 - 0
include/jsonObjectEntry.hh

@@ -0,0 +1,23 @@
+#pragma once
+
+#include "jsonElement.hh"
+
+class JSonObject;
+
+class JSonObjectEntry: public JSonElement
+{
+    public:
+        JSonObjectEntry(JSonObject*, const std::string &key, JSonElement *item);
+        ~JSonObjectEntry();
+
+        std::string stringify() const;
+
+        bool operator==(const std::string &) const;
+        const JSonElement *operator*() const;
+        JSonElement *operator*();
+
+    protected:
+        const std::string key;
+        JSonElement * const value;
+};
+

+ 74 - 122
src/curseOutput.cpp

@@ -114,9 +114,8 @@ bool CurseOutput::redraw(std::pair<int, int> &cursor, const std::pair<unsigned i
 bool CurseOutput::writeContainer(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, const JSonContainer *item)
 {
     char childDelimiter[2];
-    bool isObject = dynamic_cast<const JSonObject *>(item);
 
-    if (isObject)
+    if (dynamic_cast<const JSonObject *>(item))
         memcpy(childDelimiter, "{}", sizeof(*childDelimiter) * 2);
     else
         memcpy(childDelimiter, "[]", sizeof(*childDelimiter) * 2);
@@ -133,72 +132,60 @@ bool CurseOutput::writeContainer(std::pair<int, int> &cursor, const std::pair<un
         cursor.second += write(cursor.first, cursor.second, childDelimiter[0], maxSize.first, selection == item);
         if (cursor.second - topleft > maxSize.second -1)
                 return false;
-        if (isObject)
-        {
-            if (!writeContent(cursor, maxSize, (const JSonObject *)item))
-                return false;
-        }
-        else
-        {
-            if (!writeContent(cursor, maxSize, (const JSonArray *)item))
-                return false;
-        }
+        if (!writeContent(cursor, maxSize, (const std::list<JSonElement *> *)item))
+            return false;
         cursor.second += write(cursor.first, cursor.second, childDelimiter[1], maxSize.first, selection == item);
     }
     cursor.first -= indentLevel /2;
     return (cursor.second - topleft <= maxSize.second -1);
 }
 
-bool CurseOutput::writeContent(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, const JSonArray *item)
+bool CurseOutput::writeContent(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, const std::list<JSonElement*> *_item)
 {
+    const JSonContainer *item = (const JSonContainer *)_item;
+    bool containerIsObject = (dynamic_cast<const JSonObject *>(item) != nullptr);
     cursor.first += indentLevel /2;
-    for (JSonArray::const_iterator i = ((JSonArray *)item)->cbegin(); i != ((JSonArray *)item)->cend(); ++i)
-        if (!redraw(cursor, maxSize, *i, (JSonContainer *)item))
-            return false;
-    cursor.first -= indentLevel /2;
-    return true;
-}
-
-bool CurseOutput::writeContent(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, const JSonObject *item)
-{
-    for (JSonObject::const_iterator i = ((JSonObject *)item)->cbegin(); i != ((JSonObject *)item)->cend(); ++i)
+    for (std::list<JSonElement *>::const_iterator i = item->cbegin(); i != item->cend(); ++i)
     {
-        const std::pair<std::string, JSonElement *> ipair = *i;
-        cursor.first += indentLevel /2;
-        if (dynamic_cast<const JSonContainer *>(ipair.second) == nullptr
-                || ((const JSonContainer *) ipair.second)->size() == 0)
-        {
-            checkSelection(ipair.second, item, cursor);
-            cursor.second += write(cursor.first, cursor.second, ipair.first +": " +ipair.second->stringify(), maxSize.first, selection == ipair.second);
-            cursor.first -= indentLevel /2;
-            if (cursor.second - topleft > maxSize.second -1)
-                return false;
-        }
-        else if (collapsed.find((const JSonContainer *)ipair.second) != collapsed.end())
+        bool isObject = (dynamic_cast<const JSonObject *>(*i) != nullptr);
+        if (containerIsObject)
         {
-            char childDelimiter[2];
-            if (dynamic_cast<const JSonObject *>(ipair.second))
-                memcpy(childDelimiter, "{}", sizeof(*childDelimiter) * 2);
+            JSonObjectEntry *ent = (JSonObjectEntry*) *i;
+            std::string key = ent->stringify();
+            checkSelection(**ent, (JSonContainer*) item, cursor);
+            if (collapsed.find((const JSonContainer*)(**ent)) != collapsed.cend())
+            {
+                if (isObject)
+                    cursor.second += write(cursor.first, cursor.second, key + ": { ... }", maxSize.first, selection == **ent);
+                else
+                    cursor.second += write(cursor.first, cursor.second, key + ": [ ... ]", maxSize.first, selection == **ent);
+            }
+            else if (dynamic_cast<const JSonContainer*> (**ent) == nullptr)
+                cursor.second += write(cursor.first, cursor.second, key + ": " +((**ent)->stringify()), maxSize.first, selection == **ent);
+            else if (((JSonContainer*)(**ent))->size() == 0)
+            {
+                if (isObject)
+                    cursor.second += write(cursor.first, cursor.second, key + ": { }", maxSize.first, selection == **ent);
+                else
+                    cursor.second += write(cursor.first, cursor.second, key + ": [ ]", maxSize.first, selection == **ent);
+            }
             else
-                memcpy(childDelimiter, "[]", sizeof(*childDelimiter) * 2);
-            std::string ss = ipair.first;
-            ss.append(": ").append(&childDelimiter[0], 1).append(" ... ").append(&childDelimiter[1], 1);
-            checkSelection(ipair.second, item, cursor);
-            cursor.second += write(cursor.first, cursor.second, ss, maxSize.first, selection == ipair.second);
-            cursor.first -= indentLevel /2;
-            if (cursor.second - topleft > maxSize.second -1)
-                return false;
+            {
+                if (!writeKey(key, cursor, maxSize, selection == ent || selection == **ent))
+                    return false;
+                cursor.first -= indentLevel /2;
+                if (!redraw(cursor, maxSize, **ent, (const JSonContainer *)item))
+                    return false;
+                cursor.first -= indentLevel /2;
+            }
         }
         else
         {
-            if (!writeKey(ipair.first, cursor, maxSize, selection == ipair.second))
+            if (!redraw(cursor, maxSize, *i, (const JSonContainer *)item))
                 return false;
-            cursor.first -= indentLevel /2;
-            if (!redraw(cursor, maxSize, ipair.second, (JSonContainer *) item))
-                return false;
-            cursor.first -= indentLevel;
         }
     }
+    cursor.first -= indentLevel /2;
     return true;
 }
 
@@ -265,86 +252,48 @@ void CurseOutput::getScreenSize(std::pair<unsigned int, unsigned int> &screenSiz
     getbegyx(stdscr, bs.second, bs.first);
 }
 
-CurseOutput::t_nextKey CurseOutput::findPrev(const JSonElement *item)
+const JSonElement *CurseOutput::findPrev(const JSonElement *item)
 {
     const JSonContainer *parent = item->getParent();
     if (parent == nullptr)
-        return t_nextKey::empty(); // Root node, can't have brothers
-    if (dynamic_cast<const JSonObject *>(parent) != nullptr)
-    {
-        const JSonObject *oParent = (const JSonObject *) parent;
-        JSonObject::const_iterator it = oParent->cbegin();
-        if ((*it).second == item)
-            return t_nextKey::empty();
-        std::string prevKey = (*it).first;
-        const JSonElement *prevElem = (*it).second;
-        while ((++it) != oParent->cend())
-        {
-            if ((*it).second == item)
-                return t_nextKey(std::pair<Optional<const std::string>, const JSonElement *>(prevKey, prevElem));
-            prevKey = (*it).first;
-            prevElem = (*it).second;
-        }
-        return t_nextKey::empty();
-    }
-    if (dynamic_cast<const JSonArray *>(parent) != nullptr)
+        return nullptr; // Root node, can't have brothers
+    std::list<JSonElement *>::const_iterator it = parent->cbegin();
+    const JSonObjectEntry *ent = dynamic_cast<const JSonObjectEntry *>(*it);
+    const JSonElement *prevElem = ent ? **ent : (*it);
+    if (prevElem == item || (ent && **ent == item))
+        return nullptr; // First item
+    while ((++it) != parent->cend())
     {
-        const JSonArray *aParent = (const JSonArray *) parent;
-        JSonArray::const_iterator it = aParent->cbegin();
-        const JSonElement *prevElem = (*it);
-        if (prevElem == item)
-            return t_nextKey::empty();
-        while ((++it) != aParent->cend())
-        {
-            if (*it == item)
-                return t_nextKey(std::pair<Optional<const std::string>, const JSonElement *>(Optional<const std::string>::empty(), prevElem));
-            prevElem = (*it);
-        }
-        return t_nextKey::empty();
+        ent = dynamic_cast<const JSonObjectEntry *>(*it);
+        if (*it == item || (ent && **ent == item))
+            return prevElem;
+        prevElem = ent ? **ent : (*it);
     }
-    return t_nextKey::empty(); // Primitive, can't have child (impossible)
+    return nullptr;
 }
 
-CurseOutput::t_nextKey CurseOutput::findNext(const JSonElement *item)
+const JSonElement* CurseOutput::findNext(const JSonElement *item)
 {
     const JSonContainer *parent = item->getParent();
     if (parent == nullptr)
-        return t_nextKey::empty(); // Root node, can't have brothers
-    if (dynamic_cast<const JSonObject *>(parent) != nullptr)
+        return nullptr; // Root node, can't have brothers
+    JSonContainer::const_iterator it = parent->cbegin();
+    while (it != parent->cend())
     {
-        const JSonObject *oParent = (const JSonObject *) parent;
-        JSonObject::const_iterator it = oParent->cbegin();
-        while (it != oParent->cend())
+        const JSonObjectEntry *ent = dynamic_cast<const JSonObjectEntry *>(*it);
+        if (*it == item || (ent && **ent == item))
         {
-            if ((*it).second == item)
-            {
-                it++;
-                if (it == oParent->cend())
-                    return findNext(oParent); // Last item
-                return t_nextKey(std::pair<Optional<const std::string>, const JSonElement *>((*it).first, (*it).second));
-            }
             it++;
+            if (it == parent->cend())
+                return findNext((const JSonElement*) parent); // Last item
+            ent = dynamic_cast<const JSonObjectEntry *>(*it);
+            if (ent)
+                return **ent;
+            return *it;
         }
-        return findNext(oParent);
+        it++;
     }
-    if (dynamic_cast<const JSonArray *>(parent) != nullptr)
-    {
-        const JSonArray *aParent = (const JSonArray *) parent;
-        JSonArray::const_iterator it = aParent->cbegin();
-        while (it != aParent->cend())
-        {
-            if (*it == item)
-            {
-                it++;
-                if (it == aParent->cend())
-                    return findNext(aParent); // Last item
-                return t_nextKey(std::pair<Optional<const std::string>, const JSonElement *>(Optional<const std::string>::empty(), *it));
-            }
-            it++;
-        }
-        return findNext(aParent);
-    }
-    return t_nextKey::empty(); // Primitive, can't have child (impossible)
+    return findNext((const JSonElement*) parent);
 }
 
 void CurseOutput::checkSelection(const JSonElement *item, const JSonElement *parent, const std::pair<int, int> &cursor)
@@ -402,8 +351,8 @@ bool CurseOutput::readInput()
 
             case KEY_PPAGE:
             {
-                const t_nextKey brother = findPrev(selection);
-                if (brother.isAbsent())
+                const JSonElement *brother = findPrev(selection);
+                if (brother == nullptr)
                 {
                     const JSonContainer *parent = selection->getParent();
                     if (parent)
@@ -412,17 +361,17 @@ bool CurseOutput::readInput()
                         break;
                 }
                 else
-                    selection = brother.value().second;
+                    selection = brother;
                 return true;
                 break;
             }
 
             case KEY_NPAGE:
             {
-                const t_nextKey brother = findNext(selection);
-                if (brother.isPresent())
+                const JSonElement *brother = findNext(selection);
+                if (brother)
                 {
-                    selection = brother.value().second;
+                    selection = brother;
                     return true;
                 }
                 break;
@@ -476,7 +425,10 @@ void CurseOutput::init()
         screen = newterm(nullptr, screen_fd, screen_fd);
     }
     else
+    {
         screen = newterm(nullptr, stdout, stdin);
+        screen_fd = nullptr;
+    }
     wtimeout(stdscr, 150);
     cbreak();
     clear();

+ 0 - 5
src/jsonArray.cpp

@@ -11,11 +11,6 @@ JSonArray::~JSonArray()
     }
 }
 
-unsigned int JSonArray::size() const
-{
-    return std::list<JSonElement *>::size();
-}
-
 JSonElement *JSonArray::firstChild()
 {
     if (begin() == end())

+ 20 - 11
src/jsonObject.cpp

@@ -8,43 +8,52 @@ JSonObject::~JSonObject()
 {
     for (iterator i = begin(); i != end(); ++i)
     {
-        delete (*i).second;
+        delete (*i);
     }
 }
 
 void JSonObject::push(const std::string &key, JSonElement *child)
 {
-    (*this)[key] = child;
+    this->push_back(new JSonObjectEntry(this, key, child));
 }
 
-bool JSonObject::contains(const std::string &key) const
+JSonObject::const_iterator JSonObject::find(const std::string &key) const
 {
-    return find(key) != end();
+    JSonObject::const_iterator it = cbegin();
+    while (it != cend())
+    {
+        if ((const JSonObjectEntry &)(**it) == key)
+            return it;
+        ++it;
+    }
+    return it;
 }
 
-const JSonElement *JSonObject::get(const std::string &key) const
+bool JSonObject::contains(const std::string &key) const
 {
-    const_iterator item = find(key);
-    return item == cend() ? nullptr : (*item).second;
+    return find(key) != this->cend();
 }
 
-unsigned int JSonObject::size() const
+const JSonElement *JSonObject::get(const std::string &key) const
 {
-    return std::map<std::string, JSonElement *>::size();
+    const_iterator item = find(key);
+    if (item == cend())
+        return nullptr;
+    return *(const JSonObjectEntry &)(**item);
 }
 
 JSonElement *JSonObject::firstChild()
 {
     if (begin() == end())
         return nullptr;
-    return (*begin()).second;
+    return *begin();
 }
 
 const JSonElement *JSonObject::firstChild() const
 {
     if (cbegin() == cend())
         return nullptr;
-    return (*cbegin()).second;
+    return *cbegin();
 }
 
 std::string JSonObject::stringify() const

+ 32 - 0
src/jsonObjectEntry.cpp

@@ -0,0 +1,32 @@
+
+#include "jsonObjectEntry.hh"
+#include "jsonObject.hh"
+
+JSonObjectEntry::JSonObjectEntry(JSonObject *parent, const std::string &k, JSonElement *v): JSonElement(parent), key(k), value(v)
+{ }
+
+JSonObjectEntry::~JSonObjectEntry()
+{
+    delete value;
+}
+
+bool JSonObjectEntry::operator==(const std::string &k) const
+{
+    return key == k;
+}
+
+JSonElement *JSonObjectEntry::operator*()
+{
+    return value;
+}
+
+const JSonElement *JSonObjectEntry::operator*() const
+{
+    return value;
+}
+
+std::string JSonObjectEntry::stringify() const
+{
+    return key;
+}
+

+ 0 - 1
src/streamConsumer.cpp

@@ -65,7 +65,6 @@ JSonObject *StreamConsumer::readObject(JSonContainer *parent)
             result = new JSonObject(parent);
         else if (result->contains(key->getValue()))
             throw JsonException(stream.tellg()); //Double key
-        key->setParent(result);
         JSonElement *child = readNext(result);
         result->push(key->getValue(), child);
         delete keyObj;

+ 1 - 1
test/test2.json

@@ -1 +1 @@
-{"1":{"t0":["a", true, "b",false]},"2":{"t1":["a", true, "b",false]}, "3": "to20025to", "4":[1, 2, 3], "emptyObj":{},"emptyArr":[]}
+{"1":{"t0":["a", true, "b",false]},"2":{"t1":["a", true, "b",false]}, "3": "to20025to", "4":[1, 2, 3], "singleObj":{"a":true},"singleArr":[true],"emptyObj":{},"emptyArr":[]}