From 57fd24c8340e497796d05dfd40ef6b2b41072fc2 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 28 Jan 2025 17:08:18 +0100 Subject: [PATCH] Remove R Object Data Store (*.rda) driver --- .../expected_gdalinfo_formats.txt | 1 - ...indows_conda_expected_gdalinfo_formats.txt | 1 - autotest/gdrivers/data/r/r_test.asc | 64 -- autotest/gdrivers/data/r/r_test.rdb | Bin 412 -> 0 bytes autotest/gdrivers/r.py | 58 -- doc/source/drivers/raster/index.rst | 1 - doc/source/drivers/raster/r.rst | 50 -- frmts/CMakeLists.txt | 1 - frmts/r/CMakeLists.txt | 2 - frmts/r/rcreatecopy.cpp | 223 ------- frmts/r/rdataset.cpp | 603 ------------------ frmts/r/rdataset.h | 94 --- 12 files changed, 1098 deletions(-) delete mode 100644 autotest/gdrivers/data/r/r_test.asc delete mode 100644 autotest/gdrivers/data/r/r_test.rdb delete mode 100755 autotest/gdrivers/r.py delete mode 100644 doc/source/drivers/raster/r.rst delete mode 100644 frmts/r/CMakeLists.txt delete mode 100644 frmts/r/rcreatecopy.cpp delete mode 100644 frmts/r/rdataset.cpp delete mode 100644 frmts/r/rdataset.h diff --git a/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt b/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt index 54759dcf3534..3845c4590ace 100644 --- a/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt +++ b/.github/workflows/ubuntu_24.04/expected_gdalinfo_formats.txt @@ -69,7 +69,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda COSAR -raster- (rov): COSAR Annotated Binary Matrix (TerraSAR-X) TSX -raster- (rov): TerraSAR-X Product COASP -raster- (ro): DRDC COASP SAR Processor Raster (*.hdr) - R -raster- (rwv): R Object Data Store (*.rda) MAP -raster- (rov): OziExplorer .MAP KMLSUPEROVERLAY -raster- (rwv): Kml Super Overlay (*.kml, *.kmz) WEBP -raster- (rwv): WEBP (*.webp) diff --git a/.github/workflows/windows_conda_expected_gdalinfo_formats.txt b/.github/workflows/windows_conda_expected_gdalinfo_formats.txt index 2077516a871d..16ecf06ec26f 100644 --- a/.github/workflows/windows_conda_expected_gdalinfo_formats.txt +++ b/.github/workflows/windows_conda_expected_gdalinfo_formats.txt @@ -70,7 +70,6 @@ Supported Formats: (ro:read-only, rw:read-write, +:update, v:virtual-I/O s:subda COSAR -raster- (rov): COSAR Annotated Binary Matrix (TerraSAR-X) TSX -raster- (rov): TerraSAR-X Product COASP -raster- (ro): DRDC COASP SAR Processor Raster (*.hdr) - R -raster- (rwv): R Object Data Store (*.rda) MAP -raster- (rov): OziExplorer .MAP KMLSUPEROVERLAY -raster- (rwv): Kml Super Overlay (*.kml, *.kmz) WEBP -raster- (rwv): WEBP (*.webp) diff --git a/autotest/gdrivers/data/r/r_test.asc b/autotest/gdrivers/data/r/r_test.asc deleted file mode 100644 index b151184ec205..000000000000 --- a/autotest/gdrivers/data/r/r_test.asc +++ /dev/null @@ -1,64 +0,0 @@ -RDA2 -A -2 -133377 -131840 -1026 -1 -4105 -2 -gg -526 -40 -107 -123 -132 -115 -115 -132 -107 -123 -115 -132 -140 -132 -148 -132 -123 -123 -132 -156 -132 -140 -107 -123 -132 -115 -115 -132 -107 -123 -115 -132 -140 -132 -148 -132 -123 -123 -132 -156 -132 -140 -1026 -1 -4105 -3 -dim -13 -3 -4 -5 -2 -254 -254 diff --git a/autotest/gdrivers/data/r/r_test.rdb b/autotest/gdrivers/data/r/r_test.rdb deleted file mode 100644 index 177a2e9d8fca5bb32d2d8ce1d6f17b0ed7c53e87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 412 zcmWG?i7?`d;9_84U}9k6WMp7s1~OTgfCM80g8(N;JUtyq@BvvG4p9ey6a#}p9F$II z0C5={Vh*6vFmZJCFm*8b#0H2y7(WS(53>hG!_+0Cse_q=ZXZlN%w8A`6GvB%E)O#o frk+Cgp@l4SN@gz5|GYp94s{^S3dEqm{|CYVM(#I? diff --git a/autotest/gdrivers/r.py b/autotest/gdrivers/r.py deleted file mode 100755 index ec02766b8abe..000000000000 --- a/autotest/gdrivers/r.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env pytest -############################################################################### -# -# Project: GDAL/OGR Test Suite -# Purpose: Test R driver support. -# Author: Frank Warmerdam -# -############################################################################### -# Copyright (c) 2009, Frank Warmerdam -# -# SPDX-License-Identifier: MIT -############################################################################### - - -import gdaltest - -############################################################################### -# Perform simple read test on an ascii file. - - -def test_r_1(): - - tst = gdaltest.GDALTest("R", "r/r_test.asc", 2, 202) - - tst.testOpen() - - -############################################################################### -# Perform a simple read test on a binary (uncompressed) file. - - -def test_r_2(): - - tst = gdaltest.GDALTest("R", "r/r_test.rdb", 1, 202) - tst.testOpen() - - -############################################################################### -# Verify a simple createcopy operation with 16bit data. - - -def test_r_3(): - - tst = gdaltest.GDALTest("R", "byte.tif", 1, 4672, options=["ASCII=YES"]) - tst.testCreateCopy() - - -############################################################################### -# Test creating a compressed binary stream and reading it back. - - -def test_r_4(): - - tst = gdaltest.GDALTest("R", "byte.tif", 1, 4672) - return tst.testCreateCopy(new_filename="tmp/r_4.rda") - - -############################################################################### diff --git a/doc/source/drivers/raster/index.rst b/doc/source/drivers/raster/index.rst index f35fede51cda..fdeb1c7ecb5c 100644 --- a/doc/source/drivers/raster/index.rst +++ b/doc/source/drivers/raster/index.rst @@ -145,7 +145,6 @@ Raster drivers prf rasterlite rasterlite2 - r rdb rcm rik diff --git a/doc/source/drivers/raster/r.rst b/doc/source/drivers/raster/r.rst deleted file mode 100644 index 69a33245d250..000000000000 --- a/doc/source/drivers/raster/r.rst +++ /dev/null @@ -1,50 +0,0 @@ -.. _raster.r: - -================================================================================ -R -- R Object Data Store -================================================================================ - -.. shortname:: R - -.. built_in_by_default:: - -The R Object File Format is supported for write access, and limited read -access by GDAL. This format is the native format R uses for objects -saved with the *save* command and loaded with the *load* command. GDAL -supports writing a dataset as an array object in this format, and -supports reading files with simple rasters in essentially the same -organization. It will not read most R object files. - -Currently there is no support for reading or writing georeferencing -information. - -Driver capabilities -------------------- - -.. supports_createcopy:: - -.. supports_virtualio:: - -Creation Options ----------------- - -|about-creation-options| -The following creation options are available: - -- .. co:: ASCII - :choices: YES, NO - :default: NO - - Produce an ASCII formatted file, instead of binary, - if set to YES. - -- .. co:: COMPRESS - :choices: YES, NO - :default: YES - - Produces a compressed file if YES, otherwise an - uncompressed file. - -See Also: - -- `R Project `__ diff --git a/frmts/CMakeLists.txt b/frmts/CMakeLists.txt index 950eba3d1f14..a0f1f1d41695 100644 --- a/frmts/CMakeLists.txt +++ b/frmts/CMakeLists.txt @@ -115,7 +115,6 @@ gdal_optional_format(terragen "Terragen™ Terrain File") gdal_optional_format(blx "Magellan BLX Topo File Format") gdal_optional_format(msgn "Meteosat Second Generation (MSG) Native Archive Format (.nat)") gdal_optional_format(til "EarthWatch .TIL Driver") -gdal_optional_format(r "R Object Data Store") gdal_optional_format(northwood "NWT_GRD/NWT_GRC -- Northwood/Vertical Mapper File Format") gdal_optional_format(saga "SAGA GIS Binary Driver") gdal_optional_format(xyz "ASCII Gridded XYZ") diff --git a/frmts/r/CMakeLists.txt b/frmts/r/CMakeLists.txt deleted file mode 100644 index 0d3eeb5a67a5..000000000000 --- a/frmts/r/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_gdal_driver(TARGET gdal_R SOURCES rdataset.h rcreatecopy.cpp rdataset.cpp PLUGIN_CAPABLE NO_DEPS) -gdal_standard_includes(gdal_R) diff --git a/frmts/r/rcreatecopy.cpp b/frmts/r/rcreatecopy.cpp deleted file mode 100644 index 54ff8dbada78..000000000000 --- a/frmts/r/rcreatecopy.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/****************************************************************************** - * - * Project: R Format Driver - * Purpose: CreateCopy() implementation for R stats package object format. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2009, Frank Warmerdam - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_port.h" -#include "rdataset.h" - -#include -#include -#include - -#include "cpl_conv.h" -#include "cpl_error.h" -#include "cpl_progress.h" -#include "cpl_string.h" -#include "cpl_vsi.h" -#include "gdal.h" -#include "gdal_pam.h" -#include "gdal_priv.h" - -GDALDataset *RCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, void *pProgressData); - -/************************************************************************/ -/* ==================================================================== */ -/* Writer Implementation */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* RWriteInteger() */ -/************************************************************************/ - -static void RWriteInteger(VSILFILE *fp, int bASCII, int nValue) - -{ - if (bASCII) - { - char szOutput[50] = {'\0'}; - snprintf(szOutput, sizeof(szOutput), "%d\n", nValue); - VSIFWriteL(szOutput, 1, strlen(szOutput), fp); - } - else - { - CPL_MSBPTR32(&nValue); - VSIFWriteL(&nValue, 4, 1, fp); - } -} - -/************************************************************************/ -/* RWriteString() */ -/************************************************************************/ - -static void RWriteString(VSILFILE *fp, int bASCII, const char *pszValue) - -{ - RWriteInteger(fp, bASCII, 4105); - RWriteInteger(fp, bASCII, static_cast(strlen(pszValue))); - - if (bASCII) - { - VSIFWriteL(pszValue, 1, strlen(pszValue), fp); - VSIFWriteL("\n", 1, 1, fp); - } - else - { - VSIFWriteL(pszValue, 1, static_cast(strlen(pszValue)), fp); - } -} - -/************************************************************************/ -/* RCreateCopy() */ -/************************************************************************/ - -GDALDataset *RCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - CPL_UNUSED int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, void *pProgressData) -{ - const int nBands = poSrcDS->GetRasterCount(); - const int nXSize = poSrcDS->GetRasterXSize(); - const int nYSize = poSrcDS->GetRasterYSize(); - const bool bASCII = CPLFetchBool(papszOptions, "ASCII", false); - const bool bCompressed = CPLFetchBool(papszOptions, "COMPRESS", !bASCII); - - vsi_l_offset nSize = static_cast(nBands) * nXSize * nYSize; - if (nSize > static_cast(INT_MAX)) - { - CPLError(CE_Failure, CPLE_NotSupported, "Too big raster"); - return nullptr; - } - - // Some some rudimentary checks. - - // Setup the filename to actually use. We prefix with - // /vsigzip/ if we want compressed output. - const CPLString osAdjustedFilename = - std::string(bCompressed ? "/vsigzip/" : "") + pszFilename; - - // Create the file. - VSILFILE *fp = VSIFOpenL(osAdjustedFilename, "wb"); - if (fp == nullptr) - { - CPLError(CE_Failure, CPLE_OpenFailed, "Unable to create file %s.", - pszFilename); - return nullptr; - } - - // Write header with version, etc. - if (bASCII) - { - const char *pszHeader = "RDA2\nA\n"; - VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp); - } - else - { - const char *pszHeader = "RDX2\nX\n"; - VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp); - } - - RWriteInteger(fp, bASCII, 2); - RWriteInteger(fp, bASCII, 133377); - RWriteInteger(fp, bASCII, 131840); - - // Establish the primary pairlist with one component object. - RWriteInteger(fp, bASCII, 1026); - RWriteInteger(fp, bASCII, 1); - - // Write the object name. Eventually we should derive this - // from the filename, possible with override by a creation option. - RWriteString(fp, bASCII, "gg"); - - // For now we write the raster as a numeric array with attributes (526). - RWriteInteger(fp, bASCII, 526); - RWriteInteger(fp, bASCII, nXSize * nYSize * nBands); - - // Write the raster data. - CPLErr eErr = CE_None; - - double *padfScanline = - static_cast(CPLMalloc(nXSize * sizeof(double))); - - for (int iBand = 0; iBand < nBands; iBand++) - { - GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1); - - for (int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++) - { - eErr = poBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfScanline, - nXSize, 1, GDT_Float64, sizeof(double), 0, - nullptr); - - if (bASCII) - { - for (int iValue = 0; iValue < nXSize; iValue++) - { - char szValue[128] = {'\0'}; - CPLsnprintf(szValue, sizeof(szValue), "%.16g\n", - padfScanline[iValue]); - VSIFWriteL(szValue, 1, strlen(szValue), fp); - } - } - else - { - for (int iValue = 0; iValue < nXSize; iValue++) - CPL_MSBPTR64(padfScanline + iValue); - - VSIFWriteL(padfScanline, 8, nXSize, fp); - } - - if (eErr == CE_None && - !pfnProgress((iLine + 1) / static_cast(nYSize), nullptr, - pProgressData)) - { - eErr = CE_Failure; - CPLError(CE_Failure, CPLE_UserInterrupt, - "User terminated CreateCopy()"); - } - } - } - - CPLFree(padfScanline); - - // Write out the dims attribute. - RWriteInteger(fp, bASCII, 1026); - RWriteInteger(fp, bASCII, 1); - - RWriteString(fp, bASCII, "dim"); - - RWriteInteger(fp, bASCII, 13); - RWriteInteger(fp, bASCII, 3); - RWriteInteger(fp, bASCII, nXSize); - RWriteInteger(fp, bASCII, nYSize); - RWriteInteger(fp, bASCII, nBands); - - RWriteInteger(fp, bASCII, 254); - - // Terminate overall pairlist. - RWriteInteger(fp, bASCII, 254); - - // Cleanup. - VSIFCloseL(fp); - - if (eErr != CE_None) - return nullptr; - - // Re-open dataset, and copy any auxiliary pam information. - GDALPamDataset *poDS = - static_cast(GDALOpen(pszFilename, GA_ReadOnly)); - - if (poDS) - poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); - - return poDS; -} diff --git a/frmts/r/rdataset.cpp b/frmts/r/rdataset.cpp deleted file mode 100644 index 6879b7cdcf27..000000000000 --- a/frmts/r/rdataset.cpp +++ /dev/null @@ -1,603 +0,0 @@ -/****************************************************************************** - * - * Project: R Format Driver - * Purpose: Read/write R stats package object format. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2009, Frank Warmerdam - * Copyright (c) 2009-2010, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#include "cpl_port.h" -#include "rdataset.h" - -#include -#include -#include -#if HAVE_FCNTL_H -#include -#endif - -#include -#include -#include -#include - -#include "cpl_conv.h" -#include "cpl_error.h" -#include "cpl_progress.h" -#include "cpl_string.h" -#include "cpl_vsi.h" -#include "gdal.h" -#include "gdal_frmts.h" -#include "gdal_pam.h" -#include "gdal_priv.h" - -// constexpr int R_NILSXP = 0; -constexpr int R_LISTSXP = 2; -constexpr int R_CHARSXP = 9; -constexpr int R_INTSXP = 13; -constexpr int R_REALSXP = 14; -constexpr int R_STRSXP = 16; - -namespace -{ - -// TODO(schwehr): Move this to port/? for general use. -bool SafeMult(GIntBig a, GIntBig b, GIntBig *result) -{ - if (a == 0 || b == 0) - { - *result = 0; - return true; - } - - bool result_positive = (a >= 0 && b >= 0) || (a < 0 && b < 0); - if (result_positive) - { - // Cannot convert min() to positive. - if (a == std::numeric_limits::min() || - b == std::numeric_limits::min()) - { - *result = 0; - return false; - } - if (a < 0) - { - a = -a; - b = -b; - } - if (a > std::numeric_limits::max() / b) - { - *result = 0; - return false; - } - *result = a * b; - return true; - } - - if (b < a) - std::swap(a, b); - if (a < (std::numeric_limits::min() + 1) / b) - { - *result = 0; - return false; - } - - *result = a * b; - return true; -} - -} // namespace - -/************************************************************************/ -/* RRasterBand() */ -/************************************************************************/ - -RRasterBand::RRasterBand(RDataset *poDSIn, int nBandIn, - const double *padfMatrixValuesIn) - : padfMatrixValues(padfMatrixValuesIn) -{ - poDS = poDSIn; - nBand = nBandIn; - - eDataType = GDT_Float64; - - nBlockXSize = poDSIn->nRasterXSize; - nBlockYSize = 1; -} - -/************************************************************************/ -/* IReadBlock() */ -/************************************************************************/ - -CPLErr RRasterBand::IReadBlock(int /* nBlockXOff */, int nBlockYOff, - void *pImage) -{ - memcpy(pImage, padfMatrixValues + nBlockYOff * nBlockXSize, - nBlockXSize * 8); - return CE_None; -} - -/************************************************************************/ -/* ==================================================================== */ -/* RDataset() */ -/* ==================================================================== */ -/************************************************************************/ - -/************************************************************************/ -/* RDataset() */ -/************************************************************************/ - -RDataset::RDataset() - : fp(nullptr), bASCII(FALSE), nStartOfData(0), padfMatrixValues(nullptr) -{ -} - -/************************************************************************/ -/* ~RDataset() */ -/************************************************************************/ - -RDataset::~RDataset() -{ - FlushCache(true); - CPLFree(padfMatrixValues); - - if (fp) - VSIFCloseL(fp); -} - -/************************************************************************/ -/* ASCIIFGets() */ -/* */ -/* Fetch one line from an ASCII source into osLastStringRead. */ -/************************************************************************/ - -const char *RDataset::ASCIIFGets() - -{ - char chNextChar = '\0'; - - osLastStringRead.resize(0); - - do - { - chNextChar = '\n'; - VSIFReadL(&chNextChar, 1, 1, fp); - if (chNextChar != '\n') - osLastStringRead += chNextChar; - } while (chNextChar != '\n' && chNextChar != '\0'); - - return osLastStringRead; -} - -/************************************************************************/ -/* ReadInteger() */ -/************************************************************************/ - -int RDataset::ReadInteger() - -{ - if (bASCII) - { - return atoi(ASCIIFGets()); - } - - GInt32 nValue = 0; - - if (VSIFReadL(&nValue, 4, 1, fp) != 1) - return -1; - CPL_MSBPTR32(&nValue); - - return nValue; -} - -/************************************************************************/ -/* ReadFloat() */ -/************************************************************************/ - -double RDataset::ReadFloat() - -{ - if (bASCII) - { - return CPLAtof(ASCIIFGets()); - } - - double dfValue = 0.0; - - if (VSIFReadL(&dfValue, 8, 1, fp) != 1) - return -1; - CPL_MSBPTR64(&dfValue); - - return dfValue; -} - -/************************************************************************/ -/* ReadString() */ -/************************************************************************/ - -const char *RDataset::ReadString() - -{ - if (ReadInteger() % 256 != R_CHARSXP) - { - osLastStringRead = ""; - return ""; - } - - const int nLenSigned = ReadInteger(); - if (nLenSigned < 0) - { - osLastStringRead = ""; - return ""; - } - const size_t nLen = static_cast(nLenSigned); - - char *pachWrkBuf = static_cast(VSIMalloc(nLen)); - if (pachWrkBuf == nullptr) - { - osLastStringRead = ""; - return ""; - } - if (VSIFReadL(pachWrkBuf, 1, nLen, fp) != nLen) - { - osLastStringRead = ""; - CPLFree(pachWrkBuf); - return ""; - } - - if (bASCII) - { - // Suck up newline and any extra junk. - ASCIIFGets(); - } - - osLastStringRead.assign(pachWrkBuf, nLen); - CPLFree(pachWrkBuf); - - return osLastStringRead; -} - -/************************************************************************/ -/* ReadPair() */ -/************************************************************************/ - -bool RDataset::ReadPair(CPLString &osObjName, int &nObjCode) - -{ - nObjCode = ReadInteger(); - if (nObjCode == 254) - return true; - - if ((nObjCode % 256) != R_LISTSXP) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Did not find expected object pair object."); - return false; - } - - int nPairCount = ReadInteger(); - if (nPairCount != 1) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Did not find expected pair count of 1."); - return false; - } - - // Read the object name. - const char *pszName = ReadString(); - if (pszName == nullptr || pszName[0] == '\0') - return false; - - osObjName = pszName; - - // Confirm that we have a numeric matrix object. - nObjCode = ReadInteger(); - - return true; -} - -/************************************************************************/ -/* Identify() */ -/************************************************************************/ - -int RDataset::Identify(GDALOpenInfo *poOpenInfo) -{ - if (poOpenInfo->nHeaderBytes < 50) - return FALSE; - - // If the extension is .rda and the file type is gzip - // compressed we assume it is a gzipped R binary file. - if (memcmp(poOpenInfo->pabyHeader, "\037\213\b", 3) == 0 && - poOpenInfo->IsExtensionEqualToCI("rda")) - return TRUE; - - // Is this an ASCII or XDR binary R file? - if (!STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDA2\nA\n") && - !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDX2\nX\n")) - return FALSE; - - return TRUE; -} - -/************************************************************************/ -/* Open() */ -/************************************************************************/ - -GDALDataset *RDataset::Open(GDALOpenInfo *poOpenInfo) -{ -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - if (poOpenInfo->pabyHeader == nullptr) - return nullptr; -#else - // During fuzzing, do not use Identify to reject crazy content. - if (!Identify(poOpenInfo)) - return nullptr; -#endif - - // Confirm the requested access is supported. - if (poOpenInfo->eAccess == GA_Update) - { - CPLError(CE_Failure, CPLE_NotSupported, - "The R driver does not support update access to existing" - " datasets."); - return nullptr; - } - - // Do we need to route the file through the decompression machinery? - const bool bCompressed = - memcmp(poOpenInfo->pabyHeader, "\037\213\b", 3) == 0; - const CPLString osAdjustedFilename = - std::string(bCompressed ? "/vsigzip/" : "") + poOpenInfo->pszFilename; - - // Establish this as a dataset and open the file using VSI*L. - auto poDS = std::make_unique(); - - poDS->fp = VSIFOpenL(osAdjustedFilename, "r"); - if (poDS->fp == nullptr) - { - return nullptr; - } - - poDS->bASCII = STARTS_WITH_CI( - reinterpret_cast(poOpenInfo->pabyHeader), "RDA2\nA\n"); - - // Confirm this is a version 2 file. - VSIFSeekL(poDS->fp, 7, SEEK_SET); - if (poDS->ReadInteger() != R_LISTSXP) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "It appears %s is not a version 2 R object file after all!", - poOpenInfo->pszFilename); - return nullptr; - } - - // Skip the version values. - poDS->ReadInteger(); - poDS->ReadInteger(); - - // Confirm we have a numeric vector object in a pairlist. - CPLString osObjName; - int nObjCode = 0; - - if (!poDS->ReadPair(osObjName, nObjCode)) - { - return nullptr; - } - - if (nObjCode % 256 != R_REALSXP) - { - CPLError(CE_Failure, CPLE_OpenFailed, - "Failed to find expected numeric vector object."); - return nullptr; - } - - poDS->SetMetadataItem("R_OBJECT_NAME", osObjName); - - // Read the count. - const int nValueCount = poDS->ReadInteger(); - if (nValueCount < 0) - { - CPLError(CE_Failure, CPLE_AppDefined, "nValueCount < 0: %d", - nValueCount); - return nullptr; - } - - poDS->nStartOfData = VSIFTellL(poDS->fp); - - // TODO(schwehr): Factor in the size of doubles. - VSIStatBufL stat; - const int dStatSuccess = - VSIStatExL(osAdjustedFilename, &stat, VSI_STAT_SIZE_FLAG); - if (dStatSuccess != 0 || static_cast(nValueCount) > - stat.st_size - poDS->nStartOfData) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Corrupt file. " - "Object claims to be larger than available bytes. " - "%d > " CPL_FRMT_GUIB, - nValueCount, stat.st_size - poDS->nStartOfData); - return nullptr; - } - - // Read/Skip ahead to attributes. - if (poDS->bASCII) - { - poDS->padfMatrixValues = - static_cast(VSIMalloc2(nValueCount, sizeof(double))); - if (poDS->padfMatrixValues == nullptr) - { - CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d doubles", - nValueCount); - return nullptr; - } - for (int iValue = 0; iValue < nValueCount; iValue++) - poDS->padfMatrixValues[iValue] = poDS->ReadFloat(); - } - else - { - VSIFSeekL(poDS->fp, 8 * nValueCount, SEEK_CUR); - } - - // Read pairs till we run out, trying to find a few items that - // have special meaning to us. - poDS->nRasterXSize = 0; - poDS->nRasterYSize = 0; - int nBandCount = 0; - - while (poDS->ReadPair(osObjName, nObjCode) && nObjCode != 254) - { - if (osObjName == "dim" && nObjCode % 256 == R_INTSXP) - { - const int nCount = poDS->ReadInteger(); - if (nCount == 2) - { - poDS->nRasterXSize = poDS->ReadInteger(); - poDS->nRasterYSize = poDS->ReadInteger(); - nBandCount = 1; - } - else if (nCount == 3) - { - poDS->nRasterXSize = poDS->ReadInteger(); - poDS->nRasterYSize = poDS->ReadInteger(); - nBandCount = poDS->ReadInteger(); - } - else - { - CPLError(CE_Failure, CPLE_AppDefined, - "R 'dim' dimension wrong."); - return nullptr; - } - } - else if (nObjCode % 256 == R_REALSXP) - { - int nCount = poDS->ReadInteger(); - while (nCount > 0 && !VSIFEofL(poDS->fp)) - { - nCount--; - poDS->ReadFloat(); - } - } - else if (nObjCode % 256 == R_INTSXP) - { - int nCount = poDS->ReadInteger(); - while (nCount > 0 && !VSIFEofL(poDS->fp)) - { - nCount--; - poDS->ReadInteger(); - } - } - else if (nObjCode % 256 == R_STRSXP) - { - int nCount = poDS->ReadInteger(); - while (nCount > 0 && !VSIFEofL(poDS->fp)) - { - nCount--; - poDS->ReadString(); - } - } - else if (nObjCode % 256 == R_CHARSXP) - { - poDS->ReadString(); - } - } - - if (poDS->nRasterXSize == 0) - { - CPLError(CE_Failure, CPLE_AppDefined, - "Failed to find dim dimension information for R dataset."); - return nullptr; - } - - if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) || - !GDALCheckBandCount(nBandCount, TRUE)) - { - return nullptr; - } - - GIntBig result = 0; - bool ok = SafeMult(nBandCount, poDS->nRasterXSize, &result); - ok &= SafeMult(result, poDS->nRasterYSize, &result); - - if (!ok || nValueCount < result) - { - CPLError(CE_Failure, CPLE_AppDefined, "Not enough pixel data."); - return nullptr; - } - - // Create the raster band object(s). - for (int iBand = 0; iBand < nBandCount; iBand++) - { - std::unique_ptr poBand; - - if (poDS->bASCII) - poBand = std::make_unique( - poDS.get(), iBand + 1, - poDS->padfMatrixValues + static_cast(iBand) * - poDS->nRasterXSize * - poDS->nRasterYSize); - else - { - poBand = RawRasterBand::Create( - poDS.get(), iBand + 1, poDS->fp, - poDS->nStartOfData + - static_cast(poDS->nRasterXSize) * - poDS->nRasterYSize * 8 * iBand, - 8, poDS->nRasterXSize * 8, GDT_Float64, - RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN, - RawRasterBand::OwnFP::NO); - if (!poBand) - return nullptr; - } - poDS->SetBand(iBand + 1, std::move(poBand)); - } - - // Initialize any PAM information. - poDS->SetDescription(poOpenInfo->pszFilename); - poDS->TryLoadXML(); - - // Check for overviews. - poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename); - - return poDS.release(); -} - -/************************************************************************/ -/* GDALRegister_R() */ -/************************************************************************/ - -void GDALRegister_R() - -{ - if (GDALGetDriverByName("R") != nullptr) - return; - - GDALDriver *poDriver = new GDALDriver(); - - poDriver->SetDescription("R"); - poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); - poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "R Object Data Store"); - poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/r.html"); - poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "rda"); - poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Float32"); - poDriver->SetMetadataItem( - GDAL_DMD_CREATIONOPTIONLIST, - "" - " "); - - poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); - - poDriver->pfnOpen = RDataset::Open; - poDriver->pfnIdentify = RDataset::Identify; - poDriver->pfnCreateCopy = RCreateCopy; - - GetGDALDriverManager()->RegisterDriver(poDriver); -} diff --git a/frmts/r/rdataset.h b/frmts/r/rdataset.h deleted file mode 100644 index 94e1f8c46d00..000000000000 --- a/frmts/r/rdataset.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * - * Project: R Format Driver - * Purpose: Read/write R stats package object format. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2009, Frank Warmerdam - * Copyright (c) 2009-2010, Even Rouault - * - * SPDX-License-Identifier: MIT - ****************************************************************************/ - -#ifndef RDATASET_H_INCLUDED -#define RDATASET_H_INCLUDED - -#include -#include -#include -#include -#if HAVE_FCNTL_H -#include -#endif - -#include "cpl_conv.h" -#include "cpl_error.h" -#include "cpl_port.h" -#include "cpl_progress.h" -#include "cpl_string.h" -#include "cpl_vsi.h" -#include "gdal.h" -#include "gdal_frmts.h" -#include "gdal_pam.h" -#include "gdal_priv.h" -#include "rawdataset.h" - -GDALDataset *RCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, - int bStrict, char **papszOptions, - GDALProgressFunc pfnProgress, void *pProgressData); - -/************************************************************************/ -/* ==================================================================== */ -/* RDataset */ -/* ==================================================================== */ -/************************************************************************/ - -class RDataset final : public GDALPamDataset -{ - friend class RRasterBand; - VSILFILE *fp; - int bASCII; - CPLString osLastStringRead; - - vsi_l_offset nStartOfData; - - double *padfMatrixValues; - - const char *ASCIIFGets(); - int ReadInteger(); - double ReadFloat(); - const char *ReadString(); - bool ReadPair(CPLString &osItemName, int &nItemType); - - public: - RDataset(); - ~RDataset(); - - static GDALDataset *Open(GDALOpenInfo *); - static int Identify(GDALOpenInfo *); -}; - -/************************************************************************/ -/* ==================================================================== */ -/* RRasterBand */ -/* ==================================================================== */ -/************************************************************************/ - -class RRasterBand final : public GDALPamRasterBand -{ - friend class RDataset; - - const double *padfMatrixValues; - - public: - RRasterBand(RDataset *, int, const double *); - - virtual ~RRasterBand() - { - } - - virtual CPLErr IReadBlock(int, int, void *) override; -}; - -#endif /* RDATASET_H_INCLUDED */