Skip to content

Commit 0628d0d

Browse files
committed
CodesHandle::getBytes: use length instead of size to determine array size
1 parent 9eb32f2 commit 0628d0d

File tree

4 files changed

+59
-26
lines changed

4 files changed

+59
-26
lines changed

src/metkit/codes/BUFRDecoder.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,19 @@ void BUFRDecoder::getMetadata(const eckit::message::Message& msg, eckit::message
114114
if constexpr (std::is_same_v<Type, std::string> || std::is_arithmetic_v<Type>) {
115115
gather.setValue(name, std::forward<decltype(v)>(v));
116116
}
117+
else if constexpr (std::is_same_v<Type, std::vector<uint8_t>>) {
118+
static const char hex_digits[] = "0123456789abcdef";
119+
std::string out;
120+
out.resize(v.size() * 2);
121+
122+
for (size_t i = 0; i < v.size(); i++) {
123+
uint8_t b = v[i];
124+
out[2 * i] = hex_digits[b >> 4];
125+
out[2 * i + 1] = hex_digits[b & 0x0F];
126+
}
127+
128+
gather.setValue(name, out);
129+
}
117130
else {
118131
// Unhandled types are all array types - the prior call checking `size != 1` only allows for
119132
// scalars.

src/metkit/codes/GRIBDecoder.cc

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
#include "metkit/codes/GRIBDecoder.h"
1818
#include "metkit/codes/api/CodesAPI.h"
1919

20+
#include "eccodes.h"
21+
2022
#include <algorithm>
2123
#include <iostream>
2224

23-
#include "eccodes.h"
24-
2525

2626
namespace metkit {
2727
namespace codes {
@@ -63,29 +63,33 @@ void GRIBDecoder::getMetadata(const eckit::message::Message& msg, eckit::message
6363
break;
6464
}
6565
case eckit::message::ValueRepresentation::Native: {
66-
// https://jira.ecmwf.int/browse/ECC-2166
67-
if (name == "uuidOfHGrid") {
68-
// uuidOfHGrid returns size 1 although it contains 16 bytes
69-
gather.setValue(name, k.getString());
70-
}
71-
else {
72-
std::visit(
73-
[&](auto&& v) {
74-
using Type = std::decay_t<decltype(v)>;
75-
if constexpr (std::is_same_v<Type, std::string> || std::is_arithmetic_v<Type>) {
76-
gather.setValue(name, std::forward<decltype(v)>(v));
77-
}
78-
else {
79-
// Unhandled types are all array types - the prior call checking `size != 1` only allows
80-
// for scalars.
81-
throw eckit::Exception(
82-
std::string("Unexpected type when accessing GRIB message metadata ") +
83-
typeid(v).name(),
84-
Here());
66+
std::visit(
67+
[&](auto&& v) {
68+
using Type = std::decay_t<decltype(v)>;
69+
if constexpr (std::is_same_v<Type, std::string> || std::is_arithmetic_v<Type>) {
70+
gather.setValue(name, std::forward<decltype(v)>(v));
71+
}
72+
if constexpr (std::is_same_v<Type, std::vector<uint8_t>>) {
73+
static const char hex_digits[] = "0123456789abcdef";
74+
std::string out;
75+
out.resize(v.size() * 2);
76+
77+
for (size_t i = 0; i < v.size(); i++) {
78+
uint8_t b = v[i];
79+
out[2 * i] = hex_digits[b >> 4];
80+
out[2 * i + 1] = hex_digits[b & 0x0F];
8581
}
86-
},
87-
k.get());
88-
}
82+
gather.setValue(name, out);
83+
}
84+
else {
85+
// Unhandled types are all array types - the prior call checking `size != 1` only allows
86+
// for scalars.
87+
throw eckit::Exception(
88+
std::string("Unexpected type when accessing GRIB message metadata ") + typeid(v).name(),
89+
Here());
90+
}
91+
},
92+
k.get());
8993
break;
9094
}
9195
}

src/metkit/codes/api/CodesAPI.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "eccodes.h"
1717

18+
1819
namespace std {
1920
template <>
2021
struct default_delete<codes_handle> {
@@ -87,6 +88,7 @@ class OwningCodesHandle : public CodesHandle {
8788
void forceSet(const std::string& key, Span<const double> value) override;
8889
void forceSet(const std::string& key, Span<const float> value) override;
8990
size_t size(const std::string& key) const override;
91+
size_t length(const std::string& key) const override;
9092
CodesValue get(const std::string& key) const override;
9193
NativeType type(const std::string& key) const override;
9294
long getLong(const std::string& key) const override;
@@ -222,6 +224,12 @@ size_t OwningCodesHandle::size(const std::string& key) const {
222224
return size;
223225
}
224226

227+
size_t OwningCodesHandle::length(const std::string& key) const {
228+
size_t length;
229+
throwOnError(codes_get_length(raw(), key.c_str(), &length), Here(), "CodesHandle::length(string)", key);
230+
return length;
231+
}
232+
225233
/// Get the value of the key
226234
CodesValue OwningCodesHandle::get(const std::string& key) const {
227235
NativeType ktype = type(key);
@@ -353,7 +361,7 @@ std::vector<std::string> OwningCodesHandle::getStringArray(const std::string& ke
353361

354362
std::vector<uint8_t> OwningCodesHandle::getBytes(const std::string& key) const {
355363
std::vector<uint8_t> ret;
356-
std::size_t ksize = size(key);
364+
std::size_t ksize = length(key) / 2;
357365
ret.resize(ksize);
358366
throwOnError(codes_get_bytes(raw(), key.c_str(), ret.data(), &ksize), Here(), "CodesHandle::getBytes(string)", key);
359367
ret.resize(ksize);
@@ -506,7 +514,7 @@ class ConcreteKeyIterator : public KeyIterator {
506514
std::vector<uint8_t> getBytes() const override {
507515
std::vector<uint8_t> ret;
508516
std::string key = name();
509-
std::size_t size = refHandle_.get().size(key);
517+
std::size_t size = refHandle_.get().length(key) / 2;
510518
ret.resize(size);
511519
throwOnError(codes_keys_iterator_get_bytes(it_.get(), ret.data(), &size), Here(), "KeyIterator::getBytes()");
512520
ret.resize(size);

src/metkit/codes/api/CodesAPI.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,14 @@ class CodesHandle {
199199
/// @return For given scalars 1 is returned. For given arrays the size of the array is returned..
200200
virtual size_t size(const std::string& key) const = 0;
201201

202+
/// Returns the number of chars/bytes contained for a given key
203+
// of type string/byte array.
204+
///
205+
/// Can be used to determine if a field is storing a scalar or an array.
206+
/// @param key Name of the field that is supposed to be inspected.
207+
/// @return Number of chars/bytes of contained string/byte array
208+
virtual size_t length(const std::string& key) const = 0;
209+
202210
/// Get the value of the key.
203211
///
204212
/// High-level functionality:

0 commit comments

Comments
 (0)