/src/mysql-server/strings/int2str.cc
Line | Count | Source |
1 | | /* Copyright (c) 2000, 2025, Oracle and/or its affiliates. |
2 | | |
3 | | This program is free software; you can redistribute it and/or modify |
4 | | it under the terms of the GNU General Public License, version 2.0, |
5 | | as published by the Free Software Foundation. |
6 | | |
7 | | This program is designed to work with certain software (including |
8 | | but not limited to OpenSSL) that is licensed under separate terms, |
9 | | as designated in a particular file or component or in included license |
10 | | documentation. The authors of MySQL hereby grant you an additional |
11 | | permission to link the program and your derivative works with the |
12 | | separately licensed software that they have either included with |
13 | | the program or referenced in the documentation. |
14 | | |
15 | | Without limiting anything contained in the foregoing, this file, |
16 | | which is part of C Driver for MySQL (Connector/C), is also subject to the |
17 | | Universal FOSS Exception, version 1.0, a copy of which can be found at |
18 | | http://oss.oracle.com/licenses/universal-foss-exception. |
19 | | |
20 | | This program is distributed in the hope that it will be useful, |
21 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | | GNU General Public License, version 2.0, for more details. |
24 | | |
25 | | You should have received a copy of the GNU General Public License |
26 | | along with this program; if not, write to the Free Software |
27 | | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
28 | | |
29 | | #include "mysql/strings/int2str.h" |
30 | | |
31 | | #include <array> |
32 | | #include <cassert> |
33 | | #include <cstdint> |
34 | | #include <cstring> |
35 | | #include <iterator> |
36 | | |
37 | | #include "dig_vec.h" |
38 | | #include "integer_digits.h" |
39 | | |
40 | | /** |
41 | | Converts a 64-bit integer value to its character form and moves it to the |
42 | | destination buffer followed by a terminating NUL. If radix is -2..-36, val is |
43 | | taken to be SIGNED, if radix is 2..36, val is taken to be UNSIGNED. That is, |
44 | | val is signed if and only if radix is. All other radixes are treated as bad |
45 | | and nothing will be changed in this case. |
46 | | |
47 | | For conversion to decimal representation (radix is -10 or 10) one should use |
48 | | the optimized #longlong10_to_str() function instead. |
49 | | |
50 | | @param val the value to convert |
51 | | @param dst the buffer where the string representation should be stored |
52 | | @param radix radix of scale of notation |
53 | | @param upcase true if we should use upper-case digits |
54 | | |
55 | | @return pointer to the ending NUL character, or nullptr if radix is bad |
56 | | */ |
57 | 0 | char *ll2str(int64_t val, char *dst, int radix, bool upcase) { |
58 | 0 | char buffer[65]; |
59 | 0 | const char *const dig_vec = |
60 | 0 | upcase ? dig_vec_upper.data() : dig_vec_lower.data(); |
61 | 0 | auto uval = static_cast<uint64_t>(val); |
62 | |
|
63 | 0 | if (radix < 0) { |
64 | 0 | if (radix < -36 || radix > -2) return nullptr; |
65 | 0 | if (val < 0) { |
66 | 0 | *dst++ = '-'; |
67 | | /* Avoid integer overflow in (-val) for LLONG_MIN (BUG#31799). */ |
68 | 0 | uval = 0ULL - uval; |
69 | 0 | } |
70 | 0 | radix = -radix; |
71 | 0 | } else if (radix > 36 || radix < 2) { |
72 | 0 | return nullptr; |
73 | 0 | } |
74 | | |
75 | 0 | char *p = std::end(buffer); |
76 | 0 | do { |
77 | 0 | *--p = dig_vec[uval % radix]; |
78 | 0 | uval /= radix; |
79 | 0 | } while (uval != 0); |
80 | |
|
81 | 0 | const size_t length = std::end(buffer) - p; |
82 | 0 | memcpy(dst, p, length); |
83 | 0 | dst[length] = '\0'; |
84 | 0 | return dst + length; |
85 | 0 | } |
86 | | |
87 | | /** |
88 | | Converts a 64-bit integer to its string representation in decimal notation. |
89 | | |
90 | | It is optimized for the normal case of radix 10/-10. It takes only the sign of |
91 | | radix parameter into account and not its absolute value. |
92 | | |
93 | | @param val the value to convert |
94 | | @param dst the buffer where the string representation should be stored |
95 | | @param radix 10 if val is unsigned, -10 if val is signed |
96 | | |
97 | | @return pointer to the ending NUL character |
98 | | */ |
99 | 0 | char *longlong10_to_str(int64_t val, char *dst, int radix) { |
100 | 0 | assert(radix == 10 || radix == -10); |
101 | |
|
102 | 0 | auto uval = static_cast<uint64_t>(val); |
103 | |
|
104 | 0 | if (radix < 0) /* -10 */ |
105 | 0 | { |
106 | 0 | if (val < 0) { |
107 | 0 | *dst++ = '-'; |
108 | | /* Avoid integer overflow in (-val) for LLONG_MIN (BUG#31799). */ |
109 | 0 | uval = uint64_t{0} - uval; |
110 | 0 | } |
111 | 0 | } |
112 | |
|
113 | 0 | char *end = write_digits(uval, count_digits(uval), dst); |
114 | 0 | *end = '\0'; |
115 | 0 | return end; |
116 | 0 | } |