]> gitweb.hamatoma.de Git - crepublib/commitdiff
dirtool "statistic" works.
authorkawi <winfriedkappeler@atron.de>
Sat, 3 Jan 2015 00:46:49 +0000 (01:46 +0100)
committerkawi <winfriedkappeler@atron.de>
Sat, 3 Jan 2015 00:46:49 +0000 (01:46 +0100)
13 files changed:
base/ReDirectory.cpp
base/ReProgramArgs.cpp
base/ReStringList.cpp
base/ReStringUtils.cpp
base/ReTestUnit.cpp
cunit/cuReDirectory.cpp
cunit/cuReI18N.cpp
cunit/cuReProgramArgs.cpp
cunit/cuReStringList.cpp
cunit/cuReTraverser.cpp
cunit/testall.cpp
os/ReDirTools.cpp
os/ReDirTools.hpp [new file with mode: 0644]

index 5bbf67fc6260447804c9307deeb064e9933b6c23..80adc7caf13ab592b39a408bfa389b6c8e59a435 100644 (file)
@@ -85,7 +85,10 @@ void ReDirectory::setDir(const char* path){
        }
 #elif defined __WIN32__
     struct stat info;
-    m_valid = stat(path, &info) == 0 && S_ISDIR(info.st_mode);
+    ReByteBuffer thePath(m_path);
+    if (m_path.endsWith(ReStringUtils::pathSeparatorStr()))
+        thePath.setLength(thePath.length() - 1);
+    m_valid = stat(thePath.str(), &info) == 0 && S_ISDIR(info.st_mode);
 #endif
 }
 /** @brief Returns the name of the directory.
@@ -145,7 +148,9 @@ bool ReDirectory::findFirst(const char* pattern, bool isRegExpr){
                        rc = findNext();
                }
 #elif defined __WIN32__
-        m_handle = FindFirstFileA(pattern, &m_data);
+        ReByteBuffer full(m_path);
+        full.append(ReStringUtils::pathSeparatorStr(), -1).append(pattern, -1);
+        m_handle = FindFirstFileA(full.str(), &m_data);
         rc = m_handle != INVALID_HANDLE_VALUE;
 #endif
        }
index 2996ef5b4a0ac849b2c59bc6c1a5f096f608b086..5293e50b557dc816393c1268e928e3e5003ebe34 100644 (file)
@@ -76,6 +76,7 @@ ReProgramArgs::ReProgramArgs(const char* usageString, const char* examples)
        m_values(),
        m_args(NULL),
        m_argCount(0),
+    m_program("?"),
        m_lastError()
 {
        m_usage.split(usageString, '\n');
@@ -195,11 +196,11 @@ bool ReProgramArgs::getBool(const char* name) {
        ReByteBuffer buffer;
        ReVarArgs args;
        if (! m_properties.get(name, -1, buffer))
-               ReOptionException(this, i18n("$1 is not an option name"), name);
+               throw ReOptionException(this, i18n("$1 is not an option name"), name);
 
        properties.split(buffer.str(), '\1');
        if (properties.strOf(IxType)[0] != 'b')
-               ReOptionException(this, i18n("$1 is not an boolean option. Type is $2"), name,
+               throw ReOptionException(this, i18n("$1 is not an boolean option. Type is $2"), name,
                        properties.strOf(IxType));
 
        m_values.get(name, -1, buffer);
@@ -220,11 +221,11 @@ int ReProgramArgs::getInt(const char* name) {
        ReByteBuffer buffer;
        ReVarArgs args;
        if (! m_properties.get(name, -1, buffer))
-               ReOptionException(this, i18n("$1 is not an option name"), name);
+               throw ReOptionException(this, i18n("$1 is not an option name"), name);
 
        properties.split(buffer.str(), '\1');
        if (properties.strOf(IxType)[0] != DT_INT)
-               ReOptionException(this, i18n("$1 is not an integer option. Type is $2"), name,
+               throw ReOptionException(this, i18n("$1 is not an integer option. Type is $2"), name,
                        properties.strOf(IxType));
 
        m_values.get(name, -1, buffer);
@@ -244,12 +245,12 @@ const char* ReProgramArgs::getString(const char* name, ReByteBuffer& buffer) {
        ReStringList properties;
        ReVarArgs args;
        if (! m_properties.get(name, -1, buffer))
-               ReOptionException(this, i18n("$1 is not an option name"), name);
+               throw ReOptionException(this, i18n("$1 is not an option name"), name);
 
        properties.split(buffer.str(), '\1');
        DataType dataType = (DataType) properties.strOf(IxType)[0];
        if (dataType != DT_STRING && dataType != DT_STRING_EMPTY)
-               ReOptionException(this, i18n("$1 is not a string option. Type is $2"), name,
+               throw ReOptionException(this, i18n("$1 is not a string option. Type is $2"), name,
                        properties.strOf(IxType));
 
        m_values.get(name, -1, buffer);
@@ -321,7 +322,7 @@ void ReProgramArgs::search(char shortName, const char* longName,
                        name.set(&shortName, 1);
                else
                        name.set(longName, lengthLongName);
-               ReOptionException(this, i18n("Unknown option: $1"), name.str());
+               throw ReOptionException(this, i18n("Unknown option: $1"), name.str());
        }
 }
 /** @brief Sets the option value.
@@ -334,12 +335,12 @@ void ReProgramArgs::setValue(const char* name, const char* value, const char* da
        switch(dataType[0]){
        case DT_INT:
                if (strspn(value, "01234567890") != strlen(value))
-                       ReOptionException(this, i18n("Option $1 expect an integer as parameter, not $2"),
+                       throw ReOptionException(this, i18n("Option $1 expect an integer as parameter, not $2"),
                                        name, value);
                break;
        case DT_STRING:
                if (value[0] == '\0')
-                       ReOptionException(this, i18n("Option $1: Empty parameter is not allowed"), name);
+                       throw ReOptionException(this, i18n("Option $1: Empty parameter is not allowed"), name);
                break;
        case DT_STRING_EMPTY:
        case DT_BOOL:
@@ -392,7 +393,7 @@ bool ReProgramArgs::analyseShort(const char* opt, const char* nextArg){
                                        if (dataType[0] == DT_STRING_EMPTY)
                                                setValue(nameStr, "", dataType);
                                        else
-                                               ReOptionException(this, i18n("Option $1 has type $2! There is no parameter."),
+                                               throw ReOptionException(this, i18n("Option $1 has type $2! There is no parameter."),
                                                        nameStr, dataType);
                                } else {
                                        setValue(nameStr, nextArg, dataType);
@@ -443,14 +444,14 @@ void ReProgramArgs::analyseLong(const char* opt){
        switch(dataType[0]){
        case DT_INT:
                if (value == NULL)
-                       ReOptionException(this, i18n("Option $1: parameter expected. Use --$2=number"),
+                       throw ReOptionException(this, i18n("Option $1: parameter expected. Use --$2=number"),
                                        nameStr, nameStr);
                else
                        setValue(nameStr, value, dataType);
                break;
        case DT_STRING:
                if (value == NULL)
-                       ReOptionException(this, i18n("Option $1: parameter expected. Use --$2=string"),
+                       throw ReOptionException(this, i18n("Option $1: parameter expected. Use --$2=string"),
                                        nameStr, nameStr);
                setValue(nameStr, value, dataType);
                break;
@@ -467,7 +468,7 @@ void ReProgramArgs::analyseLong(const char* opt){
                        boolValue = "t";
                else if (!  ReStringUtils::isInList(value, ReConfigFile::m_falseValues,
                                true, ReStringUtils::AUTO_SEPARATOR))
-                       ReOptionException(this, i18n("Option $1: Not a boolean value: $2. Use true or false"),
+                       throw ReOptionException(this, i18n("Option $1: Not a boolean value: $2. Use true or false"),
                                        nameStr, value);
                // Invert the default value:
                if (properties.strOf(IxDefault)[0] == 't')
index bb10fb44d7b4f56261e35bd616890ce1325d96e6..de559c6217b6e21b18d7e75b331e15bf837d17f2 100644 (file)
@@ -29,7 +29,7 @@ ReStringList::~ReStringList() {
  * @return                     the instance itself (for chaining)
  */
 ReStringList& ReStringList::append(const char* source, Tag tagOf){
-       add(-1, source, -1, tagOf);
+       add(-1, source, strlen(source) + 1, tagOf);
        return *this;
 }
 /** @brief Appends a string at the end.
@@ -40,7 +40,7 @@ ReStringList& ReStringList::append(const char* source, Tag tagOf){
  * @return                     the instance itself (for chaining)
  */
 ReStringList& ReStringList::append(const ReByteBuffer& source, Tag tagOf){
-       add(-1, source.str(), source.length(), tagOf);
+       add(-1, source.str(), source.length() + 1, tagOf);
        return *this;
 }
 
@@ -51,7 +51,7 @@ ReStringList& ReStringList::append(const ReByteBuffer& source, Tag tagOf){
  */
 ReStringList& ReStringList::append(ReStringList& source){
        for (size_t ii = 0; ii < source.count(); ii++)
-               add(-1, source.strOf(ii), -1, source.tagOf(ii));
+               add(-1, source.strOf(ii), source.sizeOf(ii), source.tagOf(ii));
        return *this;
 }
 /** @brief Inserts a string at a given index.
@@ -63,7 +63,7 @@ ReStringList& ReStringList::append(ReStringList& source){
  *                                     This class knows nothing about this.
  */
 void ReStringList::insert(Index index, const char* source, Tag tagOf){
-       add(index, source, -1, tagOf);
+       add(index, source, strlen(source) + 1, tagOf);
 }
 /** @brief Replaces an element in the internal array: a string and a tagOf.
  *
@@ -72,7 +72,7 @@ void ReStringList::insert(Index index, const char* source, Tag tagOf){
  * @param tagOf                The tagOf of the replace element.
  */
 void ReStringList::replace(Index index, const char* source, Tag tagOf){
-       set(index, source, -1, tagOf);
+       set(index, source, strlen(source) + 1, tagOf);
 }
 /** @brief Replaces a string in the internal array.
  *
@@ -84,7 +84,7 @@ void ReStringList::replace(Index index, const char* source, Tag tagOf){
 void ReStringList::replaceString(Index index, const char* source){
        if (index < count()){
                Sequence* seq = getInfo(index);
-               set(index, source, -1, seq->m_tag);
+               set(index, source, strlen(source) + 1, seq->m_tag);
        }
 }
 /** @brief Replaces a tagOf in the internal array.
index e3dc4761eaa230624556e57aa2c8451943a6b572..544c02246f2e991629c55ce2ecb273a3d406680e 100644 (file)
@@ -7,8 +7,13 @@
 
 #include "base/rebase.hpp"
 
-char ReStringUtils::slash = ReStringUtils::initPathSeparator();
-const char* ReStringUtils::slashStr = NULL;
+#if defined __linux__
+char ReStringUtils::slash = '/';
+const char* ReStringUtils::slashStr = "/";
+#elif defined __WIN32__
+char ReStringUtils::slash = '\\';
+const char* ReStringUtils::slashStr = "\\";
+#endif
 const char ReStringUtils::AUTO_SEPARATOR = '\0';
 
 
@@ -70,6 +75,7 @@ char ReStringUtils::initPathSeparator(){
  */
 void ReStringUtils::splitPath(const char* fullname,
        ReByteBuffer* protocol, ReByteBuffer* path, ReByteBuffer* name, ReByteBuffer* ext){
+    const char currentSlash = strchr(fullname, '/') != NULL ? '/' : slash;
        const char* start = strchr(fullname, ':');
        if (protocol != NULL){
                protocol->setLength(0);
@@ -81,7 +87,7 @@ void ReStringUtils::splitPath(const char* fullname,
        else
                start++;
 
-       const char* end = strrchr(start, slash);
+       const char* end = strrchr(start, currentSlash);
 
        if (path != 0){
                path->setLength(0);
index 6fa2297abae5b2c8a0a4cd0365bd6a882d0de7db..c08eab37253288b68c181b87d142dcd2f07d37a2 100644 (file)
@@ -24,7 +24,7 @@ ReTestUnit::ReTestUnit(const char* name, const char* sourceFile)
  */
 ReTestUnit::~ReTestUnit() {
        if (m_errorCount > 0)
-               logF(true, i18n("%s: %d error(s)"), m_name, m_errorCount);
+               logF(false, i18n("+++ %s: %d error(s)"), m_name, m_errorCount);
        free((void*) m_name);
        free((void*) m_sourceFile);
 }
@@ -38,7 +38,6 @@ void ReTestUnit::assertTrue(bool condition, int lineNo)
 {
        if (! condition){
                logF(true, i18n("%s-%d: not true!"), m_sourceFile, lineNo);
-               m_errorCount++;
        }
 }
 /** @brief Checks a boolean expression. A true value will be logged.
@@ -51,7 +50,6 @@ void ReTestUnit::assertFalse(bool condition, int lineNo)
 {
        if (condition){
                logF(true, i18n("%s-%d: not false!"), m_sourceFile, lineNo);
-               m_errorCount++;
        }
 }
 /** @brief Checks a pointer expression. A not <code>null</code> value will be logged.
@@ -63,7 +61,6 @@ void ReTestUnit::assertFalse(bool condition, int lineNo)
 void ReTestUnit::assertNull(void* pointer, int lineNo){
        if (pointer != NULL){
                logF(true, "%s-%d: is not null %lx", m_sourceFile, lineNo, pointer);
-               m_errorCount++;
        }
 }
 /** @brief Checks a pointer expression. A <code>null</code> value will be logged.
@@ -75,7 +72,6 @@ void ReTestUnit::assertNull(void* pointer, int lineNo){
 void ReTestUnit::assertNotNull(void* pointer, int lineNo){
        if (pointer == NULL){
                logF(true, i18n("%s-%d: is null"), m_sourceFile, lineNo);
-               m_errorCount++;
        }
 }
 /** @brief Compares two integer values. If not equal this will be logged.
@@ -88,7 +84,6 @@ void ReTestUnit::assertEqual(int expected, int current, int lineNo){
        if (expected != current){
                logF(true, i18n("%s-%d: expected: %ld (%lx) current: %ld (%lx)"),
                        m_sourceFile, lineNo, expected, expected, current, current);
-               m_errorCount++;
        }
 }
 /** @brief Compares two integer values. If not equal this will be logged.
@@ -101,7 +96,6 @@ void ReTestUnit::assertEqual(unsigned int expected, unsigned int current, int li
        if (expected != current){
                logF(true, i18n("%s-%d: expected: %ld (%lx) current: %ld (%lx)"),
                        m_sourceFile, lineNo, expected, expected, current, current);
-               m_errorCount++;
        }
 }
 /** @brief Compares two integer values. If not equal this will be logged.
@@ -114,7 +108,6 @@ void ReTestUnit::assertEqual(int64_t expected, int64_t current, int lineNo){
        if (expected != current){
                logF(true, i18n("%s-%d: expected: %lld (%llx) current: %lld (%llx)"),
                        m_sourceFile, lineNo, expected, expected, current, current);
-               m_errorCount++;
        }
 }
 /** @brief Compares two string values. If not equal this will be logged.
@@ -128,7 +121,6 @@ void ReTestUnit::assertEqual(const char* expected, const char* current, int line
                logF(true, i18n("%s-%d: expected / current: length: %d / %d\n%.512s\n%.512s"),
                        m_sourceFile, lineNo, strlen(expected), current == NULL ? 0 : strlen(current),
                                expected, current == NULL ? "<null>" : current);
-               m_errorCount++;
        }
 }
 /** @brief Checks whether a file exists. If not this will be logged.
@@ -141,11 +133,9 @@ void ReTestUnit::assertFileExists(const char* name, int lineNo){
        if (stat(name, &info) != 0){
                logF(true, i18n("%s-%d: File does not exist: %s"),
                        m_sourceFile, lineNo, name);
-               m_errorCount++;
        } else if (S_ISDIR(info.st_mode)){
                logF(true, i18n("%s-%d: File does exist but this is a directory: %s"),
                        m_sourceFile, lineNo, name);
-               m_errorCount++;
        }
 }
 /** @brief Creates an empty temporary directory.
@@ -219,11 +209,9 @@ void ReTestUnit::assertDirExists(const char* dir, int lineNo){
        if (stat(dir, &info) != 0){
                logF(true, i18n("%s-%d: Directory does not exist: %s"),
                        m_sourceFile, lineNo, dir);
-               m_errorCount++;
        } else if (! S_ISDIR(info.st_mode)){
                logF(true, i18n("%s-%d: File exists but this is not a directory: %s"),
                        m_sourceFile, lineNo, dir);
-               m_errorCount++;
        }
 }
 
@@ -238,6 +226,8 @@ void ReTestUnit::assertDirExists(const char* dir, int lineNo){
  */
 bool ReTestUnit::log(bool isError, const char* message){
        printf("%s%s\n", isError ? "+++ " : "", message);
+    if (isError)
+        m_errorCount++;
        return ! isError;
 }
 /** @brief Logs a formated message with placeholders.
index abfae0771115fbe651918cb89cce449914f6675a..566e4e57778948b2a1c7b5d29018ddbf9fce6b1c 100644 (file)
@@ -27,13 +27,14 @@ private:
                checkEqu("abc.2.txt", finder.currentFile());
                checkF(finder.findNext());
                checkF(finder.findFirst("abx.*.txt", false));
-
+#ifdef __linux__
                checkT(finder.findFirst("abc[.][0-9][.]txt", true));
                checkEqu("abc.1.txt", finder.currentFile());
                checkT(finder.findNext());
                checkEqu("abc.2.txt", finder.currentFile());
                checkF(finder.findNext());
                checkF(finder.findFirst("abx[.][0-9][.]txt", true));
+#endif
        }
 };
 extern void testReDirectory(void);
index b19a92969f728b0f2eb1d6f7b1146f4bb002556b..6f14ae28dcafc443dca21b4802508171a6b54a69 100644 (file)
@@ -10,8 +10,8 @@ public:
        }
 private:
        void run(){
-               checkEqu("dies ist ein Test", i18n("this is a test"));
-               checkEqu("eins: 1 zwei: 2", i18nf("one: $1 two: $2").arg(1).arg(2).asCString());
+               checkEqu("this is a test", i18n("this is a test"));
+               checkEqu("one: 1 two: 2", i18nf("one: $1 two: $2").arg(1).arg(2).asCString());
 
        }
 };
index 293217659359675d03c653ea978547fe10e90744..b41e5bd3d8d576ab712c3bc241cb9ba240c76cd5 100644 (file)
@@ -12,7 +12,19 @@ private:
        void run(){
                testLong();
                testShort();
+        testWrong();
        }
+    void testWrong(){
+               ReProgramArgs args("test","example");
+               args.addBool("boolarg", "This is a boolean arg", 'b', "boolval", false);
+        try {
+            char* argv[] = { "test", "-v" };
+            args.init(2, argv);
+            checkF(true);
+        } catch (ReOptionException& exc) {
+            checkEqu("Unknown option: v", exc.getMessage());
+        }
+    }
        void testShort(){
                ReProgramArgs args("test <opts> <args>\nThis tests the usage of ReProgramArgs",
                                "$0 -b+ -B- file dir\n\ttest of an example");
index 23b527feded2bfed6c6433814e0c0b15cf8e81f3..cc2452cdfc64bfb74556caae7b47c8c0f52d3394 100644 (file)
@@ -18,9 +18,11 @@ private:
                ReStringList list;
                ReByteBuffer line;
                line.set("Hi", -1);
-               list.append(line, 1ll).append(line.append("!", -1), -5ll);
+        list.append(line, 99ll);
+        line.append("!", -1);
+               list.append(line, -5ll);
                checkEqu(2u, list.count());
-               checkEqu(1ll, list.tagOf(0));
+               checkEqu(99ll, list.tagOf(0));
                checkEqu("Hi", list.strOf(0));
 
                checkEqu(-5ll, list.tagOf(1));
index e6a8821a56e3a70fe1369118503ecd75a1b36cc6..ffc974e4dd8569646ec56ff0aaa01ff9575532de 100644 (file)
@@ -13,6 +13,8 @@ public:
        TestReTraverser() : ReTestUnit("ReTraverser", __FILE__){
         createTestDir();
         m_base = getTestDir();
+        m_base.append("traverser").append(ReTraverser::m_separatorStr, -1);
+        _mkdir(m_base.str());
                run();
        }
 private:
@@ -32,7 +34,7 @@ private:
         ReByteBuffer path(m_base);
         path.append("/").append(relPath);
         path.replaceAll("/", 1, ReTraverser::m_separatorStr, -1);
-        createFile(path.str(), path.str());
+        createFile(path.str(), relPath);
         struct stat info;
         if (stat(path.str(), &info) != 0){
             logF(true, "cannot create file %1$s", path.str());
@@ -92,7 +94,8 @@ private:
         // "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);
+        expected.set(m_base.str(), m_base.length()).append("dir1", -1)
+            .append(ReTraverser::m_separatorStr);
         // .append(ReTraverser::m_separatorStr, -1)
         checkT(buffer.endsWith(expected.str()));
         
@@ -101,17 +104,19 @@ private:
                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.startsWith("      0.000054 MB       2       3\t"));
+        expected.set(m_base.str(), m_base.length()).append("dir1", -1)
+             .append(ReTraverser::m_separatorStr);
         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.startsWith("      0.000008 MB       1       0\t"));
+        expected.set(m_base.str(), m_base.length()).append("dir2", -1)
+             .append(ReTraverser::m_separatorStr);
         checkT(buffer.endsWith(expected.str()));
 
         buffer.set(list.strOf(2), list.strLengthOf(2));
-        checkT(buffer.startsWith("      0.000191 MB       4       5\t"));
+        checkT(buffer.startsWith("      0.000067 MB       4       5\t"));
         expected.set(m_base.str(), m_base.length());
     }
 };
index 2bdc36a63a234702f4d5f2f5b0ee422e615c9bd4..8165b131eaff5722c351bff91015ce13f8709426 100644 (file)
@@ -25,15 +25,18 @@ void testBase(){
        testReString();
        extern void testReVarArgs(void);
        testReVarArgs();
-       extern void testReLogger(void);
-       testReLogger();
        extern void testReDirectory(void);
        testReDirectory();
        extern void testReProgramArgs(void);
        testReProgramArgs();
+       extern void testReLogger(void);
+       testReLogger();
 }
 void testString(){
-       void testReString();
+       extern void testReStringList(void);
+       testReStringList();
+
+    void testReString();
        testReString();
        extern void testReI18N(void);
        testReI18N();
@@ -53,9 +56,9 @@ void testOs(){
 void testAll(){
        try
        {
+               testString();
                testOs();
                testBase();
-               testString();
        } catch (ReException e){
                fprintf(stderr, "testBase.cpp: unexpected exception: %s\n", e.getMessage());
        }
index 497f39706cc40ac0b59106b1e6bdbe72043d8e11..e746646bd9a81d0774f813593a50d95d4716469a 100644 (file)
@@ -227,15 +227,47 @@ void ReDirTools::usage(const char* msg, const char* msg2){
     exit(1);
 }
 
+static const char* statisticCall[] = {
+    "<command>:"
+    "st(atistic)  [<opts_stat>] <path> [<depth>]",
+    "          shows a statistic about a directory tree",
+    "<path>    a directory path: relative or absolute",
+    "<depth>   0: only the summary of <path> will be shown",
+    "          1: shows the summery of each subdir of <path> and the total",
+    "          n: shows the summery of each subdir until level <n> and the total",
+    "          default: 1",
+    "<opts_stat>:",
+    "--quiet",
+    "-q    no additional information, e.g. runtime",
+    "--trace-interval=<n>",
+    "-t<n> trace the current path every <n> seconds.",
+    "      If n<=0: no trace. Default: 60",
+    "--kbyte",
+    "-k    output is '<kbyte> path' (like du)",
+    NULL
+};
+const char* statisticExamples[] = {
+    "Examples:",
+    "dirtool st -q -t0 e:\\windows",  
+    "dirtool statistic --quiet --kbyte --trace-interval=60 ../mail 2",  
+    "dirtool stat -q --kbyte d:data 2",  
+    NULL
+};
+
+static void printField(const char** lines){
+    for (int ix = 0; lines[ix] != NULL; ix++){
+        printf("%s\n", lines[ix]);
+    }
+}
 /**
  * Prints an message how to use the statistic module and exits.
  */
 void ReDirTools::statisticUsage(){
-    printf ("<command>:\nstatistic <path> [<depth>] [<opts_stat>]\n");
-    printf ("<opts_stat>:\n  -v   verbose\n -t<n>  trace interval\n");
-    printf ("example: dirtool statistic c:\\windows 2 -v -t60\n");
+    printField(statisticCall); 
+    printField(statisticExamples); 
 }
 
+
 /**
  * Gets the arguments for the "statistic" command and execute this.
  *
@@ -244,30 +276,53 @@ void ReDirTools::statisticUsage(){
  */
 void ReDirTools::dirStatistic(int argc, char* argv[]){
     time_t start = time(NULL);
-    bool verbose = true;
-    int traceInterval = 60;
-    if (argc < 1)
-        usage("statistic: missing path");
-    int depth = 1;
-    if (argc > 1)
-        depth = atol(argv[1]);
-    ReDirStatistic statistic;
-    statistic.setTraceInterval(traceInterval);
-    const ReStringList& list = statistic.calculate(argv[0], depth, formatWithSizeFilesAndDirs);
-    ReByteBuffer buffer;
-    for (size_t ix = 0; ix < list.count(); ix++){
-        buffer.set(list.strOf(ix), list.strLengthOf(ix));
-        printf("%s\n", buffer.str());
-    }
-    if (verbose){
-        int duration = int(time(NULL) - start);
-        printf("Duration: ");
-        if (duration >= 3600)
-            printf("%d:", duration / 3600);
-        printf("%02d:%02d\n", duration % 3600 / 60, duration % 60);
+       ReProgramArgs args(statisticCall, statisticExamples);
+    args.addBool("quiet", "no additional information", 'q', "quiet", false);
+    args.addBool("kbyte", "output is '<kbyte> <path>'", 'k', "kbyte", false);
+    args.addInt("trace", "trace each <n> seconds the current path", 't', "trace-interval", 60);
+    try {
+        args.init(argc, argv);
+        if (args.getArgCount() < 1)
+            usage("statistic: missing path");
+        int depth = 1;
+        if (args.getArgCount() > 1)
+            depth = atol(args.getArg(1));
+        ReDirStatistic statistic;
+        statistic.setTraceInterval(args.getInt("trace"));
+        void (*proc) (const ReDirStatisticData& data,
+                           ReDirStatistic& parent, ReByteBuffer& line) = &formatWithSizeFilesAndDirs;
+        if (args.getBool("kbyte"))
+            proc = &formatLikeDu;
+        const ReStringList& list = statistic.calculate(args.getArg(0), depth, proc);
+        ReByteBuffer buffer;
+        for (size_t ix = 0; ix < list.count(); ix++){
+            buffer.set(list.strOf(ix), list.strLengthOf(ix));
+            printf("%s\n", buffer.str());
+        }
+        if (! args.getBool("quiet")){
+            int duration = int(time(NULL) - start);
+            printf("Duration: ");
+            if (duration >= 3600)
+                printf("%d:", duration / 3600);
+            printf("%02d:%02d\n", duration % 3600 / 60, duration % 60);
+        }
+    } catch (ReOptionException& exc) {
+        usage(exc.getMessage());
     }
 }
 
+/**
+ * Tests whether a abrevation of an argument is given.
+ * @param full      the full name
+ * @param part      the part to test
+ * @return          <code>true</code>: part is a prefix of full
+ */
+static bool isArg(const char* full, const char* part){
+    ReByteBuffer fullArg(full);
+    bool rc = fullArg.startsWith(part, -1);
+    return rc;
+}
+
 /**
  * Gets the arguments for any command and execute this.
  *
@@ -278,9 +333,12 @@ int ReDirTools::main(int argc, char* argv[]){
     ReDirTools tools;
     if (argc < 2)
         tools.usage("missing arguments");
-    if (strcmp(argv[1], "statistic") == 0)
-        tools.dirStatistic(argc - 2, argv + 2);
-    else
+    if (isArg("statistic", argv[1]))
+        tools.dirStatistic(argc - 1, argv + 1);
+    else if (isArg("test", argv[1])){
+        void testAll();
+        testAll();
+    }else
         tools.usage("command not implemented: ", argv[1]);
         //testOs();
        ReLogger::freeGlobalLogger();
diff --git a/os/ReDirTools.hpp b/os/ReDirTools.hpp
new file mode 100644 (file)
index 0000000..3e8cf8c
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * DirTools.hpp
+ *
+ *  Created on: 30.12.2014
+ *      Author: hm
+ */
+
+#ifndef OS_DIRTOOLS_HPP_
+#define OS_DIRTOOLS_HPP_
+
+class ReDirStatisticData{
+public:
+       ReDirStatisticData();
+       ReDirStatisticData(const ReDirStatisticData& source);
+       ReDirStatisticData& operator =(const ReDirStatisticData& source);
+public:
+       void clear();
+       ReDirStatisticData& add(const ReDirStatisticData& source);
+public:
+       int64_t m_sizes;
+       int m_files;
+       int m_dirs;
+       ReByteBuffer m_path;
+};
+
+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.
+ */
+class ReDirStatistic {
+public:
+       ReDirStatistic(int deltaList = 512, int deltaBuffer = 0x10000);
+       ~ReDirStatistic();
+public:
+       const ReStringList& calculate(const char* base, int depth,
+                               void (*format)(const ReDirStatisticData& data, ReDirStatistic& parent,
+                                       ReByteBuffer& line) = formatLikeDu);
+    void setTraceInterval(int interval){
+        m_traceInterval = interval;
+    }
+private:
+       ReStringList m_list;
+    int m_traceInterval;
+    time_t m_lastTrace;
+};
+
+class ReDirTools {
+public:
+    virtual void usage(const char* msg, const char* msg2 = NULL);
+    void statisticUsage();
+    void dirStatistic(int argc, char* argv[]);
+public:
+    static int main(int argc, char* argv[]);
+public:
+    static const char* m_version;
+};
+#endif /* OS_DIRTOOLS_HPP_ */