diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp index aa2ab535501b..a7545e013980 100644 --- a/frmts/netcdf/netcdfdataset.cpp +++ b/frmts/netcdf/netcdfdataset.cpp @@ -452,10 +452,10 @@ netCDFRasterBand::netCDFRasterBand(const netCDFRasterBand::CONSTRUCTOR_OPEN &, const char *pszNoValueName = nullptr; // Find attribute name, either _FillValue or missing_value. - int status = nc_inq_att(cdfid, nZId, _FillValue, &atttype, &attlen); + int status = nc_inq_att(cdfid, nZId, NCDF_FillValue, &atttype, &attlen); if (status == NC_NOERR) { - pszNoValueName = _FillValue; + pszNoValueName = NCDF_FillValue; } else { @@ -1171,8 +1171,8 @@ CPLErr netCDFRasterBand::SetMetadataItem(const char *pszName, // Same logic as in CopyMetadata() const char *const papszIgnoreBand[] = { - CF_ADD_OFFSET, CF_SCALE_FACTOR, "valid_range", "_Unsigned", - _FillValue, "coordinates", nullptr}; + CF_ADD_OFFSET, CF_SCALE_FACTOR, "valid_range", "_Unsigned", + NCDF_FillValue, "coordinates", nullptr}; // Do not copy varname, stats, NETCDF_DIM_*, nodata // and items in papszIgnoreBand. if (STARTS_WITH(pszName, "NETCDF_VARNAME") || @@ -1490,34 +1490,34 @@ CPLErr netCDFRasterBand::SetNoDataValue(double dfNoData) if (bSignedData) { signed char cNoDataValue = static_cast(dfNoData); - status = nc_put_att_schar(cdfid, nZId, _FillValue, nc_datatype, - 1, &cNoDataValue); + status = nc_put_att_schar(cdfid, nZId, NCDF_FillValue, + nc_datatype, 1, &cNoDataValue); } else { const unsigned char ucNoDataValue = static_cast(dfNoData); - status = nc_put_att_uchar(cdfid, nZId, _FillValue, nc_datatype, - 1, &ucNoDataValue); + status = nc_put_att_uchar(cdfid, nZId, NCDF_FillValue, + nc_datatype, 1, &ucNoDataValue); } } else if (eDataType == GDT_Int16) { short nsNoDataValue = static_cast(dfNoData); - status = nc_put_att_short(cdfid, nZId, _FillValue, nc_datatype, 1, - &nsNoDataValue); + status = nc_put_att_short(cdfid, nZId, NCDF_FillValue, nc_datatype, + 1, &nsNoDataValue); } else if (eDataType == GDT_Int32) { int nNoDataValue = static_cast(dfNoData); - status = nc_put_att_int(cdfid, nZId, _FillValue, nc_datatype, 1, + status = nc_put_att_int(cdfid, nZId, NCDF_FillValue, nc_datatype, 1, &nNoDataValue); } else if (eDataType == GDT_Float32) { float fNoDataValue = static_cast(dfNoData); - status = nc_put_att_float(cdfid, nZId, _FillValue, nc_datatype, 1, - &fNoDataValue); + status = nc_put_att_float(cdfid, nZId, NCDF_FillValue, nc_datatype, + 1, &fNoDataValue); } else if (eDataType == GDT_UInt16 && reinterpret_cast(poDS)->eFormat == @@ -1525,21 +1525,21 @@ CPLErr netCDFRasterBand::SetNoDataValue(double dfNoData) { unsigned short usNoDataValue = static_cast(dfNoData); - status = nc_put_att_ushort(cdfid, nZId, _FillValue, nc_datatype, 1, - &usNoDataValue); + status = nc_put_att_ushort(cdfid, nZId, NCDF_FillValue, nc_datatype, + 1, &usNoDataValue); } else if (eDataType == GDT_UInt32 && reinterpret_cast(poDS)->eFormat == NCDF_FORMAT_NC4) { unsigned int unNoDataValue = static_cast(dfNoData); - status = nc_put_att_uint(cdfid, nZId, _FillValue, nc_datatype, 1, - &unNoDataValue); + status = nc_put_att_uint(cdfid, nZId, NCDF_FillValue, nc_datatype, + 1, &unNoDataValue); } else { - status = nc_put_att_double(cdfid, nZId, _FillValue, nc_datatype, 1, - &dfNoData); + status = nc_put_att_double(cdfid, nZId, NCDF_FillValue, nc_datatype, + 1, &dfNoData); } NCDF_ERR(status); @@ -1586,7 +1586,7 @@ CPLErr netCDFRasterBand::SetNoDataValueAsInt64(int64_t nNoData) // Write value if in update mode. if (poDS->GetAccess() == GA_Update) { - // netcdf-4 does not allow to set _FillValue after leaving define mode, + // netcdf-4 does not allow to set NCDF_FillValue after leaving define mode, // but it is ok if variable has not been written to, so only print // debug. See bug #4484. if (m_bNoDataSetAsInt64 && @@ -1616,14 +1616,14 @@ CPLErr netCDFRasterBand::SetNoDataValueAsInt64(int64_t nNoData) reinterpret_cast(poDS)->eFormat == NCDF_FORMAT_NC4) { long long tmp = static_cast(nNoData); - status = nc_put_att_longlong(cdfid, nZId, _FillValue, nc_datatype, - 1, &tmp); + status = nc_put_att_longlong(cdfid, nZId, NCDF_FillValue, + nc_datatype, 1, &tmp); } else { double dfNoData = static_cast(nNoData); - status = nc_put_att_double(cdfid, nZId, _FillValue, nc_datatype, 1, - &dfNoData); + status = nc_put_att_double(cdfid, nZId, NCDF_FillValue, nc_datatype, + 1, &dfNoData); } NCDF_ERR(status); @@ -1700,14 +1700,14 @@ CPLErr netCDFRasterBand::SetNoDataValueAsUInt64(uint64_t nNoData) reinterpret_cast(poDS)->eFormat == NCDF_FORMAT_NC4) { unsigned long long tmp = static_cast(nNoData); - status = nc_put_att_ulonglong(cdfid, nZId, _FillValue, nc_datatype, - 1, &tmp); + status = nc_put_att_ulonglong(cdfid, nZId, NCDF_FillValue, + nc_datatype, 1, &tmp); } else { double dfNoData = static_cast(nNoData); - status = nc_put_att_double(cdfid, nZId, _FillValue, nc_datatype, 1, - &dfNoData); + status = nc_put_att_double(cdfid, nZId, NCDF_FillValue, nc_datatype, + 1, &dfNoData); } NCDF_ERR(status); @@ -1757,7 +1757,7 @@ CPLErr netCDFRasterBand::DeleteNoDataValue() // Make sure we are in define mode. static_cast(poDS)->SetDefineMode(true); - status = nc_del_att(cdfid, nZId, _FillValue); + status = nc_del_att(cdfid, nZId, NCDF_FillValue); NCDF_ERR(status); @@ -8988,8 +8988,8 @@ static void CopyMetadata(GDALDataset *poSrcDS, GDALRasterBand *poSrcBand, { // Remove the following band meta but set them later from band data. const char *const papszIgnoreBand[] = { - CF_ADD_OFFSET, CF_SCALE_FACTOR, "valid_range", "_Unsigned", - _FillValue, "coordinates", nullptr}; + CF_ADD_OFFSET, CF_SCALE_FACTOR, "valid_range", "_Unsigned", + NCDF_FillValue, "coordinates", nullptr}; const char *const papszIgnoreGlobal[] = {"NETCDF_DIM_EXTRA", nullptr}; CSLConstList papszMetadata = nullptr; diff --git a/frmts/netcdf/netcdfdataset.h b/frmts/netcdf/netcdfdataset.h index 674cdd58d639..8a7aaafa4b63 100644 --- a/frmts/netcdf/netcdfdataset.h +++ b/frmts/netcdf/netcdfdataset.h @@ -181,6 +181,28 @@ static const int NCDF_DEFLATE_LEVEL = 1; /* best time/size ratio */ /* Some additional metadata */ #define OGR_SG_ORIGINAL_LAYERNAME "ogr_layer_name" +/* + * Starting `c26f7ea`, netcdf-c exposes the `NC_FillValue`[1] macro instead of + * `_FillValue` to avoid collisions with C++ standard library[2]. However, the + * previous macro, `_FillValue`, was fully removed causing netcdf-c consumers, + * including GDAL, fail to build. + * + * It's unlikely that this naming change will be backported to the previous + * netcdf-c releases, so we have to account for both macros variants. We do so + * by introducing our own macro, `NCDF_FillValue`, and using that in places + * where `_FillValue` was previously used. If `NC_FillValue` is defined by + * `netcdf.h`, `NCDF_FillValue` expands to it and, if it's not, to `_FillValue`. + * + * References: + * 1. https://github.com/Unidata/netcdf-c/commit/c26f7eabf4a1cd25353f22734f439505fe636a45 + * 2. https://github.com/Unidata/netcdf-c/issues/2858 + */ +#if defined(NC_FillValue) +#define NCDF_FillValue NC_FillValue +#elif defined(_FillValue) +#define NCDF_FillValue _FillValue +#endif + /* -------------------------------------------------------------------- */ /* CF-1 Coordinate Type Naming (Chapter 4. Coordinate Types ) */ /* -------------------------------------------------------------------- */ diff --git a/frmts/netcdf/netcdflayer.cpp b/frmts/netcdf/netcdflayer.cpp index 2603f8847d25..237b53d6fe19 100644 --- a/frmts/netcdf/netcdflayer.cpp +++ b/frmts/netcdf/netcdflayer.cpp @@ -647,14 +647,15 @@ void netCDFLayer::SetRecordDimID(int nRecordDimID) CPLErr netCDFLayer::GetFillValue(int nVarId, char **ppszValue) { - if (NCDFGetAttr(m_nLayerCDFId, nVarId, _FillValue, ppszValue) == CE_None) + if (NCDFGetAttr(m_nLayerCDFId, nVarId, NCDF_FillValue, ppszValue) == + CE_None) return CE_None; return NCDFGetAttr(m_nLayerCDFId, nVarId, "missing_value", ppszValue); } CPLErr netCDFLayer::GetFillValue(int nVarId, double *pdfValue) { - if (NCDFGetAttr(m_nLayerCDFId, nVarId, _FillValue, pdfValue) == CE_None) + if (NCDFGetAttr(m_nLayerCDFId, nVarId, NCDF_FillValue, pdfValue) == CE_None) return CE_None; return NCDFGetAttr(m_nLayerCDFId, nVarId, "missing_value", pdfValue); } diff --git a/frmts/netcdf/netcdfmultidim.cpp b/frmts/netcdf/netcdfmultidim.cpp index 42f5ea416b08..54b94730bdaf 100644 --- a/frmts/netcdf/netcdfmultidim.cpp +++ b/frmts/netcdf/netcdfmultidim.cpp @@ -3753,7 +3753,7 @@ const void *netCDFVariable::GetRawNoDataValue() const m_bGetRawNoDataValueHasRun = true; - const char *pszAttrName = _FillValue; + const char *pszAttrName = NCDF_FillValue; auto poAttr = GetAttribute(pszAttrName); if (!poAttr) { @@ -3878,9 +3878,9 @@ bool netCDFVariable::SetRawNoDataValue(const void *pNoData) m_abyNoData.clear(); nc_type atttype = NC_NAT; size_t attlen = 0; - if (nc_inq_att(m_gid, m_varid, _FillValue, &atttype, &attlen) == + if (nc_inq_att(m_gid, m_varid, NCDF_FillValue, &atttype, &attlen) == NC_NOERR) - ret = nc_del_att(m_gid, m_varid, _FillValue); + ret = nc_del_att(m_gid, m_varid, NCDF_FillValue); else ret = NC_NOERR; if (nc_inq_att(m_gid, m_varid, "missing_value", &atttype, &attlen) == @@ -3912,7 +3912,7 @@ bool netCDFVariable::SetRawNoDataValue(const void *pNoData) if (nc_inq_att(m_gid, m_varid, "missing_value", &atttype, &attlen) == NC_NOERR) { - if (nc_inq_att(m_gid, m_varid, _FillValue, &atttype, &attlen) == + if (nc_inq_att(m_gid, m_varid, NCDF_FillValue, &atttype, &attlen) == NC_NOERR) { CPLError(CE_Failure, CPLE_NotSupported, @@ -3925,7 +3925,7 @@ bool netCDFVariable::SetRawNoDataValue(const void *pNoData) } else { - ret = nc_put_att(m_gid, m_varid, _FillValue, m_nVarType, 1, + ret = nc_put_att(m_gid, m_varid, NCDF_FillValue, m_nVarType, 1, &abyTmp[0]); } } @@ -4076,7 +4076,7 @@ netCDFVariable::GetAttributes(CSLConstList papszOptions) const char szAttrName[NC_MAX_NAME + 1]; szAttrName[0] = 0; NCDF_ERR(nc_inq_attname(m_gid, m_varid, i, szAttrName)); - if (bShowAll || (!EQUAL(szAttrName, _FillValue) && + if (bShowAll || (!EQUAL(szAttrName, NCDF_FillValue) && !EQUAL(szAttrName, "missing_value") && !EQUAL(szAttrName, CF_UNITS) && !EQUAL(szAttrName, CF_SCALE_FACTOR) &&