From d76f2ca534a051fa4e4822c91a4ff7a4cc544888 Mon Sep 17 00:00:00 2001 From: kawi Date: Sat, 3 Jan 2015 01:46:49 +0100 Subject: [PATCH] dirtool "statistic" works. --- base/ReDirectory.cpp | 9 ++- base/ReProgramArgs.cpp | 27 ++++----- base/ReStringList.cpp | 12 ++-- base/ReStringUtils.cpp | 12 +++- base/ReTestUnit.cpp | 16 +----- cunit/cuReDirectory.cpp | 3 +- cunit/cuReI18N.cpp | 4 +- cunit/cuReProgramArgs.cpp | 12 ++++ cunit/cuReStringList.cpp | 6 +- cunit/cuReTraverser.cpp | 19 ++++--- cunit/testall.cpp | 11 ++-- os/ReDirTools.cpp | 112 +++++++++++++++++++++++++++++--------- os/ReDirTools.hpp | 62 +++++++++++++++++++++ 13 files changed, 225 insertions(+), 80 deletions(-) create mode 100644 os/ReDirTools.hpp diff --git a/base/ReDirectory.cpp b/base/ReDirectory.cpp index 5bbf67f..80adc7c 100644 --- a/base/ReDirectory.cpp +++ b/base/ReDirectory.cpp @@ -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 } diff --git a/base/ReProgramArgs.cpp b/base/ReProgramArgs.cpp index 2996ef5..5293e50 100644 --- a/base/ReProgramArgs.cpp +++ b/base/ReProgramArgs.cpp @@ -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') diff --git a/base/ReStringList.cpp b/base/ReStringList.cpp index bb10fb4..de559c6 100644 --- a/base/ReStringList.cpp +++ b/base/ReStringList.cpp @@ -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. diff --git a/base/ReStringUtils.cpp b/base/ReStringUtils.cpp index e3dc476..544c022 100644 --- a/base/ReStringUtils.cpp +++ b/base/ReStringUtils.cpp @@ -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); diff --git a/base/ReTestUnit.cpp b/base/ReTestUnit.cpp index 6fa2297..c08eab3 100644 --- a/base/ReTestUnit.cpp +++ b/base/ReTestUnit.cpp @@ -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 null 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 null 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 ? "" : 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. diff --git a/cunit/cuReDirectory.cpp b/cunit/cuReDirectory.cpp index abfae07..566e4e5 100644 --- a/cunit/cuReDirectory.cpp +++ b/cunit/cuReDirectory.cpp @@ -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); diff --git a/cunit/cuReI18N.cpp b/cunit/cuReI18N.cpp index b19a929..6f14ae2 100644 --- a/cunit/cuReI18N.cpp +++ b/cunit/cuReI18N.cpp @@ -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()); } }; diff --git a/cunit/cuReProgramArgs.cpp b/cunit/cuReProgramArgs.cpp index 2932176..b41e5bd 100644 --- a/cunit/cuReProgramArgs.cpp +++ b/cunit/cuReProgramArgs.cpp @@ -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 \nThis tests the usage of ReProgramArgs", "$0 -b+ -B- file dir\n\ttest of an example"); diff --git a/cunit/cuReStringList.cpp b/cunit/cuReStringList.cpp index 23b527f..cc2452c 100644 --- a/cunit/cuReStringList.cpp +++ b/cunit/cuReStringList.cpp @@ -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)); diff --git a/cunit/cuReTraverser.cpp b/cunit/cuReTraverser.cpp index e6a8821..ffc974e 100644 --- a/cunit/cuReTraverser.cpp +++ b/cunit/cuReTraverser.cpp @@ -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()); } }; diff --git a/cunit/testall.cpp b/cunit/testall.cpp index 2bdc36a..8165b13 100644 --- a/cunit/testall.cpp +++ b/cunit/testall.cpp @@ -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()); } diff --git a/os/ReDirTools.cpp b/os/ReDirTools.cpp index 497f397..e746646 100644 --- a/os/ReDirTools.cpp +++ b/os/ReDirTools.cpp @@ -227,15 +227,47 @@ void ReDirTools::usage(const char* msg, const char* msg2){ exit(1); } +static const char* statisticCall[] = { + ":" + "st(atistic) [] []", + " shows a statistic about a directory tree", + " a directory path: relative or absolute", + " 0: only the summary of will be shown", + " 1: shows the summery of each subdir of and the total", + " n: shows the summery of each subdir until level and the total", + " default: 1", + ":", + "--quiet", + "-q no additional information, e.g. runtime", + "--trace-interval=", + "-t trace the current path every seconds.", + " If n<=0: no trace. Default: 60", + "--kbyte", + "-k output is ' 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 (":\nstatistic [] []\n"); - printf (":\n -v verbose\n -t 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 ' '", 'k', "kbyte", false); + args.addInt("trace", "trace each 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 true: 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 index 0000000..3e8cf8c --- /dev/null +++ b/os/ReDirTools.hpp @@ -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_ */ -- 2.39.5