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:
62 throw InvalidInputBufferSize{buf.length, "for a floating point value type"};
63 }
64 }
65};
66
67template <typename T>
68struct FloatingPointBinaryFormatter {
69 static constexpr std::size_t size = sizeof(T);
70 T value;
71
72 explicit FloatingPointBinaryFormatter(T val) : value{val} {}
73
74 template <typename Buffer>
75 void operator()(const UserTypes& types, Buffer& buf) const {
76 using IntType = typename IntegralType<size>::type;
77 IntType int_value{};
78 std::memcpy(&int_value, &value, size);
79 IntegralBinaryFormatter<IntType>{int_value}(types, buf);
80 }
81};
82} // namespace detail
83
84//@{
85/** @name 4 byte floating point */
86template <>
88 explicit BufferParser(float& val) : FloatingPointBinaryParser(val) {}
89};
90template <>
93};
94//@}
95
96//@{
97/** @name 8 byte floating point */
98template <>
100 explicit BufferParser(double& val) : FloatingPointBinaryParser(val) {}
101};
102template <>
105};
106//@}
107
108//@{
109/** @name C++ to PostgreSQL mapping for floating point types */
110template <>
111struct CppToSystemPg<float> : PredefinedOid<PredefinedOids::kFloat4> {};
112template <>
113struct CppToSystemPg<double> : PredefinedOid<PredefinedOids::kFloat8> {};
114//@}
115
116} // namespace storages::postgres::io
117
118USERVER_NAMESPACE_END