Line data Source code
1 : /******************************************************************************
2 : *
3 : * Name: gdalmultidim_c_api_attribute.cpp
4 : * Project: GDAL Core
5 : * Purpose: C API for GDALAttribute
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 : #include "gdalmultidim_priv.h"
16 : #include "gdal_fwd.h"
17 :
18 : /************************************************************************/
19 : /* GDALAttributeRelease() */
20 : /************************************************************************/
21 :
22 : /** Release the GDAL in-memory object associated with a GDALAttribute.
23 : *
24 : * Note: when applied on a object coming from a driver, this does not
25 : * destroy the object in the file, database, etc...
26 : */
27 864 : void GDALAttributeRelease(GDALAttributeH hAttr)
28 : {
29 864 : delete hAttr;
30 864 : }
31 :
32 : /************************************************************************/
33 : /* GDALReleaseAttributes() */
34 : /************************************************************************/
35 :
36 : /** Free the return of GDALGroupGetAttributes() or GDALMDArrayGetAttributes()
37 : *
38 : * @param attributes return pointer of above methods
39 : * @param nCount *pnCount value returned by above methods
40 : */
41 133 : void GDALReleaseAttributes(GDALAttributeH *attributes, size_t nCount)
42 : {
43 445 : for (size_t i = 0; i < nCount; i++)
44 : {
45 312 : delete attributes[i];
46 : }
47 133 : CPLFree(attributes);
48 133 : }
49 :
50 : /************************************************************************/
51 : /* GDALAttributeGetName() */
52 : /************************************************************************/
53 :
54 : /** Return the name of the attribute.
55 : *
56 : * The returned pointer is valid until hAttr is released.
57 : *
58 : * This is the same as the C++ method GDALAttribute::GetName().
59 : */
60 385 : const char *GDALAttributeGetName(GDALAttributeH hAttr)
61 : {
62 385 : VALIDATE_POINTER1(hAttr, __func__, nullptr);
63 385 : return hAttr->m_poImpl->GetName().c_str();
64 : }
65 :
66 : /************************************************************************/
67 : /* GDALAttributeGetFullName() */
68 : /************************************************************************/
69 :
70 : /** Return the full name of the attribute.
71 : *
72 : * The returned pointer is valid until hAttr is released.
73 : *
74 : * This is the same as the C++ method GDALAttribute::GetFullName().
75 : */
76 50 : const char *GDALAttributeGetFullName(GDALAttributeH hAttr)
77 : {
78 50 : VALIDATE_POINTER1(hAttr, __func__, nullptr);
79 50 : return hAttr->m_poImpl->GetFullName().c_str();
80 : }
81 :
82 : /************************************************************************/
83 : /* GDALAttributeGetTotalElementsCount() */
84 : /************************************************************************/
85 :
86 : /** Return the total number of values in the attribute.
87 : *
88 : * This is the same as the C++ method
89 : * GDALAbstractMDArray::GetTotalElementsCount()
90 : */
91 212 : GUInt64 GDALAttributeGetTotalElementsCount(GDALAttributeH hAttr)
92 : {
93 212 : VALIDATE_POINTER1(hAttr, __func__, 0);
94 212 : return hAttr->m_poImpl->GetTotalElementsCount();
95 : }
96 :
97 : /************************************************************************/
98 : /* GDALAttributeGetDimensionCount() */
99 : /************************************************************************/
100 :
101 : /** Return the number of dimensions.
102 : *
103 : * This is the same as the C++ method GDALAbstractMDArray::GetDimensionCount()
104 : */
105 12 : size_t GDALAttributeGetDimensionCount(GDALAttributeH hAttr)
106 : {
107 12 : VALIDATE_POINTER1(hAttr, __func__, 0);
108 12 : return hAttr->m_poImpl->GetDimensionCount();
109 : }
110 :
111 : /************************************************************************/
112 : /* GDALAttributeGetDimensionsSize() */
113 : /************************************************************************/
114 :
115 : /** Return the dimension sizes of the attribute.
116 : *
117 : * The returned array must be freed with CPLFree()
118 : *
119 : * @param hAttr Attribute.
120 : * @param pnCount Pointer to the number of values returned. Must NOT be NULL.
121 : *
122 : * @return an array of *pnCount values.
123 : */
124 11 : GUInt64 *GDALAttributeGetDimensionsSize(GDALAttributeH hAttr, size_t *pnCount)
125 : {
126 11 : VALIDATE_POINTER1(hAttr, __func__, nullptr);
127 11 : VALIDATE_POINTER1(pnCount, __func__, nullptr);
128 11 : const auto &dims = hAttr->m_poImpl->GetDimensions();
129 11 : auto ret = static_cast<GUInt64 *>(CPLMalloc(sizeof(GUInt64) * dims.size()));
130 22 : for (size_t i = 0; i < dims.size(); i++)
131 : {
132 11 : ret[i] = dims[i]->GetSize();
133 : }
134 11 : *pnCount = dims.size();
135 11 : return ret;
136 : }
137 :
138 : /************************************************************************/
139 : /* GDALAttributeGetDataType() */
140 : /************************************************************************/
141 :
142 : /** Return the data type
143 : *
144 : * The return must be freed with GDALExtendedDataTypeRelease().
145 : */
146 505 : GDALExtendedDataTypeH GDALAttributeGetDataType(GDALAttributeH hAttr)
147 : {
148 505 : VALIDATE_POINTER1(hAttr, __func__, nullptr);
149 : return new GDALExtendedDataTypeHS(
150 505 : new GDALExtendedDataType(hAttr->m_poImpl->GetDataType()));
151 : }
152 :
153 : /************************************************************************/
154 : /* GDALAttributeReadAsRaw() */
155 : /************************************************************************/
156 :
157 : /** Return the raw value of an attribute.
158 : *
159 : * This is the same as the C++ method GDALAttribute::ReadAsRaw().
160 : *
161 : * The returned buffer must be freed with GDALAttributeFreeRawResult()
162 : *
163 : * @param hAttr Attribute.
164 : * @param pnSize Pointer to the number of bytes returned. Must NOT be NULL.
165 : *
166 : * @return a buffer of *pnSize bytes.
167 : */
168 6 : GByte *GDALAttributeReadAsRaw(GDALAttributeH hAttr, size_t *pnSize)
169 : {
170 6 : VALIDATE_POINTER1(hAttr, __func__, nullptr);
171 6 : VALIDATE_POINTER1(pnSize, __func__, nullptr);
172 12 : auto res(hAttr->m_poImpl->ReadAsRaw());
173 6 : *pnSize = res.size();
174 6 : auto ret = res.StealData();
175 6 : if (!ret)
176 : {
177 0 : *pnSize = 0;
178 0 : return nullptr;
179 : }
180 6 : return ret;
181 : }
182 :
183 : /************************************************************************/
184 : /* GDALAttributeFreeRawResult() */
185 : /************************************************************************/
186 :
187 : /** Free the return of GDALAttributeAsRaw()
188 : */
189 6 : void GDALAttributeFreeRawResult(GDALAttributeH hAttr, GByte *raw,
190 : CPL_UNUSED size_t nSize)
191 : {
192 6 : VALIDATE_POINTER0(hAttr, __func__);
193 6 : if (raw)
194 : {
195 6 : const auto &dt(hAttr->m_poImpl->GetDataType());
196 6 : const auto nDTSize(dt.GetSize());
197 6 : GByte *pabyPtr = raw;
198 6 : const auto nEltCount(hAttr->m_poImpl->GetTotalElementsCount());
199 6 : CPLAssert(nSize == nDTSize * nEltCount);
200 12 : for (size_t i = 0; i < nEltCount; ++i)
201 : {
202 6 : dt.FreeDynamicMemory(pabyPtr);
203 6 : pabyPtr += nDTSize;
204 : }
205 6 : CPLFree(raw);
206 : }
207 : }
208 :
209 : /************************************************************************/
210 : /* GDALAttributeReadAsString() */
211 : /************************************************************************/
212 :
213 : /** Return the value of an attribute as a string.
214 : *
215 : * The returned string should not be freed, and its lifetime does not
216 : * excess a next call to ReadAsString() on the same object, or the deletion
217 : * of the object itself.
218 : *
219 : * This function will only return the first element if there are several.
220 : *
221 : * This is the same as the C++ method GDALAttribute::ReadAsString()
222 : *
223 : * @return a string, or nullptr.
224 : */
225 137 : const char *GDALAttributeReadAsString(GDALAttributeH hAttr)
226 : {
227 137 : VALIDATE_POINTER1(hAttr, __func__, nullptr);
228 137 : return hAttr->m_poImpl->ReadAsString();
229 : }
230 :
231 : /************************************************************************/
232 : /* GDALAttributeReadAsInt() */
233 : /************************************************************************/
234 :
235 : /** Return the value of an attribute as a integer.
236 : *
237 : * This function will only return the first element if there are several.
238 : *
239 : * It can fail if its value can not be converted to integer.
240 : *
241 : * This is the same as the C++ method GDALAttribute::ReadAsInt()
242 : *
243 : * @return a integer, or INT_MIN in case of error.
244 : */
245 25 : int GDALAttributeReadAsInt(GDALAttributeH hAttr)
246 : {
247 25 : VALIDATE_POINTER1(hAttr, __func__, 0);
248 25 : return hAttr->m_poImpl->ReadAsInt();
249 : }
250 :
251 : /************************************************************************/
252 : /* GDALAttributeReadAsInt64() */
253 : /************************************************************************/
254 :
255 : /** Return the value of an attribute as a int64_t.
256 : *
257 : * This function will only return the first element if there are several.
258 : *
259 : * It can fail if its value can not be converted to integer.
260 : *
261 : * This is the same as the C++ method GDALAttribute::ReadAsInt64()
262 : *
263 : * @return an int64_t, or INT64_MIN in case of error.
264 : */
265 27 : int64_t GDALAttributeReadAsInt64(GDALAttributeH hAttr)
266 : {
267 27 : VALIDATE_POINTER1(hAttr, __func__, 0);
268 27 : return hAttr->m_poImpl->ReadAsInt64();
269 : }
270 :
271 : /************************************************************************/
272 : /* GDALAttributeReadAsDouble() */
273 : /************************************************************************/
274 :
275 : /** Return the value of an attribute as a double.
276 : *
277 : * This function will only return the first element if there are several.
278 : *
279 : * It can fail if its value can not be converted to double.
280 : *
281 : * This is the same as the C++ method GDALAttribute::ReadAsDouble()
282 : *
283 : * @return a double value.
284 : */
285 55 : double GDALAttributeReadAsDouble(GDALAttributeH hAttr)
286 : {
287 55 : VALIDATE_POINTER1(hAttr, __func__, 0);
288 55 : return hAttr->m_poImpl->ReadAsDouble();
289 : }
290 :
291 : /************************************************************************/
292 : /* GDALAttributeReadAsStringArray() */
293 : /************************************************************************/
294 :
295 : /** Return the value of an attribute as an array of strings.
296 : *
297 : * This is the same as the C++ method GDALAttribute::ReadAsStringArray()
298 : *
299 : * The return value must be freed with CSLDestroy().
300 : */
301 22 : char **GDALAttributeReadAsStringArray(GDALAttributeH hAttr)
302 : {
303 22 : VALIDATE_POINTER1(hAttr, __func__, nullptr);
304 22 : return hAttr->m_poImpl->ReadAsStringArray().StealList();
305 : }
306 :
307 : /************************************************************************/
308 : /* GDALAttributeReadAsIntArray() */
309 : /************************************************************************/
310 :
311 : /** Return the value of an attribute as an array of integers.
312 : *
313 : * This is the same as the C++ method GDALAttribute::ReadAsIntArray()
314 : *
315 : * @param hAttr Attribute
316 : * @param pnCount Pointer to the number of values returned. Must NOT be NULL.
317 : * @return array to be freed with CPLFree(), or nullptr.
318 : */
319 18 : int *GDALAttributeReadAsIntArray(GDALAttributeH hAttr, size_t *pnCount)
320 : {
321 18 : VALIDATE_POINTER1(hAttr, __func__, nullptr);
322 18 : VALIDATE_POINTER1(pnCount, __func__, nullptr);
323 18 : *pnCount = 0;
324 36 : auto tmp(hAttr->m_poImpl->ReadAsIntArray());
325 18 : if (tmp.empty())
326 0 : return nullptr;
327 18 : auto ret = static_cast<int *>(VSI_MALLOC2_VERBOSE(tmp.size(), sizeof(int)));
328 18 : if (!ret)
329 0 : return nullptr;
330 18 : memcpy(ret, tmp.data(), tmp.size() * sizeof(int));
331 18 : *pnCount = tmp.size();
332 18 : return ret;
333 : }
334 :
335 : /************************************************************************/
336 : /* GDALAttributeReadAsInt64Array() */
337 : /************************************************************************/
338 :
339 : /** Return the value of an attribute as an array of int64_t.
340 : *
341 : * This is the same as the C++ method GDALAttribute::ReadAsInt64Array()
342 : *
343 : * @param hAttr Attribute
344 : * @param pnCount Pointer to the number of values returned. Must NOT be NULL.
345 : * @return array to be freed with CPLFree(), or nullptr.
346 : */
347 26 : int64_t *GDALAttributeReadAsInt64Array(GDALAttributeH hAttr, size_t *pnCount)
348 : {
349 26 : VALIDATE_POINTER1(hAttr, __func__, nullptr);
350 26 : VALIDATE_POINTER1(pnCount, __func__, nullptr);
351 26 : *pnCount = 0;
352 52 : auto tmp(hAttr->m_poImpl->ReadAsInt64Array());
353 26 : if (tmp.empty())
354 0 : return nullptr;
355 : auto ret = static_cast<int64_t *>(
356 26 : VSI_MALLOC2_VERBOSE(tmp.size(), sizeof(int64_t)));
357 26 : if (!ret)
358 0 : return nullptr;
359 26 : memcpy(ret, tmp.data(), tmp.size() * sizeof(int64_t));
360 26 : *pnCount = tmp.size();
361 26 : return ret;
362 : }
363 :
364 : /************************************************************************/
365 : /* GDALAttributeReadAsDoubleArray() */
366 : /************************************************************************/
367 :
368 : /** Return the value of an attribute as an array of doubles.
369 : *
370 : * This is the same as the C++ method GDALAttribute::ReadAsDoubleArray()
371 : *
372 : * @param hAttr Attribute
373 : * @param pnCount Pointer to the number of values returned. Must NOT be NULL.
374 : * @return array to be freed with CPLFree(), or nullptr.
375 : */
376 44 : double *GDALAttributeReadAsDoubleArray(GDALAttributeH hAttr, size_t *pnCount)
377 : {
378 44 : VALIDATE_POINTER1(hAttr, __func__, nullptr);
379 44 : VALIDATE_POINTER1(pnCount, __func__, nullptr);
380 44 : *pnCount = 0;
381 88 : auto tmp(hAttr->m_poImpl->ReadAsDoubleArray());
382 44 : if (tmp.empty())
383 0 : return nullptr;
384 : auto ret =
385 44 : static_cast<double *>(VSI_MALLOC2_VERBOSE(tmp.size(), sizeof(double)));
386 44 : if (!ret)
387 0 : return nullptr;
388 44 : memcpy(ret, tmp.data(), tmp.size() * sizeof(double));
389 44 : *pnCount = tmp.size();
390 44 : return ret;
391 : }
392 :
393 : /************************************************************************/
394 : /* GDALAttributeWriteRaw() */
395 : /************************************************************************/
396 :
397 : /** Write an attribute from raw values expressed in GetDataType()
398 : *
399 : * The values should be provided in the type of GetDataType() and there should
400 : * be exactly GetTotalElementsCount() of them.
401 : * If GetDataType() is a string, each value should be a char* pointer.
402 : *
403 : * This is the same as the C++ method GDALAttribute::Write(const void*, size_t).
404 : *
405 : * @param hAttr Attribute
406 : * @param pabyValue Buffer of nLen bytes.
407 : * @param nLength Size of pabyValue in bytes. Should be equal to
408 : * GetTotalElementsCount() * GetDataType().GetSize()
409 : * @return TRUE in case of success.
410 : */
411 5 : int GDALAttributeWriteRaw(GDALAttributeH hAttr, const void *pabyValue,
412 : size_t nLength)
413 : {
414 5 : VALIDATE_POINTER1(hAttr, __func__, FALSE);
415 5 : return hAttr->m_poImpl->Write(pabyValue, nLength);
416 : }
417 :
418 : /************************************************************************/
419 : /* GDALAttributeWriteString() */
420 : /************************************************************************/
421 :
422 : /** Write an attribute from a string value.
423 : *
424 : * Type conversion will be performed if needed. If the attribute contains
425 : * multiple values, only the first one will be updated.
426 : *
427 : * This is the same as the C++ method GDALAttribute::Write(const char*)
428 : *
429 : * @param hAttr Attribute
430 : * @param pszVal Pointer to a string.
431 : * @return TRUE in case of success.
432 : */
433 210 : int GDALAttributeWriteString(GDALAttributeH hAttr, const char *pszVal)
434 : {
435 210 : VALIDATE_POINTER1(hAttr, __func__, FALSE);
436 210 : return hAttr->m_poImpl->Write(pszVal);
437 : }
438 :
439 : /************************************************************************/
440 : /* GDALAttributeWriteInt() */
441 : /************************************************************************/
442 :
443 : /** Write an attribute from a integer value.
444 : *
445 : * Type conversion will be performed if needed. If the attribute contains
446 : * multiple values, only the first one will be updated.
447 : *
448 : * This is the same as the C++ method GDALAttribute::WriteInt()
449 : *
450 : * @param hAttr Attribute
451 : * @param nVal Value.
452 : * @return TRUE in case of success.
453 : */
454 23 : int GDALAttributeWriteInt(GDALAttributeH hAttr, int nVal)
455 : {
456 23 : VALIDATE_POINTER1(hAttr, __func__, FALSE);
457 23 : return hAttr->m_poImpl->WriteInt(nVal);
458 : }
459 :
460 : /************************************************************************/
461 : /* GDALAttributeWriteInt64() */
462 : /************************************************************************/
463 :
464 : /** Write an attribute from an int64_t value.
465 : *
466 : * Type conversion will be performed if needed. If the attribute contains
467 : * multiple values, only the first one will be updated.
468 : *
469 : * This is the same as the C++ method GDALAttribute::WriteLong()
470 : *
471 : * @param hAttr Attribute
472 : * @param nVal Value.
473 : * @return TRUE in case of success.
474 : */
475 14 : int GDALAttributeWriteInt64(GDALAttributeH hAttr, int64_t nVal)
476 : {
477 14 : VALIDATE_POINTER1(hAttr, __func__, FALSE);
478 14 : return hAttr->m_poImpl->WriteInt64(nVal);
479 : }
480 :
481 : /************************************************************************/
482 : /* GDALAttributeWriteDouble() */
483 : /************************************************************************/
484 :
485 : /** Write an attribute from a double value.
486 : *
487 : * Type conversion will be performed if needed. If the attribute contains
488 : * multiple values, only the first one will be updated.
489 : *
490 : * This is the same as the C++ method GDALAttribute::Write(double);
491 : *
492 : * @param hAttr Attribute
493 : * @param dfVal Value.
494 : *
495 : * @return TRUE in case of success.
496 : */
497 12 : int GDALAttributeWriteDouble(GDALAttributeH hAttr, double dfVal)
498 : {
499 12 : VALIDATE_POINTER1(hAttr, __func__, FALSE);
500 12 : return hAttr->m_poImpl->Write(dfVal);
501 : }
502 :
503 : /************************************************************************/
504 : /* GDALAttributeWriteStringArray() */
505 : /************************************************************************/
506 :
507 : /** Write an attribute from an array of strings.
508 : *
509 : * Type conversion will be performed if needed.
510 : *
511 : * Exactly GetTotalElementsCount() strings must be provided
512 : *
513 : * This is the same as the C++ method GDALAttribute::Write(CSLConstList)
514 : *
515 : * @param hAttr Attribute
516 : * @param papszValues Array of strings.
517 : * @return TRUE in case of success.
518 : */
519 9 : int GDALAttributeWriteStringArray(GDALAttributeH hAttr,
520 : CSLConstList papszValues)
521 : {
522 9 : VALIDATE_POINTER1(hAttr, __func__, FALSE);
523 9 : return hAttr->m_poImpl->Write(papszValues);
524 : }
525 :
526 : /************************************************************************/
527 : /* GDALAttributeWriteIntArray() */
528 : /************************************************************************/
529 :
530 : /** Write an attribute from an array of int.
531 : *
532 : * Type conversion will be performed if needed.
533 : *
534 : * Exactly GetTotalElementsCount() strings must be provided
535 : *
536 : * This is the same as the C++ method GDALAttribute::Write(const int *,
537 : * size_t)
538 : *
539 : * @param hAttr Attribute
540 : * @param panValues Array of int.
541 : * @param nCount Should be equal to GetTotalElementsCount().
542 : * @return TRUE in case of success.
543 : */
544 12 : int GDALAttributeWriteIntArray(GDALAttributeH hAttr, const int *panValues,
545 : size_t nCount)
546 : {
547 12 : VALIDATE_POINTER1(hAttr, __func__, FALSE);
548 12 : return hAttr->m_poImpl->Write(panValues, nCount);
549 : }
550 :
551 : /************************************************************************/
552 : /* GDALAttributeWriteInt64Array() */
553 : /************************************************************************/
554 :
555 : /** Write an attribute from an array of int64_t.
556 : *
557 : * Type conversion will be performed if needed.
558 : *
559 : * Exactly GetTotalElementsCount() strings must be provided
560 : *
561 : * This is the same as the C++ method GDALAttribute::Write(const int64_t *,
562 : * size_t)
563 : *
564 : * @param hAttr Attribute
565 : * @param panValues Array of int64_t.
566 : * @param nCount Should be equal to GetTotalElementsCount().
567 : * @return TRUE in case of success.
568 : */
569 13 : int GDALAttributeWriteInt64Array(GDALAttributeH hAttr, const int64_t *panValues,
570 : size_t nCount)
571 : {
572 13 : VALIDATE_POINTER1(hAttr, __func__, FALSE);
573 13 : return hAttr->m_poImpl->Write(panValues, nCount);
574 : }
575 :
576 : /************************************************************************/
577 : /* GDALAttributeWriteDoubleArray() */
578 : /************************************************************************/
579 :
580 : /** Write an attribute from an array of double.
581 : *
582 : * Type conversion will be performed if needed.
583 : *
584 : * Exactly GetTotalElementsCount() strings must be provided
585 : *
586 : * This is the same as the C++ method GDALAttribute::Write(const double *,
587 : * size_t)
588 : *
589 : * @param hAttr Attribute
590 : * @param padfValues Array of double.
591 : * @param nCount Should be equal to GetTotalElementsCount().
592 : * @return TRUE in case of success.
593 : */
594 8 : int GDALAttributeWriteDoubleArray(GDALAttributeH hAttr,
595 : const double *padfValues, size_t nCount)
596 : {
597 8 : VALIDATE_POINTER1(hAttr, __func__, FALSE);
598 8 : return hAttr->m_poImpl->Write(padfValues, nCount);
599 : }
600 :
601 : /************************************************************************/
602 : /* GDALAttributeRename() */
603 : /************************************************************************/
604 :
605 : /** Rename the attribute.
606 : *
607 : * This is not implemented by all drivers.
608 : *
609 : * Drivers known to implement it: MEM, netCDF.
610 : *
611 : * This is the same as the C++ method GDALAbstractMDArray::Rename()
612 : *
613 : * @return true in case of success
614 : * @since GDAL 3.8
615 : */
616 27 : bool GDALAttributeRename(GDALAttributeH hAttr, const char *pszNewName)
617 : {
618 27 : VALIDATE_POINTER1(hAttr, __func__, false);
619 27 : VALIDATE_POINTER1(pszNewName, __func__, false);
620 27 : return hAttr->m_poImpl->Rename(pszNewName);
621 : }
|