diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:07:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:07:14 +0000 |
commit | a175314c3e5827eb193872241446f2f8f5c9d33c (patch) | |
tree | cd3d60ca99ae00829c52a6ca79150a5b6e62528b /sql/sql_type_int.h | |
parent | Initial commit. (diff) | |
download | mariadb-10.5-9e4947182e0b875da38088fdd168e775f473b8ad.tar.xz mariadb-10.5-9e4947182e0b875da38088fdd168e775f473b8ad.zip |
Adding upstream version 1:10.5.12.upstream/1%10.5.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sql/sql_type_int.h')
-rw-r--r-- | sql/sql_type_int.h | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/sql/sql_type_int.h b/sql/sql_type_int.h new file mode 100644 index 00000000..fca00f25 --- /dev/null +++ b/sql/sql_type_int.h @@ -0,0 +1,204 @@ +/* Copyright (c) 2018, 2021, MariaDB + + 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; version 2 of the License. + + 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, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef SQL_TYPE_INT_INCLUDED +#define SQL_TYPE_INT_INCLUDED + +#include "my_bit.h" // my_count_bits() + + +class Null_flag +{ +protected: + bool m_is_null; +public: + bool is_null() const { return m_is_null; } + Null_flag(bool is_null) :m_is_null(is_null) { } +}; + + +class Longlong +{ +protected: + longlong m_value; +public: + longlong value() const { return m_value; } + Longlong(longlong nr) :m_value(nr) { } +}; + + +class Longlong_null: public Longlong, public Null_flag +{ +public: + Longlong_null(longlong nr, bool is_null) + :Longlong(nr), Null_flag(is_null) + { } + explicit Longlong_null() + :Longlong(0), Null_flag(true) + { } + explicit Longlong_null(longlong nr) + :Longlong(nr), Null_flag(false) + { } + Longlong_null operator|(const Longlong_null &other) const + { + if (is_null() || other.is_null()) + return Longlong_null(); + return Longlong_null(value() | other.value()); + } + Longlong_null operator&(const Longlong_null &other) const + { + if (is_null() || other.is_null()) + return Longlong_null(); + return Longlong_null(value() & other.value()); + } + Longlong_null operator^(const Longlong_null &other) const + { + if (is_null() || other.is_null()) + return Longlong_null(); + return Longlong_null((longlong) (value() ^ other.value())); + } + Longlong_null operator~() const + { + if (is_null()) + return *this; + return Longlong_null((longlong) ~ (ulonglong) value()); + } + Longlong_null operator<<(const Longlong_null &llshift) const + { + if (is_null() || llshift.is_null()) + return Longlong_null(); + uint shift= (uint) llshift.value(); + ulonglong res= (shift < sizeof(longlong) * 8) + ? ((ulonglong) value()) << shift + : 0; + return Longlong_null((longlong) res); + } + Longlong_null operator>>(const Longlong_null &llshift) const + { + if (is_null() || llshift.is_null()) + return Longlong_null(); + uint shift= (uint) llshift.value(); + ulonglong res= (shift < sizeof(longlong) * 8) + ? ((ulonglong) value()) >> shift + : 0; + return Longlong_null((longlong) res); + } + Longlong_null bit_count() const + { + if (is_null()) + return *this; + return Longlong_null((longlong) my_count_bits((ulonglong) value())); + } +}; + + +// A longlong/ulonglong hybrid. Good to store results of val_int(). +class Longlong_hybrid: public Longlong +{ +protected: + bool m_unsigned; + int cmp_signed(const Longlong_hybrid& other) const + { + return m_value < other.m_value ? -1 : m_value == other.m_value ? 0 : 1; + } + int cmp_unsigned(const Longlong_hybrid& other) const + { + return (ulonglong) m_value < (ulonglong) other.m_value ? -1 : + m_value == other.m_value ? 0 : 1; + } +public: + Longlong_hybrid(longlong nr, bool unsigned_flag) + :Longlong(nr), m_unsigned(unsigned_flag) + { } + bool is_unsigned() const { return m_unsigned; } + bool is_unsigned_outside_of_signed_range() const + { + return m_unsigned && ((ulonglong) m_value) > (ulonglong) LONGLONG_MAX; + } + bool neg() const { return m_value < 0 && !m_unsigned; } + ulonglong abs() const + { + if (m_unsigned) + return (ulonglong) m_value; + if (m_value == LONGLONG_MIN) // avoid undefined behavior + return ((ulonglong) LONGLONG_MAX) + 1; + return m_value < 0 ? -m_value : m_value; + } + /* + Convert to an unsigned number: + - Negative numbers are converted to 0. + - Positive numbers bigger than upper_bound are converted to upper_bound. + - Other numbers are returned as is. + */ + ulonglong to_ulonglong(ulonglong upper_bound) const + { + return neg() ? 0 : + (ulonglong) m_value > upper_bound ? upper_bound : + (ulonglong) m_value; + } + uint to_uint(uint upper_bound) const + { + return (uint) to_ulonglong(upper_bound); + } + int cmp(const Longlong_hybrid& other) const + { + if (m_unsigned == other.m_unsigned) + return m_unsigned ? cmp_unsigned(other) : cmp_signed(other); + if (is_unsigned_outside_of_signed_range()) + return 1; + if (other.is_unsigned_outside_of_signed_range()) + return -1; + /* + The unsigned argument is in the range 0..LONGLONG_MAX. + The signed argument is in the range LONGLONG_MIN..LONGLONG_MAX. + Safe to compare as signed. + */ + return cmp_signed(other); + } + bool operator==(const Longlong_hybrid &nr) const + { + return cmp(nr) == 0; + } + bool operator==(ulonglong nr) const + { + return cmp(Longlong_hybrid((longlong) nr, true)) == 0; + } + bool operator==(uint nr) const + { + return cmp(Longlong_hybrid((longlong) nr, true)) == 0; + } + bool operator==(longlong nr) const + { + return cmp(Longlong_hybrid(nr, false)) == 0; + } + bool operator==(int nr) const + { + return cmp(Longlong_hybrid(nr, false)) == 0; + } +}; + + +class Longlong_hybrid_null: public Longlong_hybrid, + public Null_flag +{ +public: + Longlong_hybrid_null(const Longlong_null &nr, bool unsigned_flag) + :Longlong_hybrid(nr.value(), unsigned_flag), + Null_flag(nr.is_null()) + { } +}; + + +#endif // SQL_TYPE_INT_INCLUDED |