Selaa lähdekoodia

[Refs #12] Add ignorecase, search only numbers, object keys, string and bool

isundil 9 vuotta sitten
vanhempi
commit
f8885532e1

+ 2 - 0
CMakeLists.txt

@@ -14,6 +14,7 @@ add_executable(jsonstroll
     src/linearHistory.cpp
     src/outputFlag.cpp
     src/streamConsumer.cpp
+    src/searchPattern.cpp
 
     src/jsonElement.cpp
     src/jsonArray.cpp
@@ -42,6 +43,7 @@ add_executable(json_test
     src/jsonContainer.cpp
     src/warning.cpp
     src/linearHistory.cpp
+    src/searchPattern.cpp
     src/streamConsumer.cpp
     src/jsonArray.cpp
     src/jsonObjectEntry.cpp

+ 2 - 2
doc/jsonstroll.1

@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.3.
-.TH JSONSTROLL "1" "August 2016" "jsonstroll (jsonstroller suite) 1.0RC1 generated on Aug 12 2016" "User Commands"
+.TH JSONSTROLL "1" "August 2016" "jsonstroll (jsonstroller suite) 1.0RC1 generated on Aug 15 2016" "User Commands"
 .SH NAME
-jsonstroll \- manual page for jsonstroll (jsonstroller suite) 1.0RC1 generated on Aug 12 2016
+jsonstroll \- manual page for jsonstroll (jsonstroller suite) 1.0RC1 generated on Aug 15 2016
 .SH SYNOPSIS
 .B jsonstroll
 [\fI\,OPTIONS\/\fR]

+ 3 - 2
include/curseOutput.hh

@@ -19,6 +19,7 @@ class JSonContainer;
 class JSonArray;
 class JSonObject;
 template<class T> class Optional;
+class SearchPattern;
 
 class CurseOutput
 {
@@ -116,11 +117,11 @@ class CurseOutput
          * prompt for user input, and return it
          * @throws noInputException if user use a kill-key (to exit buffer)
         **/
-        const std::string inputSearch();
+        const SearchPattern *inputSearch();
         /**
          * find occurences of search result and fill this#search_result
         **/
-        unsigned int search(const std::string &, const JSonElement *);
+        unsigned int search(const SearchPattern &, const JSonElement *);
 
         /**
          * Write a message on the last line, using color

+ 2 - 1
include/jsonElement.hh

@@ -9,6 +9,7 @@
 #include <string>
 
 class JSonContainer;
+class SearchPattern;
 
 class JSonElement
 {
@@ -46,7 +47,7 @@ class JSonElement
         /**
          * check if this element match SearchQuery
         **/
-        virtual bool match(const std::string &) const;
+        virtual bool match(const SearchPattern &) const;
 
     private:
         JSonElement();

+ 34 - 0
include/searchPattern.hh

@@ -0,0 +1,34 @@
+#pragma once
+
+#include <string>
+
+class JSonElement;
+
+class SearchPattern
+{
+    public:
+        SearchPattern(const char *);
+        ~SearchPattern();
+
+        bool isEmpty() const;
+        bool match(const std::string &other, const JSonElement *) const;
+
+        /**
+         * Comparison function, for std::search use
+        **/
+        bool operator()(char a, char b);
+
+    private:
+        void evalFlags(const char *);
+
+        std::string pattern;
+        short flags;
+        short typeFlag;
+
+        static const short FLAG_CASE;
+        static const short TYPE_BOOL;
+        static const short TYPE_NUMBER;
+        static const short TYPE_STRING;
+        static const short TYPE_OBJKEY;
+};
+

+ 9 - 16
src/curseOutput.cpp

@@ -12,6 +12,7 @@
 #include <signal.h>
 #include <string.h>
 
+#include "searchPattern.hh"
 #include "curseOutput.hh"
 #include "jsonPrimitive.hh"
 #include "jsonObject.hh"
@@ -504,18 +505,14 @@ bool CurseOutput::readInput()
 
             case '/':
             {
-                std::string search_pattern;
-                try {
-                    search_pattern = inputSearch();
-                }
-                catch (interruptedException &e)
-                {
+                const SearchPattern *search_pattern = inputSearch();
+                if (!search_pattern)
                     return true;
-                }
                 search_result.clear();
-                if (search_pattern.empty())
+                if (search_pattern->isEmpty())
                     return true;
-                search(search_pattern, data);
+                search(*search_pattern, data);
+                delete search_pattern;
             }
 
             case 'n':
@@ -530,7 +527,7 @@ bool CurseOutput::readInput()
     return false;
 }
 
-unsigned int CurseOutput::search(const std::string &search_pattern, const JSonElement *current)
+unsigned int CurseOutput::search(const SearchPattern &search_pattern, const JSonElement *current)
 {
     const JSonContainer *container = dynamic_cast<const JSonContainer *> (current);
     const JSonObjectEntry *objEntry = dynamic_cast<const JSonObjectEntry *> (current);
@@ -615,13 +612,12 @@ void CurseOutput::unfold(const JSonElement *item)
     }
 }
 
-const std::string CurseOutput::inputSearch()
+const SearchPattern *CurseOutput::inputSearch()
 {
     std::string buffer;
     bool abort = false;
 
     curs_set(true);
-    keypad(stdscr, false);
     wtimeout(stdscr, -1);
     while (!abort)
     {
@@ -643,12 +639,9 @@ const std::string CurseOutput::inputSearch()
             buffer += c;
     }
     wtimeout(stdscr, 150);
-    keypad(stdscr, true);
     curs_set(false);
 
-    if (abort)
-        throw interruptedException();
-    return buffer;
+    return abort ? nullptr : new SearchPattern(buffer.c_str());
 }
 
 void CurseOutput::writeBottomLine(const std::string &buffer, short color) const

+ 3 - 3
src/jsonElement.cpp

@@ -7,6 +7,7 @@
 #include "jsonElement.hh"
 #include "jsonContainer.hh"
 #include "jsonObjectEntry.hh"
+#include "searchPattern.hh"
 
 JSonElement::JSonElement(JSonElement *p): parent(p)
 { }
@@ -77,9 +78,8 @@ const JSonElement* JSonElement::findNext() const
     return parent->findNext();
 }
 
-bool JSonElement::match(const std::string &search_pattern) const
+bool JSonElement::match(const SearchPattern &searchPattern) const
 {
-    const std::string str = stringify();
-    return str.find(search_pattern) != str.npos;
+    return searchPattern.match(stringify(), this);
 }
 

+ 0 - 42
src/jsonObjectEntry.cpp

@@ -37,45 +37,3 @@ std::string JSonObjectEntry::stringify() const
     return key;
 }
 
-/*
-const JSonElement *JSonObjectEntry::findPrev() const
-{
-    const JSonObject *parent = (JSonObject*) getParent();
-    if (parent == nullptr)
-        return nullptr; // Root node, can't have brothers
-    std::list<JSonElement *>::const_iterator it = parent->cbegin();
-    const JSonObjectEntry *ent = (const JSonObjectEntry *)(*it);
-    const JSonObjectEntry *prevElem = ent;
-    if (prevElem == this)
-        return nullptr; // First item
-    while ((++it) != parent->cend())
-    {
-        ent = (const JSonObjectEntry *)(*it);
-        if (*it == this)
-            return prevElem;
-        prevElem = ent;
-    }
-    return nullptr;
-}
-
-const JSonElement* JSonObjectEntry::findNext() const
-{
-    const JSonObject *parent = (const JSonObject*) this->getParent();
-    if (parent == nullptr)
-        return nullptr; // Root node, can't have brothers
-    JSonContainer::const_iterator it = parent->cbegin();
-    while (it != parent->cend())
-    {
-        if (*it == this)
-        {
-            it++;
-            if (it == parent->cend())
-                return parent->findNext(); // Last item
-            return *it;
-        }
-        it++;
-    }
-    return parent->findNext();
-}
-*/
-

+ 96 - 0
src/searchPattern.cpp

@@ -0,0 +1,96 @@
+#include <algorithm>
+#include <sstream>
+#include "searchPattern.hh"
+
+#include "jsonObjectEntry.hh"
+#include "jsonPrimitive.hh"
+
+SearchPattern::SearchPattern(const char *input): flags(0)
+{
+    size_t pos = 0;
+    bool escaped = false;
+    std::stringstream ss;
+
+    for (pos =0; input[pos]; ++pos)
+    {
+        if (escaped)
+        {
+            if (input[pos] == '/')
+                ss.put(input[pos]);
+            else
+                ss.put('\\').put(input[pos]);
+            escaped = false;
+        }
+        else if (input[pos] == '\\')
+            escaped = true;
+        else if (input[pos] == '/')
+        {
+            pattern = ss.str();
+            evalFlags(&input[pos +1]);
+            return;
+        }
+        else
+            ss.put(input[pos]);
+    }
+    pattern = ss.str();
+}
+
+SearchPattern::~SearchPattern()
+{ }
+
+void SearchPattern::evalFlags(const char *s)
+{
+    while (*s)
+    {
+        if (*s == 'i')
+        {
+            flags |= SearchPattern::FLAG_CASE;
+            std::transform(pattern.begin(), pattern.end(), pattern.begin(), ::tolower);
+        }
+        else if (*s == 'b')
+            typeFlag = SearchPattern::TYPE_BOOL;
+        else if (*s == 'n')
+            typeFlag = SearchPattern::TYPE_NUMBER;
+        else if (*s == 's')
+            typeFlag = SearchPattern::TYPE_STRING;
+        else if (*s == 'o')
+            typeFlag = SearchPattern::TYPE_OBJKEY;
+        s++;
+    }
+}
+
+bool SearchPattern::isEmpty() const
+{ return pattern.empty(); }
+
+bool SearchPattern::operator()(char a, char b)
+{
+    if (flags & SearchPattern::FLAG_CASE)
+        return std::tolower(a) == b;
+    return a == b;
+}
+
+bool SearchPattern::match(const std::string &str, const JSonElement *type) const
+{
+    if (typeFlag)
+    {
+        if (typeFlag == SearchPattern::TYPE_BOOL && !(dynamic_cast<const JSonPrimitive<bool> *>(type)))
+            return false;
+        else if (typeFlag == SearchPattern::TYPE_STRING && !(dynamic_cast<const JSonPrimitive<std::string> *>(type)))
+            return false;
+        else if (typeFlag == SearchPattern::TYPE_OBJKEY && !(dynamic_cast<const JSonObjectEntry *>(type)))
+            return false;
+        else if (typeFlag == SearchPattern::TYPE_NUMBER &&
+                !(dynamic_cast<const JSonPrimitive<int> *>(type)) &&
+                !(dynamic_cast<const JSonPrimitive<double> *>(type)) &&
+                !(dynamic_cast<const JSonPrimitive<long long> *>(type)))
+            return false;
+    }
+    return std::search(str.begin(), str.end(), pattern.begin(), pattern.end(), *this) != str.end();
+}
+
+const short SearchPattern::FLAG_CASE    = 1;
+const short SearchPattern::TYPE_BOOL    = 1;
+const short SearchPattern::TYPE_NUMBER  = 2;
+const short SearchPattern::TYPE_STRING  = 3;
+const short SearchPattern::TYPE_OBJKEY  = 4;
+

+ 2 - 2
test/test.json

@@ -4,7 +4,7 @@
         "0":"897316929176464ebc9ad085f31e7284",
         "1":"b026324c6904b2a9cb4b88d6d61c81d1",
         "2":"26ab0db90d72e28ad0ba1e22ee510510",
-        "3":"6d7fce9fee471194aa8b5b6e47267f03",
+        "3":"6d7fc\\e9/fee471194aa8b5b6e47267f03",
         "4":"48a24b70a0b376535542b996af517398",
         "5":"1dcca23355272056f04fe8bf20edfce0",
         "6":"9ae0ea9e3c9c6e1b9b6252c8395efdc1",
@@ -18,7 +18,7 @@
         "14":"367764329430db34be92fd14a7a770ee",
         "15":"8c9eb686bf3eb5bd83d9373eadf6504b",
         "16":"5b6b41ed9b343fed9cd05a66d36650f0",
-        "17":"4d095eeac8ed659b1ce69dcef32ed0dc",
+        "17":"4d095eeAC8ed659b1ce69dcef32ed0dc",
         "18":"cf4278314ef8e4b996e1b798d8eb92cf",
         "19":"3bb50ff8eeb7ad116724b56a820139fa",
         "20":"dbbf8220893d497d403bb9cdf49db7a4",