Line data Source code
1 : /******************************************************************************
2 : *
3 : * Name: gdalmultidim_attribute.cpp
4 : * Project: GDAL Core
5 : * Purpose: Implementation of GDALIHasAttribute and GDALAttribute classes
6 : * Author: Even Rouault <even.rouault at spatialys.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2019, Even Rouault <even.rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "gdal_multidim.h"
15 :
16 : #include <limits>
17 :
18 : #if defined(__clang__) || defined(_MSC_VER)
19 : #define COMPILER_WARNS_ABOUT_ABSTRACT_VBASE_INIT
20 : #endif
21 :
22 : /************************************************************************/
23 : /* ~GDALIHasAttribute() */
24 : /************************************************************************/
25 :
26 : GDALIHasAttribute::~GDALIHasAttribute() = default;
27 :
28 : /************************************************************************/
29 : /* GetAttribute() */
30 : /************************************************************************/
31 :
32 : /** Return an attribute by its name.
33 : *
34 : * If the attribute does not exist, nullptr should be silently returned.
35 : *
36 : * @note Driver implementation: this method will fallback to
37 : * GetAttributeFromAttributes() is not explicitly implemented
38 : *
39 : * Drivers known to implement it for groups and arrays: MEM, netCDF.
40 : *
41 : * This is the same as the C function GDALGroupGetAttribute() or
42 : * GDALMDArrayGetAttribute().
43 : *
44 : * @param osName Attribute name
45 : * @return the attribute, or nullptr if it does not exist or an error occurred.
46 : */
47 : std::shared_ptr<GDALAttribute>
48 10761 : GDALIHasAttribute::GetAttribute(const std::string &osName) const
49 : {
50 10761 : return GetAttributeFromAttributes(osName);
51 : }
52 :
53 : /************************************************************************/
54 : /* GetAttributeFromAttributes() */
55 : /************************************************************************/
56 :
57 : /** Possible fallback implementation for GetAttribute() using GetAttributes().
58 : */
59 : std::shared_ptr<GDALAttribute>
60 10761 : GDALIHasAttribute::GetAttributeFromAttributes(const std::string &osName) const
61 : {
62 21522 : auto attrs(GetAttributes());
63 85196 : for (const auto &attr : attrs)
64 : {
65 83404 : if (attr->GetName() == osName)
66 8969 : return attr;
67 : }
68 1792 : return nullptr;
69 : }
70 :
71 : /************************************************************************/
72 : /* GetAttributes() */
73 : /************************************************************************/
74 :
75 : /** Return the list of attributes contained in a GDALMDArray or GDALGroup.
76 : *
77 : * If the attribute does not exist, nullptr should be silently returned.
78 : *
79 : * @note Driver implementation: optionally implemented. If implemented,
80 : * GetAttribute() should also be implemented.
81 : *
82 : * Drivers known to implement it for groups and arrays: MEM, netCDF.
83 : *
84 : * This is the same as the C function GDALGroupGetAttributes() or
85 : * GDALMDArrayGetAttributes().
86 :
87 : * @param papszOptions Driver specific options determining how attributes
88 : * should be retrieved. Pass nullptr for default behavior.
89 : *
90 : * @return the attributes.
91 : */
92 : std::vector<std::shared_ptr<GDALAttribute>>
93 208 : GDALIHasAttribute::GetAttributes(CPL_UNUSED CSLConstList papszOptions) const
94 : {
95 208 : return {};
96 : }
97 :
98 : /************************************************************************/
99 : /* CreateAttribute() */
100 : /************************************************************************/
101 :
102 : /** Create an attribute within a GDALMDArray or GDALGroup.
103 : *
104 : * The attribute might not be "physically" created until a value is written
105 : * into it.
106 : *
107 : * Optionally implemented.
108 : *
109 : * Drivers known to implement it: MEM, netCDF
110 : *
111 : * This is the same as the C function GDALGroupCreateAttribute() or
112 : * GDALMDArrayCreateAttribute()
113 : *
114 : * @param osName Attribute name.
115 : * @param anDimensions List of dimension sizes, ordered from the slowest varying
116 : * dimension first to the fastest varying dimension last.
117 : * Empty for a scalar attribute (common case)
118 : * @param oDataType Attribute data type.
119 : * @param papszOptions Driver specific options determining how the attribute.
120 : * should be created.
121 : *
122 : * @return the new attribute, or nullptr if case of error
123 : */
124 0 : std::shared_ptr<GDALAttribute> GDALIHasAttribute::CreateAttribute(
125 : CPL_UNUSED const std::string &osName,
126 : CPL_UNUSED const std::vector<GUInt64> &anDimensions,
127 : CPL_UNUSED const GDALExtendedDataType &oDataType,
128 : CPL_UNUSED CSLConstList papszOptions)
129 : {
130 0 : CPLError(CE_Failure, CPLE_NotSupported,
131 : "CreateAttribute() not implemented");
132 0 : return nullptr;
133 : }
134 :
135 : /************************************************************************/
136 : /* DeleteAttribute() */
137 : /************************************************************************/
138 :
139 : /** Delete an attribute from a GDALMDArray or GDALGroup.
140 : *
141 : * Optionally implemented.
142 : *
143 : * After this call, if a previously obtained instance of the deleted object
144 : * is still alive, no method other than for freeing it should be invoked.
145 : *
146 : * Drivers known to implement it: MEM, netCDF
147 : *
148 : * This is the same as the C function GDALGroupDeleteAttribute() or
149 : * GDALMDArrayDeleteAttribute()
150 : *
151 : * @param osName Attribute name.
152 : * @param papszOptions Driver specific options determining how the attribute.
153 : * should be deleted.
154 : *
155 : * @return true in case of success
156 : * @since GDAL 3.8
157 : */
158 0 : bool GDALIHasAttribute::DeleteAttribute(CPL_UNUSED const std::string &osName,
159 : CPL_UNUSED CSLConstList papszOptions)
160 : {
161 0 : CPLError(CE_Failure, CPLE_NotSupported,
162 : "DeleteAttribute() not implemented");
163 0 : return false;
164 : }
165 :
166 : /************************************************************************/
167 : /* GDALAttribute() */
168 : /************************************************************************/
169 :
170 : //! @cond Doxygen_Suppress
171 162248 : GDALAttribute::GDALAttribute(CPL_UNUSED const std::string &osParentName,
172 0 : CPL_UNUSED const std::string &osName)
173 : #if !defined(COMPILER_WARNS_ABOUT_ABSTRACT_VBASE_INIT)
174 162248 : : GDALAbstractMDArray(osParentName, osName)
175 : #endif
176 : {
177 162248 : }
178 :
179 : GDALAttribute::~GDALAttribute() = default;
180 :
181 : //! @endcond
182 :
183 : /************************************************************************/
184 : /* GetDimensionSize() */
185 : /************************************************************************/
186 :
187 : /** Return the size of the dimensions of the attribute.
188 : *
189 : * This will be an empty array for a scalar (single value) attribute.
190 : *
191 : * This is the same as the C function GDALAttributeGetDimensionsSize().
192 : */
193 791 : std::vector<GUInt64> GDALAttribute::GetDimensionsSize() const
194 : {
195 791 : const auto &dims = GetDimensions();
196 791 : std::vector<GUInt64> ret;
197 791 : ret.reserve(dims.size());
198 974 : for (const auto &dim : dims)
199 183 : ret.push_back(dim->GetSize());
200 791 : return ret;
201 : }
202 :
203 : //! @cond Doxygen_Suppress
204 :
205 206 : GDALAttributeString::GDALAttributeString(const std::string &osParentName,
206 : const std::string &osName,
207 : const std::string &osValue,
208 206 : GDALExtendedDataTypeSubType eSubType)
209 : : GDALAbstractMDArray(osParentName, osName),
210 : GDALAttribute(osParentName, osName),
211 206 : m_dt(GDALExtendedDataType::CreateString(0, eSubType)), m_osValue(osValue)
212 : {
213 206 : }
214 :
215 : const std::vector<std::shared_ptr<GDALDimension>> &
216 96 : GDALAttributeString::GetDimensions() const
217 : {
218 96 : return m_dims;
219 : }
220 :
221 65 : const GDALExtendedDataType &GDALAttributeString::GetDataType() const
222 : {
223 65 : return m_dt;
224 : }
225 :
226 32 : bool GDALAttributeString::IRead(const GUInt64 *, const size_t *, const GInt64 *,
227 : const GPtrDiff_t *,
228 : const GDALExtendedDataType &bufferDataType,
229 : void *pDstBuffer) const
230 : {
231 32 : if (bufferDataType.GetClass() != GEDTC_STRING)
232 0 : return false;
233 32 : char *pszStr = static_cast<char *>(VSIMalloc(m_osValue.size() + 1));
234 32 : if (!pszStr)
235 0 : return false;
236 32 : memcpy(pszStr, m_osValue.c_str(), m_osValue.size() + 1);
237 32 : *static_cast<char **>(pDstBuffer) = pszStr;
238 32 : return true;
239 : }
240 :
241 74 : GDALAttributeNumeric::GDALAttributeNumeric(const std::string &osParentName,
242 : const std::string &osName,
243 74 : double dfValue)
244 : : GDALAbstractMDArray(osParentName, osName),
245 : GDALAttribute(osParentName, osName),
246 74 : m_dt(GDALExtendedDataType::Create(GDT_Float64)), m_dfValue(dfValue)
247 : {
248 74 : }
249 :
250 27 : GDALAttributeNumeric::GDALAttributeNumeric(const std::string &osParentName,
251 : const std::string &osName,
252 27 : int nValue)
253 : : GDALAbstractMDArray(osParentName, osName),
254 : GDALAttribute(osParentName, osName),
255 27 : m_dt(GDALExtendedDataType::Create(GDT_Int32)), m_nValue(nValue)
256 : {
257 27 : }
258 :
259 7 : GDALAttributeNumeric::GDALAttributeNumeric(const std::string &osParentName,
260 : const std::string &osName,
261 7 : const std::vector<GUInt32> &anValues)
262 : : GDALAbstractMDArray(osParentName, osName),
263 : GDALAttribute(osParentName, osName),
264 7 : m_dt(GDALExtendedDataType::Create(GDT_UInt32)), m_anValuesUInt32(anValues)
265 : {
266 7 : m_dims.push_back(std::make_shared<GDALDimension>(
267 14 : std::string(), "dim0", std::string(), std::string(),
268 7 : m_anValuesUInt32.size()));
269 7 : }
270 :
271 : const std::vector<std::shared_ptr<GDALDimension>> &
272 14 : GDALAttributeNumeric::GetDimensions() const
273 : {
274 14 : return m_dims;
275 : }
276 :
277 8 : const GDALExtendedDataType &GDALAttributeNumeric::GetDataType() const
278 : {
279 8 : return m_dt;
280 : }
281 :
282 4 : bool GDALAttributeNumeric::IRead(const GUInt64 *arrayStartIdx,
283 : const size_t *count, const GInt64 *arrayStep,
284 : const GPtrDiff_t *bufferStride,
285 : const GDALExtendedDataType &bufferDataType,
286 : void *pDstBuffer) const
287 : {
288 4 : if (m_dims.empty())
289 : {
290 3 : if (m_dt.GetNumericDataType() == GDT_Float64)
291 0 : GDALExtendedDataType::CopyValue(&m_dfValue, m_dt, pDstBuffer,
292 : bufferDataType);
293 : else
294 : {
295 3 : CPLAssert(m_dt.GetNumericDataType() == GDT_Int32);
296 3 : GDALExtendedDataType::CopyValue(&m_nValue, m_dt, pDstBuffer,
297 : bufferDataType);
298 : }
299 : }
300 : else
301 : {
302 1 : CPLAssert(m_dt.GetNumericDataType() == GDT_UInt32);
303 1 : GByte *pabyDstBuffer = static_cast<GByte *>(pDstBuffer);
304 30 : for (size_t i = 0; i < count[0]; ++i)
305 : {
306 29 : GDALExtendedDataType::CopyValue(
307 29 : &m_anValuesUInt32[static_cast<size_t>(arrayStartIdx[0] +
308 29 : i * arrayStep[0])],
309 29 : m_dt, pabyDstBuffer, bufferDataType);
310 29 : pabyDstBuffer += bufferDataType.GetSize() * bufferStride[0];
311 : }
312 : }
313 4 : return true;
314 : }
315 :
316 : //! @endcond
317 :
318 : /************************************************************************/
319 : /* ReadAsRaw() */
320 : /************************************************************************/
321 :
322 : /** Return the raw value of an attribute.
323 : *
324 : *
325 : * This is the same as the C function GDALAttributeReadAsRaw().
326 : */
327 258 : GDALRawResult GDALAttribute::ReadAsRaw() const
328 : {
329 258 : const auto nEltCount(GetTotalElementsCount());
330 258 : const auto &dt(GetDataType());
331 258 : const auto nDTSize(dt.GetSize());
332 : GByte *res = static_cast<GByte *>(
333 258 : VSI_MALLOC2_VERBOSE(static_cast<size_t>(nEltCount), nDTSize));
334 258 : if (!res)
335 0 : return GDALRawResult(nullptr, dt, 0);
336 258 : const auto &dims = GetDimensions();
337 258 : const auto nDims = GetDimensionCount();
338 516 : std::vector<GUInt64> startIdx(1 + nDims, 0);
339 516 : std::vector<size_t> count(1 + nDims);
340 284 : for (size_t i = 0; i < nDims; i++)
341 : {
342 26 : count[i] = static_cast<size_t>(dims[i]->GetSize());
343 : }
344 258 : if (!Read(startIdx.data(), count.data(), nullptr, nullptr, dt, &res[0],
345 258 : &res[0], static_cast<size_t>(nEltCount * nDTSize)))
346 : {
347 0 : VSIFree(res);
348 0 : return GDALRawResult(nullptr, dt, 0);
349 : }
350 258 : return GDALRawResult(res, dt, static_cast<size_t>(nEltCount));
351 : }
352 :
353 : /************************************************************************/
354 : /* ReadAsString() */
355 : /************************************************************************/
356 :
357 : /** Return the value of an attribute as a string.
358 : *
359 : * The returned string should not be freed, and its lifetime does not
360 : * excess a next call to ReadAsString() on the same object, or the deletion
361 : * of the object itself.
362 : *
363 : * This function will only return the first element if there are several.
364 : *
365 : * This is the same as the C function GDALAttributeReadAsString()
366 : *
367 : * @return a string, or nullptr.
368 : */
369 4784 : const char *GDALAttribute::ReadAsString() const
370 : {
371 4784 : const auto nDims = GetDimensionCount();
372 9568 : std::vector<GUInt64> startIdx(1 + nDims, 0);
373 9568 : std::vector<size_t> count(1 + nDims, 1);
374 4784 : char *szRet = nullptr;
375 4784 : if (!Read(startIdx.data(), count.data(), nullptr, nullptr,
376 4784 : GDALExtendedDataType::CreateString(), &szRet, &szRet,
377 14351 : sizeof(szRet)) ||
378 4783 : szRet == nullptr)
379 : {
380 5 : return nullptr;
381 : }
382 4779 : m_osCachedVal = szRet;
383 4779 : CPLFree(szRet);
384 4779 : return m_osCachedVal.c_str();
385 : }
386 :
387 : /************************************************************************/
388 : /* ReadAsInt() */
389 : /************************************************************************/
390 :
391 : /** Return the value of an attribute as a integer.
392 : *
393 : * This function will only return the first element if there are several.
394 : *
395 : * It can fail if its value can not be converted to integer.
396 : *
397 : * This is the same as the C function GDALAttributeReadAsInt()
398 : *
399 : * @return a integer, or INT_MIN in case of error.
400 : */
401 2903 : int GDALAttribute::ReadAsInt() const
402 : {
403 2903 : const auto nDims = GetDimensionCount();
404 5806 : std::vector<GUInt64> startIdx(1 + nDims, 0);
405 2903 : std::vector<size_t> count(1 + nDims, 1);
406 2903 : int nRet = INT_MIN;
407 2903 : Read(startIdx.data(), count.data(), nullptr, nullptr,
408 5806 : GDALExtendedDataType::Create(GDT_Int32), &nRet, &nRet, sizeof(nRet));
409 5806 : return nRet;
410 : }
411 :
412 : /************************************************************************/
413 : /* ReadAsInt64() */
414 : /************************************************************************/
415 :
416 : /** Return the value of an attribute as an int64_t.
417 : *
418 : * This function will only return the first element if there are several.
419 : *
420 : * It can fail if its value can not be converted to long.
421 : *
422 : * This is the same as the C function GDALAttributeReadAsInt64()
423 : *
424 : * @return an int64_t, or INT64_MIN in case of error.
425 : */
426 131 : int64_t GDALAttribute::ReadAsInt64() const
427 : {
428 131 : const auto nDims = GetDimensionCount();
429 262 : std::vector<GUInt64> startIdx(1 + nDims, 0);
430 131 : std::vector<size_t> count(1 + nDims, 1);
431 131 : int64_t nRet = INT64_MIN;
432 131 : Read(startIdx.data(), count.data(), nullptr, nullptr,
433 262 : GDALExtendedDataType::Create(GDT_Int64), &nRet, &nRet, sizeof(nRet));
434 262 : return nRet;
435 : }
436 :
437 : /************************************************************************/
438 : /* ReadAsDouble() */
439 : /************************************************************************/
440 :
441 : /** Return the value of an attribute as a double.
442 : *
443 : * This function will only return the first element if there are several.
444 : *
445 : * It can fail if its value can not be converted to double.
446 : *
447 : * This is the same as the C function GDALAttributeReadAsInt()
448 : *
449 : * @return a double value.
450 : */
451 4003 : double GDALAttribute::ReadAsDouble() const
452 : {
453 4003 : const auto nDims = GetDimensionCount();
454 8006 : std::vector<GUInt64> startIdx(1 + nDims, 0);
455 4003 : std::vector<size_t> count(1 + nDims, 1);
456 4003 : double dfRet = 0;
457 4003 : Read(startIdx.data(), count.data(), nullptr, nullptr,
458 4003 : GDALExtendedDataType::Create(GDT_Float64), &dfRet, &dfRet,
459 4003 : sizeof(dfRet));
460 8006 : return dfRet;
461 : }
462 :
463 : /************************************************************************/
464 : /* ReadAsStringArray() */
465 : /************************************************************************/
466 :
467 : /** Return the value of an attribute as an array of strings.
468 : *
469 : * This is the same as the C function GDALAttributeReadAsStringArray()
470 : */
471 224 : CPLStringList GDALAttribute::ReadAsStringArray() const
472 : {
473 224 : const auto nElts = GetTotalElementsCount();
474 224 : if (nElts > static_cast<unsigned>(std::numeric_limits<int>::max() - 1))
475 0 : return CPLStringList();
476 : char **papszList = static_cast<char **>(
477 224 : VSI_CALLOC_VERBOSE(static_cast<int>(nElts) + 1, sizeof(char *)));
478 224 : const auto &dims = GetDimensions();
479 224 : const auto nDims = GetDimensionCount();
480 448 : std::vector<GUInt64> startIdx(1 + nDims, 0);
481 448 : std::vector<size_t> count(1 + nDims);
482 356 : for (size_t i = 0; i < nDims; i++)
483 : {
484 132 : count[i] = static_cast<size_t>(dims[i]->GetSize());
485 : }
486 224 : Read(startIdx.data(), count.data(), nullptr, nullptr,
487 224 : GDALExtendedDataType::CreateString(), papszList, papszList,
488 224 : sizeof(char *) * static_cast<int>(nElts));
489 817 : for (int i = 0; i < static_cast<int>(nElts); i++)
490 : {
491 593 : if (papszList[i] == nullptr)
492 13 : papszList[i] = CPLStrdup("");
493 : }
494 224 : return CPLStringList(papszList);
495 : }
496 :
497 : /************************************************************************/
498 : /* ReadAsIntArray() */
499 : /************************************************************************/
500 :
501 : /** Return the value of an attribute as an array of integers.
502 : *
503 : * This is the same as the C function GDALAttributeReadAsIntArray().
504 : */
505 18 : std::vector<int> GDALAttribute::ReadAsIntArray() const
506 : {
507 18 : const auto nElts = GetTotalElementsCount();
508 : #if SIZEOF_VOIDP == 4
509 : if (nElts > static_cast<size_t>(nElts))
510 : return {};
511 : #endif
512 18 : std::vector<int> res(static_cast<size_t>(nElts));
513 18 : const auto &dims = GetDimensions();
514 18 : const auto nDims = GetDimensionCount();
515 36 : std::vector<GUInt64> startIdx(1 + nDims, 0);
516 36 : std::vector<size_t> count(1 + nDims);
517 38 : for (size_t i = 0; i < nDims; i++)
518 : {
519 20 : count[i] = static_cast<size_t>(dims[i]->GetSize());
520 : }
521 18 : Read(startIdx.data(), count.data(), nullptr, nullptr,
522 36 : GDALExtendedDataType::Create(GDT_Int32), &res[0], res.data(),
523 18 : res.size() * sizeof(res[0]));
524 36 : return res;
525 : }
526 :
527 : /************************************************************************/
528 : /* ReadAsInt64Array() */
529 : /************************************************************************/
530 :
531 : /** Return the value of an attribute as an array of int64_t.
532 : *
533 : * This is the same as the C function GDALAttributeReadAsInt64Array().
534 : */
535 90 : std::vector<int64_t> GDALAttribute::ReadAsInt64Array() const
536 : {
537 90 : const auto nElts = GetTotalElementsCount();
538 : #if SIZEOF_VOIDP == 4
539 : if (nElts > static_cast<size_t>(nElts))
540 : return {};
541 : #endif
542 90 : std::vector<int64_t> res(static_cast<size_t>(nElts));
543 90 : const auto &dims = GetDimensions();
544 90 : const auto nDims = GetDimensionCount();
545 180 : std::vector<GUInt64> startIdx(1 + nDims, 0);
546 180 : std::vector<size_t> count(1 + nDims);
547 180 : for (size_t i = 0; i < nDims; i++)
548 : {
549 90 : count[i] = static_cast<size_t>(dims[i]->GetSize());
550 : }
551 90 : Read(startIdx.data(), count.data(), nullptr, nullptr,
552 180 : GDALExtendedDataType::Create(GDT_Int64), &res[0], res.data(),
553 90 : res.size() * sizeof(res[0]));
554 180 : return res;
555 : }
556 :
557 : /************************************************************************/
558 : /* ReadAsDoubleArray() */
559 : /************************************************************************/
560 :
561 : /** Return the value of an attribute as an array of double.
562 : *
563 : * This is the same as the C function GDALAttributeReadAsDoubleArray().
564 : */
565 123 : std::vector<double> GDALAttribute::ReadAsDoubleArray() const
566 : {
567 123 : const auto nElts = GetTotalElementsCount();
568 : #if SIZEOF_VOIDP == 4
569 : if (nElts > static_cast<size_t>(nElts))
570 : return {};
571 : #endif
572 123 : std::vector<double> res(static_cast<size_t>(nElts));
573 123 : const auto &dims = GetDimensions();
574 123 : const auto nDims = GetDimensionCount();
575 246 : std::vector<GUInt64> startIdx(1 + nDims, 0);
576 246 : std::vector<size_t> count(1 + nDims);
577 230 : for (size_t i = 0; i < nDims; i++)
578 : {
579 107 : count[i] = static_cast<size_t>(dims[i]->GetSize());
580 : }
581 123 : Read(startIdx.data(), count.data(), nullptr, nullptr,
582 246 : GDALExtendedDataType::Create(GDT_Float64), &res[0], res.data(),
583 123 : res.size() * sizeof(res[0]));
584 246 : return res;
585 : }
586 :
587 : /************************************************************************/
588 : /* Write() */
589 : /************************************************************************/
590 :
591 : /** Write an attribute from raw values expressed in GetDataType()
592 : *
593 : * The values should be provided in the type of GetDataType() and there should
594 : * be exactly GetTotalElementsCount() of them.
595 : * If GetDataType() is a string, each value should be a char* pointer.
596 : *
597 : * This is the same as the C function GDALAttributeWriteRaw().
598 : *
599 : * @param pabyValue Buffer of nLen bytes.
600 : * @param nLen Size of pabyValue in bytes. Should be equal to
601 : * GetTotalElementsCount() * GetDataType().GetSize()
602 : * @return true in case of success.
603 : */
604 173 : bool GDALAttribute::Write(const void *pabyValue, size_t nLen)
605 : {
606 173 : if (nLen != GetTotalElementsCount() * GetDataType().GetSize())
607 : {
608 0 : CPLError(CE_Failure, CPLE_AppDefined,
609 : "Length is not of expected value");
610 0 : return false;
611 : }
612 173 : const auto &dims = GetDimensions();
613 173 : const auto nDims = GetDimensionCount();
614 346 : std::vector<GUInt64> startIdx(1 + nDims, 0);
615 346 : std::vector<size_t> count(1 + nDims);
616 199 : for (size_t i = 0; i < nDims; i++)
617 : {
618 26 : count[i] = static_cast<size_t>(dims[i]->GetSize());
619 : }
620 173 : return Write(startIdx.data(), count.data(), nullptr, nullptr, GetDataType(),
621 173 : pabyValue, pabyValue, nLen);
622 : }
623 :
624 : /************************************************************************/
625 : /* Write() */
626 : /************************************************************************/
627 :
628 : /** Write an attribute from a string value.
629 : *
630 : * Type conversion will be performed if needed. If the attribute contains
631 : * multiple values, only the first one will be updated.
632 : *
633 : * This is the same as the C function GDALAttributeWriteString().
634 : *
635 : * @param pszValue Pointer to a string.
636 : * @return true in case of success.
637 : */
638 418 : bool GDALAttribute::Write(const char *pszValue)
639 : {
640 418 : const auto nDims = GetDimensionCount();
641 836 : std::vector<GUInt64> startIdx(1 + nDims, 0);
642 418 : std::vector<size_t> count(1 + nDims, 1);
643 418 : return Write(startIdx.data(), count.data(), nullptr, nullptr,
644 836 : GDALExtendedDataType::CreateString(), &pszValue, &pszValue,
645 836 : sizeof(pszValue));
646 : }
647 :
648 : /************************************************************************/
649 : /* WriteInt() */
650 : /************************************************************************/
651 :
652 : /** Write an attribute from a integer value.
653 : *
654 : * Type conversion will be performed if needed. If the attribute contains
655 : * multiple values, only the first one will be updated.
656 : *
657 : * This is the same as the C function GDALAttributeWriteInt().
658 : *
659 : * @param nVal Value.
660 : * @return true in case of success.
661 : */
662 23 : bool GDALAttribute::WriteInt(int nVal)
663 : {
664 23 : const auto nDims = GetDimensionCount();
665 46 : std::vector<GUInt64> startIdx(1 + nDims, 0);
666 23 : std::vector<size_t> count(1 + nDims, 1);
667 23 : return Write(startIdx.data(), count.data(), nullptr, nullptr,
668 46 : GDALExtendedDataType::Create(GDT_Int32), &nVal, &nVal,
669 46 : sizeof(nVal));
670 : }
671 :
672 : /************************************************************************/
673 : /* WriteInt64() */
674 : /************************************************************************/
675 :
676 : /** Write an attribute from an int64_t value.
677 : *
678 : * Type conversion will be performed if needed. If the attribute contains
679 : * multiple values, only the first one will be updated.
680 : *
681 : * This is the same as the C function GDALAttributeWriteInt().
682 : *
683 : * @param nVal Value.
684 : * @return true in case of success.
685 : */
686 14 : bool GDALAttribute::WriteInt64(int64_t nVal)
687 : {
688 14 : const auto nDims = GetDimensionCount();
689 28 : std::vector<GUInt64> startIdx(1 + nDims, 0);
690 14 : std::vector<size_t> count(1 + nDims, 1);
691 14 : return Write(startIdx.data(), count.data(), nullptr, nullptr,
692 28 : GDALExtendedDataType::Create(GDT_Int64), &nVal, &nVal,
693 28 : sizeof(nVal));
694 : }
695 :
696 : /************************************************************************/
697 : /* Write() */
698 : /************************************************************************/
699 :
700 : /** Write an attribute from a double value.
701 : *
702 : * Type conversion will be performed if needed. If the attribute contains
703 : * multiple values, only the first one will be updated.
704 : *
705 : * This is the same as the C function GDALAttributeWriteDouble().
706 : *
707 : * @param dfVal Value.
708 : * @return true in case of success.
709 : */
710 40 : bool GDALAttribute::Write(double dfVal)
711 : {
712 40 : const auto nDims = GetDimensionCount();
713 80 : std::vector<GUInt64> startIdx(1 + nDims, 0);
714 40 : std::vector<size_t> count(1 + nDims, 1);
715 40 : return Write(startIdx.data(), count.data(), nullptr, nullptr,
716 80 : GDALExtendedDataType::Create(GDT_Float64), &dfVal, &dfVal,
717 80 : sizeof(dfVal));
718 : }
719 :
720 : /************************************************************************/
721 : /* Write() */
722 : /************************************************************************/
723 :
724 : /** Write an attribute from an array of strings.
725 : *
726 : * Type conversion will be performed if needed.
727 : *
728 : * Exactly GetTotalElementsCount() strings must be provided
729 : *
730 : * This is the same as the C function GDALAttributeWriteStringArray().
731 : *
732 : * @param vals Array of strings.
733 : * @return true in case of success.
734 : */
735 9 : bool GDALAttribute::Write(CSLConstList vals)
736 : {
737 9 : if (static_cast<size_t>(CSLCount(vals)) != GetTotalElementsCount())
738 : {
739 1 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid number of input values");
740 1 : return false;
741 : }
742 8 : const auto nDims = GetDimensionCount();
743 16 : std::vector<GUInt64> startIdx(1 + nDims, 0);
744 8 : std::vector<size_t> count(1 + nDims);
745 8 : const auto &dims = GetDimensions();
746 17 : for (size_t i = 0; i < nDims; i++)
747 9 : count[i] = static_cast<size_t>(dims[i]->GetSize());
748 8 : return Write(startIdx.data(), count.data(), nullptr, nullptr,
749 8 : GDALExtendedDataType::CreateString(), vals, vals,
750 16 : static_cast<size_t>(GetTotalElementsCount()) * sizeof(char *));
751 : }
752 :
753 : /************************************************************************/
754 : /* Write() */
755 : /************************************************************************/
756 :
757 : /** Write an attribute from an array of int.
758 : *
759 : * Type conversion will be performed if needed.
760 : *
761 : * Exactly GetTotalElementsCount() strings must be provided
762 : *
763 : * This is the same as the C function GDALAttributeWriteIntArray()
764 : *
765 : * @param vals Array of int.
766 : * @param nVals Should be equal to GetTotalElementsCount().
767 : * @return true in case of success.
768 : */
769 12 : bool GDALAttribute::Write(const int *vals, size_t nVals)
770 : {
771 12 : if (nVals != GetTotalElementsCount())
772 : {
773 1 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid number of input values");
774 1 : return false;
775 : }
776 11 : const auto nDims = GetDimensionCount();
777 22 : std::vector<GUInt64> startIdx(1 + nDims, 0);
778 11 : std::vector<size_t> count(1 + nDims);
779 11 : const auto &dims = GetDimensions();
780 22 : for (size_t i = 0; i < nDims; i++)
781 11 : count[i] = static_cast<size_t>(dims[i]->GetSize());
782 11 : return Write(startIdx.data(), count.data(), nullptr, nullptr,
783 11 : GDALExtendedDataType::Create(GDT_Int32), vals, vals,
784 22 : static_cast<size_t>(GetTotalElementsCount()) * sizeof(GInt32));
785 : }
786 :
787 : /************************************************************************/
788 : /* Write() */
789 : /************************************************************************/
790 :
791 : /** Write an attribute from an array of int64_t.
792 : *
793 : * Type conversion will be performed if needed.
794 : *
795 : * Exactly GetTotalElementsCount() strings must be provided
796 : *
797 : * This is the same as the C function GDALAttributeWriteLongArray()
798 : *
799 : * @param vals Array of int64_t.
800 : * @param nVals Should be equal to GetTotalElementsCount().
801 : * @return true in case of success.
802 : */
803 13 : bool GDALAttribute::Write(const int64_t *vals, size_t nVals)
804 : {
805 13 : if (nVals != GetTotalElementsCount())
806 : {
807 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid number of input values");
808 0 : return false;
809 : }
810 13 : const auto nDims = GetDimensionCount();
811 26 : std::vector<GUInt64> startIdx(1 + nDims, 0);
812 13 : std::vector<size_t> count(1 + nDims);
813 13 : const auto &dims = GetDimensions();
814 26 : for (size_t i = 0; i < nDims; i++)
815 13 : count[i] = static_cast<size_t>(dims[i]->GetSize());
816 13 : return Write(startIdx.data(), count.data(), nullptr, nullptr,
817 13 : GDALExtendedDataType::Create(GDT_Int64), vals, vals,
818 13 : static_cast<size_t>(GetTotalElementsCount()) *
819 13 : sizeof(int64_t));
820 : }
821 :
822 : /************************************************************************/
823 : /* Write() */
824 : /************************************************************************/
825 :
826 : /** Write an attribute from an array of double.
827 : *
828 : * Type conversion will be performed if needed.
829 : *
830 : * Exactly GetTotalElementsCount() strings must be provided
831 : *
832 : * This is the same as the C function GDALAttributeWriteDoubleArray()
833 : *
834 : * @param vals Array of double.
835 : * @param nVals Should be equal to GetTotalElementsCount().
836 : * @return true in case of success.
837 : */
838 8 : bool GDALAttribute::Write(const double *vals, size_t nVals)
839 : {
840 8 : if (nVals != GetTotalElementsCount())
841 : {
842 1 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid number of input values");
843 1 : return false;
844 : }
845 7 : const auto nDims = GetDimensionCount();
846 14 : std::vector<GUInt64> startIdx(1 + nDims, 0);
847 7 : std::vector<size_t> count(1 + nDims);
848 7 : const auto &dims = GetDimensions();
849 15 : for (size_t i = 0; i < nDims; i++)
850 8 : count[i] = static_cast<size_t>(dims[i]->GetSize());
851 7 : return Write(startIdx.data(), count.data(), nullptr, nullptr,
852 7 : GDALExtendedDataType::Create(GDT_Float64), vals, vals,
853 14 : static_cast<size_t>(GetTotalElementsCount()) * sizeof(double));
854 : }
|