LCOV - code coverage report
Current view: top level - snapwebsites - glob_dir.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 61 1.6 %
Date: 2019-12-15 17:13:15 Functions: 2 12 16.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Snap Websites Servers -- glob a directory and enumerate the files
       2             : // Copyright (c) 2016-2019  Made to Order Software Corp.  All Rights Reserved
       3             : //
       4             : // https://snapwebsites.org/
       5             : // contact@m2osw.com
       6             : //
       7             : // This program is free software; you can redistribute it and/or modify
       8             : // it under the terms of the GNU General Public License as published by
       9             : // the Free Software Foundation; either version 2 of the License, or
      10             : // (at your option) any later version.
      11             : //
      12             : // This program is distributed in the hope that it will be useful,
      13             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             : // GNU General Public License for more details.
      16             : //
      17             : // You should have received a copy of the GNU General Public License
      18             : // along with this program; if not, write to the Free Software
      19             : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      20             : //
      21             : 
      22             : // self
      23             : //
      24             : #include "glob_dir.h"
      25             : 
      26             : // snapwebsites lib
      27             : //
      28             : #include "log.h"
      29             : 
      30             : 
      31             : // last include
      32             : //
      33             : #include <snapdev/poison.h>
      34             : 
      35             : 
      36             : 
      37             : namespace snap
      38             : {
      39             : 
      40             : 
      41             : namespace
      42             : {
      43             : 
      44             : 
      45           0 : int glob_err_callback(char const * epath, int eerrno)
      46             : {
      47           0 :     SNAP_LOG_ERROR("an error occurred while reading directory under \"")
      48           0 :         (epath)
      49           0 :         ("\". Got error: ")
      50           0 :         (eerrno)
      51           0 :         (", ")
      52           0 :         (strerror(eerrno))
      53           0 :         (".");
      54             : 
      55             :     // do not abort on a directory read error...
      56           0 :     return 0;
      57             : }
      58             : 
      59             : 
      60             : }
      61             : // no name namespace
      62             : 
      63             : 
      64             : /** \class glob_dir
      65             :  * \brief Enumerate the contents of a directory using a wildcard.
      66             :  *
      67             :  * This class encapsulates and hides a Unix 'C' `glob_t` structure.
      68             :  *
      69             :  * It allows enumeration of a single folder at the first level
      70             :  * using a path containing a Unix shell compatible wildcard.
      71             :  */
      72             : 
      73             : 
      74             : /** \brief Create an empty directory.
      75             :  *
      76             :  * The default constructor creates an empty directory. You are expected
      77             :  * to call the set_path() function at least once before attempting to
      78             :  * enumerate files.
      79             :  *
      80             :  * \sa set_path()
      81             :  */
      82           0 : glob_dir::glob_dir()
      83             : {
      84             :     // Empty
      85           0 : }
      86             : 
      87             : 
      88             : /** \brief Create a glob_dir from a path and flags.
      89             :  *
      90             :  * This constructor calls set_path() immediately using the two parameters
      91             :  * passed to it.
      92             :  *
      93             :  * \param[in] path  The path including the Unix shell wildcards.
      94             :  * \param[in] flags  A set of GLOB_... flags.
      95             :  * \param[in] allow_empty  Just return on an empty glob().
      96             :  *
      97             :  * \sa set_path()
      98             :  */
      99           0 : glob_dir::glob_dir( char const * path, int const flags, bool allow_empty )
     100             : {
     101           0 :     set_path( path, flags, allow_empty );
     102           0 : }
     103             : 
     104             : 
     105             : /** \brief Create a glob_dir from a path and flags.
     106             :  *
     107             :  * This constructor calls set_path() immediately using the two parameters
     108             :  * passed to it.
     109             :  *
     110             :  * \param[in] path  The path including the Unix shell wildcards.
     111             :  * \param[in] flags  A set of GLOB_... flags.
     112             :  * \param[in] allow_empty  Just return on an empty glob().
     113             :  *
     114             :  * \sa set_path()
     115             :  */
     116           0 : glob_dir::glob_dir( std::string const & path, int const flags, bool allow_empty )
     117             : {
     118           0 :     set_path( path, flags, allow_empty );
     119           0 : }
     120             : 
     121             : 
     122             : /** \brief Create a glob_dir from a path and flags.
     123             :  *
     124             :  * This constructor calls set_path() immediately using the two parameters
     125             :  * passed to it.
     126             :  *
     127             :  * \param[in] path  The path including the Unix shell wildcards.
     128             :  * \param[in] flags  A set of GLOB_... flags.
     129             :  * \param[in] allow_empty  Just return on an empty glob().
     130             :  *
     131             :  * \sa set_path()
     132             :  */
     133           0 : glob_dir::glob_dir( QString const & path, int const flags, bool allow_empty )
     134             : {
     135           0 :     set_path( path, flags, allow_empty );
     136           0 : }
     137             : 
     138             : 
     139             : /** \brief Set the path to read with glob().
     140             :  *
     141             :  * This function is an overload which accepts a bare pointer as input.
     142             :  *
     143             :  * \param[in] path  The path including the Unix shell wildcards.
     144             :  * \param[in] flags  A set of GLOB_... flags.
     145             :  * \param[in] allow_empty  Just return on an empty glob().
     146             :  */
     147           0 : void glob_dir::set_path( char const * path, int const flags, bool allow_empty )
     148             : {
     149           0 :     if(path != nullptr)
     150             :     {
     151           0 :         set_path(std::string(path), flags, allow_empty);
     152             :     }
     153           0 : }
     154             : 
     155             : 
     156             : /** \brief Set the path to read with glob().
     157             :  *
     158             :  * This function passes the \p path parameter to the glob() function and
     159             :  * saves the results in an internally managed glob_t structure.
     160             :  *
     161             :  * The flags are as specified in the glob(3) function (try `man glob`).
     162             :  *
     163             :  * The path is expected to already include a wildcard. Without a wildcard,
     164             :  * it probably won't work as expected.
     165             :  *
     166             :  * The function doesn't return anything. Instead it will memorize the
     167             :  * results and enumerate them once the enumerate_glob() function is called.
     168             :  *
     169             :  * \note
     170             :  * Do not worry about the globfree(), this class handles that part internally.
     171             :  *
     172             :  * \todo
     173             :  * Offer another function to retrieve a vector of strings instead of only an
     174             :  * enumeration function.
     175             :  *
     176             :  * \param[in] path  The path including the Unix shell wildcards.
     177             :  * \param[in] flags  A set of GLOB_... flags.
     178             :  * \param[in] allow_empty  Just return on an empty glob().
     179             :  */
     180           0 : void glob_dir::set_path( std::string const & path, int const flags, bool allow_empty )
     181             : {
     182           0 :     f_dir = glob_pointer_t( new glob_t );
     183           0 :     *f_dir = glob_t();
     184           0 :     int const r(glob(path.c_str(), flags, glob_err_callback, f_dir.get()));
     185           0 :     if(r != 0)
     186             :     {
     187             :         // do nothing when errors occur
     188             :         //
     189           0 :         QString err_msg;
     190           0 :         switch(r)
     191             :         {
     192           0 :         case GLOB_NOSPACE:
     193           0 :             err_msg = "glob() did not have enough memory to alllocate its buffers.";
     194           0 :             break;
     195             : 
     196           0 :         case GLOB_ABORTED:
     197           0 :             err_msg = "glob() was aborted after a read error.";
     198           0 :             break;
     199             : 
     200           0 :         case GLOB_NOMATCH:
     201           0 :             if(allow_empty)
     202             :             {
     203           0 :                 return;
     204             :             }
     205           0 :             err_msg = QString("glob() could not find any files matching the specified glob pattern: \"%1\".")
     206           0 :                                 .arg(QString::fromUtf8(path.c_str()));
     207           0 :             break;
     208             : 
     209           0 :         default:
     210           0 :             err_msg = QString("unknown glob() error code: %1.").arg(r);
     211           0 :             break;
     212             : 
     213             :         }
     214           0 :         throw glob_dir_exception( r, err_msg );
     215             :     }
     216             : }
     217             : 
     218             : 
     219             : /** \brief Set the path to read with glob().
     220             :  *
     221             :  * This function is an overload with a QString. See the set_path() function
     222             :  * with an std::string for more details.
     223             :  *
     224             :  * \param[in] path  The path including the Unix shell wildcards.
     225             :  * \param[in] flags  A set of GLOB_... flags.
     226             :  * \param[in] allow_empty  Just return on an empty glob().
     227             :  */
     228           0 : void glob_dir::set_path( QString const & path, int const flags, bool allow_empty )
     229             : {
     230           0 :     set_path(path.toUtf8().data(), flags, allow_empty);
     231           0 : }
     232             : 
     233             : 
     234             : /** \brief Enumerate full filenames with an std::string.
     235             :  *
     236             :  * This function enumerates all the filenames found in this glob
     237             :  * calling your callback once per file. This function expects
     238             :  * an std::string. You can also enumerate using a QString.
     239             :  *
     240             :  * \param[in] func  The function to call on each filename.
     241             :  */
     242           0 : void glob_dir::enumerate_glob( std::function<void (std::string path)> func ) const
     243             : {
     244           0 :     if(f_dir != nullptr)
     245             :     {
     246           0 :         for(size_t idx(0); idx < f_dir->gl_pathc; ++idx)
     247             :         {
     248           0 :             func(f_dir->gl_pathv[idx]);
     249             :         }
     250             :     }
     251           0 : }
     252             : 
     253             : 
     254             : /** \brief Enumerate full filenames with a QString.
     255             :  *
     256             :  * This function enumerates all the filenames found in this glob
     257             :  * calling your callback once per file. This function expects
     258             :  * a QString. You can also enumerate using an std::string.
     259             :  *
     260             :  * \param[in] func  The function to call on each filename.
     261             :  */
     262           0 : void glob_dir::enumerate_glob( std::function<void (QString path)> func ) const
     263             : {
     264           0 :     if(f_dir != nullptr)
     265             :     {
     266           0 :         for(size_t idx(0); idx < f_dir->gl_pathc; ++idx)
     267             :         {
     268           0 :             func(QString::fromUtf8(f_dir->gl_pathv[idx]));
     269             :         }
     270             :     }
     271           0 : }
     272             : 
     273             : 
     274             : 
     275             : 
     276           6 : } // namespace snap
     277             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13