From 00551b2caacdc6f4987889394379cd42a353cce2 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 15 Jul 2024 15:26:28 +0200 Subject: [PATCH 01/94] OGR SQL: do not make backslash a special character inside single-quoted strings, to improve compliance wih SQL92 The backslash followed by single-quote sequence was dealt as a way of escaping the single-quote character, but this also prevented to use backslash at the end of a single-quoted literal. So no longer make backslash a special character inside single-quoted strings Fixes #10416 --- autotest/ogr/ogr_sql_test.py | 4 ++-- ogr/swq.cpp | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/autotest/ogr/ogr_sql_test.py b/autotest/ogr/ogr_sql_test.py index a3041c326e81..e9c187219bed 100755 --- a/autotest/ogr/ogr_sql_test.py +++ b/autotest/ogr/ogr_sql_test.py @@ -1206,11 +1206,11 @@ def test_ogr_sql_42(data_ds): def test_ogr_sql_43(data_ds): - sql = "SELECT '\"' as a, '\\'' as b, '''' as c FROM poly" + sql = "SELECT '\"' as a, '\\' as b, '''' as c FROM poly" with data_ds.ExecuteSQL(sql) as sql_lyr: feat = sql_lyr.GetNextFeature() assert feat["a"] == '"' - assert feat["b"] == "'" + assert feat["b"] == "\\" assert feat["c"] == "'" diff --git a/ogr/swq.cpp b/ogr/swq.cpp index 38d983d42489..01c78b3ce0f1 100644 --- a/ogr/swq.cpp +++ b/ogr/swq.cpp @@ -118,11 +118,14 @@ int swqlex(YYSTYPE *ppNode, swq_parse_context *context) while (*pszInput != '\0') { - if (chQuote == '"' && *pszInput == '\\' && pszInput[1] == '"') - pszInput++; - else if (chQuote == '\'' && *pszInput == '\\' && - pszInput[1] == '\'') + // Not totally sure we need to preserve this way of escaping for + // strings between double-quotes + if (chQuote == '"' && *pszInput == '\\') + { pszInput++; + if (*pszInput == '\0') + break; + } else if (chQuote == '\'' && *pszInput == '\'' && pszInput[1] == '\'') pszInput++; From ab0993402464d9d5af373d3e814c3c506ba49388 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 18 Jul 2024 18:59:55 +0200 Subject: [PATCH 02/94] NITF 12-bit JPEG writer: fix potential crash if raster width > block width Fixes #10441 --- autotest/gdrivers/nitf.py | 26 ++++++++++++++++++++++++++ frmts/nitf/nitfwritejpeg.cpp | 32 ++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/autotest/gdrivers/nitf.py b/autotest/gdrivers/nitf.py index a24070cbdc97..5c98b3e73fcd 100755 --- a/autotest/gdrivers/nitf.py +++ b/autotest/gdrivers/nitf.py @@ -1744,6 +1744,32 @@ def test_nitf_42(not_jpeg_9b): ds = None +############################################################################### +# Check creating a 12-bit JPEG compressed NITF + + +def test_nitf_write_jpeg12(not_jpeg_9b, tmp_path): + # Check if JPEG driver supports 12bit JPEG reading/writing + jpg_drv = gdal.GetDriverByName("JPEG") + md = jpg_drv.GetMetadata() + if md[gdal.DMD_CREATIONDATATYPES].find("UInt16") == -1: + pytest.skip("12bit jpeg not available") + + ds = gdal.GetDriverByName("MEM").Create("", 10000, 1, 3, gdal.GDT_UInt16) + ds.GetRasterBand(1).Fill(4096) + ds.GetRasterBand(2).Fill(0) + ds.GetRasterBand(3).Fill(4096) + out_filename = str(tmp_path / "out.ntf") + with gdal.quiet_errors(): + gdal.GetDriverByName("NITF").CreateCopy(out_filename, ds, options=["IC=C3"]) + + ds = gdal.Open(out_filename) + assert ds.GetRasterBand(1).DataType == gdal.GDT_UInt16 + assert [ + ds.GetRasterBand(i + 1).GetStatistics(0, 1)[2] for i in range(3) + ] == pytest.approx([4095, 0, 4095], abs=1) + + ############################################################################### # Test CreateCopy() in IC=C8 with various JPEG2000 drivers diff --git a/frmts/nitf/nitfwritejpeg.cpp b/frmts/nitf/nitfwritejpeg.cpp index ab4053a4edb0..1b418ad32f1b 100644 --- a/frmts/nitf/nitfwritejpeg.cpp +++ b/frmts/nitf/nitfwritejpeg.cpp @@ -218,7 +218,7 @@ int NITFWriteJPEGBlock(GDALDataset *poSrcDS, VSILFILE *fp, int nBlockXOff, const int nXSize = poSrcDS->GetRasterXSize(); const int nYSize = poSrcDS->GetRasterYSize(); - const double nTotalPixels = static_cast(nXSize * nYSize); + const double nTotalPixels = static_cast(nXSize) * nYSize; int nBlockXSizeToRead = nBlockXSize; if (nBlockXSize * nBlockXOff + nBlockXSize > nXSize) @@ -248,22 +248,38 @@ int NITFWriteJPEGBlock(GDALDataset *poSrcDS, VSILFILE *fp, int nBlockXOff, static_cast(nBands) * nWorkDTSize * nBlockXSize, nWorkDTSize, nullptr); -#if !defined(JPEG_LIB_MK1_OR_12BIT) /* Repeat the last pixel till the end of the line */ /* to minimize discontinuity */ if (nBlockXSizeToRead < nBlockXSize) { for (int iBand = 0; iBand < nBands; iBand++) { - GByte bVal = - pabyScanline[nBands * (nBlockXSizeToRead - 1) + iBand]; - for (int iX = nBlockXSizeToRead; iX < nBlockXSize; iX++) +#if defined(JPEG_LIB_MK1_OR_12BIT) + if (eWorkDT == GDT_UInt16) { - pabyScanline[nBands * iX + iBand] = bVal; + GUInt16 *panScanline = + reinterpret_cast(pabyScanline); + const GUInt16 nVal = + panScanline[nBands * (nBlockXSizeToRead - 1) + + iBand]; + for (int iX = nBlockXSizeToRead; iX < nBlockXSize; iX++) + { + panScanline[nBands * iX + iBand] = nVal; + } + } + else +#endif + { + GByte bVal = + pabyScanline[nBands * (nBlockXSizeToRead - 1) + + iBand]; + for (int iX = nBlockXSizeToRead; iX < nBlockXSize; iX++) + { + pabyScanline[nBands * iX + iBand] = bVal; + } } } } -#endif } #if defined(JPEG_LIB_MK1_OR_12BIT) @@ -272,7 +288,7 @@ int NITFWriteJPEGBlock(GDALDataset *poSrcDS, VSILFILE *fp, int nBlockXOff, { GUInt16 *panScanline = reinterpret_cast(pabyScanline); - for (int iPixel = 0; iPixel < nXSize * nBands; iPixel++) + for (int iPixel = 0; iPixel < nBlockXSize * nBands; iPixel++) { if (panScanline[iPixel] > 4095) { From 9f162425322942801891e84602ed15622f2e5dd3 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 18 Jul 2024 21:20:17 +0200 Subject: [PATCH 03/94] Doc: API: mention header file to include Fixes #10431 --- doc/source/api/gdalattribute_cpp.rst | 5 +++++ doc/source/api/gdaldataset_cpp.rst | 8 ++++++++ doc/source/api/gdaldimension_cpp.rst | 8 ++++++++ doc/source/api/gdaldriver_cpp.rst | 5 +++++ doc/source/api/gdalextendeddatatype_cpp.rst | 5 +++++ doc/source/api/gdalgroup_cpp.rst | 8 ++++++++ doc/source/api/gdalmdarray_cpp.rst | 8 ++++++++ doc/source/api/gdalrasterband_cpp.rst | 8 ++++++++ doc/source/api/gdalwarp_cpp.rst | 8 ++++++++ doc/source/api/gnm_cpp.rst | 8 ++++++++ doc/source/api/ogrfeature_cpp.rst | 5 +++++ doc/source/api/ogrfeaturestyle_cpp.rst | 8 ++++++++ doc/source/api/ogrgeometry_cpp.rst | 5 ++++- doc/source/api/ogrlayer_cpp.rst | 8 ++++++++ doc/source/api/ogrspatialref.rst | 8 ++++++++ 15 files changed, 104 insertions(+), 1 deletion(-) diff --git a/doc/source/api/gdalattribute_cpp.rst b/doc/source/api/gdalattribute_cpp.rst index cfd95ebd601f..bcf8d58f0f31 100644 --- a/doc/source/api/gdalattribute_cpp.rst +++ b/doc/source/api/gdalattribute_cpp.rst @@ -9,6 +9,11 @@ GDALAttribute C++ API ================================================================================ +Include file +------------ + +:file:`gdal_priv.h` + GDALAttribute class ------------------- diff --git a/doc/source/api/gdaldataset_cpp.rst b/doc/source/api/gdaldataset_cpp.rst index 5f9938a0d0d8..a47ecfe3f74a 100644 --- a/doc/source/api/gdaldataset_cpp.rst +++ b/doc/source/api/gdaldataset_cpp.rst @@ -9,6 +9,14 @@ GDALDataset C++ API ================================================================================ +Include file +------------ + +:file:`gdal_priv.h` + +GDALDataset class +----------------- + .. doxygenclass:: GDALDataset :project: api :members: diff --git a/doc/source/api/gdaldimension_cpp.rst b/doc/source/api/gdaldimension_cpp.rst index 2a32768d9ea6..e6dbb1d89980 100644 --- a/doc/source/api/gdaldimension_cpp.rst +++ b/doc/source/api/gdaldimension_cpp.rst @@ -9,6 +9,14 @@ GDALDimension C++ API ================================================================================ +Include file +------------ + +:file:`gdal_priv.h` + +GDALDimension class +------------------- + .. doxygenclass:: GDALDimension :project: api :members: diff --git a/doc/source/api/gdaldriver_cpp.rst b/doc/source/api/gdaldriver_cpp.rst index d9dfcf145e57..2081ec3a03bf 100644 --- a/doc/source/api/gdaldriver_cpp.rst +++ b/doc/source/api/gdaldriver_cpp.rst @@ -9,6 +9,11 @@ GDALDriver C++ API ================================================================================ +Include file +------------ + +:file:`gdal_priv.h` + GDALDriver class ---------------- diff --git a/doc/source/api/gdalextendeddatatype_cpp.rst b/doc/source/api/gdalextendeddatatype_cpp.rst index 40123ddfedcb..b1755cce378f 100644 --- a/doc/source/api/gdalextendeddatatype_cpp.rst +++ b/doc/source/api/gdalextendeddatatype_cpp.rst @@ -9,6 +9,11 @@ GDALExtendedDataType C++ API ================================================================================ +Include file +------------ + +:file:`gdal_priv.h` + GDALExtendedDataType class -------------------------- diff --git a/doc/source/api/gdalgroup_cpp.rst b/doc/source/api/gdalgroup_cpp.rst index 0436b92046e5..cfd1b2324404 100644 --- a/doc/source/api/gdalgroup_cpp.rst +++ b/doc/source/api/gdalgroup_cpp.rst @@ -9,6 +9,14 @@ GDALGroup C++ API ================================================================================ +Include file +------------ + +:file:`gdal_priv.h` + +GDALGroup class +--------------- + .. doxygenclass:: GDALGroup :project: api :members: diff --git a/doc/source/api/gdalmdarray_cpp.rst b/doc/source/api/gdalmdarray_cpp.rst index b77169a98d0a..2d811ba6d79f 100644 --- a/doc/source/api/gdalmdarray_cpp.rst +++ b/doc/source/api/gdalmdarray_cpp.rst @@ -9,6 +9,14 @@ GDALMDArray C++ API ================================================================================ +Include file +------------ + +:file:`gdal_priv.h` + +GDALMDArray class +----------------- + .. doxygenclass:: GDALMDArray :project: api :members: diff --git a/doc/source/api/gdalrasterband_cpp.rst b/doc/source/api/gdalrasterband_cpp.rst index b5c1146fbb90..9dd6204aa516 100644 --- a/doc/source/api/gdalrasterband_cpp.rst +++ b/doc/source/api/gdalrasterband_cpp.rst @@ -9,6 +9,14 @@ GDALRasterBand C++ API ================================================================================ +Include file +------------ + +:file:`gdal_priv.h` + +GDALRasterBand class +-------------------- + .. doxygenclass:: GDALRasterBand :project: api :members: diff --git a/doc/source/api/gdalwarp_cpp.rst b/doc/source/api/gdalwarp_cpp.rst index 47b57394a7d3..8d19a8d044ee 100644 --- a/doc/source/api/gdalwarp_cpp.rst +++ b/doc/source/api/gdalwarp_cpp.rst @@ -9,5 +9,13 @@ Warper C++ API ================================================================================ +Include file +------------ + +:file:`gdalwarper.h` + +Warper C++ API +-------------- + .. doxygenfile:: gdalwarper.h :project: api diff --git a/doc/source/api/gnm_cpp.rst b/doc/source/api/gnm_cpp.rst index ac05bffca4fb..ac11caf60ad3 100644 --- a/doc/source/api/gnm_cpp.rst +++ b/doc/source/api/gnm_cpp.rst @@ -9,5 +9,13 @@ Geographic Network C++ API ================================================================================ +Include file +------------ + +:file:`gnm.h` + +Geographic Network C++ API +-------------------------- + .. doxygenfile:: gnm.h :project: api diff --git a/doc/source/api/ogrfeature_cpp.rst b/doc/source/api/ogrfeature_cpp.rst index 9d1833db43a4..22fd1e8a0506 100644 --- a/doc/source/api/ogrfeature_cpp.rst +++ b/doc/source/api/ogrfeature_cpp.rst @@ -9,6 +9,11 @@ OGRFeature C++ API ================================================================================ +Include file +------------ + +:file:`ogr_feature.h` + OGRFeature class ---------------- diff --git a/doc/source/api/ogrfeaturestyle_cpp.rst b/doc/source/api/ogrfeaturestyle_cpp.rst index 825adc0da519..2e330ac7da62 100644 --- a/doc/source/api/ogrfeaturestyle_cpp.rst +++ b/doc/source/api/ogrfeaturestyle_cpp.rst @@ -9,5 +9,13 @@ OGRFeature Style C++ API ================================================================================ +Include file +------------ + +:file:`ogr_featurestyle.h` + +OGRFeature Style C++ API +------------------------ + .. doxygenfile:: ogr_featurestyle.h :project: api diff --git a/doc/source/api/ogrgeometry_cpp.rst b/doc/source/api/ogrgeometry_cpp.rst index 340880b7e6ce..c09c35bd7bbe 100644 --- a/doc/source/api/ogrgeometry_cpp.rst +++ b/doc/source/api/ogrgeometry_cpp.rst @@ -9,7 +9,10 @@ OGRGeometry C++ API ================================================================================ -Include file: ogr_geometry.h +Include file +------------ + +:file:`ogr_geometry.h` OGRGeometryFactory class ------------------------ diff --git a/doc/source/api/ogrlayer_cpp.rst b/doc/source/api/ogrlayer_cpp.rst index c3d3422b8d6d..951d1b8b4440 100644 --- a/doc/source/api/ogrlayer_cpp.rst +++ b/doc/source/api/ogrlayer_cpp.rst @@ -9,6 +9,14 @@ OGRLayer C++ API ================================================================================ +Include file +------------ + +:file:`ogrsf_frmts.h` + +OGRLayer class +-------------- + .. doxygenclass:: OGRLayer :project: api :members: diff --git a/doc/source/api/ogrspatialref.rst b/doc/source/api/ogrspatialref.rst index 31cb013e8b30..56b9c7ecf287 100644 --- a/doc/source/api/ogrspatialref.rst +++ b/doc/source/api/ogrspatialref.rst @@ -9,5 +9,13 @@ Spatial Reference System C++ API ================================================================================ +Include file +------------ + +:file:`ogr_spatialref.h` + +Spatial Reference System C++ API +-------------------------------- + .. doxygenfile:: ogr_spatialref.h :project: api From 3a99d23631088d623ed9c3d24eca70135c1a0200 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 18 Jul 2024 23:52:30 +0200 Subject: [PATCH 04/94] netCDF multidim: add OpenMDArray() options to set up nc_set_var_chunk_cache() --- autotest/gdrivers/netcdf_multidim.py | 24 ++++++++++ doc/source/drivers/raster/netcdf.rst | 22 +++++++++ frmts/netcdf/netcdfdataset.h | 6 +-- frmts/netcdf/netcdfdrivercore.cpp | 11 +++++ frmts/netcdf/netcdfmultidim.cpp | 70 +++++++++++++++++++++++++++- 5 files changed, 128 insertions(+), 5 deletions(-) diff --git a/autotest/gdrivers/netcdf_multidim.py b/autotest/gdrivers/netcdf_multidim.py index bc9ea089c208..c9492f866f06 100755 --- a/autotest/gdrivers/netcdf_multidim.py +++ b/autotest/gdrivers/netcdf_multidim.py @@ -4084,3 +4084,27 @@ def test2(): test() test2() + + +############################################################################### + + +def test_netcdf_multidim_chunk_cache_options(): + + ds = gdal.OpenEx("data/netcdf/nc4_vars.nc", gdal.OF_MULTIDIM_RASTER) + rg = ds.GetRootGroup() + + var = rg.OpenMDArray( + "Band1", + [ + "RAW_DATA_CHUNK_CACHE_SIZE=2000000", + "CHUNK_SLOTS=1000", + "PREEMPTION=0.9", + "INCLUDE_CHUNK_CACHE_PARAMETERS_IN_STRUCTURAL_INFO=YES", + ], + ) + assert var.GetStructuralInfo() == { + "RAW_DATA_CHUNK_CACHE_SIZE": "2000000", + "CHUNK_SLOTS": "1000", + "PREEMPTION": "0.900000", + } diff --git a/doc/source/drivers/raster/netcdf.rst b/doc/source/drivers/raster/netcdf.rst index df960742a559..9769eebf66bc 100644 --- a/doc/source/drivers/raster/netcdf.rst +++ b/doc/source/drivers/raster/netcdf.rst @@ -700,6 +700,28 @@ The :cpp:func:`GDALGroup::OpenMDArray` method supports the following options: fill value will be used as nodata when there is no _FillValue or missing_value attribute (except on variables of type Byte, UByte, Char) +- RAW_DATA_CHUNK_CACHE_SIZE=. (GDAL >= 3.10, advanced libnetcdf parameter) + The total size of the libnetcdf raw data chunk cache, in bytes. Default value + (at least for some versions of libnetcdf) is 1 MB. Only for netCDF4/HDF5 files. + +- CHUNK_SLOTS=. (GDAL >= 3.10, advanced libnetcdf parameter) + The total size of the libnetcdf raw data chunk cache, in bytes. + Default value (at least for some versions of libnetcdf) is 521. + Only for netCDF4/HDF5 files. + +- PREEMPTION= between 0 and 1. (GDAL >= 3.10, advanced libnetcdf parameter) + Indicates how much chunks from libnetcdf chunk cache that have been fully read + are favored for preemption. + A value of zero means fully read chunks are treated no differently than other + chunks (the preemption is strictly least-recently used) while a value of one + means fully read chunks are always preempted before other chunks. + Default value (at least for some versions of libnetcdf) is 0.75. + Only for netCDF4/HDF5 files. + +For RAW_DATA_CHUNK_CACHE_SIZE, CHUNK_SLOTS and PREEMPTION, consult +`nc_set_var_chunk_cache `__ and +`documentation about netCDF chunk cacke `__ + The :cpp:func:`GDALGroup::CreateMDArray` method supports the following options: - NC_TYPE=NC_CHAR/NC_BYTE/NC_INT64/NC_UINT64: to overload the netCDF data type diff --git a/frmts/netcdf/netcdfdataset.h b/frmts/netcdf/netcdfdataset.h index 8f14bf4b882c..674cdd58d639 100644 --- a/frmts/netcdf/netcdfdataset.h +++ b/frmts/netcdf/netcdfdataset.h @@ -144,9 +144,9 @@ static const int NCDF_DEFLATE_LEVEL = 1; /* best time/size ratio */ if (NCDF_ERR_status_ != NC_NOERR) \ { \ CPLError(CE_Failure, CPLE_AppDefined, \ - "netcdf error #%d : %s .\nat (%s,%s,%d)\n", status, \ - nc_strerror(NCDF_ERR_status_), __FILE__, __FUNCTION__, \ - __LINE__); \ + "netcdf error #%d : %s .\nat (%s,%s,%d)\n", \ + NCDF_ERR_status_, nc_strerror(NCDF_ERR_status_), \ + __FILE__, __FUNCTION__, __LINE__); \ } \ } while (0) diff --git a/frmts/netcdf/netcdfdrivercore.cpp b/frmts/netcdf/netcdfdrivercore.cpp index 84c273922364..507ae89b78d0 100644 --- a/frmts/netcdf/netcdfdrivercore.cpp +++ b/frmts/netcdf/netcdfdrivercore.cpp @@ -555,6 +555,17 @@ void netCDFDriverSetCommonMetadata(GDALDriver *poDriver) "