Line data Source code
1 : /*************************************************************************** 2 : gdal_subdatasetinfo.cpp - GDALSubdatasetInfo 3 : 4 : --------------------- 5 : begin : 21.7.2023 6 : copyright : (C) 2023 by Alessndro Pasotti 7 : email : elpaso@itopen.it 8 : *************************************************************************** 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 "gdalsubdatasetinfo.h" 30 : #include "gdal_priv.h" 31 : #include <algorithm> 32 : #include <stdexcept> 33 : 34 : /************************************************************************/ 35 : /* Subdataset informational functions */ 36 : /************************************************************************/ 37 : 38 1079 : GDALSubdatasetInfoH GDALGetSubdatasetInfo(const char *pszFileName) 39 : { 40 : // Iterate all drivers 41 1079 : GDALDriverManager *poDM_ = GetGDALDriverManager(); 42 1079 : const int nDriverCount = poDM_->GetDriverCount(); 43 237181 : for (int iDriver = 0; iDriver < nDriverCount; ++iDriver) 44 : { 45 236195 : GDALDriver *poDriver = poDM_->GetDriver(iDriver); 46 236195 : if (!poDriver->pfnGetSubdatasetInfoFunc) 47 : { 48 229020 : continue; 49 : } 50 : const char *pszDMDSubdatasets = 51 7175 : GDALGetMetadataItem(poDriver, GDAL_DMD_SUBDATASETS, nullptr); 52 7175 : if (!pszDMDSubdatasets || !CPLTestBool(pszDMDSubdatasets)) 53 : { 54 0 : continue; 55 : } 56 : 57 : GDALSubdatasetInfo *poGetSubdatasetInfo = 58 7175 : poDriver->pfnGetSubdatasetInfoFunc(pszFileName); 59 : 60 7175 : if (!poGetSubdatasetInfo) 61 : { 62 7082 : continue; 63 : } 64 : 65 93 : return static_cast<GDALSubdatasetInfoH>(poGetSubdatasetInfo); 66 : } 67 986 : return nullptr; 68 : } 69 : 70 : /************************************************************************/ 71 : /* GDALDestroySubdatasetInfo() */ 72 : /************************************************************************/ 73 : 74 : /** 75 : * \brief Destroys subdataset info. 76 : * 77 : * This function is the same as the C++ method GDALSubdatasetInfo::~GDALSubdatasetInfo() 78 : */ 79 93 : void GDALDestroySubdatasetInfo(GDALSubdatasetInfoH hInfo) 80 : 81 : { 82 93 : delete hInfo; 83 93 : } 84 : 85 35 : char *GDALSubdatasetInfoGetPathComponent(GDALSubdatasetInfoH hInfo) 86 : { 87 35 : return CPLStrdup(hInfo->GetPathComponent().c_str()); 88 : } 89 : 90 61 : char *GDALSubdatasetInfoGetSubdatasetComponent(GDALSubdatasetInfoH hInfo) 91 : { 92 61 : return CPLStrdup(hInfo->GetSubdatasetComponent().c_str()); 93 : } 94 : 95 21 : char *GDALSubdatasetInfoModifyPathComponent(GDALSubdatasetInfoH hInfo, 96 : const char *pszNewFileName) 97 : { 98 21 : return CPLStrdup(hInfo->ModifyPathComponent(pszNewFileName).c_str()); 99 : } 100 : 101 107 : GDALSubdatasetInfo::GDALSubdatasetInfo(const std::string &fileName) 102 : : m_fileName(fileName), m_pathComponent(), m_cleanedPathComponent(), 103 107 : m_subdatasetComponent(), m_driverPrefixComponent() 104 : { 105 107 : } 106 : 107 152 : std::string GDALSubdatasetInfo::GetPathComponent() const 108 : { 109 152 : init(); 110 152 : return m_cleanedPathComponent; 111 : } 112 : 113 : std::string 114 31 : GDALSubdatasetInfo::ModifyPathComponent(const std::string &newPathName) const 115 : { 116 31 : init(); 117 : 118 62 : std::string replaced{m_fileName}; 119 : 120 : try 121 : { 122 62 : auto newPathName_{newPathName}; 123 31 : if (m_isQuoted) 124 : { 125 26 : if (newPathName_.length() >= 2 && newPathName_.at(0) != '"' && 126 10 : newPathName_.at(newPathName_.length() - 1) != '"') 127 : { 128 10 : newPathName_ = quote(newPathName_); 129 : } 130 : } 131 31 : replaced.replace(replaced.find(m_pathComponent), 132 31 : m_pathComponent.length(), newPathName_); 133 : } 134 0 : catch (const std::out_of_range &) 135 : { 136 0 : return ""; 137 : } 138 : 139 31 : return replaced; 140 : } 141 : 142 116 : std::string GDALSubdatasetInfo::GetSubdatasetComponent() const 143 : { 144 116 : init(); 145 116 : return m_subdatasetComponent; 146 : } 147 : 148 : //! @cond Doxygen_Suppress 149 51 : std::string GDALSubdatasetInfo::unquote(const std::string &path) 150 : { 151 51 : if (path.length() >= 2) 152 : { 153 51 : std::string cleanedPath{path}; 154 102 : if (cleanedPath.at(0) == '"' && 155 51 : cleanedPath.at(cleanedPath.length() - 1) == '"') 156 : { 157 51 : cleanedPath = cleanedPath.substr(1, cleanedPath.length() - 2); 158 53 : while (cleanedPath.find(R"(\")") != std::string::npos) 159 : { 160 2 : const auto pos{cleanedPath.find(R"(\")")}; 161 2 : if (pos == 0 || cleanedPath.at(pos - 1) != '\\') 162 : { 163 2 : cleanedPath.erase(pos, 1); 164 : } 165 : } 166 51 : return cleanedPath; 167 : } 168 : } 169 0 : return path; 170 : } 171 : 172 10 : std::string GDALSubdatasetInfo::quote(const std::string &path) 173 : { 174 20 : std::string quotedPath{'"'}; 175 336 : for (size_t i = 0; i < path.length(); ++i) 176 : { 177 326 : if (path.at(i) == '"') 178 : { 179 0 : quotedPath += R"(\")"; 180 : } 181 : else 182 : { 183 326 : quotedPath += path.at(i); 184 : } 185 : } 186 20 : return quotedPath + '"'; 187 : } 188 : 189 299 : void GDALSubdatasetInfo::init() const 190 : { 191 299 : if (!m_initialized) 192 : { 193 107 : GDALSubdatasetInfo *this_ = const_cast<GDALSubdatasetInfo *>(this); 194 107 : this_->parseFileName(); 195 107 : this_->m_isQuoted = 196 158 : m_pathComponent.length() >= 2 && m_pathComponent.at(0) == '"' && 197 51 : m_pathComponent.at(m_pathComponent.length() - 1) == '"'; 198 : this_->m_cleanedPathComponent = 199 107 : m_isQuoted ? unquote(m_pathComponent) : m_pathComponent; 200 107 : m_initialized = true; 201 : } 202 299 : } 203 : 204 : //! @endcond