]> gitweb.hamatoma.de Git - crepublib/commitdiff
ReTraverser implemented
authorkawi <winfriedkappeler@atron.de>
Tue, 30 Dec 2014 14:58:46 +0000 (15:58 +0100)
committerkawi <winfriedkappeler@atron.de>
Tue, 30 Dec 2014 14:58:46 +0000 (15:58 +0100)
base/ReHashList.cpp
base/ReHashList.hpp
cunit/cuReTraverser.cpp
os/ReTraverser.cpp
os/ReTraverser.hpp

index 178eae29284c498b0710248f2f85ec3fdf969fb9..580e552947e6de4504b21daba6bbb7aa989b8196 100644 (file)
@@ -74,7 +74,7 @@ void ReHashList::put(const char* key, const char* value){
  * @param value                        The value.
  */
 void ReHashList::put(const ReByteBuffer& key, const ReByteBuffer& value){
-       put(key.buffer(), key.length(), value.buffer(), value.length());
+       put(key.str(), key.length(), value.str(), value.length());
 }
 /** @brief Returns the value of a key value pair.
  *
@@ -94,7 +94,7 @@ bool ReHashList::get(const Byte* key, size_t keyLength,
        if (rc){
                ReSeqList::Sequence* seq = m_keys.getInfo(ix);
                // m_tag contains the index into m_values:
-               Byte* ptr = m_values.buffer() + seq->m_tag;
+               const Byte* ptr = m_values.str() + seq->m_tag;
                // m_values contains <length><sequence>:
                size_t valLength = * (size_t*) ptr;
                ptr += sizeof (size_t);
@@ -110,8 +110,8 @@ bool ReHashList::get(const Byte* key, size_t keyLength,
  * @return false: The key was not found. true: The key was found.
  */
 bool ReHashList::get(const ReByteBuffer& key,
-               ReByteBuffer value) const{
-       bool rc = get(key.buffer(), key.length(), value);
+               ReByteBuffer& value) const{
+       bool rc = get(key.str(), key.length(), value);
        return rc;
 }
 /** @brief Deletes all entries in the list.
@@ -141,7 +141,7 @@ bool ReHashList::next(size_t& position, ReByteBuffer* key, ReByteBuffer* value){
                        memcpy(key->buffer(), ptr, seq->m_length);
                }
                if (value != NULL){
-                       const Byte* ptr = m_values.buffer() + seq->m_tag;
+                       const Byte* ptr = m_values.str() + seq->m_tag;
                        size_t length = * (size_t*) ptr;
                        ptr += sizeof (size_t);
                        value->setLength(length);
index 09f5e861a9ac0216a287bd5cecb766f6033873e8..d91d79bdbfbc9875d8433ea4ddc2177b1c13606e 100644 (file)
@@ -23,7 +23,7 @@ public:
 public:
        void clear();
        bool get(const Byte* key, size_t keyLength, ReByteBuffer& value) const;
-       bool get(const ReByteBuffer& key, ReByteBuffer value) const;
+       bool get(const ReByteBuffer& key, ReByteBuffer& value) const;
        bool next(size_t& position, ReByteBuffer* key, ReByteBuffer* val);
        void put(const Byte* key, size_t keyLength, const Byte* value, size_t valueLength);
        void put(const char* key, const char* value);
index 1fecf215667fe96e44ea160913fecf9541b0601d..6869162893f0feca1866fde4ca1c271d6ca1cf4d 100644 (file)
 class TestReTraverser : public ReTestUnit {
 public:
        TestReTraverser() : ReTestUnit("ReTraverser", __FILE__){
+        createTestDir();
+        m_base = getTestDir();
                run();
        }
 private:
+    ReByteBuffer m_base;
+private:
+    void makeDir(const char* relPath){
+        ReByteBuffer path(m_base);
+        path.append("/").append(relPath);
+        path.replaceAll("/", 1, ReTraverser::m_separatorStr, -1);
+        _mkdir(path.str());
+        struct stat info;
+        if (stat(path.str(), &info) != 0){
+            logF(true, "cannot create dir %1$s", path.str());
+        }
+    }
+    void makeFile(const char* relPath){
+        ReByteBuffer path(m_base);
+        path.append("/").append(relPath);
+        path.replaceAll("/", 1, ReTraverser::m_separatorStr, -1);
+        createFile(path.str(), path.str());
+        struct stat info;
+        if (stat(path.str(), &info) != 0){
+            logF(true, "cannot create file %1$s", path.str());
+        }
+    }
+    void initTree(){
+        makeFile("1.txt");
+        makeDir("dir1");
+        makeDir("dir2");
+        makeDir("dir1/dir1_1");
+        makeDir("dir1/dir1_2");
+        makeDir("dir1/dir1_2/dir1_2_1");
+        makeFile("dir1/dir1_2/dir1_2_1/x1.txt");
+        makeFile("dir1/dir1_2/dir1_2_1/x2.txt");
+    }
        void run(){
-               testReplaceSubstring();
+        initTree();
+               testBasic();
        }
-       void testReplaceSubstring(){
-               ReTraverser traverser("/tmp/test");
+    void checkOneFile(const char* node, const char* parent, const ReHashList& hash){
+        ReByteBuffer path, expected;
+        checkT(hash.get(ReByteBuffer(node), path));
+        expected.set(parent, -1);
+        if (! expected.endsWith(ReTraverser::m_separatorStr))
+            expected.append(ReTraverser::m_separatorStr);
+        if (! path.endsWith(expected.str(), -1))
+            checkT(false); 
+    }
+       void testBasic(){
+               ReTraverser traverser(m_base.str());
                int level = 0;
-               const DirStatus_t* entry = traverser.nextFile(level);
+               DirStatus_t* entry;
+        ReHashList hash;
+        while( (entry = traverser.rawNextFile(level)) != NULL){
+            hash.put(ReByteBuffer(entry->node(), -1), entry->m_path);
+            logF(false, "%d: %-12s %2d %s", 
+                level, entry->node(),
+                int(entry->fileSize()),
+                entry->m_path.str());
+        }
+        checkOneFile("x1.txt", "dir1_2_1", hash);
+        checkOneFile("x2.txt", "dir1_2_1", hash);
+        checkOneFile("dir1_2_1", "dir1_2", hash);
+        checkOneFile("dir1_1", "dir1", hash);
+        checkOneFile("dir1_2", "dir1", hash);
+        checkOneFile("dir1", m_base.str(), hash);
+
                //checkEqu("xy12.ab", nameOfEntry(entry));
        }
 };
index 098860eac1d49e5b4f0c131c56ff4138f1cf732b..052d38cf945a36120158d6e45ce1b7ca1e6ebc64 100644 (file)
@@ -37,13 +37,24 @@ HANDLE findFirstEntry(const char* path, DirInfoStruct_t* data){
 #define initEntryBuffer(entry) ((entry)->m_data = &(entry)->m_dataBuffer)\r
 #endif\r
 \r
-const char* DirStatus_t::nameOfEntry() const{\r
+const char* DirStatus_t::node() const{\r
 #ifdef __linux__\r
     return m_data->d_name;\r
 #elif defined __WIN32__\r
     return m_data->cFileName;\r
 #endif\r
 }\r
+bool DirStatus_t::isDotDir() const{\r
+#ifdef __linux__\r
+    bool rc = m_data->d_name[0] == '.' && (m_data->d_name[1] == '\0' \r
+        || (m_data->d_name[1] == '.' && m_data->d_name[2] == '\0'));\r
+#elif defined __WIN32__\r
+    bool rc = m_data->cFileName[0] == '.' && (m_data->cFileName[1] == '\0' \r
+        || (m_data->cFileName[1] == '.' && m_data->cFileName[2] == '\0'));\r
+#endif\r
+    return rc;\r
+}\r
+\r
 bool DirStatus_t::isDirectory() {\r
 #ifdef __linux__\r
     return (m_data->d_type != DT_UNKNOWN && m_data->d_type == DT_DIR) || S_ISDIR(getStatus()->st_mode);\r
@@ -144,7 +155,7 @@ bool DirEntryFilter_t::match(DirStatus_t& entry){
                        break;\r
                if (m_maxAge != 0 && DirStatus_t::filetimeToTime(entry.modified()) > m_maxAge)\r
                        break;\r
-               if (m_nodePatterns != NULL && ! m_nodePatterns->match(entry.nameOfEntry()))\r
+               if (m_nodePatterns != NULL && ! m_nodePatterns->match(entry.node()))\r
                        break;\r
                if (m_pathPatterns != NULL && ! m_pathPatterns->match(entry.m_path.str()))\r
                        break;\r
@@ -174,9 +185,10 @@ struct stat* DirStatus_t::getStatus() {
  */\r
 ReTraverser::ReTraverser(const char* base) :\r
        m_level(-1),\r
-       m_base(base)\r
+       m_base(base),\r
+    // m_dirs\r
+    m_passNoForDirSearch(2)\r
 {\r
-       initEntry(base, 0);\r
 }\r
 \r
 /**\r
@@ -198,16 +210,22 @@ ReTraverser::~ReTraverser() {
 DirStatus_t* ReTraverser::rawNextFile(int& level)\r
 {\r
        DirStatus_t* rc = NULL;\r
-       bool again = false;\r
+    bool alreadyRead = false;\r
+       bool again;\r
        do{\r
+        again = false;\r
                if (m_level < 0){\r
                        // first call:\r
-                       initEntry(m_base.str(), 0);\r
-                       if (! isUndefHandle(m_dirs[0].m_handle))\r
-                               rc = &m_dirs[0];\r
+                       if (initEntry(m_base.str(), NULL, 0)){\r
+                if (1 != m_passNoForDirSearch)\r
+                                   rc = &m_dirs[0];\r
+                else\r
+                    again = alreadyRead = true;\r
+            }\r
                } else {\r
-                       DirStatus_t* current = &m_dirs[level];\r
-                       if (findNextEntry(current->m_handle, current->m_data)){\r
+                       DirStatus_t* current = &m_dirs[m_level];\r
+                       if (alreadyRead || findNextEntry(current->m_handle, current->m_data)){\r
+                alreadyRead = false;\r
                                // a file or directory found:\r
                                if (current->m_passNo != m_passNoForDirSearch){\r
                                        // we search for any file:\r
@@ -215,35 +233,32 @@ DirStatus_t* ReTraverser::rawNextFile(int& level)
                                } else {\r
                                        // we are interested only in subdirectories:\r
                                        again = true;\r
-                                       if (rc->isDirectory()){\r
-                                               // open a new level:\r
-                                               level++;\r
-                                               m_base.append(ReTraverser::m_separatorStr);\r
-                                               m_base.append(rc->nameOfEntry());\r
-                                               initEntry(m_base.str(), level + 1);\r
+                    if (! current->isDotDir() && current->isDirectory()){\r
+                                               // open a new level\r
+                                               alreadyRead = initEntry(current->m_path, current->node() , m_level + 1);\r
                                        }\r
                                }\r
                        } else {\r
                                // the current subdir does not have more files:\r
                                if (current->m_passNo == 1){\r
                                        // we start the second pass:\r
-                                       initEntry(m_base.str(), m_level);\r
+                                       alreadyRead = initEntry(current->m_path, NULL, -1);\r
                                        current->m_passNo = 2;\r
-                                       if (! isUndefHandle(m_dirs[0].m_handle))\r
-                                               rc = &m_dirs[0];\r
-                                       else\r
-                                               again = true;\r
+                                       again = true;\r
                                } else {\r
-                                       // this subdirectory is complete. We go to the parent directory:\r
+                                       // this subdirectory is complete. We continue in the parent directory:\r
                                        closeDir(current->m_handle);\r
                                        setHandleUndef(current->m_handle);\r
-                                       if (--level > 0){\r
+                                       if ( --m_level > 0){\r
                                                again = true;\r
                                        }\r
                                }\r
                        }\r
                }\r
+        if (rc != NULL && rc->isDotDir())\r
+            again = true;\r
        } while(again);\r
+    level = m_level;\r
        return rc;\r
 }\r
 /**\r
@@ -272,19 +287,32 @@ DirStatus_t* ReTraverser::nextFile(int& level, DirEntryFilter_t* filter){
 /**\r
  * Initializes an entry in the directory entry stack.\r
  *\r
- * @param path         the name of the directory belonging to the entry\r
- * @param level        the index of the entry in the stack\r
+ * @param parent       the parent directory of the entry\r
+ * @param node      the name of the directory belonging to the entry (without path)\r
+ * @param level            the index of the entry in the stack.<br>\r
+ *                  If < 0: m_levels and m_path will not be changed\r
+ * @return          <code>true</code>: a new file is available<br>\r
+ *                  <cude>false/code>: findFirstEntry() signals: no entry.\r
  */\r
-void ReTraverser::initEntry(const char* path, int level){\r
+bool ReTraverser::initEntry(const ReByteBuffer& parent, const char* node, int level){\r
+    bool rc = false;\r
        if (level < MAX_ENTRY_STACK_DEPTH){\r
-               DirStatus_t* current = &m_dirs[level];\r
+        if (level >= 0)\r
+            m_level = level;\r
+               DirStatus_t* current = &m_dirs[m_level];\r
                initEntryBuffer(current);\r
-               current->m_handle = findFirstEntry(path, current->m_data);\r
-               if (! isUndefHandle(current->m_handle)){\r
-                       current->m_path.set(path, -1);\r
-               }\r
-               m_level = level;\r
+        current->m_passNo = 1;\r
+        if (level >= 0){\r
+            current->m_path.set(parent.str(), parent.length());\r
+            if (! parent.endsWith(m_separatorStr))\r
+                current->m_path.append(m_separatorStr);\r
+            if (node != NULL)\r
+                current->m_path.append(node).append(m_separatorStr);\r
+        }\r
+               current->m_handle = findFirstEntry(current->m_path.str(), current->m_data);\r
+               rc = ! isUndefHandle(current->m_handle);\r
        }\r
+    return rc;\r
 }\r
 \r
 /**\r
index 8ce31d8106b37b5fc789f13b22d57de369e7ffd2..0c928af11836fafd51688c2a74093cb04766da48 100644 (file)
@@ -36,14 +36,16 @@ typedef WIN32_FIND_DATAA DirInfoStruct_t;
 #endif
 class DirStatus_t{
 public:
-    const char* nameOfEntry() const;
+    const char* node() const;
     bool isDirectory();
     bool isLink();
     bool isRegular();
     FileSize_t fileSize();
     const FileTime_t* modified();
+    bool isDotDir() const;
 public:
        ReByteBuffer m_path;
+    // a pointer to the data:
        DirInfoStruct_t* m_data;
        FindFileHandle_t m_handle;
        int m_passNo;
@@ -85,7 +87,7 @@ public:
        DirStatus_t* rawNextFile(int& level);
        DirStatus_t* nextFile(int& level, DirEntryFilter_t* filter = NULL);
 protected:
-       void initEntry(const char* path, int level);
+       bool initEntry(const ReByteBuffer& parent, const char* node, int level);
        void freeEntry(int level);
 
 protected: