• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 16247597625

13 Jul 2025 09:19AM UTC coverage: 90.574% (-0.001%) from 90.575%
16247597625

push

github

web-flow
Merge pull request #4974 from randombit/jack/fix-clang-tidy-modernize-loop-convert

Enable and fix clang-tidy warning modernize-loop-convert

99094 of 109407 relevant lines covered (90.57%)

12407263.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.51
/src/lib/math/bigint/big_code.cpp
1
/*
2
* BigInt Encoding/Decoding
3
* (C) 1999-2010,2012,2019,2021 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/bigint.h>
9

10
#include <botan/hex.h>
11
#include <botan/mem_ops.h>
12
#include <botan/internal/divide.h>
13
#include <botan/internal/stl_util.h>
14

15
namespace Botan {
16

17
namespace {
18

19
consteval word decimal_conversion_radix() {
20
   if constexpr(sizeof(word) == 8) {
21
      return 10000000000000000000U;
22
   } else {
23
      return 1000000000U;
24
   }
25
}
26

27
consteval size_t decimal_conversion_radix_digits() {
28
   if constexpr(sizeof(word) == 8) {
29
      return 19;
30
   } else {
31
      return 9;
32
   }
33
}
34

35
}  // namespace
36

37
std::string BigInt::to_dec_string() const {
57✔
38
   // Use the largest power of 10 that fits in a word
39
   constexpr word conversion_radix = decimal_conversion_radix();
57✔
40
   constexpr size_t radix_digits = decimal_conversion_radix_digits();
57✔
41

42
   // (over-)estimate of the number of digits needed; log2(10) ~ 3.3219
43
   const size_t digit_estimate = static_cast<size_t>(1 + (static_cast<double>(this->bits()) / 3.32));
57✔
44

45
   // (over-)estimate of db such that conversion_radix^db > *this
46
   const size_t digit_blocks = (digit_estimate + radix_digits - 1) / radix_digits;
57✔
47

48
   BigInt value = *this;
57✔
49
   value.set_sign(Positive);
57✔
50

51
   // Extract groups of digits into words
52
   std::vector<word> digit_groups(digit_blocks);
57✔
53

54
   for(size_t i = 0; i != digit_blocks; ++i) {
125✔
55
      word remainder = 0;
68✔
56
      ct_divide_word(value, conversion_radix, value, remainder);
68✔
57
      digit_groups[i] = remainder;
68✔
58
   }
59

60
   BOTAN_ASSERT_NOMSG(value.is_zero());
114✔
61

62
   // Extract digits from the groups
63
   std::vector<uint8_t> digits(digit_blocks * radix_digits);
57✔
64

65
   for(size_t i = 0; i != digit_blocks; ++i) {
125✔
66
      word remainder = digit_groups[i];
68✔
67
      for(size_t j = 0; j != radix_digits; ++j) {
1,360✔
68
         // Compiler should convert div/mod by 10 into mul by magic constant
69
         const word digit = remainder % 10;
1,292✔
70
         remainder /= 10;
1,292✔
71
         digits[radix_digits * i + j] = static_cast<uint8_t>(digit);
1,292✔
72
      }
73
   }
74

75
   // remove leading zeros
76
   while(!digits.empty() && digits.back() == 0) {
926✔
77
      digits.pop_back();
869✔
78
   }
79

80
   BOTAN_ASSERT_NOMSG(digit_estimate >= digits.size());
57✔
81

82
   // Reverse the digits to big-endian and format to text
83
   std::string s;
57✔
84
   s.reserve(1 + digits.size());
57✔
85

86
   if(is_negative()) {
57✔
87
      s += "-";
5✔
88
   }
89

90
   // Reverse and convert to textual digits
91
   // TODO(Botan4) use std::ranges::reverse_view here once available (need newer Clang)
92
   // NOLINTNEXTLINE(modernize-loop-convert)
93
   for(auto i = digits.rbegin(); i != digits.rend(); ++i) {
480✔
94
      s.push_back(*i + '0');  // assumes ASCII
423✔
95
   }
96

97
   if(s.empty()) {
57✔
98
      s += "0";
6✔
99
   }
100

101
   return s;
114✔
102
}
114✔
103

104
std::string BigInt::to_hex_string() const {
84✔
105
   const size_t this_bytes = this->bytes();
84✔
106
   std::vector<uint8_t> bits(std::max<size_t>(1, this_bytes));
141✔
107

108
   if(this_bytes > 0) {
84✔
109
      this->serialize_to(bits);
82✔
110
   }
111

112
   std::string hrep;
84✔
113
   if(is_negative()) {
84✔
114
      hrep += "-";
5✔
115
   }
116
   hrep += "0x";
84✔
117
   hrep += hex_encode(bits);
168✔
118
   return hrep;
84✔
119
}
84✔
120

121
/*
122
* Encode two BigInt, with leading 0s if needed, and concatenate
123
*/
124
secure_vector<uint8_t> BigInt::encode_fixed_length_int_pair(const BigInt& n1, const BigInt& n2, size_t bytes) {
97✔
125
   if(n1.is_negative() || n2.is_negative()) {
97✔
126
      throw Encoding_Error("encode_fixed_length_int_pair: values must be positive");
×
127
   }
128
   if(n1.bytes() > bytes || n2.bytes() > bytes) {
97✔
129
      throw Encoding_Error("encode_fixed_length_int_pair: values too large to encode properly");
×
130
   }
131
   secure_vector<uint8_t> output(2 * bytes);
97✔
132
   BufferStuffer stuffer(output);
97✔
133
   n1.serialize_to(stuffer.next(bytes));
97✔
134
   n2.serialize_to(stuffer.next(bytes));
97✔
135
   return output;
97✔
136
}
×
137

138
BigInt BigInt::decode(std::span<const uint8_t> buf, Base base) {
×
139
   if(base == Binary) {
×
140
      return BigInt::from_bytes(buf);
×
141
   }
142
   return BigInt::decode(buf.data(), buf.size(), base);
×
143
}
144

145
/*
146
* Decode a BigInt
147
*/
148
BigInt BigInt::decode(const uint8_t buf[], size_t length, Base base) {
46,637✔
149
   if(base == Binary) {
46,637✔
150
      return BigInt::from_bytes(std::span{buf, length});
×
151
   } else if(base == Hexadecimal) {
46,637✔
152
      BigInt r;
42,389✔
153
      secure_vector<uint8_t> binary;
42,389✔
154

155
      if(length % 2 == 1) {
42,389✔
156
         // Handle lack of leading 0
157
         const char buf0_with_leading_0[2] = {'0', static_cast<char>(buf[0])};
4,224✔
158

159
         binary = hex_decode_locked(buf0_with_leading_0, 2);
8,448✔
160

161
         if(length > 1) {
4,224✔
162
            binary += hex_decode_locked(cast_uint8_ptr_to_char(&buf[1]), length - 1, false);
6,100✔
163
         }
164
      } else {
165
         binary = hex_decode_locked(cast_uint8_ptr_to_char(buf), length, false);
76,330✔
166
      }
167

168
      r.assign_from_bytes(binary);
42,389✔
169
      return r;
42,389✔
170
   } else if(base == Decimal) {
46,637✔
171
      BigInt r;
4,248✔
172
      // This could be made faster using the same trick as to_dec_string
173
      for(size_t i = 0; i != length; ++i) {
382,912✔
174
         const char c = buf[i];
378,664✔
175

176
         if(c < '0' || c > '9') {
378,664✔
177
            throw Invalid_Argument("BigInt::decode: invalid decimal char");
×
178
         }
179

180
         const uint8_t x = c - '0';
378,664✔
181
         BOTAN_ASSERT_NOMSG(x < 10);
378,664✔
182

183
         r *= 10;
378,664✔
184
         r += x;
378,664✔
185
      }
186
      return r;
4,248✔
187
   } else {
4,248✔
188
      throw Invalid_Argument("Unknown BigInt decoding method");
×
189
   }
190
}
191

192
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc