16 #include "eckit/eckit_ecbuild_config.h"
17 #include "eckit/io/Buffer.h"
18 #include "eckit/system/SystemInfo.h"
19 #include "eckit/testing/Test.h"
30 using namespace eckit;
31 using namespace eckit::testing;
59 const std::string& codec_name,
60 bool bigEndian=
false) {
62 data.insert(data.begin(), 4, 0);
63 data[bigEndian ? 3 : 0] =
static_cast<unsigned char>(codec_name.size());
65 data.insert(data.begin() + 4, codec_name.begin(), codec_name.end());
67 return 4 + codec_name.length();
78 if (eckit::system::SystemInfo::isBigEndian() == bigEndianData) {
89 const char*
data()
const {
return buffer_; }
90 eckit::Offset
position()
const {
return position_; }
92 char*
get() {
return &buffer_[position_]; }
94 ASSERT(p >= &buffer_[0]);
95 ASSERT(p - &buffer_[0] <
static_cast<long>(buffer_.size()));
96 position_ =
static_cast<size_t>(p - &buffer_[0]);
114 CASE(
"Constant values consume no space in the output data buffer") {
119 const char* expected_data[] = {
123 "\xb7\xe6\x87\xb4\x80\x65\xd2\x41",
124 "\xb7\xe6\x87\xb4\x80\x65\xd2\x41",
125 "\x00\x00\x00\x00\x00\x00\x00\x00",
131 for (
int i = 0;
i < 2;
i++) {
133 bool bigEndianOutput = (
i == 1);
135 std::vector<unsigned char> data;
137 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
138 size_t len = (j == 0) ? 4 : 8;
139 data.insert(data.end(), expected_data[j], expected_data[j] + len);
141 std::reverse(data.end()-len, data.end());
146 std::unique_ptr<Codec>
c;
147 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
153 c->missingValue(0.0);
157 c->gatherStats(1234567890.1234567);
158 c->gatherStats(1234567890.1234567);
159 c->gatherStats(1234567890.1234567);
160 c->gatherStats(1234567890.1234567);
161 c->gatherStats(1234567890.1234567);
163 EXPECT(!
c->hasMissing());
169 EXPECT(ds.
position() == eckit::Offset(28));
170 EXPECT(::memcmp(&data[0], ds.
data(), data.size()) == 0);
176 std::vector<unsigned char> buf(1024, 0);
177 EXPECT(
c->encode(&buf[0], 1234567890.1234567) == &buf[0]);
178 EXPECT(
c->encode(&buf[0], 1234567890.1234567) == &buf[0]);
179 EXPECT(
c->encode(&buf[0], 1234567890.1234567) == &buf[0]);
180 EXPECT(
c->encode(&buf[0], 1234567890.1234567) == &buf[0]);
181 EXPECT(
c->encode(&buf[0], 1234567890.1234567) == &buf[0]);
183 for (
size_t n = 0; n < buf.size(); n++)
189 CASE(
"Constant integer values consume no space in the output data buffer") {
194 const char* expected_data[] = {
198 "\x00\x00\x80\xb4\x80\x65\xd2\x41",
199 "\x00\x00\x80\xb4\x80\x65\xd2\x41",
200 "\x00\x00\x00\x00\x00\x00\x00\x00",
206 for (
int i = 0;
i < 2;
i++) {
208 bool bigEndianOutput = (
i == 1);
210 std::vector<unsigned char> data;
212 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
213 size_t len = (j == 0) ? 4 : 8;
214 data.insert(data.end(), expected_data[j], expected_data[j] + len);
216 std::reverse(data.end()-len, data.end());
221 std::unique_ptr<Codec>
c;
222 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
228 c->missingValue(0.0);
232 int64_t x = 1234567890;
233 double& rx(
reinterpret_cast<double&
>(x));
240 EXPECT(!
c->hasMissing());
246 EXPECT(ds.
position() == eckit::Offset(28));
247 EXPECT(::memcmp(&data[0], ds.
data(), data.size()) == 0);
253 std::vector<unsigned char> buf(1024, 0);
254 EXPECT(
c->encode(&buf[0], rx) == &buf[0]);
255 EXPECT(
c->encode(&buf[0], rx) == &buf[0]);
256 EXPECT(
c->encode(&buf[0], rx) == &buf[0]);
257 EXPECT(
c->encode(&buf[0], rx) == &buf[0]);
258 EXPECT(
c->encode(&buf[0], rx) == &buf[0]);
260 for (
size_t n = 0; n < buf.size(); n++)
267 CASE(
"constant strings consume no output data space") {
275 const char* expected_data[] = {
281 "\x00\x00\x00\x00\x00\x00\x00\x00",
286 for (
int i = 0;
i < 2;
i++) {
288 bool bigEndianOutput = (
i == 1);
290 std::vector<unsigned char> data;
292 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
293 size_t len = (j == 0) ? 4 : 8;
294 data.insert(data.end(), expected_data[j], expected_data[j] + len);
300 std::unique_ptr<Codec>
c;
301 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
307 c->missingValue(0.0);
311 const char*
str =
"hi-there";
312 c->gatherStats(*
reinterpret_cast<const double*
>(
str));
313 c->gatherStats(*
reinterpret_cast<const double*
>(
str));
314 c->gatherStats(*
reinterpret_cast<const double*
>(
str));
315 c->gatherStats(*
reinterpret_cast<const double*
>(
str));
317 EXPECT(!
c->hasMissing());
323 EXPECT(ds.
position() == eckit::Offset(28));
324 EXPECT(::memcmp(&data[0], ds.
data(), data.size()) == 0);
330 std::vector<unsigned char> buf(1024, 0);
331 EXPECT(
c->encode(&buf[0], *
reinterpret_cast<const double*
>(
str)) == &buf[0]);
332 EXPECT(
c->encode(&buf[0], *
reinterpret_cast<const double*
>(
str)) == &buf[0]);
333 EXPECT(
c->encode(&buf[0], *
reinterpret_cast<const double*
>(
str)) == &buf[0]);
334 EXPECT(
c->encode(&buf[0], *
reinterpret_cast<const double*
>(
str)) == &buf[0]);
336 for (
size_t n = 0; n < buf.size(); n++)
342 CASE(
"Constant integer or missing value behaves a bit oddly") {
350 double customMissingValue = 2222222222;
351 double baseValue = 987654321.9876;
352 const size_t expectedHdrSize = 28;
354 const char* expected_data[] = {
360 "\xad\x69\xfe\x58\x34\x6f\xcd\x41",
361 "\xad\x69\xfe\xd7\x34\x6f\xcd\x41",
362 "\x00\x00\xc0\x71\x8d\x8e\xe0\x41"
367 for (
int i = 0;
i < 2;
i++) {
369 bool bigEndianOutput = (
i == 1);
371 std::vector<unsigned char> data;
373 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
374 size_t len = (j == 0) ? 4 : 8;
375 data.insert(data.end(), expected_data[j], expected_data[j] + len);
377 std::reverse(data.end()-len, data.end());
383 data.push_back(0xff);
384 for (
size_t n = 0; n < 255; n++) {
385 data.push_back(
static_cast<unsigned char>(n));
387 data.push_back(0xff);
391 std::unique_ptr<Codec>
c;
392 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
398 c->missingValue(customMissingValue);
399 EXPECT(!
c->hasMissing());
403 c->gatherStats(baseValue + 0);
404 c->gatherStats(customMissingValue);
405 for (
size_t n = 0; n < 255; n++) {
406 c->gatherStats(baseValue + n);
408 c->gatherStats(customMissingValue);
411 EXPECT(
c->hasMissing());
417 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize));
424 EXPECT((posNext =
c->encode(ds.
get(), baseValue + 0)) == (ds.
get() + 1));
426 EXPECT((posNext =
c->encode(ds.
get(), customMissingValue)) == (ds.
get() + 1));
429 for (
size_t n = 0; n < 255; n++) {
430 EXPECT((posNext =
c->encode(ds.
get(), baseValue + n)) == (ds.
get() + 1));
434 EXPECT((posNext =
c->encode(ds.
get(), customMissingValue)) == (ds.
get() + 1));
440 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize + nelem));
442 EXPECT(::memcmp(&data[0], ds.
data(), expectedHdrSize + nelem) == 0);
447 CASE(
"real constant or missing value is not quite constant") {
454 double customMissingValue = -2222222222;
455 double baseValue = 987654321.9876;
456 const size_t expectedHdrSize = 28;
458 const char* expected_data[] = {
462 "\xad\x69\xfe\x58\x34\x6f\xcd\x41",
463 "\xad\x69\xfe\xd7\x34\x6f\xcd\x41",
464 "\x00\x00\xc0\x71\x8d\x8e\xe0\xc1"
469 for (
int i = 0;
i < 2;
i++) {
471 bool bigEndianOutput = (
i == 1);
473 std::vector<unsigned char> data;
475 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
476 size_t len = (j == 0) ? 4 : 8;
477 data.insert(data.end(), expected_data[j], expected_data[j] + len);
479 std::reverse(data.end()-len, data.end());
485 data.push_back(0xff);
486 for (
size_t n = 0; n < 255; n++) {
487 data.push_back(
static_cast<unsigned char>(n));
489 data.push_back(0xff);
493 std::unique_ptr<Codec>
c;
494 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
500 c->missingValue(customMissingValue);
501 EXPECT(!
c->hasMissing());
505 c->gatherStats(baseValue + 0);
506 c->gatherStats(customMissingValue);
507 for (
size_t n = 0; n < 255; n++) {
508 c->gatherStats(baseValue + n);
510 c->gatherStats(customMissingValue);
513 EXPECT(
c->hasMissing());
519 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize));
526 EXPECT((posNext =
c->encode(ds.
get(), baseValue + 0)) == (ds.
get() + 1));
528 EXPECT((posNext =
c->encode(ds.
get(), customMissingValue)) == (ds.
get() + 1));
530 for (
size_t n = 0; n < 255; n++) {
531 EXPECT((posNext =
c->encode(ds.
get(), baseValue + n)) == (ds.
get() + 1));
534 EXPECT((posNext =
c->encode(ds.
get(), customMissingValue)) == (ds.
get() + 1));
540 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize + nelem));
549 EXPECT(::memcmp(&data[0], ds.
data(), expectedHdrSize + nelem) == 0);
554 CASE(
"Character strings are 8-byte sequences coerced into being treated as doubles") {
558 const size_t expectedHdrSize = 32;
560 const char* expected_data[] = {
564 "\x00\x00\x00\x00\x00\x00\x00\x00",
565 "\x00\x00\x00\x00\x00\x00\x00\x00",
566 "\x00\x00\x00\x00\x00\x00\x00\x00",
572 "\0\xff\0\xff\0\xff\0\xff",
574 "\xff\xff\xff\xff\xff\xff\xff\xff",
579 for (
int i = 0;
i < 2;
i++) {
581 bool bigEndianOutput = (
i == 1);
583 std::vector<unsigned char> data;
585 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
586 size_t len = (j == 0 || j == 4) ? 4 : 8;
587 data.insert(data.end(), expected_data[j], expected_data[j] + len);
590 if (bigEndianOutput && j < 5)
591 std::reverse(data.end()-len, data.end());
596 std::unique_ptr<Codec>
c;
597 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
603 c->missingValue(0.0);
604 EXPECT(!
c->hasMissing());
608 c->gatherStats(*
reinterpret_cast<const double*
>(expected_data[5]));
609 c->gatherStats(*
reinterpret_cast<const double*
>(expected_data[6]));
610 c->gatherStats(*
reinterpret_cast<const double*
>(expected_data[7]));
611 c->gatherStats(*
reinterpret_cast<const double*
>(expected_data[8]));
612 c->gatherStats(*
reinterpret_cast<const double*
>(expected_data[9]));
614 EXPECT(!
c->hasMissing());
620 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize));
626 for(
size_t n = 5; n < 10; n++) {
627 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(expected_data[n])))
638 size_t dataSize = (8 * 5);
640 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize + dataSize));
641 EXPECT(::memcmp(&data[0], ds.
data(), 4) == 0);
642 EXPECT(::memcmp(&data[28], &ds.
data()[28], expectedHdrSize + dataSize - 28) == 0);
647 CASE(
"long floating point values can include the missing data value") {
649 const uint64_t inf_bits = 0x7ff0000000000000;
650 const uint64_t neg_inf_bits = 0xfff0000000000000;
651 const uint64_t sig_nan_bits = 0xfffffffffffff77f;
652 const uint64_t quiet_nan_bits = 0xffffffffffffff7f;
654 const size_t expectedHdrSize = 28;
655 double customMissingValue = 2222222222;
657 const char* expected_data[] = {
661 "\x00\x00\x00\x00\x00\x00\xf0\xff",
662 "\x00\x00\x00\x00\x00\x00\xf0\x7f",
663 "\x00\x00\xc0\x71\x8d\x8e\xe0\x41",
666 "\x00\x00\x00\x00\x00\x00\x00\x00",
667 "\x53\xa4\x0c\x54\x34\x6f\x9d\x41",
668 "\x9b\xe6\x57\xb7\x80\x65\x02\xc2",
669 "\x00\x00\x00\x00\x00\x00\xf0\x7f",
670 "\x00\x00\x00\x00\x00\x00\xf0\xff",
671 "\x7f\xf7\xff\xff\xff\xff\xff\xff",
672 "\x7f\xff\xff\xff\xff\xff\xff\xff",
673 "\x00\x00\xc0\xff\xff\xff\xdf\xc1",
674 "\x00\x00\xc0\x71\x8d\x8e\xe0\x41"
679 for (
int i = 0;
i < 2;
i++) {
681 bool bigEndianOutput = (
i == 1);
683 std::vector<unsigned char> data;
685 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
686 size_t len = (j == 0) ? 4 : 8;
687 data.insert(data.end(), expected_data[j], expected_data[j] + len);
689 std::reverse(data.end()-len, data.end());
694 std::unique_ptr<Codec>
c;
695 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
701 c->missingValue(customMissingValue);
702 EXPECT(!
c->hasMissing());
707 c->gatherStats(123456789.0123456);
708 c->gatherStats(-9876543210.9876);
709 double v = *
reinterpret_cast<const double*
>(&inf_bits);
710 EXPECT(std::isinf(v));
713 v = *
reinterpret_cast<const double*
>(&neg_inf_bits);
714 EXPECT(std::isinf(v));
717 v = *
reinterpret_cast<const double*
>(&sig_nan_bits);
718 EXPECT(std::isnan(v));
720 v = *
reinterpret_cast<const double*
>(&quiet_nan_bits);
721 EXPECT(std::isnan(v));
723 c->gatherStats(customMissingValue);
724 c->gatherStats(-2147483647);
727 EXPECT(
c->hasMissing());
733 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize));
740 EXPECT((posNext =
c->encode(ds.
get(), 0.0)) == (ds.
get() + 8));
742 EXPECT((posNext =
c->encode(ds.
get(), 123456789.0123456)) == (ds.
get() + 8));
744 EXPECT((posNext =
c->encode(ds.
get(), -9876543210.9876)) == (ds.
get() + 8));
746 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(&inf_bits))) == (ds.
get() + 8));
748 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(&neg_inf_bits))) == (ds.
get() + 8));
750 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(&sig_nan_bits))) == (ds.
get() + 8));
752 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(&quiet_nan_bits))) == (ds.
get() + 8));
754 EXPECT((posNext =
c->encode(ds.
get(), -2147483647)) == (ds.
get() + 8));
756 EXPECT((posNext =
c->encode(ds.
get(), customMissingValue)) == (ds.
get() + 8));
761 size_t data_size = (9 * 8);
762 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize + data_size));
771 EXPECT(::memcmp(&data[0], ds.
data(), expectedHdrSize + data_size) == 0);
776 CASE(
"short floating point values can include the missing data value") {
781 const uint64_t inf_bits = 0x7ff0000000000000;
782 const uint64_t neg_inf_bits = 0xfff0000000000000;
783 const uint32_t sig_nan_bits = 0xffffbf7f;
784 const uint32_t quiet_nan_bits = 0xffffff7f;
786 const size_t expectedHdrSize = 28;
787 double customMissingValue = -22222222222;
789 const char* expected_data[] = {
793 "\x00\x00\x00\x00\x00\x00\xf0\xff",
794 "\x00\x00\x00\x00\x00\x00\xf0\x7f",
795 "\x00\x00\x38\xce\x30\xb2\x14\xc2",
810 for (
int i = 0;
i < 4;
i++) {
812 bool bigEndianOutput = (
i % 2 == 0);
813 bool secondCodec = (
i > 1);
815 std::vector<unsigned char> data;
817 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
818 size_t len = (j == 0 || j > 3) ? 4 : 8;
819 data.insert(data.end(), expected_data[j], expected_data[j] + len);
821 std::reverse(data.end()-len, data.end());
826 uint32_t mv = secondCodec ? 0xff7fffff : 0x00800000;
827 data.insert(data.end(),
reinterpret_cast<const unsigned char*
>(&mv),
reinterpret_cast<const unsigned char*
>(&mv)+4);
829 std::reverse(data.end()-4, data.end());
833 std::unique_ptr<Codec>
c;
834 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
848 c->missingValue(customMissingValue);
849 EXPECT(!
c->hasMissing());
854 c->gatherStats(654321.123);
855 c->gatherStats(1.17549435082229e-38);
856 c->gatherStats(-3.40282346638529e+38);
857 double v = *
reinterpret_cast<const double*
>(&inf_bits);
858 EXPECT(std::isinf(v));
861 v = *
reinterpret_cast<const double*
>(&neg_inf_bits);
862 EXPECT(std::isinf(v));
865 v =
static_cast<double>(*
reinterpret_cast<const float*
>(&sig_nan_bits));
866 EXPECT(std::isnan(v));
868 v =
static_cast<double>(*
reinterpret_cast<const float*
>(&quiet_nan_bits));
869 EXPECT(std::isnan(v));
871 c->gatherStats(customMissingValue);
874 EXPECT(
c->hasMissing());
880 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize));
891 EXPECT((posNext =
c->encode(ds.
get(), 0.0)) == (ds.
get() + 4));
893 EXPECT((posNext =
c->encode(ds.
get(), 654321.123)) == (ds.
get() + 4));
896 size_t offsetMissing = 0;
898 EXPECT((posNext =
c->encode(ds.
get(), 1.17549435082229e-38)) == (ds.
get() + 4));
900 EXPECT_THROWS_AS(
c->encode(ds.
get(), -3.40282346638529e+38), eckit::AssertionFailed);
904 EXPECT_THROWS_AS(
c->encode(ds.
get(), 1.17549435082229e-38), eckit::AssertionFailed);
907 EXPECT((posNext =
c->encode(ds.
get(), -3.40282346638529e+38)) == (ds.
get() + 4));
911 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(&inf_bits))) == (ds.
get() + 4));
913 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(&neg_inf_bits))) == (ds.
get() + 4));
915 EXPECT((posNext =
c->encode(ds.
get(),
static_cast<double>(*
reinterpret_cast<const float*
>(&sig_nan_bits)))) == (ds.
get() + 4));
917 EXPECT((posNext =
c->encode(ds.
get(),
static_cast<double>(*
reinterpret_cast<const float*
>(&quiet_nan_bits)))) == (ds.
get() + 4));
919 EXPECT((posNext =
c->encode(ds.
get(), customMissingValue)) == (ds.
get() + 4));
924 size_t data_size = (9 * 4);
925 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize + data_size));
936 EXPECT(offsetMissing != 0);
937 EXPECT(::memcmp(&data[0], ds.
data(), offsetMissing) == 0);
938 EXPECT(::memcmp(&data[0] + offsetMissing + 4,
939 ds.
data() + offsetMissing + 4,
940 expectedHdrSize + data_size - offsetMissing - 4) == 0);
945 CASE(
"32bit integers are as-is") {
947 const size_t expectedHdrSize = 28;
949 const char* expected_data[] = {
953 "\x00\x00\x00\x00\x00\x00\xe0\xc1",
954 "\x00\x00\xc0\xff\xff\xff\xdf\x41",
955 "\x00\x00\x00\x1c\xaf\x7d\xaa\x41",
968 for (
int i = 0;
i < 2;
i++) {
970 bool bigEndianOutput = (
i == 1);
972 std::vector<unsigned char> data;
974 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
975 size_t len = (j == 0 || j > 3) ? 4 : 8;
976 data.insert(data.end(), expected_data[j], expected_data[j] + len);
978 std::reverse(data.end()-len, data.end());
983 std::unique_ptr<Codec>
c;
984 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
990 c->missingValue(222222222);
991 EXPECT(!
c->hasMissing());
997 c->gatherStats(2147483647);
998 c->gatherStats(-2147483648);
999 EXPECT(!
c->hasMissing());
1000 c->gatherStats(222222222);
1001 EXPECT(
c->hasMissing());
1002 c->gatherStats(-6543210);
1008 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize));
1015 EXPECT((posNext =
c->encode(ds.
get(), 0)) == (ds.
get() + 4));
1017 EXPECT((posNext =
c->encode(ds.
get(), -1)) == (ds.
get() + 4));
1019 EXPECT((posNext =
c->encode(ds.
get(), 2147483647)) == (ds.
get() + 4));
1021 EXPECT((posNext =
c->encode(ds.
get(), -2147483648)) == (ds.
get() + 4));
1023 EXPECT((posNext =
c->encode(ds.
get(), 222222222)) == (ds.
get() + 4));
1025 EXPECT((posNext =
c->encode(ds.
get(), -6543210)) == (ds.
get() + 4));
1030 size_t data_size = (6 * 4);
1031 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize + data_size));
1040 EXPECT(::memcmp(&data[0], ds.
data(), expectedHdrSize + data_size) == 0);
1045 CASE(
"16bit integers are stored with an offset. This need not (strictly) be integral!!") {
1051 const double customMissingValue = 6.54565456545599971850917315786e-123;
1052 const double baseVal = -123.45;
1053 const size_t expectedHdrSize = 28;
1055 const char* expected_data[] = {
1059 "\xcd\xcc\xcc\xcc\xcc\xdc\x5e\xc0",
1060 "\x9a\x99\x99\x99\x71\xf0\xef\x40",
1061 "\x04\x4f\xab\xa0\xe4\x4e\x91\x26",
1073 for (
int i = 0;
i < 4;
i++) {
1075 bool bigEndianOutput = (
i % 2 == 0);
1077 bool withMissing = (
i > 1);
1085 std::vector<unsigned char> data;
1087 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
1088 size_t len = (j == 0) ? 4 : (j > 3) ? 2 : 8;
1089 data.insert(data.end(), expected_data[j], expected_data[j] + len);
1090 if (bigEndianOutput)
1091 std::reverse(data.end()-len, data.end());
1097 uint16_t mv = withMissing ? 0xffff : 0x007b;
1098 data.insert(data.end(),
reinterpret_cast<const unsigned char*
>(&mv),
reinterpret_cast<const unsigned char*
>(&mv) + 2);
1099 if (bigEndianOutput)
1100 std::reverse(data.end()-2, data.end());
1104 std::unique_ptr<Codec>
c;
1105 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
1119 c->missingValue(customMissingValue);
1120 EXPECT(!
c->hasMissing());
1124 c->gatherStats(baseVal + 0.0);
1125 c->gatherStats(baseVal + 65535);
1126 c->gatherStats(baseVal + 32767);
1127 c->gatherStats(baseVal + 32768);
1128 c->gatherStats(baseVal + 12345);
1129 EXPECT(!
c->hasMissing());
1130 c->gatherStats(customMissingValue);
1131 EXPECT(
c->hasMissing());
1137 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize));
1148 EXPECT((posNext =
c->encode(ds.
get(), baseVal + 0.0)) == (ds.
get() + 2));
1151 EXPECT_THROWS_AS(
c->encode(ds.
get(), baseVal + 65535), eckit::AssertionFailed);
1152 EXPECT((posNext =
c->encode(ds.
get(), customMissingValue)) == (ds.
get() + 2));
1154 EXPECT((posNext =
c->encode(ds.
get(), baseVal + 65535)) == (ds.
get() + 2));
1157 EXPECT((posNext =
c->encode(ds.
get(), baseVal + 32767)) == (ds.
get() + 2));
1159 EXPECT((posNext =
c->encode(ds.
get(), baseVal + 32768)) == (ds.
get() + 2));
1161 EXPECT((posNext =
c->encode(ds.
get(), baseVal + 12345)) == (ds.
get() + 2));
1163 EXPECT((posNext =
c->encode(ds.
get(), customMissingValue)) == (ds.
get() + 2));
1168 size_t data_size = (6 * 2);
1169 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize + data_size));
1178 EXPECT(::memcmp(&data[0], ds.
data(), expectedHdrSize + data_size) == 0);
1183 CASE(
"8bit integers are stored with an offset. This need not (strictly) be integral!!") {
1189 const double customMissingValue = 6.54565456545599971850917315786e-123;
1190 const double baseVal = -5000.5;
1191 const size_t expectedHdrSize = 28;
1193 const char* expected_data[] = {
1197 "\x00\x00\x00\x00\x80\x88\xb3\xc0",
1198 "\x00\x00\x00\x00\x80\x89\xb2\xc0",
1199 "\x04\x4f\xab\xa0\xe4\x4e\x91\x26",
1204 for (
int i = 0;
i < 4;
i++) {
1206 bool bigEndianOutput = (
i % 2 == 0);
1208 bool withMissing = (
i > 1);
1216 std::vector<unsigned char> data;
1218 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
1219 size_t len = (j == 0) ? 4 : 8;
1220 data.insert(data.end(), expected_data[j], expected_data[j] + len);
1221 if (bigEndianOutput)
1222 std::reverse(data.end()-len, data.end());
1227 for (
int n = 0; n < 256; n++) {
1228 data.push_back(
static_cast<unsigned char>(n));
1234 data.push_back(withMissing ? 0xff : 0x88);
1238 std::unique_ptr<Codec>
c;
1239 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
1253 c->missingValue(customMissingValue);
1254 EXPECT(!
c->hasMissing());
1259 for (
size_t n = 0; n < 256; n++) {
1260 c->gatherStats(baseVal + n);
1262 EXPECT(!
c->hasMissing());
1263 c->gatherStats(customMissingValue);
1264 EXPECT(
c->hasMissing());
1270 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize));
1281 for (
size_t n = 0; n < 255; n++) {
1282 EXPECT((posNext =
c->encode(ds.
get(), baseVal + n)) == (ds.
get() + 1));
1287 EXPECT_THROWS_AS(
c->encode(ds.
get(), baseVal + 255), eckit::AssertionFailed);
1288 EXPECT((posNext =
c->encode(ds.
get(), customMissingValue)) == (ds.
get() + 1));
1290 EXPECT((posNext =
c->encode(ds.
get(), baseVal + 255)) == (ds.
get() + 1));
1294 EXPECT((posNext =
c->encode(ds.
get(), customMissingValue)) == (ds.
get() + 1));
1299 size_t data_size = (257 * 1);
1300 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize + data_size));
1309 EXPECT(::memcmp(&data[0], ds.
data(), expectedHdrSize + data_size) == 0);
1314 CASE(
"Character strings can be stored in a flat list, and indexed") {
1318 const size_t expectedHdrSize = 144;
1320 const char* expected_data[] = {
1324 "\x6f\x70\x71\x72\x73\x74\x75\x76",
1325 "\x00\x00\x00\x00\x00\x00\x00\x00",
1326 "\x00\x00\x00\x00\x00\x00\x00\x00",
1337 "\x02\x00\x00\x00",
"ab",
"\x00\x00\x00\x00",
"\x00\x00\x00\x00",
1338 "\x06\x00\x00\x00",
"ghijkl",
"\x00\x00\x00\x00",
"\x01\x00\x00\x00",
1339 "\x08\x00\x00\x00",
"mnopqrst",
"\x00\x00\x00\x00",
"\x02\x00\x00\x00",
1340 "\x08\x00\x00\x00",
"uvwxyzab",
"\x00\x00\x00\x00",
"\x03\x00\x00\x00",
1341 "\x08\x00\x00\x00",
"ghijklmn",
"\x00\x00\x00\x00",
"\x04\x00\x00\x00",
1342 "\x08\x00\x00\x00",
"opqrstuv",
"\x00\x00\x00\x00",
"\x05\x00\x00\x00",
1347 for (
int i = 0;
i < 4;
i++) {
1349 bool bigEndianOutput = (
i % 2 == 0);
1351 bool bits16 = (
i > 1);
1359 std::vector<unsigned char> data;
1361 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
1363 (j < 5) ? ((j == 0 || j == 4) ? 4 : 8)
1364 : ((j+2) % 4 == 0 ? ::strlen(expected_data[j]) : 4);
1365 data.insert(data.end(), expected_data[j], expected_data[j] + len);
1368 if (bigEndianOutput && !((j > 5) && ((j+2) % 4 == 0)))
1369 std::reverse(data.end()-len, data.end());
1374 for (
int n = 0; n < 6; n++) {
1375 if (bits16 && bigEndianOutput)
1377 data.push_back(
static_cast<unsigned char>(n));
1378 if (bits16 && !bigEndianOutput)
1384 std::unique_ptr<Codec>
c;
1385 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
1399 c->missingValue(0.0);
1400 EXPECT(!
c->hasMissing());
1404 const char* s1 =
"ab";
1405 const char* s2 =
"ghijkl";
1406 const char* s3 =
"mnopqrst";
1407 const char* s4 =
"uvwxyzabcdef";
1408 const char* s5 =
"ghijklmn";
1409 const char* s6 =
"opqrstuv";
1413 c->gatherStats(*
reinterpret_cast<const double*
>(s1));
1414 c->gatherStats(*
reinterpret_cast<const double*
>(s2));
1415 c->gatherStats(*
reinterpret_cast<const double*
>(s3));
1416 c->gatherStats(*
reinterpret_cast<const double*
>(s4));
1417 c->gatherStats(*
reinterpret_cast<const double*
>(s5));
1418 c->gatherStats(*
reinterpret_cast<const double*
>(s6));
1419 EXPECT(!
c->hasMissing());
1425 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize));
1432 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s1))) == (ds.
get() + (bits16 ? 2 : 1)));
1434 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s2))) == (ds.
get() + (bits16 ? 2 : 1)));
1436 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s3))) == (ds.
get() + (bits16 ? 2 : 1)));
1438 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s4))) == (ds.
get() + (bits16 ? 2 : 1)));
1440 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s5))) == (ds.
get() + (bits16 ? 2 : 1)));
1442 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s6))) == (ds.
get() + (bits16 ? 2 : 1)));
1447 size_t data_size = (6 * (bits16 ? 2 : 1));
1448 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize + data_size));
1457 EXPECT(::memcmp(&data[0], ds.
data(), expectedHdrSize + data_size) == 0);
1462 CASE(
"Character strings can be stored in a flat list, and indexed, and longer than 8 bytes") {
1466 const size_t expectedHdrSize = 156;
1468 const char* expected_data[] = {
1472 "\x6f\x70\x71\x72\x73\x74\x75\x76",
1473 "\x00\x00\x00\x00\x00\x00\x00\x00",
1474 "\x00\x00\x00\x00\x00\x00\x00\x00",
1485 "\x02\x00\x00\x00",
"ab",
"\x00\x00\x00\x00",
"\x00\x00\x00\x00",
1486 "\x06\x00\x00\x00",
"ghijkl",
"\x00\x00\x00\x00",
"\x01\x00\x00\x00",
1487 "\x08\x00\x00\x00",
"mnopqrst",
"\x00\x00\x00\x00",
"\x02\x00\x00\x00",
1488 "\x0c\x00\x00\x00",
"uvwxyzabcdef",
"\x00\x00\x00\x00",
"\x03\x00\x00\x00",
1489 "\x10\x00\x00\x00",
"ghijklmnopqrstuv",
"\x00\x00\x00\x00",
"\x04\x00\x00\x00",
1490 "\x08\x00\x00\x00",
"opqrstuv",
"\x00\x00\x00\x00",
"\x05\x00\x00\x00",
1495 for (
int i = 0;
i < 4;
i++) {
1497 bool bigEndianOutput = (
i % 2 == 0);
1499 bool bits16 = (
i > 1);
1507 std::vector<unsigned char> data;
1509 for (
size_t j = 0; j <
sizeof(expected_data) /
sizeof(
const char*); j++) {
1511 (j < 5) ? ((j == 0 || j == 4) ? 4 : 8)
1512 : ((j+2) % 4 == 0 ? ::strlen(expected_data[j]) : 4);
1513 data.insert(data.end(), expected_data[j], expected_data[j] + len);
1516 if (bigEndianOutput && !((j > 5) && ((j+2) % 4 == 0)))
1517 std::reverse(data.end()-len, data.end());
1522 for (
int n = 0; n < 6; n++) {
1523 if (bits16 && bigEndianOutput)
1525 data.push_back(
static_cast<unsigned char>(n));
1526 if (bits16 && !bigEndianOutput)
1532 std::unique_ptr<Codec>
c;
1533 if (bigEndianOutput == eckit::system::SystemInfo::isBigEndian()) {
1547 c->missingValue(0.0);
1548 EXPECT(!
c->hasMissing());
1551 c->dataSizeDoubles(2);
1555 const char* s1 =
"ab";
1556 const char* s2 =
"ghijkl";
1557 const char* s3 =
"mnopqrst";
1558 const char* s4 =
"uvwxyzabcdef";
1559 const char* s5 =
"ghijklmnopqrstuvwxyz";
1560 const char* s6 =
"opqrstuv";
1564 c->gatherStats(*
reinterpret_cast<const double*
>(s1));
1565 c->gatherStats(*
reinterpret_cast<const double*
>(s2));
1566 c->gatherStats(*
reinterpret_cast<const double*
>(s3));
1567 c->gatherStats(*
reinterpret_cast<const double*
>(s4));
1568 c->gatherStats(*
reinterpret_cast<const double*
>(s5));
1569 c->gatherStats(*
reinterpret_cast<const double*
>(s6));
1570 EXPECT(!
c->hasMissing());
1576 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize));
1583 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s1))) == (ds.
get() + (bits16 ? 2 : 1)));
1585 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s2))) == (ds.
get() + (bits16 ? 2 : 1)));
1587 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s3))) == (ds.
get() + (bits16 ? 2 : 1)));
1589 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s4))) == (ds.
get() + (bits16 ? 2 : 1)));
1591 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s5))) == (ds.
get() + (bits16 ? 2 : 1)));
1593 EXPECT((posNext =
c->encode(ds.
get(), *
reinterpret_cast<const double*
>(s6))) == (ds.
get() + (bits16 ? 2 : 1)));
1598 size_t data_size = (6 * (bits16 ? 2 : 1));
1599 EXPECT(ds.
position() == eckit::Offset(expectedHdrSize + data_size));
1608 EXPECT(::memcmp(&data[0], ds.
data(), expectedHdrSize + data_size) == 0);
1616 return run_tests(argc, argv);
EndianCodecSave(bool bigEndianData, Codec &codec)
eckit::Offset position() const
const char * data() const
static double integerMDI()
void save(GeneralDataStream &ds)
eckit::Offset position() const
int main(int argc, char *argv[])
CASE("Constant values consume no space in the output data buffer")
size_t prepend_codec_selection_header(std::vector< unsigned char > &data, const std::string &codec_name, bool bigEndian=false)