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