Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Win32 File Name Iteration Boost Way

, 3 Nov 2005 CPOL
A Port of ::FindFirstFile to Boost.Range and Boost.Foreach
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.3.10: http://docutils.sourceforge.net/" />
<title>Tomato.FindFile</title>
<meta name="author" content="MB" />
<style type="text/css">

@import "http://p-stade.sourceforge.net/doc/boost.css";
@import "http://p-stade.sourceforge.net/doc/poost.css";

</style>
</head>
<body>
<div class="document" id="tomato-findfile">
<h1 class="title">Tomato.FindFile</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>MB</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference" href="mailto:mb2act&#64;yahoo.co.jp">mb2act&#64;yahoo.co.jp</a></td></tr>
<tr class="field"><th class="docinfo-name">License:</th><td class="field-body">Distributed under the <a class="reference" href="http://www.boost.org/LICENSE_1_0.txt">Boost Software License Version 1.0</a></td>
</tr>
<tr><th class="docinfo-name">Version:</th>
<td>0.90.1</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first"><a name="table-of-contents"><strong>Table of Contents</strong></a></p>
<ul class="auto-toc simple">
<li><a class="reference" href="#introduction" id="id11" name="id11">1&nbsp;&nbsp;&nbsp;Introduction</a></li>
<li><a class="reference" href="#requirements" id="id12" name="id12">2&nbsp;&nbsp;&nbsp;Requirements</a></li>
<li><a class="reference" href="#find-file-range" id="id13" name="id13">3&nbsp;&nbsp;&nbsp;find_file_range</a></li>
<li><a class="reference" href="#foreach-will-come" id="id14" name="id14">4&nbsp;&nbsp;&nbsp;Foreach will come.</a></li>
<li><a class="reference" href="#filtering" id="id15" name="id15">5&nbsp;&nbsp;&nbsp;Filtering</a></li>
<li><a class="reference" href="#transforming" id="id16" name="id16">6&nbsp;&nbsp;&nbsp;Transforming</a></li>
<li><a class="reference" href="#chain-of-range-adaptors" id="id17" name="id17">7&nbsp;&nbsp;&nbsp;Chain of Range Adaptors</a></li>
<li><a class="reference" href="#points-of-interest" id="id18" name="id18">8&nbsp;&nbsp;&nbsp;Points of Interest</a></li>
<li><a class="reference" href="#references" id="id19" name="id19">9&nbsp;&nbsp;&nbsp;References</a></li>
</ul>
</div>
<div class="section" id="introduction">
<h1><a class="toc-backref" href="#id11" name="introduction">1&nbsp;&nbsp;&nbsp;Introduction</a></h1>
<p>I was inspired by the excellent article, <a class="reference" href="http://www.codeproject.com/file/win32fileiter.asp">Win32 file name iteration STL way</a>.
I think the problem of the article is that the handle of <tt class="docutils literal"><span class="pre">::FindFirstFile</span></tt> is managed by iterators.
After combating <a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a> for months, I realized that <a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a> could remove that complexity.
The result was named <tt class="docutils literal"><span class="pre">find_file_range</span></tt>, which is the direct translation from <tt class="docutils literal"><span class="pre">::FindFirstFile</span></tt> to C++.</p>
</div>
<div class="section" id="requirements">
<h1><a class="toc-backref" href="#id12" name="requirements">2&nbsp;&nbsp;&nbsp;Requirements</a></h1>
<ul class="simple">
<li>Microsoft Visual C++ .NET Version 7.1</li>
<li><a class="reference" href="http://www.boost.org/">Boost C++ Libraries Version 1.33.0</a> (no compilation required unless building demo)</li>
<li><a class="reference" href="http://boost-consulting.com/vault/index.php?&amp;direction=0&amp;order=&amp;directory=Algorithms">Boost.Foreach</a></li>
<li><a class="reference" href="http://boost-consulting.com/vault/index.php?&amp;direction=0&amp;order=&amp;directory=Algorithms">Boost.RangeEx</a></li>
</ul>
</div>
<div class="section" id="find-file-range">
<h1><a class="toc-backref" href="#id13" name="find-file-range">3&nbsp;&nbsp;&nbsp;find_file_range</a></h1>
<p><tt class="docutils literal"><span class="pre">find_file_range</span></tt> is a model of <a class="reference" href="http://www.boost.org/libs/range/doc/range.html#single_pass_range">Single Pass Range</a> whose <tt class="docutils literal"><span class="pre">value_type</span></tt> is <tt class="docutils literal"><span class="pre">WIN32_FIND_DATA</span></tt>.
If you are not familiar with <a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a> concepts, 
you could regard it as something like a <a class="reference" href="http://www.sgi.com/tech/stl/Container.html">Container</a> which provides <a class="reference" href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>s:</p>
<pre class="cpp_source">
find_file_range ffrng(<span class="cpp_string_literal">&quot;*.*&quot;</span>);
<span class="cpp_keyword">typedef </span>boost::range_result_iterator&lt;find_file_range&gt;::type iter_t;
<span class="cpp_keyword">for </span>(iter_t it = boost::begin(ffrng), last = boost::end(ffrng); it != last; ++it) {
  std::cout &lt;&lt; it-&gt;cFileName &lt;&lt; std::endl;
}</pre>

<p>If you iterate <tt class="docutils literal"><span class="pre">find_file_range</span></tt> twice, the behavior is undefined.
This code proves <tt class="docutils literal"><span class="pre">find_file_range</span></tt> is a thin wrapper of <tt class="docutils literal"><span class="pre">::FindFirstFile</span></tt>,
but seems somewhat clumsy. Why must we write the idiom hundreds of times?
If you resent it, he will come.</p>
</div>
<div class="section" id="foreach-will-come">
<h1><a class="toc-backref" href="#id14" name="foreach-will-come">4&nbsp;&nbsp;&nbsp;Foreach will come.</a></h1>
<p><a class="reference" href="http://boost-consulting.com/vault/index.php?&amp;direction=0&amp;order=&amp;directory=Algorithms">Boost.Foreach</a> (accepted into <a class="reference" href="http://www.boost.org/">Boost</a>, but not yet part of the release) provides <tt class="docutils literal"><span class="pre">foreach</span></tt> 
that is missing from C++:</p>
<pre class="cpp_source">
find_file_range ffrng(<span class="cpp_string_literal">&quot;*.*&quot;</span>);
BOOST_FOREACH (WIN32_FIND_DATA&amp; data, ffrng) {
  std::cout &lt;&lt; data.cFileName &lt;&lt; std::endl;
}</pre>

<p>Is this a new language? No, It's C++. The implementation is magical.
If you are interested in it, check <a class="reference" href="http://www.artima.com/cppsource/foreachP.html">Conditional Love: FOREACH Redux</a> written by the author.</p>
</div>
<div class="section" id="filtering">
<h1><a class="toc-backref" href="#id15" name="filtering">5&nbsp;&nbsp;&nbsp;Filtering</a></h1>
<p>One class, one responsibility. <tt class="docutils literal"><span class="pre">find_file_range</span></tt> doesn't offer any filtering using 
<tt class="docutils literal"><span class="pre">dwFileAttributes</span></tt> of <tt class="docutils literal"><span class="pre">WIN32_FIND_DATA</span></tt>.
Instead, <a class="reference" href="http://www.sgi.com/tech/stl/AdaptablePredicate.html">Adaptable Predicate</a>s named <tt class="docutils literal"><span class="pre">find_file_is_xxx</span></tt> are provided.
They are available for <tt class="docutils literal"><span class="pre">boost::make_filter_range</span></tt>, which is a part of <a class="reference" href="http://boost-consulting.com/vault/index.php?&amp;direction=0&amp;order=&amp;directory=Algorithms">Boost.RangeEx</a>:</p>
<pre class="cpp_source">
find_file_range ffrng(<span class="cpp_string_literal">&quot;*.*&quot;</span>);
BOOST_FOREACH (
  WIN32_FIND_DATA&amp; data,
  boost::make_filter_range(ffrng, boost::not1(find_file_is_dots()))
)
{
  std::cout &lt;&lt; data.cFileName &lt;&lt; std::endl;
}</pre>

<p><tt class="docutils literal"><span class="pre">std::not1</span></tt> is completely broken by reference-to-reference problem, so you must use 
<tt class="docutils literal"><span class="pre">boost::not1</span></tt> from <a class="reference" href="http://www.boost.org/libs/functional/">Boost.Functional</a>.</p>
</div>
<div class="section" id="transforming">
<h1><a class="toc-backref" href="#id16" name="transforming">6&nbsp;&nbsp;&nbsp;Transforming</a></h1>
<p>As a mark of respect for the original article, <tt class="docutils literal"><span class="pre">find_file_construct</span></tt> template that 
makes a model of <a class="reference" href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">Adaptable Unary Functor</a> is provided for those
who want to get <tt class="docutils literal"><span class="pre">cFileName</span></tt> of <tt class="docutils literal"><span class="pre">WIN32_FIND_DATA</span></tt> as a string object.
It is available for <tt class="docutils literal"><span class="pre">boost::make_transform_range</span></tt>:</p>
<pre class="cpp_source">
find_file_range ffrng(<span class="cpp_string_literal">&quot;*.*&quot;</span>);
BOOST_FOREACH (
  std::string <span class="cpp_keyword">const</span>&amp; filename,
  boost::make_transform_range(ffrng, find_file_construct&lt;std::string&gt;())
)
{
  std::cout &lt;&lt; filename &lt;&lt; std::endl;
}</pre>

<p><tt class="docutils literal"><span class="pre">find_file_construct</span></tt> template takes a type <a class="reference" href="http://www.sgi.com/tech/stl/Sequence.html">Sequence</a>.
If your string type is not a <a class="reference" href="http://www.sgi.com/tech/stl/Sequence.html">Sequence</a> like <tt class="docutils literal"><span class="pre">CString</span></tt>, you could use <tt class="docutils literal"><span class="pre">find_file_stringize</span></tt> instead.</p>
</div>
<div class="section" id="chain-of-range-adaptors">
<h1><a class="toc-backref" href="#id17" name="chain-of-range-adaptors">7&nbsp;&nbsp;&nbsp;Chain of Range Adaptors</a></h1>
<p>The chain of filterings and transformings also is available:</p>
<pre class="cpp_source">
find_file_range ffrng(<span class="cpp_string_literal">&quot;*.*&quot;</span>);
BOOST_FOREACH (
  std::string <span class="cpp_keyword">const</span>&amp; filename,
  boost::make_transform_range(
    boost::make_filter_range(
      boost::make_filter_range(
        ffrng,
        boost::not1(find_file_is_hidden())
      ),
      boost::not1(find_file_is_directory())
    ),
    find_file_stringize&lt;std::string&gt;()
  )
)
{
  std::cout &lt;&lt; filename &lt;&lt; std::endl;
}</pre>

<p>This chain is lazy and functional, but unreadable. And so <a class="reference" href="http://boost-consulting.com/vault/index.php?&amp;direction=0&amp;order=&amp;directory=Algorithms">Boost.RangeEx</a> provides <a class="reference" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1871.html#range-adapters-part-4">Range Adaptors</a>:</p>
<pre class="cpp_source">
find_file_range ffrng(<span class="cpp_string_literal">&quot;*.*&quot;</span>);
BOOST_FOREACH (
  std::string <span class="cpp_keyword">const</span>&amp; filename,
  ffrng |
    boost::adaptor::filter(boost::not1(find_file_is_hidden())) |
    boost::adaptor::filter(boost::not1(find_file_is_directory())) |
    boost::adaptor::transform(find_file_construct&lt;std::string&gt;())
)
{
  std::cout &lt;&lt; filename &lt;&lt; std::endl;
}</pre>

<p>This is rather &quot;procedural&quot; and shows the future of C++.</p>
</div>
<div class="section" id="points-of-interest">
<h1><a class="toc-backref" href="#id18" name="points-of-interest">8&nbsp;&nbsp;&nbsp;Points of Interest</a></h1>
<p><tt class="docutils literal"><span class="pre">find_file_range</span></tt> is just like a disposable container and 
doesn't offer any additional functionalities unlike <a class="reference" href="http://www.boost.org/libs/filesystem/doc/index.htm">Boost.Filesystem</a>,
but it doesn't demand any additional resources.
<a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a> concepts are wide-open to such classes.
In fact, <tt class="docutils literal"><span class="pre">find_file_range</span></tt> depends on that you don't iterate twice,
while <tt class="docutils literal"><span class="pre">boost::iterator_range</span></tt> depends on that holding iterators are valid.
You could easily make many classes conform to the concepts. I hope this article helps:</p>
<pre class="cpp_source">
std::string inputs; {
  boost::copy(make_istream_range&lt;<span class="cpp_keyword">char</span>&gt;(std::cin), std::back_inserter(inputs));
}
std::cout &lt;&lt; inputs &lt;&lt; std::endl;</pre>

</div>
<div class="section" id="references">
<h1><a class="toc-backref" href="#id19" name="references">9&nbsp;&nbsp;&nbsp;References</a></h1>
<ul class="simple">
<li><a class="reference" href="http://p-stade.sourceforge.net/">P-Stade</a></li>
<li><a class="reference" href="http://www.boost.org/">Boost C++ Libraries</a></li>
<li><a class="reference" href="http://boost-consulting.com/vault/index.php?&amp;direction=0&amp;order=&amp;directory=Algorithms">Boost.Foreach</a></li>
<li><a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a></li>
<li><a class="reference" href="http://boost-consulting.com/vault/index.php?&amp;direction=0&amp;order=&amp;directory=Algorithms">Boost.RangeEx</a></li>
<li><a class="reference" href="http://www.artima.com/cppsource/foreachP.html">Conditional Love: FOREACH Redux</a></li>
</ul>
</div>
</div>
<div class="footer">
<hr class="footer" />
<a class="reference" href="../src/tomato_find_file.rst">View document source</a>.
Generated on: 2005-11-11 01:29 UTC.
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.

</div>
</body>
</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

mb2sync

Japan Japan
I am worried about my poor English...

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150123.1 | Last Updated 4 Nov 2005
Article Copyright 2005 by mb2sync
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid