From 4cf2a3ad98c00a9ab1cb6bdfe686e6bf54a7be44 Mon Sep 17 00:00:00 2001 From: Hamatoma Date: Wed, 4 Feb 2015 23:25:21 +0100 Subject: [PATCH] Refactoring: ReTool --- os/ReDirTools.cpp | 73 ++++++++++++++++++++++++++++++++------------ os/ReDirTools.hpp | 47 +++++++++++++++++----------- os/ReTraverser.cpp | 52 ++++++++++++++++--------------- os/ReTraverser.hpp | 8 ++--- string/ReMatcher.hpp | 20 ++++++++++-- 5 files changed, 130 insertions(+), 70 deletions(-) diff --git a/os/ReDirTools.cpp b/os/ReDirTools.cpp index 087bf9d..f125b6b 100644 --- a/os/ReDirTools.cpp +++ b/os/ReDirTools.cpp @@ -23,7 +23,7 @@ enum LOCATION_DIRTOOL { LC_SET_PROPERTIES_2, // 50110 LC_SET_PROPERTIES_3, // 50111 }; -const char* ReDirTools::m_version = "2015.01.30"; +const char* ReDirTools::m_version = "2015.02.04"; static const char* s_helpSummary[] = { "dirtool or dt ", @@ -118,6 +118,8 @@ ReDirOptions::ReDirOptions(const char* usage[], const char* examples[]) : m_output(stdout), m_verboseLevel(V_NORMAL) { + m_nodePatterns.setIgnoreCase(true); + m_pathPatterns.setIgnoreCase(true); } /** * Destructor. @@ -176,8 +178,8 @@ void ReDirOptions::addStandardFilterOptions(){ "A directory will be entered if at least one of the positive patterns\n" "and none of the 'not patterns' matches\n" "examples:\n" - "';*/music/;pic*' enters music and xy/Music and PIC and pictures but not xy/pic and img\n" - "';*;-*/.git;.hg' ignores .git and xy/z/.git and .ht, but enters xy/.hg"), + "';music;pic*' enters music and xy/Music and PIC and pictures but not xy/pic and img\n" + "';*;-.git;.hg' ignores .git and xy/z/.git and .ht"), 'P', "path-pattern", false, NULL); m_programArgs.addString("nodepattern", i18n("a list of patterns for the basename (name without path) separated by ';'\n" @@ -357,6 +359,9 @@ const char* ReDirOptions::checkPatternList(const char* value){ throw ReOptionException(&m_programArgs, i18n("invalid separator (first character): $1 use ';' instead"), value); + if (strchr(value, OS_SEPARATOR_CHAR) != NULL) + throw ReOptionException(&m_programArgs, + i18n("slash not allowed in pattern list: $2"), value); return value; } /** @@ -559,6 +564,44 @@ void ReDirOptions::setFilterFromProgramArgs(ReDirEntryFilter_t& filter){ } } } + +/** + * Constructor. + * + * @param usage a string vector with a message how to use the command + * @param example a string vector with some examples how to use the command + */ +ReTool::ReTool(const char* usage[], const char* example[]) : + ReDirOptions(usage, example), + ReDirStatisticData(), + m_traverser(NULL) +{ +} + +/** + * Destructor. + */ +ReTool::~ReTool(){ +} + +/** + * Prints a message. + * + * Often overwritten by a subclass. + * + * @param currentFile message for the trace + * @return true (for chaining) + */ +bool ReTool::trace(const char* currentFile){ + ReByteBuffer buffer(" "); + int duration = int(time(NULL) - m_startTime); + buffer.appendInt(duration / 60).appendInt(duration % 60, ":%02d: "); + buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser->directories()).append(" dir(s)"); + buffer.appendInt(m_files).append("/", 1).appendInt(m_traverser->files()).append(" dir(s)"); + buffer.append(currentFile); + fputs(buffer.str(), stdout); + return true; +} /** * Constructor. */ @@ -604,8 +647,9 @@ ReDirStatistic::ReDirStatistic(int deltaList, int deltaBuffer) : m_traceInterval(0), m_lastTrace(0) { + // standard short options: D d O o P p T t v y Z z m_programArgs.addBool("kbyte", - i18n("output is ' ' (like unix 'du' command)"), + i18n("output format is ' ' (like unix 'du' command)"), 'k', "kbyte", false); addStandardFilterOptions(); } @@ -645,10 +689,10 @@ void ReDirStatisticData::clear(){ const ReStringList& ReDirStatistic::calculate(const char* base, int level, void (*formatter)(const ReDirStatisticData& data, ReDirStatistic& parent, ReByteBuffer& line)){ - ReDirEntryFilter_t filter; + ReDirEntryFilter_t filter; ReTraverser traverser(base); - setFilterFromProgramArgs(filter); - traverser.setPropertiesFromFilter(&filter); + setFilterFromProgramArgs(filter); + traverser.setPropertiesFromFilter(&filter); if (level > 1024) level = 1024; else if (level < 0) @@ -663,7 +707,6 @@ const ReStringList& ReDirStatistic::calculate(const char* base, int level, ReDirStatisticData* current = dataStack[0]; current->m_path.set(base, -1); ReByteBuffer line; - int traceCount = 0; bool useFilter = filter.m_minSize > 0 || filter.m_maxSize != -1 || filter.m_minAge != 0 || filter.m_maxAge != 0 || m_nodePatterns.count() > 0; @@ -705,14 +748,6 @@ const ReStringList& ReDirStatistic::calculate(const char* base, int level, } else if (! useFilter || filter.match(*entry)){ current->m_sizes += entry->fileSize(); current->m_files++; - if (++traceCount % 100 == 0 && m_traceInterval > 0){ - time_t now = time(NULL); - int diff = int(now - m_lastTrace); - if (diff >= m_traceInterval){ - fprintf(m_output, "%s\n", current->m_path.str()); - m_lastTrace = now; - } - } } } // close all dirs with parents: @@ -848,7 +883,7 @@ void ReDirTools::usage(const char* msg, const char* msg2){ * Constructor. */ ReDirList::ReDirList() : - ReDirOptions(s_listUsage, s_listExamples) + ReTool(s_listUsage, s_listExamples) { m_programArgs.addBool("short", i18n("output is only path and basename"), '1', "--short", false); @@ -915,7 +950,7 @@ void ReDirList::list(int argc, const char* argv[]){ * Constructor. */ ReDirBatch::ReDirBatch() : - ReDirOptions(s_batchUsage, s_batchExamples) + ReTool(s_batchUsage, s_batchExamples) { // standard short options: D d O o P p T t v y Z z m_programArgs.addString("first", @@ -1093,7 +1128,7 @@ void ReDirSync::makeDirWithParents(ReByteBuffer& path, int minWidth, * Constructor. */ ReDirSync::ReDirSync() : - ReDirOptions(s_syncUsage, s_syncExamples), + ReTool(s_syncUsage, s_syncExamples), m_buffer() { // standard short options: D d O o P p T t v y Z z diff --git a/os/ReDirTools.hpp b/os/ReDirTools.hpp index d5053a1..0cd22aa 100644 --- a/os/ReDirTools.hpp +++ b/os/ReDirTools.hpp @@ -10,7 +10,7 @@ #ifndef OS_DIRTOOLS_HPP_ #define OS_DIRTOOLS_HPP_ -class ReDirOptions : ReTraceUnit{ +class ReDirOptions : public ReTraceUnit{ public: enum VerboseLevel { V_UNDEF, @@ -72,7 +72,32 @@ typedef struct { } ReFileProperties_t; #endif -class ReDirBatch : public ReDirOptions { +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 ReTool : public ReDirOptions, public ReDirStatisticData { +public: + ReTool(const char* usage[], const char* example[]); + virtual ~ReTool(); +public: + virtual bool trace(const char* currentFile); +protected: + ReTraverser* m_traverser; +}; + +class ReDirBatch : public ReTool { public: ReDirBatch(); public: @@ -81,7 +106,7 @@ public: { return false; } }; -class ReDirSync : public ReDirOptions { +class ReDirSync : public ReTool { public: ReDirSync(); public: @@ -101,7 +126,7 @@ protected: ReByteBuffer m_buffer; }; -class ReDirList : public ReDirOptions { +class ReDirList : public ReTool { public: ReDirList(); public: @@ -111,20 +136,6 @@ public: }; -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, diff --git a/os/ReTraverser.cpp b/os/ReTraverser.cpp index 8d38ce8..d3f13bc 100644 --- a/os/ReTraverser.cpp +++ b/os/ReTraverser.cpp @@ -383,25 +383,27 @@ struct stat* ReDirStatus_t::getStatus() { return &m_status; } #endif - -/** -* Constructor. -* -* @param triggerCount efficiency: only every N calls a time check takes place -* @param interval the minimum number of seconds between two traces -*/ -ReTraceUnit::ReTraceUnit(int triggerCount, int interval) : - m_count(0), - m_triggerCount(triggerCount), - m_lastTrace(time(NULL)), - m_interval(interval) -{ -} -/** - * Destructor. - */ -ReTraceUnit::~ReTraceUnit(){ -} + +/** +* Constructor. +* +* @param triggerCount efficiency: only every N calls a time check takes place +* @param interval the minimum number of seconds between two traces +*/ +ReTraceUnit::ReTraceUnit(int triggerCount, int interval) : + m_count(0), + m_triggerCount(triggerCount), + m_lastTrace(0), + m_interval(interval), + m_startTime(time(NULL)) +{ + m_lastTrace = m_startTime; +} +/** + * Destructor. + */ +ReTraceUnit::~ReTraceUnit(){ +} /** * Prints a message. @@ -411,10 +413,10 @@ ReTraceUnit::~ReTraceUnit(){ * @param message message for the trace * @return true (for chaining) */ -bool ReTraceUnit::trace(const char* message){ - printf("%d\n", message); - return true; -} +bool ReTraceUnit::trace(const char* message){ + printf("%d\n", message); + return true; +} /** * Constructor. @@ -502,8 +504,8 @@ ReDirStatus_t* ReTraverser::rawNextFile(int& level) again = true; if (m_level < m_maxLevel && current->isDirectory() && ! current->isDotDir() && ! current->isLink() - && (m_dirPatterns == NULL || isAllowedDir(current->m_path, - current->node()))){ + && (m_dirPatterns == NULL + || isAllowedDir(current->node()))){ // open a new level alreadyRead = initEntry(current->m_path, current->node() , m_level + 1); m_directories++; diff --git a/os/ReTraverser.hpp b/os/ReTraverser.hpp index cb4b1b6..b37766d 100644 --- a/os/ReTraverser.hpp +++ b/os/ReTraverser.hpp @@ -128,6 +128,7 @@ protected: int m_triggerCount; time_t m_lastTrace; int m_interval; + time_t m_startTime; }; #define MAX_ENTRY_STACK_DEPTH 256 class ReTraverser { @@ -180,15 +181,12 @@ protected: void freeEntry(int level); /** * Tests whether a directory should be processed. - * @param path the path of the subdir * @param node the base name of the subdir * @return true: the subdir will be processed
* false: do not enter this subdir */ - inline bool isAllowedDir(ReByteBuffer& path, const char* node){ - int ix = path.length(); - bool rc = m_dirPatterns->match(path.append(node)); - path.setLength(ix); + inline bool isAllowedDir(const char* node){ + bool rc = m_dirPatterns->match(node); return rc; } protected: diff --git a/string/ReMatcher.hpp b/string/ReMatcher.hpp index e12bd41..5e34f1c 100644 --- a/string/ReMatcher.hpp +++ b/string/ReMatcher.hpp @@ -77,6 +77,12 @@ public: virtual bool match(const ReByteBuffer& toTest, ReHit* hit = NULL) const; virtual bool search(const ReByteBuffer& toTest, ReHit* hit = NULL, bool greedy = false) const; + /** Sets the mode whether the case will be ignored or not. + * @param onNotOff true: the case will be ignored. + */ + void setIgnoreCase(bool onNotOff){ + m_ignoreCase = onNotOff; + } const char* status(ReByteBuffer& buffer, const char* prefix) const; protected: bool searchTokens(const ReByteBuffer& toTest, int from, int to, @@ -84,9 +90,10 @@ protected: private: ReByteBuffer m_pattern; ReStringList m_tokens; + bool m_ignoreCase; }; -class RePatternList{ +class RePatternList { public: RePatternList(); ~RePatternList(); @@ -110,11 +117,18 @@ public: /** Returns the original pattern string. * @return the string describing the patterns. */ - const char* patternString() const - { return m_patternString.str(); } + const char* patternString() const + { return m_patternString.str(); } void set(const char* patterns, bool ignoreCase = false, const char* separator = NULL, const char* notPrefix = "-"); const char* status(ReByteBuffer& buffer, const char* prefix) const; + /** Sets the mode whether the case will be ignored or not. + * @param onNotOff true: the case will be ignored. + */ + void setIgnoreCase(bool onNotOff){ + for (int ii = 0; ii < m_count; ii++) + m_patterns[ii]->setIgnoreCase(onNotOff); + } private: int setOne(int index, const char* pattern, size_t patternLength, bool ignoreCase, const ReByteBuffer& notPrefix); -- 2.39.5