userver: userver/storages/postgres/io/floating_point_types.hpp Source File
Loading...
Searching...
No Matches
floating_point_types.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/io/floating_point_types.hpp
4/// @brief Floating point I/O support
5/// @ingroup userver_postgres_parse_and_format
6
7#include <cstring>
8
9#include <boost/endian/arithmetic.hpp>
10#include <userver/storages/postgres/io/buffer_io_base.hpp>
11#include <userver/storages/postgres/io/integral_types.hpp>
12#include <userver/storages/postgres/io/traits.hpp>
13#include <userver/storages/postgres/io/type_mapping.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace storages::postgres::io {
18
19namespace detail {
20
21template <std::size_t>
22struct FloatingPointType;
23
24template <>
25struct FloatingPointType<4> {
26 using type = float;
27};
28
29template <>
30struct FloatingPointType<8> {
31 using type = double;
32};
33
34template <std::size_t Size>
35struct FloatingPointBySizeParser {
36 using FloatType = typename FloatingPointType<Size>::type;
37 using IntType = typename IntegralType<Size>::type;
38 using IntParser = IntegralBySizeParser<Size>;
39
40 static FloatType ParseBuffer(const FieldBuffer& buf) {
41 const IntType tmp = IntParser::ParseBuffer(buf);
42 FloatType float_value{};
43 std::memcpy(&float_value, &tmp, Size);
44 return float_value;
45 }
46};
47
48template <typename T>
49struct FloatingPointBinaryParser : BufferParserBase<T> {
50 using BaseType = BufferParserBase<T>;
51 using BaseType::BaseType;
52
53 void operator()(const FieldBuffer& buf) {
54 switch (buf.length) {
55 case 4:
56 this->value = FloatingPointBySizeParser<4>::ParseBuffer(buf);
57 break;
58 case 8:
59 this->value = FloatingPointBySizeParser<8>::ParseBuffer(buf);
60 break;
61 default:
63 fmt::format("Buffer size {} is invalid for a floating point value type", buf.length)};
64 }
65 }
66};
67
68template <typename T>
69struct FloatingPointBinaryFormatter {
70 static constexpr std::size_t size = sizeof(T);
71 T value;
72
73 explicit FloatingPointBinaryFormatter(T val) : value{val} {}
74
75 template <typename Buffer>
76 void operator()(const UserTypes& types, Buffer& buf) const {
77 using IntType = typename IntegralType<size>::type;
78 IntType int_value{};
79 std::memcpy(&int_value, &value, size);
80 IntegralBinaryFormatter<IntType>{int_value}(types, buf);
81 }
82};
83} // namespace detail
84
85//@{
86/** @name 4 byte floating point */
87template <>
88struct BufferParser<float> : detail::FloatingPointBinaryParser<float> {
89 explicit BufferParser(float& val) : FloatingPointBinaryParser(val) {}
90};
91template <>
92struct BufferFormatter<float> : detail::FloatingPointBinaryFormatter<float> {
93 explicit BufferFormatter(float val) : FloatingPointBinaryFormatter(val) {}
94};
95//@}
96
97//@{
98/** @name 8 byte floating point */
99template <>
100struct BufferParser<double> : detail::FloatingPointBinaryParser<double> {
101 explicit BufferParser(double& val) : FloatingPointBinaryParser(val) {}
102};
103template <>
104struct BufferFormatter<double> : detail::FloatingPointBinaryFormatter<double> {
105 explicit BufferFormatter(double val) : FloatingPointBinaryFormatter(val) {}
106};
107//@}
108
109//@{
110/** @name C++ to PostgreSQL mapping for floating point types */
111template <>
112struct CppToSystemPg<float> : PredefinedOid<PredefinedOids::kFloat4> {};
113template <>
114struct CppToSystemPg<double> : PredefinedOid<PredefinedOids::kFloat8> {};
115//@}
116
117} // namespace storages::postgres::io
118
119USERVER_NAMESPACE_END