Program Listing for File integer.h
↰ Return to documentation for file (liberate/serialization/integer.h
)
/*
* This file is part of liberate.
*
* Author(s): Jens Finkhaeuser <jens@finkhaeuser.de>
*
* Copyright (c) 2020-2021 Jens Finkhaeuser.
* Copyright (c) 2022 Interpeer gUG (haftungsbeschränkt)
*
* SPDX-License-Identifier: GPL-3.0-only
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBERATE_SERIALIZATION_INTEGER_H
#define LIBERATE_SERIALIZATION_INTEGER_H
#ifndef __cplusplus
#error You are trying to include a C++ only header file
#endif
#include <liberate.h>
#include <cstddef>
#include <type_traits>
#include <liberate/types/type_traits.h>
namespace liberate::serialization {
template <typename T>
struct enable_integer_serialization
{};
template <typename T>
struct enable_integer_serialization<T const>
: enable_integer_serialization<T>
{};
template <typename T>
struct enable_integer_serialization<T volatile>
: enable_integer_serialization<T>
{};
template <typename T>
struct enable_integer_serialization<T const volatile>
: enable_integer_serialization<T>
{};
template <typename T>
using integer_serialization_enabled = typename enable_integer_serialization<T>::type;
template <> struct enable_integer_serialization<char> { using type = std::size_t; };
template <> struct enable_integer_serialization<signed char> { using type = std::size_t; };
template <> struct enable_integer_serialization<unsigned char> { using type = std::size_t; };
#if defined(LIBERATE_HAVE_WHCAR_T)
template <> struct enable_integer_serialization<wchar_t> { using type = std::size_t; };
#endif
#if defined(LIBERATE_HAVE_CHAR8_T)
template <> struct enable_integer_serialization<char8_t> { using type = std::size_t; };
#endif
template <> struct enable_integer_serialization<char16_t> { using type = std::size_t; };
template <> struct enable_integer_serialization<char32_t> { using type = std::size_t; };
template <> struct enable_integer_serialization<short> { using type = std::size_t; };
template <> struct enable_integer_serialization<unsigned short> { using type = std::size_t; };
template <> struct enable_integer_serialization<int> { using type = std::size_t; };
template <> struct enable_integer_serialization<unsigned int> { using type = std::size_t; };
template <> struct enable_integer_serialization<long> { using type = std::size_t; };
template <> struct enable_integer_serialization<unsigned long> { using type = std::size_t; };
template <> struct enable_integer_serialization<long long> { using type = std::size_t; };
template <> struct enable_integer_serialization<unsigned long long> { using type = std::size_t; };
namespace detail {
template <
typename outT,
typename inT
>
constexpr integer_serialization_enabled<inT>
serialize_int_impl(outT * output, std::size_t const & output_length, inT const & value)
{
if (!output || !output_length) {
return 0;
}
constexpr std::size_t const input_size = sizeof(inT);
constexpr std::size_t const out_unit_size = sizeof(outT);
if (input_size > out_unit_size * output_length) {
return 0;
}
std::size_t written = 0;
for (std::size_t i = 0 ; i < input_size / out_unit_size ; ++i) {
output[i] = static_cast<outT>(value >>
((input_size - ((i + 1) * out_unit_size)) * 8)
);
++written;
}
return written;
}
template <
typename outT,
typename inT
>
constexpr integer_serialization_enabled<outT>
deserialize_int_impl(outT & output, inT const * input, std::size_t input_length)
{
if (!input || !input_length) {
return 0;
}
constexpr std::size_t const output_size = sizeof(outT);
constexpr std::size_t const in_unit_size = sizeof(inT);
if (output_size > in_unit_size * input_length) {
return 0;
}
std::size_t read = 0;
output = outT{0};
using unsigned_inT = typename std::make_unsigned<inT>::type;
constexpr unsigned_inT const IN_MASK = ~unsigned_inT{0};
for (std::size_t i = output_size / in_unit_size ; i > 0 ; --i) {
output += (static_cast<outT>(input[i - 1]) & IN_MASK) << (output_size - (i * in_unit_size)) * 8;
++read; // flawfinder: ignore
}
return read; // flawfinder: ignore
}
} // namespace detail
template <
typename outT,
typename inT,
std::enable_if_t<liberate::types::is_8bit_type<outT>::value, int> = 0
>
constexpr integer_serialization_enabled<inT>
serialize_int(outT * output, std::size_t output_length, inT const & value)
{
return detail::serialize_int_impl(output, output_length, value);
}
template <
typename outT,
typename inT,
std::enable_if_t<liberate::types::is_8bit_type<inT>::value, int> = 0
>
constexpr integer_serialization_enabled<outT>
deserialize_int(outT & output, inT const * input, std::size_t const & input_length)
{
return detail::deserialize_int_impl(output, input, input_length);
}
} // namespace liberate::serialization
#endif // guard