Skip to content

Commit

Permalink
Create QgsGdalUtils::pathIsCheapToOpen
Browse files Browse the repository at this point in the history
Returns true if a dataset is considered "cheap" to open.

The logic is very rudimentary for now, and considers only the file
size of a few hardcoded formats.
  • Loading branch information
nyalldawson committed Jul 23, 2021
1 parent 5455e91 commit f818a62
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/core/qgsgdalutils.cpp
Expand Up @@ -26,6 +26,7 @@
#include <QNetworkProxy>
#include <QString>
#include <QImage>
#include <QFileInfo>

bool QgsGdalUtils::supportsRasterCreate( GDALDriverH driver )
{
Expand Down Expand Up @@ -514,4 +515,31 @@ void QgsGdalUtils::setupProxy()
}
}
}

bool QgsGdalUtils::pathIsCheapToOpen( const QString &path, int smallFileSizeLimit )
{
const QFileInfo info( path );
const long long size = info.size();

// if size could not be determined, safest to flag path as expensive
if ( size == 0 )
return false;

const QString suffix = info.suffix().toLower();
static QStringList sFileSizeDependentExtensions
{
QStringLiteral( "xlsx" ),
QStringLiteral( "ods" ),
QStringLiteral( "csv" )
};
if ( sFileSizeDependentExtensions.contains( suffix ) )
{
// path corresponds to a file type which is only cheap to open for small files
return size < smallFileSizeLimit;
}

// treat all other formats as expensive.
// TODO -- flag formats which only require a quick header parse as cheap
return false;
}
#endif
16 changes: 16 additions & 0 deletions src/core/qgsgdalutils.h
Expand Up @@ -132,6 +132,22 @@ class CORE_EXPORT QgsGdalUtils
static void setupProxy();
#endif

/**
* Returns TRUE if the dataset at the specified \a path is considered "cheap" to open.
*
* Datasets which are considered cheap to open may correspond to very small file sizes, or data types
* which only require some inexpensive header parsing to open.
*
* One use case for this method is to test whether a remote dataset can be safely opened
* to resolve the geometry types and other metadata without causing undue network traffic.
*
* The \a smallFileSizeLimit argument specifies the maximum file size (in bytes) which will
* be considered as small.
*
* \since QGIS 3.22
*/
static bool pathIsCheapToOpen( const QString &path, int smallFileSizeLimit = 50000 );

friend class TestQgsGdalUtils;
};

Expand Down
16 changes: 16 additions & 0 deletions tests/src/core/testqgsgdalutils.cpp
Expand Up @@ -41,6 +41,7 @@ class TestQgsGdalUtils: public QObject
void testResampleSingleBandRaster();
void testImageToDataset();
void testResampleImageToImage();
void testPathIsCheapToOpen();

private:

Expand Down Expand Up @@ -268,6 +269,21 @@ void TestQgsGdalUtils::testResampleImageToImage()
QCOMPARE( qAlpha( res.pixel( 40, 40 ) ), 255 );
}

void TestQgsGdalUtils::testPathIsCheapToOpen()
{
// should be safe and report false paths which don't exist
QVERIFY( !QgsGdalUtils::pathIsCheapToOpen( "/not/a/file" ) );

// for now, tiff aren't marked as cheap to open
QVERIFY( !QgsGdalUtils::pathIsCheapToOpen( QStringLiteral( TEST_DATA_DIR ) + "/big_raster.tif" ) );

// a csv is considered cheap to open
QVERIFY( QgsGdalUtils::pathIsCheapToOpen( QStringLiteral( TEST_DATA_DIR ) + "/delimitedtext/test.csv" ) );

// ... unless it's larger than the specified file size limit (500 bytes)
QVERIFY( !QgsGdalUtils::pathIsCheapToOpen( QStringLiteral( TEST_DATA_DIR ) + "/delimitedtext/testdms.csv", 500 ) );
}

double TestQgsGdalUtils::identify( GDALDatasetH dataset, int band, int px, int py )
{
GDALRasterBandH hBand = GDALGetRasterBand( dataset, band );
Expand Down

0 comments on commit f818a62

Please sign in to comment.