]> gitweb.hamatoma.de Git - crepublib/commitdiff
ReDirStatistic works
authorkawi <winfriedkappeler@atron.de>
Thu, 1 Jan 2015 22:31:47 +0000 (23:31 +0100)
committerkawi <winfriedkappeler@atron.de>
Thu, 1 Jan 2015 22:31:47 +0000 (23:31 +0100)
cunit/cuReTraverser.cpp
os/DirTools.hpp
os/ReDirTools.cpp
os/ReTraverser.cpp

index e4d448d71a092d732668aa4b66b9b94ef4283039..e6a8821a56e3a70fe1369118503ecd75a1b36cc6 100644 (file)
@@ -47,6 +47,7 @@ private:
         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");
+        makeFile("dir2/2.x");
     }
        void run(){
       initTree();
@@ -85,10 +86,34 @@ private:
                ReDirStatistic stat;
                const ReStringList& list = stat.calculate(m_base.str(), 1);
                ReByteBuffer buffer;
+        ReByteBuffer expected;
                log(false, list.join("\n", buffer).str());
                checkEqu(3u, list.count());
-               checkEqu("", list.strOf(0));
-       }
+        // "1  t:\temp\winfried\2\retestunit\dir1\n"
+        buffer.set(list.strOf(0), list.strLengthOf(0));
+        checkT(buffer.startsWith("1\t"));
+        expected.set(m_base.str(), m_base.length()).append("dir1", -1);
+        // .append(ReTraverser::m_separatorStr, -1)
+        checkT(buffer.endsWith(expected.str()));
+        
+        buffer.setLength(0);
+        const ReStringList& list2 = stat.calculate(m_base.str(), 1, formatWithSizeFilesAndDirs);
+               log(false, list2.join("\n", buffer).str());
+        
+        buffer.set(list.strOf(0), list.strLengthOf(0));
+        checkT(buffer.startsWith("      0.000116 MB       2       3\t"));
+        expected.set(m_base.str(), m_base.length()).append("dir1", -1);
+        checkT(buffer.endsWith(expected.str()));
+
+        buffer.set(list.strOf(1), list.strLengthOf(1));
+        checkT(buffer.startsWith("      0.000039 MB       1       0\t"));
+        expected.set(m_base.str(), m_base.length()).append("dir2", -1);
+        checkT(buffer.endsWith(expected.str()));
+
+        buffer.set(list.strOf(2), list.strLengthOf(2));
+        checkT(buffer.startsWith("      0.000191 MB       4       5\t"));
+        expected.set(m_base.str(), m_base.length());
+    }
 };
 extern void testReTraverser(void);
 
index 95041153827df5d9bd0d512af844f672a3a5c51c..f714b94b8ecaf8142540e48f9be2dab8ab957a2c 100644 (file)
@@ -26,6 +26,9 @@ public:
 class ReDirStatistic;
 extern void formatLikeDu(const ReDirStatisticData& data, ReDirStatistic& parent,
                        ReByteBuffer& line);
+extern void formatWithSizeFilesAndDirs(const ReDirStatisticData& data,
+                       ReDirStatistic& parent, ReByteBuffer& line);
+
 /**
  * Calculates a statistic of a directory tree.
  */
index cab433655097c4e91f397f11027b71de5129e4fa..de84c4232a1a9d01c766e99393b56b02f0274462 100644 (file)
@@ -93,6 +93,7 @@ const ReStringList& ReDirStatistic::calculate(const char* base, int level,
                level = 1024;
        else if (level < 0)
                level = 0;
+    m_list.clear();
        ReDirStatisticData** dataStack = new ReDirStatisticData*[level + 1];
        memset(dataStack, 0, sizeof dataStack[0] * (level + 1));
        dataStack[0] = new ReDirStatisticData();
@@ -103,17 +104,25 @@ const ReStringList& ReDirStatistic::calculate(const char* base, int level,
        current->m_path.set(base, -1);
        ReByteBuffer line;
        while( (entry = traverser.rawNextFile(currentDepth))){
-               if (! entry->m_path.equals(current->m_path)){
+               if (currentDepth <= level && ! entry->m_path.equals(current->m_path)){
                        if (currentDepth <= topOfStack){
-                               // close the entries of the stack above the new current:
-                               while(topOfStack > currentDepth){
+                               // close the entries of the stack above the new top level:
+                               while(topOfStack >= currentDepth){
                                        // Add the data to the parent:
-                                       dataStack[topOfStack - 1]->add(*dataStack[topOfStack]);
-                                       // Append it to the result:
-                                       (*formatter)(*dataStack[topOfStack - 1], *this, line);
+                    if (topOfStack > 0)
+                        dataStack[topOfStack - 1]->add(*dataStack[topOfStack]);
+                                       // Append it to the result:
+                                       (*formatter)(*dataStack[topOfStack], *this, line);
                                        m_list.append(line);
+                    topOfStack--;
                                }
-                       } else if (currentDepth < level){
+                // We reuse the top of stack:
+                topOfStack++;
+                current = dataStack[topOfStack];
+                // exchange the top of stack with the new found directory:
+                current->clear();
+                               current->m_path.set(entry->m_path.str(), entry->m_path.length());;
+                       } else {
                                // set up a new stack entry:
                                if (currentDepth != topOfStack + 1)
                                        assert(currentDepth == topOfStack + 1);
@@ -133,13 +142,18 @@ const ReStringList& ReDirStatistic::calculate(const char* base, int level,
                        current->m_files++;
                }
        }
+    // close all dirs with parents:
        while(topOfStack > 0){
                // Add the data to the parent:
                dataStack[topOfStack - 1]->add(*dataStack[topOfStack]);
                // Append it to the result:
-               (*formatter)(*dataStack[topOfStack - 1], *this, line);
+               (*formatter)(*dataStack[topOfStack], *this, line);
                m_list.append(line);
+        topOfStack--;
        }
+    // ... and the overall summery:
+    (*formatter)(*dataStack[0], *this, line);
+       m_list.append(line);
        // free the resources:
        for (int ix = 0; ix <= level; ix++)
                delete dataStack[ix];
@@ -161,5 +175,27 @@ const ReStringList& ReDirStatistic::calculate(const char* base, int level,
 void formatLikeDu(const ReDirStatisticData& data,
                        ReDirStatistic& parent, ReByteBuffer& line){
        line.setLength(0);
-       line.append(int(data.m_sizes / 1024)).append("\t").append(data.m_path);
+    // Round up to the next KiByte:
+       line.appendInt(int((data.m_sizes + 1023) / 1024)).append("\t").append(data.m_path);
+}
+
+/**
+ * Formats a line in a standard way: MBytes, file count and directory count.
+ *
+ * This is a possible parameter of <code>ReDirStatistic::calculate()</code>.
+ *
+ * @param data         statistic data, including path name
+ * @param parent       the caller (<code>ReDirStatistic</code>). This allows to deliver
+ *                                     a context to this formatting routine (through derivation of
+ *                                     <code>ReDirStatistic</code>)
+ * @param line         OUT: the formatted line, the conclusion of the statistic data
+ */
+void formatWithSizeFilesAndDirs(const ReDirStatisticData& data,
+                       ReDirStatistic& parent, ReByteBuffer& line){
+       line.setLength(0);
+    // Round up to the next KiByte:
+    char buffer[256];
+    snprintf(buffer, sizeof buffer, "%14.6f MB %7d %7d\t",
+        data.m_sizes / 1E6, data.m_files, data.m_dirs);
+       line.append(buffer, -1).append(data.m_path);
 }
index c870d9c54ef47f9fc3683c2af3ea0e7963adde4f..0ff17b3a93deb9631817301b3c9703d5dcddab5c 100644 (file)
@@ -25,7 +25,7 @@ const char* const ReTraverser::m_separatorStr = "\\";
 #define isUndefHandle(handle) ((handle) == INVALID_HANDLE_VALUE)\r
 #define setHandleUndef(h) ((h) = INVALID_HANDLE_VALUE)\r
 #define findNextEntry(handle, data) (FindNextFileA(handle, data) != 0)\r
-#define initEntryBuffer(entry) ((entry)->m_data = &(entry)->m_dataBuffer)\r
+#define initEntryBuffer(entry) ((entry)->m_data = &(entry)->m_data)\r
 #endif\r
 \r
 ReDirStatus_t::ReDirStatus_t() :\r
@@ -56,7 +56,7 @@ void ReDirStatus_t::freeEntry(){
        }\r
 #elif defined __WIN32__\r
        if (m_handle != INVALID_HANDLE_VALUE){\r
-               CloseDir(m_handle);\r
+               FindClose(m_handle);\r
                m_handle = INVALID_HANDLE_VALUE;\r
        }\r
 #endif\r
@@ -72,7 +72,7 @@ const char* ReDirStatus_t::node() const{
 #ifdef __linux__\r
     return m_data->d_name;\r
 #elif defined __WIN32__\r
-    return m_data->cFileName;\r
+    return m_data.cFileName;\r
 #endif\r
 }\r
 /**\r
@@ -85,8 +85,8 @@ bool ReDirStatus_t::isDotDir() const{
     bool rc = m_data == NULL || (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
+    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
@@ -136,7 +136,7 @@ bool ReDirStatus_t::isDirectory() {
 #ifdef __linux__\r
     return (m_data->d_type != DT_UNKNOWN && m_data->d_type == DT_DIR) || S_ISDIR(getStatus()->st_mode);\r
 #elif defined __WIN32__\r
-    return 0 != (m_dataBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
+    return 0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
 #endif\r
 }\r
 /**\r
@@ -151,7 +151,7 @@ bool ReDirStatus_t::isLink() {
 #ifdef __linux__\r
     rc = (m_data->d_type != DT_UNKNOWN && m_data->d_type == DT_LNK) || S_ISLNK(getStatus()->st_mode);\r
 #elif defined __WIN32__\r
-    rc = 0 != (m_dataBuffer.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT);\r
+    rc = 0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT);\r
 #endif\r
     return rc;\r
 }\r
@@ -164,7 +164,7 @@ bool ReDirStatus_t::isRegular() {
 #ifdef __linux__\r
     return (m_data->d_type != DT_UNKNOWN && m_data->d_type == DT_REG) || S_ISREG(getStatus()->st_mode);\r
 #elif defined __WIN32__\r
-    return 0 != (m_dataBuffer.dwFileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE));\r
+    return 0 != (m_data.dwFileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE));\r
 #endif\r
 }\r
 /**\r
@@ -176,7 +176,7 @@ FileSize_t ReDirStatus_t::fileSize() {
 #ifdef __linux__\r
     return getStatus()->st_size;\r
 #elif defined __WIN32__\r
-    return ((int64_t) m_dataBuffer.nFileSizeHigh << 32) + m_dataBuffer.nFileSizeLow;\r
+    return ((int64_t) m_data.nFileSizeHigh << 32) + m_data.nFileSizeLow;\r
 #endif\r
 }\r
 /**\r
@@ -188,7 +188,7 @@ const FileTime_t* ReDirStatus_t::modified() {
 #ifdef __linux__\r
     return &(getStatus()->st_mtime);\r
 #elif defined __WIN32__\r
-    return &m_dataBuffer.ftLastWriteTime;\r
+    return &m_data.ftLastWriteTime;\r
 #endif\r
 }\r
 \r
@@ -361,7 +361,7 @@ ReDirStatus_t* ReTraverser::rawNextFile(int& level)
                                } else {\r
                                        // this subdirectory is complete. We continue in the parent directory:\r
                                        current->freeEntry();\r
-                                       if ( --m_level > 0){\r
+                                       if ( --m_level >= 0){\r
                                                again = true;\r
                                        }\r
                                }\r