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 using ValueType = typename BaseType::ValueType;
53
54 void operator()(const FieldBuffer& buf) {
55 switch (buf.length) {
56 case 4:
57 this->value = NumericCast<ValueType>(FloatingPointBySizeParser<4>::ParseBuffer(buf));
58 break;
59 case 8:
60 this->value = NumericCast<ValueType>(FloatingPointBySizeParser<8>::ParseBuffer(buf));
61 break;
62 default:
64 fmt::format("Buffer size {} is invalid for a floating point value type", buf.length)
65 };
66 }
67 }
68};
69
70template <typename T>
71struct FloatingPointBinaryFormatter {
72 static constexpr std::size_t size = sizeof(T);
73 T value;
74
75 explicit FloatingPointBinaryFormatter(T val)
76 : value{val}
77 {}
78
79 template <typename Buffer>
80 void operator()(const UserTypes& types, Buffer& buf) const {
81 using IntType = typename IntegralType<size>::type;
82 IntType int_value{};
83 std::memcpy(&int_value, &value, size);
84 IntegralBinaryFormatter<IntType>{int_value}(types, buf);
85 }
86};
87} // namespace detail
88
89//@{
90/** @name 4 byte floating point */
91template <>
92struct BufferParser<float> : detail::FloatingPointBinaryParser<float> {
93 explicit BufferParser(float& val)
94 : FloatingPointBinaryParser(val)
95 {}
96};
97template <>
98struct BufferFormatter<float> : detail::FloatingPointBinaryFormatter<float> {
99 explicit BufferFormatter(float val)
100 : FloatingPointBinaryFormatter(val)
101 {}
102};
103//@}
104
105//@{
106/** @name 8 byte floating point */
107template <>
108struct BufferParser<double> : detail::FloatingPointBinaryParser<double> {
109 explicit BufferParser(double& val)
110 : FloatingPointBinaryParser(val)
111 {}
112};
113template <>
114struct BufferFormatter<double> : detail::FloatingPointBinaryFormatter<double> {
115 explicit BufferFormatter(double val)
116 : FloatingPointBinaryFormatter(val)
117 {}
118};
119//@}
120
121//@{
122/** @name C++ to PostgreSQL mapping for floating point types */
123template <>
124struct CppToSystemPg<float> : PredefinedOid<PredefinedOids::kFloat4> {};
125template <>
126struct CppToSystemPg<double> : PredefinedOid<PredefinedOids::kFloat8> {};
127//@}
128
129} // namespace storages::postgres::io
130
131USERVER_NAMESPACE_END