Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: netCDF read/write Driver
4 : * Purpose: GDAL bindings over netCDF library.
5 : * Author: Even Rouault <even.rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "netcdfdataset.h"
14 :
15 13 : bool netCDFWriterConfiguration::SetNameValue(
16 : CPLXMLNode *psNode, std::map<CPLString, CPLString> &oMap)
17 : {
18 13 : const char *pszName = CPLGetXMLValue(psNode, "name", nullptr);
19 13 : const char *pszValue = CPLGetXMLValue(psNode, "value", nullptr);
20 13 : if (pszName != nullptr && pszValue != nullptr)
21 : {
22 4 : oMap[pszName] = pszValue;
23 4 : return true;
24 : }
25 9 : CPLError(CE_Failure, CPLE_IllegalArg, "Missing name/value");
26 9 : return false;
27 : }
28 :
29 26 : bool netCDFWriterConfiguration::Parse(const char *pszFilename)
30 : {
31 26 : CPLXMLNode *psRoot = STARTS_WITH(pszFilename, "<Configuration")
32 26 : ? CPLParseXMLString(pszFilename)
33 1 : : CPLParseXMLFile(pszFilename);
34 26 : if (psRoot == nullptr)
35 2 : return false;
36 48 : CPLXMLTreeCloser oCloser(psRoot);
37 :
38 33 : for (CPLXMLNode *psIter = psRoot->psChild; psIter != nullptr;
39 9 : psIter = psIter->psNext)
40 : {
41 30 : if (psIter->eType != CXT_Element)
42 0 : continue;
43 30 : if (EQUAL(psIter->pszValue, "DatasetCreationOption"))
44 : {
45 4 : if (!SetNameValue(psIter, m_oDatasetCreationOptions))
46 : {
47 3 : return false;
48 : }
49 : }
50 26 : else if (EQUAL(psIter->pszValue, "LayerCreationOption"))
51 : {
52 4 : if (!SetNameValue(psIter, m_oLayerCreationOptions))
53 : {
54 3 : return false;
55 : }
56 : }
57 22 : else if (EQUAL(psIter->pszValue, "Attribute"))
58 : {
59 6 : netCDFWriterConfigAttribute oAtt;
60 6 : if (oAtt.Parse(psIter))
61 : {
62 2 : m_aoAttributes.push_back(std::move(oAtt));
63 : }
64 : else
65 : {
66 4 : return false;
67 : }
68 : }
69 16 : else if (EQUAL(psIter->pszValue, "Field"))
70 : {
71 5 : netCDFWriterConfigField oField;
72 5 : if (oField.Parse(psIter))
73 : {
74 6 : m_oFields[!oField.m_osName.empty()
75 4 : ? oField.m_osName
76 10 : : CPLString("__") + oField.m_osNetCDFName] =
77 3 : oField;
78 : }
79 : else
80 : {
81 2 : return false;
82 : }
83 : }
84 11 : else if (EQUAL(psIter->pszValue, "Layer"))
85 : {
86 10 : netCDFWriterConfigLayer oLayer;
87 10 : if (oLayer.Parse(psIter))
88 : {
89 1 : m_oLayers[oLayer.m_osName] = std::move(oLayer);
90 : }
91 : else
92 : {
93 9 : return false;
94 : }
95 : }
96 : else
97 : {
98 1 : CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
99 : }
100 : }
101 :
102 3 : m_bIsValid = true;
103 :
104 3 : return true;
105 : }
106 :
107 16 : bool netCDFWriterConfigAttribute::Parse(CPLXMLNode *psNode)
108 : {
109 16 : const char *pszName = CPLGetXMLValue(psNode, "name", nullptr);
110 16 : const char *pszValue = CPLGetXMLValue(psNode, "value", nullptr);
111 16 : const char *pszType = CPLGetXMLValue(psNode, "type", "string");
112 16 : if (!EQUAL(pszType, "string") && !EQUAL(pszType, "integer") &&
113 3 : !EQUAL(pszType, "double"))
114 : {
115 2 : CPLError(CE_Failure, CPLE_NotSupported, "type='%s' unsupported",
116 : pszType);
117 2 : return false;
118 : }
119 14 : if (pszName == nullptr || pszValue == nullptr)
120 : {
121 7 : CPLError(CE_Failure, CPLE_IllegalArg, "Missing name/value");
122 7 : return false;
123 : }
124 7 : m_osName = pszName;
125 7 : m_osValue = pszValue;
126 7 : m_osType = pszType;
127 7 : return true;
128 : }
129 :
130 8 : bool netCDFWriterConfigField::Parse(CPLXMLNode *psNode)
131 : {
132 8 : const char *pszName = CPLGetXMLValue(psNode, "name", nullptr);
133 8 : const char *pszNetCDFName = CPLGetXMLValue(psNode, "netcdf_name", pszName);
134 8 : const char *pszMainDim = CPLGetXMLValue(psNode, "main_dim", nullptr);
135 8 : if (pszName == nullptr && pszNetCDFName == nullptr)
136 : {
137 2 : CPLError(CE_Failure, CPLE_IllegalArg,
138 : "Both name and netcdf_name are missing");
139 2 : return false;
140 : }
141 6 : if (pszName != nullptr)
142 4 : m_osName = pszName;
143 6 : if (pszNetCDFName != nullptr)
144 6 : m_osNetCDFName = pszNetCDFName;
145 6 : if (pszMainDim != nullptr)
146 2 : m_osMainDim = pszMainDim;
147 :
148 22 : for (CPLXMLNode *psIter = psNode->psChild; psIter != nullptr;
149 16 : psIter = psIter->psNext)
150 : {
151 17 : if (psIter->eType != CXT_Element)
152 12 : continue;
153 5 : if (EQUAL(psIter->pszValue, "Attribute"))
154 : {
155 5 : netCDFWriterConfigAttribute oAtt;
156 5 : if (oAtt.Parse(psIter))
157 : {
158 4 : m_aoAttributes.push_back(std::move(oAtt));
159 : }
160 : else
161 : {
162 1 : return false;
163 : }
164 : }
165 : else
166 : {
167 0 : CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
168 : }
169 : }
170 :
171 5 : return true;
172 : }
173 :
174 10 : bool netCDFWriterConfigLayer::Parse(CPLXMLNode *psNode)
175 : {
176 10 : const char *pszName = CPLGetXMLValue(psNode, "name", nullptr);
177 10 : const char *pszNetCDFName = CPLGetXMLValue(psNode, "netcdf_name", pszName);
178 10 : if (pszName == nullptr)
179 : {
180 1 : CPLError(CE_Failure, CPLE_IllegalArg, "Missing name");
181 1 : return false;
182 : }
183 9 : m_osName = pszName;
184 9 : if (pszNetCDFName != nullptr)
185 9 : m_osNetCDFName = pszNetCDFName;
186 :
187 25 : for (CPLXMLNode *psIter = psNode->psChild; psIter != nullptr;
188 16 : psIter = psIter->psNext)
189 : {
190 24 : if (psIter->eType != CXT_Element)
191 11 : continue;
192 13 : if (EQUAL(psIter->pszValue, "LayerCreationOption"))
193 : {
194 5 : if (!netCDFWriterConfiguration::SetNameValue(
195 5 : psIter, m_oLayerCreationOptions))
196 : {
197 3 : return false;
198 : }
199 : }
200 8 : else if (EQUAL(psIter->pszValue, "Attribute"))
201 : {
202 5 : netCDFWriterConfigAttribute oAtt;
203 5 : if (oAtt.Parse(psIter))
204 : {
205 1 : m_aoAttributes.push_back(std::move(oAtt));
206 : }
207 : else
208 : {
209 4 : return false;
210 : }
211 : }
212 3 : else if (EQUAL(psIter->pszValue, "Field"))
213 : {
214 3 : netCDFWriterConfigField oField;
215 3 : if (oField.Parse(psIter))
216 : {
217 4 : m_oFields[!oField.m_osName.empty()
218 3 : ? oField.m_osName
219 7 : : CPLString("__") + oField.m_osNetCDFName] =
220 4 : std::move(oField);
221 : }
222 : else
223 : {
224 1 : return false;
225 : }
226 : }
227 : else
228 : {
229 0 : CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
230 : }
231 : }
232 :
233 1 : return true;
234 : }
|