]> gitweb.hamatoma.de Git - crepublib/commitdiff
"dirtool list" command implemented
authorkawi <winfriedkappeler@atron.de>
Sat, 3 Jan 2015 23:41:18 +0000 (00:41 +0100)
committerkawi <winfriedkappeler@atron.de>
Sat, 3 Jan 2015 23:41:18 +0000 (00:41 +0100)
base/ReProgramArgs.cpp
base/ReProgramArgs.hpp
cunit/cuReProgramArgs.cpp
cunit/cuReTraverser.cpp
os/ReDirTools.cpp
os/ReDirTools.hpp
os/ReTraverser.cpp
os/ReTraverser.hpp

index 29bd3e49880be36629640c21bf34e3353128bf0c..ce7d449b7454efc289ddf07036c9e038da8673e6 100644 (file)
@@ -61,6 +61,7 @@ ReProgramArgs::ReProgramArgs(const char* usageList[], const char* examples[])
                }
        }
 }
+
 /** @brief Constructor.
  *
  * @param usage                A string with the description of the usage.
@@ -97,6 +98,16 @@ ReProgramArgs::ReProgramArgs(const char* usageString, const char* examples)
 ReProgramArgs::~ReProgramArgs() {
 }
 
+/**
+ * Sets the usage message.
+ *
+ * @param usage     a vector of lines without '\n'
+ */
+void ReProgramArgs::setUsage(const char* usage[]){
+    m_usage.clear();
+    for (int ix = 0; usage[ix] != NULL; ix++)
+        m_usage.append(usage[ix]);
+}
 /** @brief Puts the property infos into the property string.
  *
  * The <strong>property string</strong> is a string stored in the hashlist.
index a07b08ec452fa381f822476d4d894a53785d67c0..b5243d428a72792269447e489e4e2c82396702c1 100644 (file)
@@ -72,6 +72,7 @@ public:
        void setLastError(const char* message);
        void help(const char* message, bool issueLastError, ReStringList& lines);
        void help(const char* message, bool issueLastError, FILE* stream);
+    void setUsage(const char* usage[]);
 
 private:
        void addProperties(const char*name, const char* description, char shortOpt,
@@ -80,7 +81,7 @@ private:
        void setValue(const char* name, const char* value, const char* dataType);
        bool analyseShort(const char* opt, const char* nextArg);
        void analyseLong(const char* opt);
-private:
+protected:
        ReStringList    m_usage;
        ReStringList    m_examples;
        ReHashList              m_properties;
index b41e5bd3d8d576ab712c3bc241cb9ba240c76cd5..eb05e1f7efcb42ced229b8ecb6013041d002f649 100644 (file)
@@ -13,6 +13,7 @@ private:
                testLong();
                testShort();
         testWrong();
+        testSetUsage();
        }
     void testWrong(){
                ReProgramArgs args("test","example");
@@ -69,6 +70,19 @@ private:
 
                args.help("Not really an error!", false, stdout);
        }
+    void testSetUsage(){
+        class MyArgs : public ReProgramArgs {
+        public:
+            MyArgs() : ReProgramArgs("", "example") {}
+        public:
+            ReStringList& usage() { return m_usage; }
+        };
+        MyArgs args;
+        const char* usage[] = { "x1", "x2", NULL };
+        args.setUsage(usage);
+        checkEqu("x1", args.usage().strOf(0));
+        checkEqu("x2", args.usage().strOf(1));
+    }
        void testLong(){
                const char* call[] = {
                                "test <opts> <args>",
index 59cf55e9a4f310d9186786b040af2fa4bc20e085..81151daf2f5aec8f9c95b304e1f17f592a253fff 100644 (file)
@@ -79,8 +79,8 @@ private:
         static const char* usage2[] = { "x1", "x2", "x3", NULL };
         MyOptions opts;
         opts.initCompoundUsage(sizeof usage1 + sizeof usage2);
-        opts.addCompundUsage(usage1);
-        opts.addCompundUsage(usage2);
+        opts.addCompoundUsage(usage1);
+        opts.addCompoundUsage(usage2);
         checkEqu(7, opts.count());
         checkEqu("line1", opts.usage()[0]);
         checkEqu("line2", opts.usage()[1]);
@@ -113,7 +113,7 @@ private:
         char* argv[] = { "x", "-y1970.01.02", "-o1970.01.03", 
             "-D5", "-d1", "-z1k", "-Z2M", "*"
         };
-        DirEntryFilter_t filter;
+        ReDirEntryFilter_t filter;
         opts.programArgs().init(sizeof argv / sizeof argv[0], argv);
         opts.setFilterFromProgramArgs(filter);
         // local time: +3600
index 2180298caaa4cd97a93a8cff11d2abb589fdd4ae..28a707af5e4e8c9d450cf142cbd6ea81af6ac726 100644 (file)
@@ -10,6 +10,8 @@
 
 const char* ReDirTools::m_version = "2015.01.03";
 
+static const char* s_empty[] = { NULL };
+
 static const char* s_standardFilterUsage[] = {
     "-D<n> or --max-depth=<n> Default: 512",
     "   the depth of the subdirectory is lower or equal <n>",
@@ -22,6 +24,20 @@ static const char* s_standardFilterUsage[] = {
     "   <v> is a date (e.g. 2015.02.17) or number followed by an unit",
     "   units: m(inutes) h(hours), d(days). Default: m(inutes)",
     "   examples: -o25 --older-than=30d -o24h -o2009.3.2/12:00 -o1999.01.01",
+    "-P<p> or --pathname-pattern=<p>",
+    "   a list of patterns for the path (without basename) separated by ';'",
+    "   Each pattern can contain '*' as wildcard",
+    "   If the first character is '^' the pattern is a 'not pattern':"
+    "   A directory will be entered if at least one of the positive patterns and none",
+    "   of the 'not patterns' matches",
+    "   examples: '*;^*/.git/' '*/cache/;*/temp/",
+    "-p<p> or --basename-pattern=<p>",
+    "   a list of patterns for the basename (filename without path) separated by ';'",
+    "   Each pattern can contain '*' as wildcard",
+    "   If the first character is '^' the pattern is a 'not pattern':"
+    "   A file will be found if at least one of the positive patterns and none",
+    "   of the 'not patterns' matches",
+    "   examples: '*.cpp;*.hpp;Make*' '*;^*.bak;^*~",
     "-t<l> or --type=<l>",
     "   the file type",
     "   <l> is a list of <v> values:",
@@ -50,6 +66,49 @@ const char* s_listUsage[] = {
     "   lists the metadata (size, modification date ...) of the selected files",
     NULL
 };
+const char* s_listExamples[] = {
+    "dirtool list --min-size=10M e:\\data",
+    "dirtool list --type=f -y7d --size=10M -p*.cpp;*.hpp;Makefile*;^*~ /home/data" ,
+    NULL
+};
+
+static const char* s_helpSummary[] = {
+    "dirtool or dt <command> <opts>",
+    "   Useful commands around a directry tree",
+    "   Type 'dirtool help <command>' for more help",
+    "<command>:",
+    "help          shows info about the arguments/options",
+    "list          shows the meta data of the selected files",
+    "statistic     shows statistics about a direcctory tree",
+    NULL
+};
+
+static const char* s_statisticUsage[] = {
+    "<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>:",
+    "-q or --quiet",
+    "   does not show additional information, e.g. runtime",
+    "-t<n> or --trace-interval=<n>",
+    "   trace the current path every <n> seconds.",
+    "   If n<=0: no trace. Default: 60",
+    "-k or --kbyte",
+    "   output is '<kbyte> path' (like du)",
+    NULL
+};
+const char* s_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
+};
 
 
 /**
@@ -60,7 +119,8 @@ const char* s_listUsage[] = {
  */
 ReDirOptions::ReDirOptions(const char* usage[], const char* examples[]) :
     m_programArgs(usage, examples),
-    m_patternList(),
+    m_nodePatterns(),
+    m_pathPatterns(),
     m_compoundUsage(NULL),
     m_countCompoundUsage(0)
 {
@@ -87,7 +147,7 @@ void ReDirOptions::initCompoundUsage(size_t size){
  * Adds a usage component to the compound usage message list.
  * @param usage     a string vector containing a part of the usage message
  */
-void ReDirOptions::addCompundUsage(const char** usage){
+void ReDirOptions::addCompoundUsage(const char** usage){
     int start = 0;
     while(m_compoundUsage[start] != NULL)
         assert(++start < m_countCompoundUsage);
@@ -108,6 +168,8 @@ void ReDirOptions::addStandardFilterOptions(){
     m_programArgs.addString("younger", "younger than", 'y', "younger-than", false, NULL);
     m_programArgs.addString("maxsize", "maximal filesize", 'Z', "max-size", false, NULL);
     m_programArgs.addString("minsize", "minimal filesize", 'z', "min-size", false, NULL);
+    m_programArgs.addString("nodepattern", "pattern list for the basename", 'p', "basename-pattern", false, NULL);
+    m_programArgs.addString("pathpattern", "pattern list for the path", 'P', "path-pattern", false, NULL);
 }
 
 /**
@@ -237,24 +299,41 @@ time_t ReDirOptions::checkSize(const char* value){
  *
  * @param filter    OUT: the filter to set
  */
-void ReDirOptions::setFilterFromProgramArgs(DirEntryFilter_t& filter){
+void ReDirOptions::setFilterFromProgramArgs(ReDirEntryFilter_t& filter){
     ReByteBuffer buffer;
-    if (m_programArgs.getString("younger", buffer) != NULL)
-        filter.m_maxAge = checkDate(m_programArgs.getString("younger", buffer));
-    if (m_programArgs.getString("older", buffer) != NULL)
-        filter.m_minAge = checkDate(m_programArgs.getString("older", buffer));
-    if (m_programArgs.getString("maxsize", buffer) != NULL)
-        filter.m_maxSize = checkSize(m_programArgs.getString("maxsize", buffer));
-    if (m_programArgs.getString("minsize", buffer) != NULL)
-        filter.m_minSize = checkSize(m_programArgs.getString("minsize", buffer));
+    if (m_programArgs.getString("younger", buffer)[0] != '\0')
+        filter.m_maxAge = checkDate(buffer.str());
+    if (m_programArgs.getString("older", buffer)[0] != '\0')
+        filter.m_minAge = checkDate(buffer.str());
+    if (m_programArgs.getString("maxsize", buffer)[0] != '\0')
+        filter.m_maxSize = checkSize(buffer.str());
+    if (m_programArgs.getString("minsize", buffer)[0] != '\0')
+        filter.m_minSize = checkSize(buffer.str());
     filter.m_minDepth = m_programArgs.getInt("mindepth");
     filter.m_maxDepth = m_programArgs.getInt("maxdepth");
-    if (m_programArgs.getArgCount() > 0)
-    {
-        m_patternList.set(m_programArgs.getArg(0));
-        filter.m_nodePatterns = &m_patternList;
+    if (m_programArgs.getString("nodepattern", buffer) != NULL){
+        m_nodePatterns.set(buffer.str());
+        filter.m_nodePatterns = &m_nodePatterns;
+    }
+    if (m_programArgs.getString("pathpattern", buffer) != NULL){
+        m_pathPatterns.set(buffer.str());
+        filter.m_pathPatterns = &m_nodePatterns;
     }
 }
+/**
+ * Prints a help message, the error message and exits.
+ *
+ * @param errorMessage  the error message.
+ * @param message2      an additional message
+ */
+
+void ReDirOptions::help(const char* errorMessage, const char* message2 ){
+    ReByteBuffer msg(errorMessage, -1);
+    if (message2 != NULL)
+        msg.append(message2, -1);
+    m_programArgs.help(msg.str(), false, stdout);
+    exit(1);
+}
 /**
  * Checks the correctness of the standard filter options.
  * 
@@ -490,33 +569,11 @@ 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>:",
-    "-q or --quiet",
-    "   does not show additional information, e.g. runtime",
-    "-t<n> or --trace-interval=<n>",
-    "   trace the current path every <n> seconds.",
-    "   If n<=0: no trace. Default: 60",
-    "-k or --kbyte",
-    "   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
-};
-
+/**
+ * Prints a vector of lines.
+ * 
+ * @param lines     a vector of lines without newline ('\n')
+ */
 static void printField(const char** lines){
     for (int ix = 0; lines[ix] != NULL; ix++){
         printf("%s\n", lines[ix]);
@@ -527,8 +584,55 @@ static void printField(const char** lines){
  * Prints an message how to use the statistic module and exits.
  */
 void ReDirTools::statisticUsage(){
-    printField(statisticCall); 
-    printField(statisticExamples); 
+    printField(s_statisticUsage); 
+    printField(s_statisticExamples); 
+}
+
+/**
+ * Constructor.
+ */
+ReDirList::ReDirList() :
+    ReDirOptions(s_empty, s_listExamples)
+{
+    addStandardFilterOptions();
+    initCompoundUsage(sizeof s_listUsage + sizeof s_standardFilterUsage);
+    addCompoundUsage(s_listUsage);
+    addCompoundUsage(s_standardFilterUsage);
+    m_programArgs.setUsage(m_compoundUsage);
+}
+
+/**
+ * Gets the arguments for the "list" command and execute this.
+ *
+ * @param argc      the number of arguments
+ * @param argav     the argument vector
+ */
+void ReDirList::list(int argc, char* argv[]){
+    ReDirEntryFilter_t filter;
+    try {
+        m_programArgs.init(argc, argv);
+        setFilterFromProgramArgs(filter);
+        if (m_programArgs.getArgCount() == 0)
+            help(i18n("no arguments given (missing path)"));
+        ReByteBuffer bufferRights;
+        ReByteBuffer bufferTime;
+        for (int ix = 0; ix < m_programArgs.getArgCount(); ix++){
+            ReTraverser traverser(m_programArgs.getArg(ix));
+            traverser.setMinLevel(filter.m_maxDepth);
+            traverser.setMaxLevel(filter.m_maxDepth);
+            int level;
+            ReDirStatus_t* entry;
+            while( (entry = traverser.nextFile(level, &filter)) != NULL){
+                if (! printOneFile(entry))
+                    printf("%s %12lld %s %s%s\n",
+                    entry->rightsAsString(bufferRights), entry->fileSize(), 
+                    entry->filetimeAsString(bufferTime), 
+                    entry->m_path.str(), entry->node());
+            }
+        }
+    } catch(ReOptionException& exc){
+        help(exc.getMessage());
+    }
 }
 
 /**
@@ -538,6 +642,8 @@ void ReDirTools::statisticUsage(){
  * @param argav     the argument vector
  */
 void ReDirTools::list(int argc, char* argv[]){
+    ReDirList lister;
+    lister.list(argc, argv);
 }
 
 
@@ -549,7 +655,7 @@ void ReDirTools::list(int argc, char* argv[]){
  */
 void ReDirTools::statistic(int argc, char* argv[]){
     time_t start = time(NULL);
-       ReProgramArgs args(statisticCall, statisticExamples);
+       ReProgramArgs args(s_statisticUsage, s_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);
@@ -595,14 +701,6 @@ static bool isArg(const char* full, const char* part){
     bool rc = fullArg.startsWith(part, -1);
     return rc;
 }
-static const char* helpSummary[] = {
-    "dirtool or dt <command> <opts>",
-    "<command>:",
-    "help          shows info about the arguments/options",
-    "list          shows info about selected files",
-    "statistic     shows statistics about a direcctory tree",
-    NULL
-};
 /**
  * Gets the arguments for any command and execute this.
  *
@@ -613,13 +711,16 @@ int ReDirTools::main(int argc, char* argv[]){
     ReDirTools tools;
     if (argc < 2)
         tools.usage("missing arguments");
-    if (isArg("list", argv[1]))
-        tools.list(argc - 1, argv + 1);
-    else if (isArg("help", argv[1]))
-        printField(helpSummary);
-    else if (isArg("statistic", argv[1]))
-        tools.statistic(argc - 1, argv + 1);
-    else if (isArg("test", argv[1])){
+    argc--;
+    argv++;
+    const char* arg0 = argv[0];
+    if (isArg("list", arg0))
+        tools.list(argc, argv);
+    else if (isArg("help", arg0))
+        printField(s_helpSummary);
+    else if (isArg("statistic", arg0))
+        tools.statistic(argc, argv);
+    else if (isArg("test", arg0)){
         void testAll();
         testAll();
     }else
index 1992563df1ee219d6d32b37203cb15fa52c683e8..53d4e7d04bb6569c8dc5b1a33eb88ab58f63c515 100644 (file)
@@ -16,24 +16,30 @@ public:
     void addStandardFilterOptions();
     void checkStandardFilterOptions();
     void initCompoundUsage(size_t size);
-    void addCompundUsage(const char** usage);
+    void addCompoundUsage(const char** usage);
     const char** compoundUsage() const
     { return m_compoundUsage; }
     ReProgramArgs& programArgs()
     { return m_programArgs; }
     time_t checkDate(const char* value);
     int64_t checkSize(const char* value);
-    void setFilterFromProgramArgs(DirEntryFilter_t& filter);
+    void setFilterFromProgramArgs(ReDirEntryFilter_t& filter);
+    void help(const char* errorMessage, const char* message2 = NULL);
 protected:
     ReProgramArgs m_programArgs;
-    RePatternList m_patternList;
+    RePatternList m_nodePatterns;
+    RePatternList m_pathPatterns;
     const char** m_compoundUsage;
     int m_countCompoundUsage;
 };
 
 class ReDirList : public ReDirOptions {
+public:
+    ReDirList();
 public:
     void list(int argc, char* argv[]);
+    virtual bool printOneFile(ReDirStatus_t* entry)
+    { return false; }
 };
 class ReDirStatisticData{
 public:
index 9facff4196a35fc4bedcf61340b9f737cc4315c8..f2f9d14b7ee01afd582b8f870c81c9aa85e43c71 100644 (file)
@@ -66,6 +66,33 @@ const char* ReDirStatus_t::node() const{
     return m_data.cFileName;\r
 #endif\r
 }\r
+/**\r
+ * Returns the file rights as a string.\r
+ *\r
+ * @param buffer    OUT: the file rights\r
+ * @return          <code>buffer.str()</code> (for chaining)\r
+ */\r
+const char* ReDirStatus_t::rightsAsString(ReByteBuffer& buffer) {\r
+    buffer.setLength(0);\r
+#if defined __linux__\r
+#elif defined __WIN32__\r
+#endif\r
+    return buffer.str();\r
+}\r
+\r
+/**\r
+ * Returns the file time as a string.\r
+ *\r
+ * @param buffer    OUT: the file time\r
+ * @return          <code>buffer.str()</code> (for chaining)\r
+ */\r
+const char* ReDirStatus_t::filetimeAsString(ReByteBuffer& buffer) {\r
+    time_t time1 = filetimeToTime(modified());\r
+    struct tm* time2 = localtime(&time1);\r
+    buffer.setLength(4+2*1+2*2+1+3*2+2*1);\r
+    strftime(buffer.buffer(), buffer.length(), "%y.%m.%d %H:%M:%S", time2);\r
+    return buffer.str();\r
+}\r
 /**\r
  * Tests whether the instance contains data about "." or "..".\r
  *\r
@@ -218,7 +245,7 @@ void  ReDirStatus_t::timeToFiletime(time_t time, FileTime_t& filetime){
 /**\r
  * Constructor.\r
  */\r
-DirEntryFilter_t::DirEntryFilter_t() :\r
+ReDirEntryFilter_t::ReDirEntryFilter_t() :\r
        m_regulars(true),\r
        m_specials(true),\r
        m_directories(true),\r
@@ -236,12 +263,12 @@ DirEntryFilter_t::DirEntryFilter_t() :
 /**\r
  * Destructor.\r
  */\r
-DirEntryFilter_t::~DirEntryFilter_t(){\r
+ReDirEntryFilter_t::~ReDirEntryFilter_t(){\r
 }\r
 /**\r
  *\r
  */\r
-bool DirEntryFilter_t::match(ReDirStatus_t& entry){\r
+bool ReDirEntryFilter_t::match(ReDirStatus_t& entry){\r
        bool rc = false;\r
        do {\r
                if (! m_directories && entry.isDirectory())\r
@@ -288,6 +315,8 @@ struct stat* ReDirStatus_t::getStatus() {
  */\r
 ReTraverser::ReTraverser(const char* base) :\r
        m_level(-1),\r
+    m_minLevel(0),\r
+    m_maxLevel(512),\r
        m_base(base),\r
     // m_dirs\r
     m_passNoForDirSearch(2)\r
@@ -350,7 +379,8 @@ ReDirStatus_t* ReTraverser::rawNextFile(int& level)
                                } else {\r
                                        // we are interested only in true subdirectories:\r
                                        again = true;\r
-                    if (current->isDirectory() && ! current->isDotDir() && ! current->isLink()){\r
+                    if (current->isDirectory() && ! current->isDotDir() && ! current->isLink()\r
+                        && m_level < m_maxLevel){\r
                                                // open a new level\r
                                                alreadyRead = initEntry(current->m_path, current->node() , m_level + 1);\r
                                        }\r
@@ -391,7 +421,7 @@ ReDirStatus_t* ReTraverser::rawNextFile(int& level)
  *                                     otherwise: the info about the next file in the\r
  *                                     directory tree\r
  */\r
-ReDirStatus_t* ReTraverser::nextFile(int& level, DirEntryFilter_t* filter){\r
+ReDirStatus_t* ReTraverser::nextFile(int& level, ReDirEntryFilter_t* filter){\r
        ReDirStatus_t* rc = rawNextFile(level);\r
        while (rc != NULL){\r
                if (filter == NULL || filter->match(*rc)){\r
index e18dad49039ab967b74cea869f6699f7b96e3a08..d817327658ca6857555afa74b52907a15ebdc93a 100644 (file)
@@ -35,6 +35,8 @@ public:
     FileSize_t fileSize();
     const FileTime_t* modified();
     bool isDotDir() const;
+    const char* rightsAsString(ReByteBuffer& buffer);
+    const char* filetimeAsString(ReByteBuffer& buffer);
 public:
        ReByteBuffer m_path;
        int m_passNo;
@@ -52,10 +54,10 @@ public:
     static time_t filetimeToTime(const FileTime_t* time);
     static void timeToFiletime(time_t time, FileTime_t& filetime);
 };
-class DirEntryFilter_t {
+class ReDirEntryFilter_t {
 public:
-       DirEntryFilter_t();
-       ~DirEntryFilter_t();
+       ReDirEntryFilter_t();
+       ~ReDirEntryFilter_t();
 public:
        bool match(ReDirStatus_t& entry);
 public:
@@ -78,12 +80,23 @@ public:
        virtual ~ReTraverser();
 public:
        ReDirStatus_t* rawNextFile(int& level);
-       ReDirStatus_t* nextFile(int& level, DirEntryFilter_t* filter = NULL);
+       ReDirStatus_t* nextFile(int& level, ReDirEntryFilter_t* filter = NULL);
+    /** Sets the maximal depth.
+     * @param value     the value to set
+    */
+    void setMinLevel(int value)
+    { m_minLevel = value; }
+    /** Sets the minimal depth.
+     * @param value     the value to set
+    */
+    void setMaxLevel(int value)
+    { m_minLevel = value; }
 protected:
        bool initEntry(const ReByteBuffer& parent, const char* node, int level);
        void freeEntry(int level);
-
 protected:
+    int m_minLevel;
+    int m_maxLevel;
        int m_level;
        ReByteBuffer m_base;
        ReDirStatus_t* m_dirs[MAX_ENTRY_STACK_DEPTH];