LCOV - code coverage report
Current view: top level - port - cpl_progress.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 38 38 100.0 %
Date: 2024-04-29 01:40:10 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  CPL - Common Portability Library
       4             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       5             :  * Purpose:  Progress function implementations.
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2013, Frank Warmerdam
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "cpl_progress.h"
      30             : 
      31             : #include <cmath>
      32             : #include <cstdio>
      33             : 
      34             : #include <algorithm>
      35             : 
      36             : #include "cpl_conv.h"
      37             : 
      38             : /************************************************************************/
      39             : /*                         GDALDummyProgress()                          */
      40             : /************************************************************************/
      41             : 
      42             : /**
      43             :  * \brief Stub progress function.
      44             :  *
      45             :  * This is a stub (does nothing) implementation of the GDALProgressFunc()
      46             :  * semantics.  It is primarily useful for passing to functions that take
      47             :  * a GDALProgressFunc() argument but for which the application does not want
      48             :  * to use one of the other progress functions that actually do something.
      49             :  */
      50             : 
      51      413881 : int CPL_STDCALL GDALDummyProgress(double /* dfComplete */,
      52             :                                   const char * /* pszMessage */,
      53             :                                   void * /* pData */)
      54             : {
      55      413881 :     return TRUE;
      56             : }
      57             : 
      58             : /************************************************************************/
      59             : /*                         GDALScaledProgress()                         */
      60             : /************************************************************************/
      61             : typedef struct
      62             : {
      63             :     GDALProgressFunc pfnProgress;
      64             :     void *pData;
      65             :     double dfMin;
      66             :     double dfMax;
      67             : } GDALScaledProgressInfo;
      68             : 
      69             : /**
      70             :  * \brief Scaled progress transformer.
      71             :  *
      72             :  * This is the progress function that should be passed along with the
      73             :  * callback data returned by GDALCreateScaledProgress().
      74             :  */
      75             : 
      76      292301 : int CPL_STDCALL GDALScaledProgress(double dfComplete, const char *pszMessage,
      77             :                                    void *pData)
      78             : 
      79             : {
      80      292301 :     GDALScaledProgressInfo *psInfo =
      81             :         reinterpret_cast<GDALScaledProgressInfo *>(pData);
      82             : 
      83             :     // Optimization if GDALCreateScaledProgress() provided with
      84             :     // GDALDummyProgress.
      85      292301 :     if (psInfo == nullptr)
      86      234439 :         return TRUE;
      87             : 
      88      115724 :     return psInfo->pfnProgress(dfComplete * (psInfo->dfMax - psInfo->dfMin) +
      89       57862 :                                    psInfo->dfMin,
      90       57862 :                                pszMessage, psInfo->pData);
      91             : }
      92             : 
      93             : /************************************************************************/
      94             : /*                      GDALCreateScaledProgress()                      */
      95             : /************************************************************************/
      96             : 
      97             : /**
      98             :  * \brief Create scaled progress transformer.
      99             :  *
     100             :  * Sometimes when an operations wants to report progress it actually
     101             :  * invokes several subprocesses which also take GDALProgressFunc()s,
     102             :  * and it is desirable to map the progress of each sub operation into
     103             :  * a portion of 0.0 to 1.0 progress of the overall process.  The scaled
     104             :  * progress function can be used for this.
     105             :  *
     106             :  * For each subsection a scaled progress function is created and
     107             :  * instead of passing the overall progress func down to the sub functions,
     108             :  * the GDALScaledProgress() function is passed instead.
     109             :  *
     110             :  * @param dfMin the value to which 0.0 in the sub operation is mapped.
     111             :  * @param dfMax the value to which 1.0 is the sub operation is mapped.
     112             :  * @param pfnProgress the overall progress function.
     113             :  * @param pData the overall progress function callback data.
     114             :  *
     115             :  * @return pointer to pass as pProgressArg to sub functions.  Should be freed
     116             :  * with GDALDestroyScaledProgress().
     117             :  *
     118             :  * Example:
     119             :  *
     120             :  * \code
     121             :  *   int MyOperation( ..., GDALProgressFunc pfnProgress, void *pProgressData );
     122             :  *
     123             :  *   {
     124             :  *       void *pScaledProgress;
     125             :  *
     126             :  *       pScaledProgress = GDALCreateScaledProgress( 0.0, 0.5, pfnProgress,
     127             :  *                                                   pProgressData );
     128             :  *       GDALDoLongSlowOperation( ..., GDALScaledProgress, pScaledProgress );
     129             :  *       GDALDestroyScaledProgress( pScaledProgress );
     130             :  *
     131             :  *       pScaledProgress = GDALCreateScaledProgress( 0.5, 1.0, pfnProgress,
     132             :  *                                                   pProgressData );
     133             :  *       GDALDoAnotherOperation( ..., GDALScaledProgress, pScaledProgress );
     134             :  *       GDALDestroyScaledProgress( pScaledProgress );
     135             :  *
     136             :  *       return ...;
     137             :  *   }
     138             :  * \endcode
     139             :  */
     140             : 
     141      491362 : void *CPL_STDCALL GDALCreateScaledProgress(double dfMin, double dfMax,
     142             :                                            GDALProgressFunc pfnProgress,
     143             :                                            void *pData)
     144             : 
     145             : {
     146      491362 :     if (pfnProgress == nullptr || pfnProgress == GDALDummyProgress)
     147      487630 :         return nullptr;
     148             : 
     149             :     GDALScaledProgressInfo *psInfo = static_cast<GDALScaledProgressInfo *>(
     150        3732 :         CPLCalloc(sizeof(GDALScaledProgressInfo), 1));
     151             : 
     152        3732 :     if (std::abs(dfMin - dfMax) < 0.0000001)
     153         163 :         dfMax = dfMin + 0.01;
     154             : 
     155        3732 :     psInfo->pData = pData;
     156        3732 :     psInfo->pfnProgress = pfnProgress;
     157        3732 :     psInfo->dfMin = dfMin;
     158        3732 :     psInfo->dfMax = dfMax;
     159             : 
     160        3732 :     return static_cast<void *>(psInfo);
     161             : }
     162             : 
     163             : /************************************************************************/
     164             : /*                     GDALDestroyScaledProgress()                      */
     165             : /************************************************************************/
     166             : 
     167             : /**
     168             :  * \brief Cleanup scaled progress handle.
     169             :  *
     170             :  * This function cleans up the data associated with a scaled progress function
     171             :  * as returned by GADLCreateScaledProgress().
     172             :  *
     173             :  * @param pData scaled progress handle returned by GDALCreateScaledProgress().
     174             :  */
     175             : 
     176      491288 : void CPL_STDCALL GDALDestroyScaledProgress(void *pData)
     177             : 
     178             : {
     179      491288 :     CPLFree(pData);
     180      491287 : }
     181             : 
     182             : /************************************************************************/
     183             : /*                          GDALTermProgress()                          */
     184             : /************************************************************************/
     185             : 
     186             : /**
     187             :  * \fn GDALTermProgress(double, const char*, void*)
     188             :  * \brief Simple progress report to terminal.
     189             :  *
     190             :  * This progress reporter prints simple progress report to the
     191             :  * terminal window.  The progress report generally looks something like
     192             :  * this:
     193             : 
     194             : \verbatim
     195             : 0...10...20...30...40...50...60...70...80...90...100 - done.
     196             : \endverbatim
     197             : 
     198             :  * Every 2.5% of progress another number or period is emitted.  Note that
     199             :  * GDALTermProgress() uses internal static data to keep track of the last
     200             :  * percentage reported and will get confused if two terminal based progress
     201             :  * reportings are active at the same time.
     202             :  *
     203             :  * The GDALTermProgress() function maintains an internal memory of the
     204             :  * last percentage complete reported in a static variable, and this makes
     205             :  * it unsuitable to have multiple GDALTermProgress()'s active either in a
     206             :  * single thread or across multiple threads.
     207             :  *
     208             :  * @param dfComplete completion ratio from 0.0 to 1.0.
     209             :  * @param pszMessage optional message.
     210             :  * @param pProgressArg ignored callback data argument.
     211             :  *
     212             :  * @return Always returns TRUE indicating the process should continue.
     213             :  */
     214             : 
     215       22789 : int CPL_STDCALL GDALTermProgress(double dfComplete,
     216             :                                  CPL_UNUSED const char *pszMessage,
     217             :                                  CPL_UNUSED void *pProgressArg)
     218             : {
     219             :     const int nThisTick =
     220       22789 :         std::min(40, std::max(0, static_cast<int>(dfComplete * 40.0)));
     221             : 
     222             :     // Have we started a new progress run?
     223             :     static int nLastTick = -1;
     224       22789 :     if (nThisTick < nLastTick && nLastTick >= 39)
     225          18 :         nLastTick = -1;
     226             : 
     227       22789 :     if (nThisTick <= nLastTick)
     228       16782 :         return TRUE;
     229             : 
     230       21192 :     while (nThisTick > nLastTick)
     231             :     {
     232       15185 :         ++nLastTick;
     233       15185 :         if (nLastTick % 4 == 0)
     234        4113 :             fprintf(stdout, "%d", (nLastTick / 4) * 10);
     235             :         else
     236       11072 :             fprintf(stdout, ".");
     237             :     }
     238             : 
     239        6007 :     if (nThisTick == 40)
     240         368 :         fprintf(stdout, " - done.\n");
     241             :     else
     242        5639 :         fflush(stdout);
     243             : 
     244        6007 :     return TRUE;
     245             : }

Generated by: LCOV version 1.14