[cpp-xmltooling] branch master updated: DirectoryWalker utility API.

Scott Cantor cantor.2 at osu.edu
Mon Apr 2 15:27:37 EDT 2018


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch master
in repository cpp-xmltooling.

View the commit online:
http://git.shibboleth.net/view/?p=cpp-xmltooling.git;a=commit;h=e30f15a408e125a77ec34bd3b06a1a7435c1779a

The following commit(s) were added to refs/heads/master by this push:
       new  e30f15a   DirectoryWalker utility API.
e30f15a is described below

commit e30f15a408e125a77ec34bd3b06a1a7435c1779a
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Apr 2 15:27:27 2018 -0400

    DirectoryWalker utility API.
---
 Projects/vc15/xmltooling/xmltooling-lite.vcxproj   |   2 +
 .../xmltooling/xmltooling-lite.vcxproj.filters     |   6 +
 Projects/vc15/xmltooling/xmltooling.vcxproj        |   2 +
 .../vc15/xmltooling/xmltooling.vcxproj.filters     |   6 +
 .../vc15/xmltoolingtest/xmltoolingtest.vcxproj     |  19 ++-
 .../xmltoolingtest/xmltoolingtest.vcxproj.filters  |   6 +
 configure.ac                                       |   1 +
 xmltooling/Makefile.am                             |   2 +
 xmltooling/util/DirectoryWalker.cpp                | 145 +++++++++++++++++++++
 xmltooling/util/DirectoryWalker.h                  | 100 ++++++++++++++
 xmltoolingtest/DataSealerTest.h                    |   3 +-
 xmltoolingtest/DirectoryWalkerTest.h               |  89 +++++++++++++
 xmltoolingtest/Makefile.am                         |  43 +++---
 xmltoolingtest/data/dirwalk-empty/.gitkeep         |   0
 xmltoolingtest/data/dirwalk/bar.txt                |   1 +
 xmltoolingtest/data/dirwalk/baz.xml                |   1 +
 xmltoolingtest/data/dirwalk/foo.txt                |   1 +
 xmltoolingtest/data/dirwalk/nested/.gitkeep        |   0
 xmltoolingtest/data/dirwalk/nested/foo.txt         |   1 +
 19 files changed, 402 insertions(+), 26 deletions(-)

diff --git a/Projects/vc15/xmltooling/xmltooling-lite.vcxproj b/Projects/vc15/xmltooling/xmltooling-lite.vcxproj
index 497173f..9ce61d3 100644
--- a/Projects/vc15/xmltooling/xmltooling-lite.vcxproj
+++ b/Projects/vc15/xmltooling/xmltooling-lite.vcxproj
@@ -218,6 +218,7 @@
     <ClCompile Include="..\..\..\XMLTooling\QName.cpp" />
     <ClCompile Include="..\..\..\XMLTooling\unicode.cpp" />
     <ClCompile Include="..\..\..\xmltooling\util\CloneInputStream.cpp" />
+    <ClCompile Include="..\..\..\xmltooling\util\DirectoryWalker.cpp" />
     <ClCompile Include="..\..\..\XMLTooling\version.cpp" />
     <ClCompile Include="..\..\..\XMLTooling\XMLObjectBuilder.cpp" />
     <ClCompile Include="..\..\..\XMLTooling\XMLToolingConfig.cpp" />
@@ -262,6 +263,7 @@
     <ClInclude Include="..\..\..\XMLTooling\QName.h" />
     <ClInclude Include="..\..\..\XMLTooling\unicode.h" />
     <ClInclude Include="..\..\..\xmltooling\util\CloneInputStream.h" />
+    <ClInclude Include="..\..\..\xmltooling\util\DirectoryWalker.h" />
     <ClInclude Include="..\..\..\XMLTooling\version.h" />
     <ClInclude Include="..\..\..\XMLTooling\XMLObject.h" />
     <ClInclude Include="..\..\..\XMLTooling\XMLObjectBuilder.h" />
diff --git a/Projects/vc15/xmltooling/xmltooling-lite.vcxproj.filters b/Projects/vc15/xmltooling/xmltooling-lite.vcxproj.filters
index 6b7e866..c8f45fa 100644
--- a/Projects/vc15/xmltooling/xmltooling-lite.vcxproj.filters
+++ b/Projects/vc15/xmltooling/xmltooling-lite.vcxproj.filters
@@ -147,6 +147,9 @@
     <ClCompile Include="..\..\..\xmltooling\util\CloneInputStream.cpp">
       <Filter>Source Files\util</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\xmltooling\util\DirectoryWalker.cpp">
+      <Filter>Source Files\util</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\XMLTooling\AbstractAttributeExtensibleXMLObject.h">
@@ -284,6 +287,9 @@
     <ClInclude Include="..\..\..\xmltooling\util\CloneInputStream.h">
       <Filter>Header Files\util</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\xmltooling\util\DirectoryWalker.h">
+      <Filter>Header Files\util</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\..\XMLTooling\xmltooling.rc">
diff --git a/Projects/vc15/xmltooling/xmltooling.vcxproj b/Projects/vc15/xmltooling/xmltooling.vcxproj
index e18801c..d5e54d7 100644
--- a/Projects/vc15/xmltooling/xmltooling.vcxproj
+++ b/Projects/vc15/xmltooling/xmltooling.vcxproj
@@ -216,6 +216,7 @@
     <ClCompile Include="..\..\..\xmltooling\security\impl\VersionedDataSealerKeyStrategy.cpp" />
     <ClCompile Include="..\..\..\XMLTooling\unicode.cpp" />
     <ClCompile Include="..\..\..\XMLTooling\util\CloneInputStream.cpp" />
+    <ClCompile Include="..\..\..\xmltooling\util\DirectoryWalker.cpp" />
     <ClCompile Include="..\..\..\XMLTooling\version.cpp" />
     <ClCompile Include="..\..\..\XMLTooling\XMLObjectBuilder.cpp" />
     <ClCompile Include="..\..\..\XMLTooling\XMLToolingConfig.cpp" />
@@ -296,6 +297,7 @@
     <ClInclude Include="..\..\..\XMLTooling\security\PKIXPathValidatorParams.h" />
     <ClInclude Include="..\..\..\XMLTooling\unicode.h" />
     <ClInclude Include="..\..\..\XMLTooling\util\CloneInputStream.h" />
+    <ClInclude Include="..\..\..\xmltooling\util\DirectoryWalker.h" />
     <ClInclude Include="..\..\..\XMLTooling\version.h" />
     <ClInclude Include="..\..\..\XMLTooling\XMLObject.h" />
     <ClInclude Include="..\..\..\XMLTooling\XMLObjectBuilder.h" />
diff --git a/Projects/vc15/xmltooling/xmltooling.vcxproj.filters b/Projects/vc15/xmltooling/xmltooling.vcxproj.filters
index f1e1702..27ffd67 100644
--- a/Projects/vc15/xmltooling/xmltooling.vcxproj.filters
+++ b/Projects/vc15/xmltooling/xmltooling.vcxproj.filters
@@ -282,6 +282,9 @@
     <ClCompile Include="..\..\..\xmltooling\security\impl\VersionedDataSealerKeyStrategy.cpp">
       <Filter>Source Files\security\impl</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\xmltooling\util\DirectoryWalker.cpp">
+      <Filter>Source Files\util</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\XMLTooling\AbstractAttributeExtensibleXMLObject.h">
@@ -539,6 +542,9 @@
     <ClInclude Include="..\..\..\xmltooling\security\impl\ManagedResource.h">
       <Filter>Source Files\security\impl</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\xmltooling\util\DirectoryWalker.h">
+      <Filter>Header Files\util</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\..\XMLTooling\xmltooling.rc">
diff --git a/Projects/vc15/xmltoolingtest/xmltoolingtest.vcxproj b/Projects/vc15/xmltoolingtest/xmltoolingtest.vcxproj
index 76402b3..a4feb33 100644
--- a/Projects/vc15/xmltoolingtest/xmltoolingtest.vcxproj
+++ b/Projects/vc15/xmltoolingtest/xmltoolingtest.vcxproj
@@ -108,7 +108,7 @@
       <DisableSpecificWarnings>4275</DisableSpecificWarnings>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>xerces-c_3D.lib;xsec_2D.lib;$(SSLLib);%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>log4shib1D.lib;xerces-c_3D.lib;xsec_2D.lib;$(SSLLib);%(AdditionalDependencies)</AdditionalDependencies>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <RandomizedBaseAddress>false</RandomizedBaseAddress>
@@ -133,7 +133,7 @@
       <DisableSpecificWarnings>4275</DisableSpecificWarnings>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>xerces-c_3D.lib;xsec_2D.lib;$(SSLLibD);%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>log4shib1D.lib;xerces-c_3D.lib;xsec_2D.lib;$(SSLLibD);%(AdditionalDependencies)</AdditionalDependencies>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <DataExecutionPrevention>
@@ -150,7 +150,7 @@
       <DisableSpecificWarnings>4275</DisableSpecificWarnings>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>xerces-c_3.lib;xsec_2.lib;$(SSLLib);%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>log4shib1.lib;xerces-c_3.lib;xsec_2.lib;$(SSLLib);%(AdditionalDependencies)</AdditionalDependencies>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
@@ -174,7 +174,7 @@
       <DisableSpecificWarnings>4275</DisableSpecificWarnings>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>xerces-c_3.lib;xsec_2.lib;$(SSLLib);%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>log4shib1.lib;xerces-c_3.lib;xsec_2.lib;$(SSLLib);%(AdditionalDependencies)</AdditionalDependencies>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
@@ -188,6 +188,7 @@
     <ClCompile Include="ComplexXMLObjectTest.cpp" />
     <ClCompile Include="DataSealerTest.cpp" />
     <ClCompile Include="DateTimeTest.cpp" />
+    <ClCompile Include="DirectoryWalkerTest.cpp" />
     <ClCompile Include="EncryptionTest.cpp" />
     <ClCompile Include="ExceptionTest.cpp" />
     <ClCompile Include="ExplicitKeyTrustEngineTest.cpp" />
@@ -478,6 +479,16 @@
       <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).cpp;%(Outputs)</Outputs>
       <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).cpp;%(Outputs)</Outputs>
     </CustomBuild>
+    <CustomBuild Include="..\..\..\xmltoolingtest\DirectoryWalkerTest.h">
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Filename).cpp;%(Outputs)</Outputs>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Filename).cpp;%(Outputs)</Outputs>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).cpp;%(Outputs)</Outputs>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).cpp;%(Outputs)</Outputs>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">perl.exe -w $(CxxTestRoot)\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "%(Filename)".cpp "%(FullPath)"</Command>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">perl.exe -w $(CxxTestRoot)\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "%(Filename)".cpp "%(FullPath)"</Command>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">perl.exe -w $(CxxTestRoot)\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "%(Filename)".cpp "%(FullPath)"</Command>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">perl.exe -w $(CxxTestRoot)\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "%(Filename)".cpp "%(FullPath)"</Command>
+    </CustomBuild>
     <ClInclude Include="..\..\..\XMLToolingTest\XMLObjectBaseTestCase.h" />
   </ItemGroup>
   <ItemGroup>
diff --git a/Projects/vc15/xmltoolingtest/xmltoolingtest.vcxproj.filters b/Projects/vc15/xmltoolingtest/xmltoolingtest.vcxproj.filters
index e63362a..4703ab6 100644
--- a/Projects/vc15/xmltoolingtest/xmltoolingtest.vcxproj.filters
+++ b/Projects/vc15/xmltoolingtest/xmltoolingtest.vcxproj.filters
@@ -71,6 +71,9 @@
     <ClCompile Include="DataSealerTest.cpp">
       <Filter>Generated Code</Filter>
     </ClCompile>
+    <ClCompile Include="DirectoryWalkerTest.cpp">
+      <Filter>Generated Code</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\XMLToolingTest\XMLObjectBaseTestCase.h">
@@ -141,5 +144,8 @@
     <CustomBuild Include="..\..\..\xmltoolingtest\DataSealerTest.h">
       <Filter>Unit Tests</Filter>
     </CustomBuild>
+    <CustomBuild Include="..\..\..\xmltoolingtest\DirectoryWalkerTest.h">
+      <Filter>Unit Tests</Filter>
+    </CustomBuild>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/configure.ac b/configure.ac
index 7c2aec1..19f569f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,6 +66,7 @@ esac
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
 AC_TYPE_SIZE_T
+AC_HEADER_DIRENT
 
 # Checks for library functions.
 AC_CHECK_FUNCS([strchr strdup strstr timegm gmtime_r strcasecmp])
diff --git a/xmltooling/Makefile.am b/xmltooling/Makefile.am
index 27d54af..c358684 100644
--- a/xmltooling/Makefile.am
+++ b/xmltooling/Makefile.am
@@ -109,6 +109,7 @@ soapinclude_HEADERS = \
 utilinclude_HEADERS = \
 	util/CloneInputStream.h \
 	util/CurlURLInputStream.h \
+	util/DirectoryWalker.h \
 	util/NDC.h \
 	util/ParserPool.h \
 	util/PathResolver.h \
@@ -198,6 +199,7 @@ common_sources = \
 	soap/impl/SOAPImpl.cpp \
 	soap/impl/SOAPSchemaValidators.cpp \
 	util/CloneInputStream.cpp \
+	util/DirectoryWalker.cpp \
 	util/NDC.cpp \
 	util/ParserPool.cpp \
 	util/PathResolver.cpp \
diff --git a/xmltooling/util/DirectoryWalker.cpp b/xmltooling/util/DirectoryWalker.cpp
new file mode 100644
index 0000000..4817c5a
--- /dev/null
+++ b/xmltooling/util/DirectoryWalker.cpp
@@ -0,0 +1,145 @@
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the
+ * License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ */
+
+/**
+ * DirectoryWalker.cpp
+ *
+ * Iterates over directory entries.
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "util/DirectoryWalker.h"
+
+#ifdef WIN32
+# include <windows.h>
+#else
+# include <boost/algorithm/string.hpp>
+# if defined(HAVE_SYS_TYPES_H) && defined(HAVE_DIRENT_H)
+#  include <dirent.h>
+#  include <sys/types.h>
+# else
+#  error Unsupported directory library headers.
+# endif
+#endif
+
+using xmltooling::logging::Category;
+using namespace xmltooling;
+using namespace std;
+
+DirectoryWalker::DirectoryWalker(Category& log, const char* path, bool recurse)
+    : m_log(log), m_path(path), m_recurse(recurse)
+{
+}
+
+DirectoryWalker::~DirectoryWalker()
+{
+}
+
+void DirectoryWalker::_walk(
+    const char* path, const DirectoryWalkerCallback& callback_fn, void* callback_data, const char* startsWith, const char* endsWith
+    ) const
+{
+#ifdef WIN32
+    string searchpath = string(path) + '/';
+    if (startsWith)
+        searchpath += startsWith;
+    searchpath += '*';
+    if (endsWith)
+        searchpath += endsWith;
+    m_log.debug("searching path (%s)", searchpath.c_str());
+
+    WIN32_FIND_DATA f;
+    HANDLE h = FindFirstFile(searchpath.c_str(), &f);
+    if (h == INVALID_HANDLE_VALUE) {
+        if (GetLastError() != ERROR_FILE_NOT_FOUND)
+            m_log.warn("Unable to open directory (%s)", path);
+        else
+            m_log.debug("no matching entries in directory (%s)", path);
+        return;
+    }
+    do {
+        if (f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+            if (!strcmp(f.cFileName, ".") || !strcmp(f.cFileName, ".."))
+                continue;
+            if (m_recurse) {
+                m_log.debug("processing nested directory (%s)", f.cFileName);
+                string nested = string(path) + '/' + f.cFileName;
+                _walk(nested.c_str(), callback_fn, callback_data, startsWith, endsWith);
+            }
+            else {
+                m_log.debug("recursion disabled, skipping nested directory (%s)", f.cFileName);
+            }
+        }
+        else {
+            string fullname = string(path) + '/' + f.cFileName;
+            struct stat stat_buf;
+            if (stat(fullname.c_str(), &stat_buf) == 0) {
+                m_log.debug("invoking callback for file (%s)", fullname.c_str());
+                callback_fn(fullname.c_str(), stat_buf, callback_data);
+            }
+            else {
+                m_log.warn("unable to access (%s)", fullname.c_str());
+            }
+        }
+    } while (FindNextFile(h, &f));
+    FindClose(h);
+#else
+    DIR* d = opendir(path);
+    if (!d) {
+        m_log.warn("Unable to open directory (%s)", path);
+        return;
+    }
+    char dir_buf[sizeof(struct dirent) + PATH_MAX];
+    struct dirent* ent = (struct dirent*)dir_buf;
+    struct dirent* entptr = nullptr;
+    while (readdir_r(d, ent, &entptr) == 0 && entptr) {
+        if (!strcmp(entptr->d_name, ".") || !strcmp(entptr->d_name, ".."))
+            continue;
+        else if (startsWith || endsWith) {
+            string fname(entptr->d_name);
+            if ((startsWith && !boost::algorithm::starts_with(fname, startsWith)) ||
+                (endsWith && boost::algorithm::ends_with(fname, endsWith))) {
+                continue;
+            }
+        }
+
+        string fullname = string(path) + '/' + entptr->d_name;
+        struct stat stat_buf;
+        if (stat(fullname.c_str(), &stat_buf) != 0) {
+            m_log.warn("unable to access (%s)", fullname.c_str());
+        }
+        else if (S_ISDIR(stat_buf.st_mode)) {
+            if (m_recurse) {
+                m_log.debug("processing nested directory (%s)", entptr->d_name);
+                _walk(fullname.c_str(), callback_fn, callback_data, startsWith, endsWith);
+            }
+            else {
+                m_log.debug("recursion disabled, skipping nested directory (%s)", entptr->d_name);
+            }
+        }
+        else {
+            m_log.debug("invoking callback for file (%s)", fullname.c_str());
+            callback_fn(fullname.c_str(), stat_buf, callback_data);
+        }
+    }
+    closedir(d);
+#endif
+    }
\ No newline at end of file
diff --git a/xmltooling/util/DirectoryWalker.h b/xmltooling/util/DirectoryWalker.h
new file mode 100644
index 0000000..8210b32
--- /dev/null
+++ b/xmltooling/util/DirectoryWalker.h
@@ -0,0 +1,100 @@
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the
+ * License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ */
+
+/**
+ * @file xmltooling/util/DirectoryWalker.h
+ *
+ * Iterates over directory entries.
+ */
+
+#if !defined(__xmltooling_dirwalk_h__)
+#define __xmltooling_dirwalk_h__
+
+#include <xmltooling/logging.h>
+
+#include <string>
+#include <sys/stat.h>
+
+namespace xmltooling {
+
+#if defined (_MSC_VER)
+#    pragma warning( push )
+#    pragma warning( disable : 4251 )
+#endif
+
+    /**
+     * Portable directory walker that invokes a callback function for every file in a
+     * directory, optionally doing depth-first recursion of nested directories.
+     */
+    class XMLTOOL_API DirectoryWalker
+    {
+        MAKE_NONCOPYABLE(DirectoryWalker);
+    public:
+
+        /**
+         * Constructor.
+         *
+         * @param path directory path to walk
+         * @param recurse true iff nested directories should be processed
+         */
+        DirectoryWalker(logging::Category& log, const char* path, bool recurse=false);
+
+        virtual ~DirectoryWalker();
+
+        /** Callback function, passed the file pathname, stat buffer, and optional callback data. */
+        typedef void (*DirectoryWalkerCallback)(const char* pathname, struct stat& stat_buf, void* data);
+
+        /**
+         * Perform a depth-first traversal of the directory.
+         *
+         * @param callback_fn   callback function to invoke for each match
+         * @param callback_data optional pointer to pass to callback
+         * @param startsWith    optional prefix matching, skipping non-matching entries
+         * @param endsWith      optional suffix matching, skipping non-matching entries
+         */
+        void walk(
+            const DirectoryWalkerCallback& callback_fn,
+            void* callback_data = nullptr,
+            const char* startsWith = nullptr,
+            const char* endsWith = nullptr
+            ) const {
+            _walk(m_path.c_str(), callback_fn, callback_data, startsWith, endsWith);
+        }
+
+    private:
+        void _walk(
+            const char* path,
+            const DirectoryWalkerCallback& callback_fn,
+            void* callback_data = nullptr,
+            const char* startsWith = nullptr,
+            const char* endsWith = nullptr
+        ) const;
+
+        logging::Category& m_log;
+        std::string m_path;
+        bool m_recurse;
+    };
+
+#if defined (_MSC_VER)
+#   pragma warning( pop )
+#endif
+};
+
+#endif /* __xmltooling_dirwalk_h__ */
diff --git a/xmltoolingtest/DataSealerTest.h b/xmltoolingtest/DataSealerTest.h
index 90e6dc1..6fb85a5 100644
--- a/xmltoolingtest/DataSealerTest.h
+++ b/xmltoolingtest/DataSealerTest.h
@@ -85,7 +85,8 @@ public:
 
 		static const XMLCh _path[] = UNICODE_LITERAL_4(p, a, t, h);
 		DOMElement* root = doc->createElementNS(nullptr, _path);
-		auto_ptr_XMLCh widepath("../xmltoolingtest/data/sealer.keys");
+        string sealerpath = data_path + "sealer.keys";
+		auto_ptr_XMLCh widepath(sealerpath.c_str());
 		root->setAttributeNS(nullptr, _path, widepath.get());
 		doc->appendChild(root);
 
diff --git a/xmltoolingtest/DirectoryWalkerTest.h b/xmltoolingtest/DirectoryWalkerTest.h
new file mode 100644
index 0000000..641c063
--- /dev/null
+++ b/xmltoolingtest/DirectoryWalkerTest.h
@@ -0,0 +1,89 @@
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the
+ * License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ */
+
+#include "XMLObjectBaseTestCase.h"
+
+#include <xmltooling/exceptions.h>
+#include <xmltooling/logging.h>
+#include <xmltooling/util/DirectoryWalker.h>
+
+using namespace xmltooling::logging;
+
+class DirectoryWalkerTest : public CxxTest::TestSuite {
+    unsigned int m_count;
+    Category& m_log;
+
+    friend void counting_callback(const char* pathname, struct stat& stat_buf, void* data);
+
+public:
+    DirectoryWalkerTest() : m_log(Category::getInstance("DirectoryWalkerTest")) {
+
+    }
+
+    void setUp() {
+        m_count = 0;
+    }
+
+    void testNoAccess() {
+        DirectoryWalker walker(m_log, "invalid");
+        walker.walk(counting_callback, this);
+        TS_ASSERT_EQUALS(m_count, 0);
+	}
+
+    void testEmpty() {
+        string path = data_path + "dirwalk-empty";
+        DirectoryWalker walker(m_log, path.c_str());
+        walker.walk(counting_callback, this);
+        TS_ASSERT_EQUALS(m_count, 0);
+    }
+
+    void testShallow() {
+        string path = data_path + "dirwalk";
+        DirectoryWalker walker(m_log, path.c_str());
+        walker.walk(counting_callback, this);
+        TS_ASSERT_EQUALS(m_count, 3);
+    }
+
+    void testNested() {
+        string path = data_path + "dirwalk";
+        DirectoryWalker walker(m_log, path.c_str(), true);
+        walker.walk(counting_callback, this);
+        TS_ASSERT_EQUALS(m_count, 4);
+    }
+
+    void testPrefixed() {
+        string path = data_path + "dirwalk";
+        DirectoryWalker walker(m_log, path.c_str(), true);
+        walker.walk(counting_callback, this, "foo");
+        TS_ASSERT_EQUALS(m_count, 1);
+    }
+
+    void testSuffixed() {
+        string path = data_path + "dirwalk";
+        DirectoryWalker walker(m_log, path.c_str(), true);
+        walker.walk(counting_callback, this, nullptr, ".txt");
+        TS_ASSERT_EQUALS(m_count, 2);
+    }
+};
+
+static void counting_callback(const char* pathname, struct stat& stat_buf, void* data) {
+    if (!strstr(pathname, ".gitkeep"))
+        reinterpret_cast<DirectoryWalkerTest*>(data)->m_count++;
+}
diff --git a/xmltoolingtest/Makefile.am b/xmltoolingtest/Makefile.am
index 79d25d3..6ee6790 100644
--- a/xmltoolingtest/Makefile.am
+++ b/xmltoolingtest/Makefile.am
@@ -19,35 +19,36 @@ endif
 
 if BUILD_XMLSEC
 xmlsec_sources = \
-    DataSealerTest.h \
-    EncryptionTest.h \
-    FilesystemCredentialResolverTest.h \
+	DataSealerTest.h \
+	EncryptionTest.h \
+	FilesystemCredentialResolverTest.h \
 	ExplicitKeyTrustEngineTest.h \
-    InlineKeyResolverTest.h \
-    MemoryStorageServiceTest.h \
-    PKIXEngineTest.h \
-    SecurityHelperTest.h \
-    SignatureTest.h
+	InlineKeyResolverTest.h \
+	MemoryStorageServiceTest.h \
+	PKIXEngineTest.h \
+	SecurityHelperTest.h \
+	SignatureTest.h
 else
 xmlsec_sources =
 endif
 
 xmltoolingtest_h = \
-    ComplexXMLObjectTest.h \
-    DateTimeTest.h \
-    ExceptionTest.h \
-    KeyInfoTest.h \
-    MarshallingTest.h \
-    NonVisibleNamespaceTest.h \
-    SOAPTest.h \
-    UnmarshallingTest.h \
-    TemplateEngineTest.h \
-    xmltoolingtest.h \
-    ${xmlsec_sources}
+	ComplexXMLObjectTest.h \
+	DateTimeTest.h \
+	DirectoryWalkerTest.h \
+	ExceptionTest.h \
+	KeyInfoTest.h \
+	MarshallingTest.h \
+	NonVisibleNamespaceTest.h \
+	SOAPTest.h \
+	UnmarshallingTest.h \
+	TemplateEngineTest.h \
+	xmltoolingtest.h \
+	${xmlsec_sources}
 
 noinst_HEADERS = \
-    XMLObjectBaseTestCase.h \
-    $(xmltoolingtest_h)
+	XMLObjectBaseTestCase.h \
+	$(xmltoolingtest_h)
 
 nodist_xmltoolingtest_SOURCES = $(xmltoolingtest_h:.h=.cpp)
 
diff --git a/xmltoolingtest/data/dirwalk-empty/.gitkeep b/xmltoolingtest/data/dirwalk-empty/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/xmltoolingtest/data/dirwalk/bar.txt b/xmltoolingtest/data/dirwalk/bar.txt
new file mode 100644
index 0000000..ba0e162
--- /dev/null
+++ b/xmltoolingtest/data/dirwalk/bar.txt
@@ -0,0 +1 @@
+bar
\ No newline at end of file
diff --git a/xmltoolingtest/data/dirwalk/baz.xml b/xmltoolingtest/data/dirwalk/baz.xml
new file mode 100644
index 0000000..7315e1b
--- /dev/null
+++ b/xmltoolingtest/data/dirwalk/baz.xml
@@ -0,0 +1 @@
+<baz/>
\ No newline at end of file
diff --git a/xmltoolingtest/data/dirwalk/foo.txt b/xmltoolingtest/data/dirwalk/foo.txt
new file mode 100644
index 0000000..1910281
--- /dev/null
+++ b/xmltoolingtest/data/dirwalk/foo.txt
@@ -0,0 +1 @@
+foo
\ No newline at end of file
diff --git a/xmltoolingtest/data/dirwalk/nested/.gitkeep b/xmltoolingtest/data/dirwalk/nested/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/xmltoolingtest/data/dirwalk/nested/foo.txt b/xmltoolingtest/data/dirwalk/nested/foo.txt
new file mode 100644
index 0000000..1910281
--- /dev/null
+++ b/xmltoolingtest/data/dirwalk/nested/foo.txt
@@ -0,0 +1 @@
+foo
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list