Switch to standard C++ header filename convention

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2022-02-03 13:33:25 +01:00
parent 364ed2cfd4
commit 90de5d7140

View File

@ -1,288 +1,288 @@
/* /*
SPDX-License-Identifier: GPL-3.0-or-later SPDX-License-Identifier: GPL-3.0-or-later
Copyright © 2016-2022 Amebis Copyright © 2016-2022 Amebis
*/ */
#pragma once #pragma once
#include <ios> #include <ios>
#include <istream> #include <istream>
#include <ostream> #include <ostream>
namespace stdex { namespace stdex {
namespace idrec { namespace idrec {
/// ///
/// Reads record ID /// Reads record ID
/// ///
/// \param[in] stream Input stream /// \param[in] stream Input stream
/// \param[out] id Record ID /// \param[out] id Record ID
/// \param[in] end Position limit. Default is -1 (no limit). /// \param[in] end Position limit. Default is -1 (no limit).
/// ///
/// \returns /// \returns
/// - \c true when succeeded /// - \c true when succeeded
/// - \c false otherwise /// - \c false otherwise
/// ///
template <class T_ID> template <class T_ID>
inline _Success_(return) bool read_id(_In_ std::istream& stream, _Out_ T_ID &id, _In_opt_ std::streamoff end = (std::streamoff)-1) inline _Success_(return) bool read_id(_In_ std::istream& stream, _Out_ T_ID &id, _In_opt_ std::streamoff end = (std::streamoff)-1)
{ {
if (end == (std::streamoff)-1 || stream.tellg() < end) { if (end == (std::streamoff)-1 || stream.tellg() < end) {
stream.read((char*)&id, sizeof(id)); stream.read((char*)&id, sizeof(id));
return stream.good(); return stream.good();
} else } else
return false; return false;
} }
/// ///
/// Skips current record data /// Skips current record data
/// ///
/// \param[in] stream Input stream /// \param[in] stream Input stream
/// ///
/// \returns /// \returns
/// - \c true when successful /// - \c true when successful
/// - \c false otherwise /// - \c false otherwise
/// ///
template <class T_SIZE, unsigned int ALIGN> template <class T_SIZE, unsigned int ALIGN>
inline bool ignore(_In_ std::istream& stream) inline bool ignore(_In_ std::istream& stream)
{ {
// Read record size. // Read record size.
T_SIZE size; T_SIZE size;
stream.read((char*)&size, sizeof(size)); stream.read((char*)&size, sizeof(size));
if (!stream.good()) return false; if (!stream.good()) return false;
// Skip the record data. // Skip the record data.
size += (T_SIZE)(ALIGN - size) % ALIGN; size += (T_SIZE)(ALIGN - size) % ALIGN;
stream.ignore(size); stream.ignore(size);
if (!stream.good()) return false; if (!stream.good()) return false;
return true; return true;
} }
/// ///
/// Finds record data /// Finds record data
/// ///
/// \param[in] stream Input stream /// \param[in] stream Input stream
/// \param[in] id Record ID /// \param[in] id Record ID
/// \param[in] end Position limit. Default is -1 (no limit). /// \param[in] end Position limit. Default is -1 (no limit).
/// ///
/// \returns /// \returns
/// - \c true when found /// - \c true when found
/// - \c false otherwise /// - \c false otherwise
/// ///
template <class T_ID, class T_SIZE, unsigned int ALIGN> template <class T_ID, class T_SIZE, unsigned int ALIGN>
inline bool find(_In_ std::istream& stream, _In_ T_ID id, _In_opt_ std::streamoff end = (std::streamoff)-1) inline bool find(_In_ std::istream& stream, _In_ T_ID id, _In_opt_ std::streamoff end = (std::streamoff)-1)
{ {
T_ID _id; T_ID _id;
while (end == (std::streamoff)-1 || stream.tellg() < end) { while (end == (std::streamoff)-1 || stream.tellg() < end) {
stream.read((char*)&_id, sizeof(_id)); stream.read((char*)&_id, sizeof(_id));
if (!stream.good()) return false; if (!stream.good()) return false;
if (_id == id) { if (_id == id) {
// The record was found. // The record was found.
return true; return true;
} else } else
ignore<T_SIZE, ALIGN>(stream); ignore<T_SIZE, ALIGN>(stream);
} }
return false; return false;
} }
/// ///
/// Writes record header /// Writes record header
/// ///
/// \param[in] stream Output stream /// \param[in] stream Output stream
/// \param[in] id Record ID /// \param[in] id Record ID
/// ///
/// \returns Position of the record header start in \p stream. Save for later \c close call. /// \returns Position of the record header start in \p stream. Save for later \c close call.
/// ///
template <class T_ID, class T_SIZE> template <class T_ID, class T_SIZE>
inline std::streamoff open(_In_ std::ostream& stream, _In_ T_ID id) inline std::streamoff open(_In_ std::ostream& stream, _In_ T_ID id)
{ {
std::streamoff start = stream.tellp(); std::streamoff start = stream.tellp();
// Write ID. // Write ID.
if (stream.fail()) return (std::streamoff)-1; if (stream.fail()) return (std::streamoff)-1;
stream.write((const char*)&id, sizeof(id)); stream.write((const char*)&id, sizeof(id));
// Write 0 as a placeholder for data size. // Write 0 as a placeholder for data size.
if (stream.fail()) return (std::streamoff)-1; if (stream.fail()) return (std::streamoff)-1;
T_SIZE size = 0; T_SIZE size = 0;
stream.write((const char*)&size, sizeof(size)); stream.write((const char*)&size, sizeof(size));
return start; return start;
} }
/// ///
/// Updates record header /// Updates record header
/// ///
/// \param[in] stream Output stream /// \param[in] stream Output stream
/// \param[in] start Start position of the record in \p stream /// \param[in] start Start position of the record in \p stream
/// ///
/// \returns Position of the record end in \p stream /// \returns Position of the record end in \p stream
/// ///
template <class T_ID, class T_SIZE, unsigned int ALIGN> template <class T_ID, class T_SIZE, unsigned int ALIGN>
inline std::streamoff close(_In_ std::ostream& stream, _In_ std::streamoff start) inline std::streamoff close(_In_ std::ostream& stream, _In_ std::streamoff start)
{ {
std::streamoff end = stream.tellp(); std::streamoff end = stream.tellp();
T_SIZE T_SIZE
size = (T_SIZE)(end - start - sizeof(T_ID) - sizeof(T_SIZE)), size = (T_SIZE)(end - start - sizeof(T_ID) - sizeof(T_SIZE)),
remainder = (T_SIZE)(ALIGN - size) % ALIGN; // Number of bytes we need to add, to keep the data integral number of ALIGN blocks long remainder = (T_SIZE)(ALIGN - size) % ALIGN; // Number of bytes we need to add, to keep the data integral number of ALIGN blocks long
if (remainder) { if (remainder) {
// Append padding. // Append padding.
static const char padding[ALIGN] = {}; static const char padding[ALIGN] = {};
stream.write(padding, remainder); stream.write(padding, remainder);
end += remainder; end += remainder;
} }
// Update the data size. // Update the data size.
if (stream.fail()) return (std::streamoff)-1; if (stream.fail()) return (std::streamoff)-1;
stream.seekp(start + sizeof(T_ID)); stream.seekp(start + sizeof(T_ID));
stream.write((const char*)&size, sizeof(size)); stream.write((const char*)&size, sizeof(size));
stream.seekp(end); stream.seekp(end);
return end; return end;
} }
/// ///
/// Helper class for read/write of records to/from memory /// Helper class for read/write of records to/from memory
/// ///
template <class T, class T_ID, class T_SIZE, unsigned int ALIGN> template <class T, class T_ID, class T_SIZE, unsigned int ALIGN>
class record class record
{ {
public: public:
/// ///
/// Constructs the class /// Constructs the class
/// ///
/// \param[in] d Reference to record data /// \param[in] d Reference to record data
/// ///
inline record(_In_ T &d) : data(d) {} inline record(_In_ T &d) : data(d) {}
/// ///
/// Constructs the class /// Constructs the class
/// ///
/// \param[in] d Reference to record data /// \param[in] d Reference to record data
/// ///
inline record(_In_ const T &d) : data((T&)d) {} inline record(_In_ const T &d) : data((T&)d) {}
/// ///
/// Assignment operator /// Assignment operator
/// ///
/// \param[in] r Source record /// \param[in] r Source record
/// ///
/// \returns A const reference to this struct /// \returns A const reference to this struct
/// ///
inline const record<T, T_ID, T_SIZE, ALIGN>& operator =(_In_ const record<T, T_ID, T_SIZE, ALIGN> &r) inline const record<T, T_ID, T_SIZE, ALIGN>& operator =(_In_ const record<T, T_ID, T_SIZE, ALIGN> &r)
{ {
data = r.data; data = r.data;
return *this; return *this;
} }
/// ///
/// Writes record header /// Writes record header
/// ///
/// \param[in] stream Output stream /// \param[in] stream Output stream
/// ///
/// \returns Position of the record header start in \p stream. Save for later \c close call. /// \returns Position of the record header start in \p stream. Save for later \c close call.
/// ///
static inline std::streamoff open(_In_ std::ostream& stream) static inline std::streamoff open(_In_ std::ostream& stream)
{ {
return stdex::idrec::open<T_ID, T_SIZE>(stream, id); return stdex::idrec::open<T_ID, T_SIZE>(stream, id);
} }
/// ///
/// Updates record header /// Updates record header
/// ///
/// \param[in] stream Output stream /// \param[in] stream Output stream
/// \param[in] start Start position of the record in \p stream /// \param[in] start Start position of the record in \p stream
/// ///
/// \returns Position of the record end in \p stream /// \returns Position of the record end in \p stream
/// ///
static inline std::streamoff close(_In_ std::ostream& stream, _In_ std::streamoff start) static inline std::streamoff close(_In_ std::ostream& stream, _In_ std::streamoff start)
{ {
return stdex::idrec::close<T_ID, T_SIZE, ALIGN>(stream, start); return stdex::idrec::close<T_ID, T_SIZE, ALIGN>(stream, start);
} }
/// ///
/// Finds record data /// Finds record data
/// ///
/// \param[in] stream Input stream /// \param[in] stream Input stream
/// \param[in] end Position limit. Default is -1 (no limit). /// \param[in] end Position limit. Default is -1 (no limit).
/// ///
/// \returns /// \returns
/// - \c true when found /// - \c true when found
/// - \c false otherwise /// - \c false otherwise
/// ///
static inline bool find(_In_ std::istream& stream, _In_opt_ std::streamoff end = (std::streamoff)-1) static inline bool find(_In_ std::istream& stream, _In_opt_ std::streamoff end = (std::streamoff)-1)
{ {
return stdex::idrec::find<T_ID, T_SIZE, ALIGN>(stream, id, end); return stdex::idrec::find<T_ID, T_SIZE, ALIGN>(stream, id, end);
} }
static const T_ID id; ///< Record id static const T_ID id; ///< Record id
T &data; ///< Record data reference T &data; ///< Record data reference
}; };
}; };
}; };
/// ///
/// Writes record to a stream /// Writes record to a stream
/// ///
/// \param[in] stream Output stream /// \param[in] stream Output stream
/// \param[in] r Record /// \param[in] r Record
/// ///
/// \returns The stream \p stream /// \returns The stream \p stream
/// ///
template <class T, class T_ID, class T_SIZE, unsigned int ALIGN> template <class T, class T_ID, class T_SIZE, unsigned int ALIGN>
inline std::ostream& operator <<(_In_ std::ostream& stream, _In_ const stdex::idrec::record<T, T_ID, T_SIZE, ALIGN> r) inline std::ostream& operator <<(_In_ std::ostream& stream, _In_ const stdex::idrec::record<T, T_ID, T_SIZE, ALIGN> r)
{ {
// Parameter r does not need to be passed by reference. It has only one field (data), which is a reference itself already. The id field is static anyway. // Parameter r does not need to be passed by reference. It has only one field (data), which is a reference itself already. The id field is static anyway.
std::streamoff start = r.open(stream); std::streamoff start = r.open(stream);
if (stream.fail()) return stream; if (stream.fail()) return stream;
stream << r.data; stream << r.data;
r.close(stream, start); r.close(stream, start);
return stream; return stream;
} }
/// ///
/// Reads record from a stream /// Reads record from a stream
/// ///
/// \param[in] stream Input stream /// \param[in] stream Input stream
/// \param[out] r Record /// \param[out] r Record
/// ///
/// \returns The stream \p stream /// \returns The stream \p stream
/// ///
template <class T, class T_ID, class T_SIZE, unsigned int ALIGN> template <class T, class T_ID, class T_SIZE, unsigned int ALIGN>
inline std::istream& operator >>(_In_ std::istream& stream, _In_ stdex::idrec::record<T, T_ID, T_SIZE, ALIGN> r) inline std::istream& operator >>(_In_ std::istream& stream, _In_ stdex::idrec::record<T, T_ID, T_SIZE, ALIGN> r)
{ {
// Parameter r does not need to be passed by reference. It has only one field (data), which is a reference itself already. The id field is static anyway. // Parameter r does not need to be passed by reference. It has only one field (data), which is a reference itself already. The id field is static anyway.
// Read data size. // Read data size.
T_SIZE size; T_SIZE size;
stream.read((char*)&size, sizeof(size)); stream.read((char*)&size, sizeof(size));
if (!stream.good()) return stream; if (!stream.good()) return stream;
// Read data. // Read data.
std::streamoff start = stream.tellg(); std::streamoff start = stream.tellg();
stream >> r.data; // TODO: operator >> should not read past the record data! Make a size limited stream and read from it instead. stream >> r.data; // TODO: operator >> should not read past the record data! Make a size limited stream and read from it instead.
size += (T_SIZE)(ALIGN - size) % ALIGN; size += (T_SIZE)(ALIGN - size) % ALIGN;
stream.seekg(start + size); stream.seekg(start + size);
return stream; return stream;
} }