13 #include "eckit/io/DataHandle.h"
14 #include "eckit/io/Buffer.h"
15 #include "eckit/types/FixedString.h"
16 #include "eckit/utils/MD5.h"
23 using namespace eckit;
41 eckit::FixedString<5> magic;
43 long bytesRead = dh.read(&magic,
sizeof(magic));
44 if (bytesRead == 0)
return false;
45 if (bytesRead !=
sizeof(magic))
throw ODBIncomplete(dh.title(), Here());
46 if (magic !=
"\xff\xffODA")
throw ODBInvalid(dh.title(),
"Incorrect MAGIC", Here());
50 template <
typename ByteOrder>
55 constexpr
size_t basic_header_size = 12 + 32 + 4;
56 char basicBuffer[basic_header_size];
58 if (dh.read(basicBuffer,
sizeof(basicBuffer)) !=
sizeof(basicBuffer))
throw ODBIncomplete(dh.title(), Here());
62 int32_t formatVersionMajor;
63 ds1.
read(formatVersionMajor);
66 int32_t formatVersionMinor;
67 ds1.
read(formatVersionMinor);
68 ASSERT(
"File format version not supported" && formatVersionMinor <= FORMAT_VERSION_NUMBER_MINOR && formatVersionMinor > 3);
70 std::string headerDigest;
71 ds1.
read(headerDigest);
78 eckit::Buffer buffer(headerSize);
79 if (dh.read(buffer, headerSize) != headerSize)
throw ODBIncomplete(dh.title(), Here());
84 md5.add(buffer.data(), buffer.size());
85 std::string actualHeaderDigest = md5.digest();
86 if (headerDigest != actualHeaderDigest)
throw ODBInvalid(dh.title(),
"Header digest incorrect", Here());
91 int64_t nextFrameOffset;
92 ds2.
read(nextFrameOffset);
97 int64_t prevFrameOffset;
98 ds2.
read(prevFrameOffset);
99 ASSERT(prevFrameOffset == 0);
103 int64_t numberOfRows;
104 ds2.
read(numberOfRows);
108 eckit::Log::debug() <<
"Header::load: numberOfRows = " << numberOfRows << std::endl;
126 load<OtherByteOrder>(dh);
128 load<SameByteOrder>(dh);
135 template <
typename ByteOrder>
141 constexpr
size_t initial_header_size = 9 + 8 + 4 + 32 + 4;
144 bool serialised =
false;
145 char* variableHeaderStart = 0;
146 int32_t variableHeaderSize;
148 while (!serialised) {
150 variableHeaderStart = buffer + initial_header_size;
153 ds.
write(
static_cast<int64_t
>(dataSize));
154 ds.
write(
static_cast<int64_t
>(0));
155 ds.
write(
static_cast<int64_t
>(rowsNumber));
160 ds.
write(properties);
168 buffer = eckit::Buffer(buffer.size() * 2);
175 md5.add(variableHeaderStart, variableHeaderSize);
176 std::string headerDigest = md5.digest();
193 ds.
write(headerDigest);
195 ds.
write(
static_cast<int32_t
>(variableHeaderSize));
197 ASSERT(ds.
position() == eckit::Offset(initial_header_size));
199 return std::make_pair(std::move(buffer), variableHeaderSize + ds.
position());
static ODBAPISettings & instance()
eckit::Offset position() const
void write(const T &elem)
std::map< std::string, std::string > Properties
const int32_t FORMAT_VERSION_NUMBER_MAJOR
const uint16_t ODA_MAGIC_NUMBER
const int32_t BYTE_ORDER_INDICATOR
std::vector< double > Flags
const int32_t FORMAT_VERSION_NUMBER_MINOR