summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2022-08-17 09:17:56 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2022-08-17 09:18:39 -0700
commitfcfc7a6d15eab5aff86d7b90c9e38fa386a103fa (patch)
treeec697cf6574f311f9f373df7d19f307d9c185781
parent934f613818ffcb26c942dff4a80be9a4031c662c (diff)
Fix "unsafe narrowing" warnings in absl, 5/n.
Addresses failures with the following, in some files: -Wshorten-64-to-32 -Wimplicit-int-conversion -Wsign-compare -Wsign-conversion -Wtautological-unsigned-zero-compare (This specific CL focuses on .cc files in strings/internal/.) Bug: chromium:1292951 PiperOrigin-RevId: 468215101 Change-Id: I07fa487bcf2cf62d403489c3be7a5997cdef8987
-rw-r--r--absl/strings/internal/charconv_bigint.cc8
-rw-r--r--absl/strings/internal/charconv_parse.cc4
-rw-r--r--absl/strings/internal/cord_internal.h5
-rw-r--r--absl/strings/internal/cord_rep_btree.cc7
-rw-r--r--absl/strings/internal/cord_rep_btree.h5
-rw-r--r--absl/strings/internal/cord_rep_btree_navigator.cc10
-rw-r--r--absl/strings/internal/cordz_info.cc13
-rw-r--r--absl/strings/internal/cordz_info.h8
-rw-r--r--absl/strings/internal/cordz_statistics.h8
-rw-r--r--absl/strings/internal/memutil.cc15
-rw-r--r--absl/strings/internal/str_format/arg.cc35
-rw-r--r--absl/strings/internal/str_format/bind.cc5
-rw-r--r--absl/strings/internal/str_format/extension.cc3
-rw-r--r--absl/strings/internal/str_format/float_conversion.cc390
14 files changed, 283 insertions, 233 deletions
diff --git a/absl/strings/internal/charconv_bigint.cc b/absl/strings/internal/charconv_bigint.cc
index ebf8c079..282b639e 100644
--- a/absl/strings/internal/charconv_bigint.cc
+++ b/absl/strings/internal/charconv_bigint.cc
@@ -242,7 +242,7 @@ int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,
// decimal exponent to compensate.
--exponent_adjust;
}
- int digit = (*begin - '0');
+ char digit = (*begin - '0');
--significant_digits;
if (significant_digits == 0 && std::next(begin) != end &&
(digit == 0 || digit == 5)) {
@@ -255,7 +255,7 @@ int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,
// 500000...000000000001 to correctly round up, rather than to nearest.
++digit;
}
- queued = 10 * queued + digit;
+ queued = 10 * queued + static_cast<uint32_t>(digit);
++digits_queued;
if (digits_queued == kMaxSmallPowerOfTen) {
MultiplyBy(kTenToNth[kMaxSmallPowerOfTen]);
@@ -341,8 +341,8 @@ std::string BigUnsigned<max_words>::ToString() const {
std::string result;
// Build result in reverse order
while (copy.size() > 0) {
- int next_digit = copy.DivMod<10>();
- result.push_back('0' + next_digit);
+ uint32_t next_digit = copy.DivMod<10>();
+ result.push_back('0' + static_cast<char>(next_digit));
}
if (result.empty()) {
result.push_back('0');
diff --git a/absl/strings/internal/charconv_parse.cc b/absl/strings/internal/charconv_parse.cc
index d29acaf4..98823def 100644
--- a/absl/strings/internal/charconv_parse.cc
+++ b/absl/strings/internal/charconv_parse.cc
@@ -190,11 +190,11 @@ bool IsDigit<16>(char ch) {
template <>
unsigned ToDigit<10>(char ch) {
- return ch - '0';
+ return static_cast<unsigned>(ch - '0');
}
template <>
unsigned ToDigit<16>(char ch) {
- return kAsciiToInt[static_cast<unsigned char>(ch)];
+ return static_cast<unsigned>(kAsciiToInt[static_cast<unsigned char>(ch)]);
}
template <>
diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h
index 29954112..601457ee 100644
--- a/absl/strings/internal/cord_internal.h
+++ b/absl/strings/internal/cord_internal.h
@@ -129,8 +129,9 @@ class RefcountAndFlags {
}
// Returns the current reference count using acquire semantics.
- inline int32_t Get() const {
- return count_.load(std::memory_order_acquire) >> kNumFlags;
+ inline size_t Get() const {
+ return static_cast<size_t>(count_.load(std::memory_order_acquire) >>
+ kNumFlags);
}
// Returns whether the atomic integer is 1.
diff --git a/absl/strings/internal/cord_rep_btree.cc b/absl/strings/internal/cord_rep_btree.cc
index cacbf3da..7ce36128 100644
--- a/absl/strings/internal/cord_rep_btree.cc
+++ b/absl/strings/internal/cord_rep_btree.cc
@@ -17,6 +17,7 @@
#include <cassert>
#include <cstdint>
#include <iostream>
+#include <ostream>
#include <string>
#include "absl/base/attributes.h"
@@ -55,8 +56,10 @@ inline bool exhaustive_validation() {
// Prints the entire tree structure or 'rep'. External callers should
// not specify 'depth' and leave it to its default (0) value.
// Rep may be a CordRepBtree tree, or a SUBSTRING / EXTERNAL / FLAT node.
-void DumpAll(const CordRep* rep, bool include_contents, std::ostream& stream,
- int depth = 0) {
+void DumpAll(const CordRep* rep,
+ bool include_contents,
+ std::ostream& stream,
+ size_t depth = 0) {
// Allow for full height trees + substring -> flat / external nodes.
assert(depth <= CordRepBtree::kMaxDepth + 2);
std::string sharing = const_cast<CordRep*>(rep)->refcount.IsOne()
diff --git a/absl/strings/internal/cord_rep_btree.h b/absl/strings/internal/cord_rep_btree.h
index 2cbc09ec..eed5609e 100644
--- a/absl/strings/internal/cord_rep_btree.h
+++ b/absl/strings/internal/cord_rep_btree.h
@@ -95,8 +95,9 @@ class CordRepBtree : public CordRep {
// local stack variable compared to Cord's current near 400 bytes stack use.
// The maximum `height` value of a node is then `kMaxDepth - 1` as node height
// values start with a value of 0 for leaf nodes.
- static constexpr int kMaxDepth = 12;
- static constexpr int kMaxHeight = kMaxDepth - 1;
+ static constexpr size_t kMaxDepth = 12;
+ // See comments on height() for why this is an int and not a size_t.
+ static constexpr int kMaxHeight = static_cast<int>(kMaxDepth - 1);
// `Action` defines the action for unwinding changes done at the btree's leaf
// level that need to be propagated up to the parent node(s). Each operation
diff --git a/absl/strings/internal/cord_rep_btree_navigator.cc b/absl/strings/internal/cord_rep_btree_navigator.cc
index 9b896a3d..6ed20c23 100644
--- a/absl/strings/internal/cord_rep_btree_navigator.cc
+++ b/absl/strings/internal/cord_rep_btree_navigator.cc
@@ -90,7 +90,7 @@ CordRepBtreeNavigator::Position CordRepBtreeNavigator::Skip(size_t n) {
// edges that must be skipped.
while (height > 0) {
node = edge->btree();
- index_[height] = index;
+ index_[height] = static_cast<uint8_t>(index);
node_[--height] = node;
index = node->begin();
edge = node->Edge(index);
@@ -101,7 +101,7 @@ CordRepBtreeNavigator::Position CordRepBtreeNavigator::Skip(size_t n) {
edge = node->Edge(index);
}
}
- index_[0] = index;
+ index_[0] = static_cast<uint8_t>(index);
return {edge, n};
}
@@ -126,7 +126,7 @@ ReadResult CordRepBtreeNavigator::Read(size_t edge_offset, size_t n) {
do {
length -= edge->length;
while (++index == node->end()) {
- index_[height] = index;
+ index_[height] = static_cast<uint8_t>(index);
if (++height > height_) {
subtree->set_end(subtree_end);
if (length == 0) return {subtree, 0};
@@ -154,7 +154,7 @@ ReadResult CordRepBtreeNavigator::Read(size_t edge_offset, size_t n) {
// edges that must be read, adding 'down' nodes to `subtree`.
while (height > 0) {
node = edge->btree();
- index_[height] = index;
+ index_[height] = static_cast<uint8_t>(index);
node_[--height] = node;
index = node->begin();
edge = node->Edge(index);
@@ -178,7 +178,7 @@ ReadResult CordRepBtreeNavigator::Read(size_t edge_offset, size_t n) {
subtree->edges_[subtree_end++] = Substring(edge, 0, length);
}
subtree->set_end(subtree_end);
- index_[0] = index;
+ index_[0] = static_cast<uint8_t>(index);
return {tree, length};
}
diff --git a/absl/strings/internal/cordz_info.cc b/absl/strings/internal/cordz_info.cc
index dac3fd8b..530f33be 100644
--- a/absl/strings/internal/cordz_info.cc
+++ b/absl/strings/internal/cordz_info.cc
@@ -35,7 +35,7 @@ namespace cord_internal {
using ::absl::base_internal::SpinLockHolder;
#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr int CordzInfo::kMaxStackDepth;
+constexpr size_t CordzInfo::kMaxStackDepth;
#endif
ABSL_CONST_INIT CordzInfo::List CordzInfo::global_list_{absl::kConstInit};
@@ -291,7 +291,7 @@ CordzInfo::MethodIdentifier CordzInfo::GetParentMethod(const CordzInfo* src) {
: src->method_;
}
-int CordzInfo::FillParentStack(const CordzInfo* src, void** stack) {
+size_t CordzInfo::FillParentStack(const CordzInfo* src, void** stack) {
assert(stack);
if (src == nullptr) return 0;
if (src->parent_stack_depth_) {
@@ -302,11 +302,14 @@ int CordzInfo::FillParentStack(const CordzInfo* src, void** stack) {
return src->stack_depth_;
}
-CordzInfo::CordzInfo(CordRep* rep, const CordzInfo* src,
+CordzInfo::CordzInfo(CordRep* rep,
+ const CordzInfo* src,
MethodIdentifier method)
: rep_(rep),
- stack_depth_(absl::GetStackTrace(stack_, /*max_depth=*/kMaxStackDepth,
- /*skip_count=*/1)),
+ stack_depth_(
+ static_cast<size_t>(absl::GetStackTrace(stack_,
+ /*max_depth=*/kMaxStackDepth,
+ /*skip_count=*/1))),
parent_stack_depth_(FillParentStack(src, parent_stack_)),
method_(method),
parent_method_(GetParentMethod(src)),
diff --git a/absl/strings/internal/cordz_info.h b/absl/strings/internal/cordz_info.h
index 026d5b99..8e86f223 100644
--- a/absl/strings/internal/cordz_info.h
+++ b/absl/strings/internal/cordz_info.h
@@ -196,7 +196,7 @@ class ABSL_LOCKABLE CordzInfo : public CordzHandle {
std::atomic<CordzInfo*> head ABSL_GUARDED_BY(mutex){nullptr};
};
- static constexpr int kMaxStackDepth = 64;
+ static constexpr size_t kMaxStackDepth = 64;
explicit CordzInfo(CordRep* rep, const CordzInfo* src,
MethodIdentifier method);
@@ -216,7 +216,7 @@ class ABSL_LOCKABLE CordzInfo : public CordzHandle {
// `stack_` depending on `parent_stack_` being empty, returning the size of
// the parent stack.
// Returns 0 if `src` is null.
- static int FillParentStack(const CordzInfo* src, void** stack);
+ static size_t FillParentStack(const CordzInfo* src, void** stack);
void ODRCheck() const {
#ifndef NDEBUG
@@ -244,8 +244,8 @@ class ABSL_LOCKABLE CordzInfo : public CordzHandle {
void* stack_[kMaxStackDepth];
void* parent_stack_[kMaxStackDepth];
- const int stack_depth_;
- const int parent_stack_depth_;
+ const size_t stack_depth_;
+ const size_t parent_stack_depth_;
const MethodIdentifier method_;
const MethodIdentifier parent_method_;
CordzUpdateTracker update_tracker_;
diff --git a/absl/strings/internal/cordz_statistics.h b/absl/strings/internal/cordz_statistics.h
index 57071905..9f558df4 100644
--- a/absl/strings/internal/cordz_statistics.h
+++ b/absl/strings/internal/cordz_statistics.h
@@ -45,12 +45,12 @@ struct CordzStatistics {
};
// The size of the cord in bytes. This matches the result of Cord::size().
- int64_t size = 0;
+ size_t size = 0;
// The estimated memory used by the sampled cord. This value matches the
// value as reported by Cord::EstimatedMemoryUsage().
// A value of 0 implies the property has not been recorded.
- int64_t estimated_memory_usage = 0;
+ size_t estimated_memory_usage = 0;
// The effective memory used by the sampled cord, inversely weighted by the
// effective indegree of each allocated node. This is a representation of the
@@ -59,14 +59,14 @@ struct CordzStatistics {
// by multiple Cord instances, and for cases where a Cord includes the same
// node multiple times (either directly or indirectly).
// A value of 0 implies the property has not been recorded.
- int64_t estimated_fair_share_memory_usage = 0;
+ size_t estimated_fair_share_memory_usage = 0;
// The total number of nodes referenced by this cord.
// For ring buffer Cords, this includes the 'ring buffer' node.
// For btree Cords, this includes all 'CordRepBtree' tree nodes as well as all
// the substring, flat and external nodes referenced by the tree.
// A value of 0 implies the property has not been recorded.
- int64_t node_count = 0;
+ size_t node_count = 0;
// Detailed node counts per type
NodeCounts node_counts;
diff --git a/absl/strings/internal/memutil.cc b/absl/strings/internal/memutil.cc
index 2519c688..44996a75 100644
--- a/absl/strings/internal/memutil.cc
+++ b/absl/strings/internal/memutil.cc
@@ -54,10 +54,11 @@ size_t memspn(const char* s, size_t slen, const char* accept) {
cont:
c = *p++;
- if (slen-- == 0) return p - 1 - s;
+ if (slen-- == 0)
+ return static_cast<size_t>(p - 1 - s);
for (spanp = accept; (sc = *spanp++) != '\0';)
if (sc == c) goto cont;
- return p - 1 - s;
+ return static_cast<size_t>(p - 1 - s);
}
size_t memcspn(const char* s, size_t slen, const char* reject) {
@@ -68,9 +69,10 @@ size_t memcspn(const char* s, size_t slen, const char* reject) {
while (slen-- != 0) {
c = *p++;
for (spanp = reject; (sc = *spanp++) != '\0';)
- if (sc == c) return p - 1 - s;
+ if (sc == c)
+ return static_cast<size_t>(p - 1 - s);
}
- return p - s;
+ return static_cast<size_t>(p - s);
}
char* mempbrk(const char* s, size_t slen, const char* accept) {
@@ -97,8 +99,9 @@ const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
const char* hayend = phaystack + haylen - neelen + 1;
// A static cast is used here to work around the fact that memchr returns
// a void* on Posix-compliant systems and const void* on Windows.
- while ((match = static_cast<const char*>(
- memchr(phaystack, pneedle[0], hayend - phaystack)))) {
+ while (
+ (match = static_cast<const char*>(memchr(
+ phaystack, pneedle[0], static_cast<size_t>(hayend - phaystack))))) {
if (memcmp(match, pneedle, neelen) == 0)
return match;
else
diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc
index 02aeeebe..007e8e83 100644
--- a/absl/strings/internal/str_format/arg.cc
+++ b/absl/strings/internal/str_format/arg.cc
@@ -77,7 +77,7 @@ class IntDigits {
v >>= 3;
} while (v);
start_ = p;
- size_ = storage_ + sizeof(storage_) - p;
+ size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);
}
// Print the signed or unsigned integer as decimal.
@@ -86,7 +86,8 @@ class IntDigits {
void PrintAsDec(T v) {
static_assert(std::is_integral<T>::value, "");
start_ = storage_;
- size_ = numbers_internal::FastIntToBuffer(v, storage_) - storage_;
+ size_ = static_cast<size_t>(numbers_internal::FastIntToBuffer(v, storage_) -
+ storage_);
}
void PrintAsDec(int128 v) {
@@ -115,7 +116,7 @@ class IntDigits {
if (add_neg) {
*--p = '-';
}
- size_ = storage_ + sizeof(storage_) - p;
+ size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);
start_ = p;
}
@@ -138,7 +139,7 @@ class IntDigits {
++p;
}
start_ = p;
- size_ = storage_ + sizeof(storage_) - p;
+ size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);
}
// Print the unsigned integer as hex using uppercase.
@@ -154,7 +155,7 @@ class IntDigits {
v >>= 4;
} while (v);
start_ = p;
- size_ = storage_ + sizeof(storage_) - p;
+ size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);
}
// The printed value including the '-' sign if available.
@@ -208,10 +209,12 @@ string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {
return {};
}
-bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+bool ConvertCharImpl(char v,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink) {
size_t fill = 0;
- if (conv.width() >= 0) fill = conv.width();
+ if (conv.width() >= 0)
+ fill = static_cast<size_t>(conv.width());
ReducePadding(1, &fill);
if (!conv.has_left_flag()) sink->Append(fill, ' ');
sink->Append(1, v);
@@ -225,7 +228,8 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
// Print as a sequence of Substrings:
// [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]
size_t fill = 0;
- if (conv.width() >= 0) fill = conv.width();
+ if (conv.width() >= 0)
+ fill = static_cast<size_t>(conv.width());
string_view formatted = as_digits.without_neg_or_zero();
ReducePadding(formatted, &fill);
@@ -236,10 +240,9 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
string_view base_indicator = BaseIndicator(as_digits, conv);
ReducePadding(base_indicator, &fill);
- int precision = conv.precision();
- bool precision_specified = precision >= 0;
- if (!precision_specified)
- precision = 1;
+ bool precision_specified = conv.precision() >= 0;
+ size_t precision =
+ precision_specified ? static_cast<size_t>(conv.precision()) : size_t{1};
if (conv.has_alt_flag() &&
conv.conversion_char() == FormatConversionCharInternal::o) {
@@ -247,7 +250,7 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
// "For o conversion, it increases the precision (if necessary) to
// force the first digit of the result to be zero."
if (formatted.empty() || *formatted.begin() != '0') {
- int needed = static_cast<int>(formatted.size()) + 1;
+ size_t needed = formatted.size() + 1;
precision = std::max(precision, needed);
}
}
@@ -287,7 +290,7 @@ bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
// FormatConversionChar is declared, but not defined.
switch (static_cast<uint8_t>(conv.conversion_char())) {
case static_cast<uint8_t>(FormatConversionCharInternal::c):
- return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
+ return ConvertCharImpl(static_cast<char>(v), conv, sink);
case static_cast<uint8_t>(FormatConversionCharInternal::o):
as_digits.PrintAsOct(static_cast<U>(v));
@@ -375,7 +378,7 @@ FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
len = std::strlen(v);
} else {
// If precision is set, we look for the NUL-terminator on the valid range.
- len = std::find(v, v + conv.precision(), '\0') - v;
+ len = static_cast<size_t>(std::find(v, v + conv.precision(), '\0') - v);
}
return {ConvertStringArg(string_view(v, len), conv, sink)};
}
diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc
index c988ba8f..77a42223 100644
--- a/absl/strings/internal/str_format/bind.cc
+++ b/absl/strings/internal/str_format/bind.cc
@@ -32,7 +32,8 @@ inline bool BindFromPosition(int position, int* value,
return false;
}
// -1 because positions are 1-based
- return FormatArgImplFriend::ToInt(pack[position - 1], value);
+ return FormatArgImplFriend::ToInt(pack[static_cast<size_t>(position) - 1],
+ value);
}
class ArgContext {
@@ -56,7 +57,7 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound,
const FormatArgImpl* arg = nullptr;
int arg_position = unbound->arg_position;
if (static_cast<size_t>(arg_position - 1) >= pack_.size()) return false;
- arg = &pack_[arg_position - 1]; // 1-based
+ arg = &pack_[static_cast<size_t>(arg_position - 1)]; // 1-based
if (unbound->flags != Flags::kBasic) {
int width = unbound->width.value();
diff --git a/absl/strings/internal/str_format/extension.cc b/absl/strings/internal/str_format/extension.cc
index f93153d5..2a0ceb13 100644
--- a/absl/strings/internal/str_format/extension.cc
+++ b/absl/strings/internal/str_format/extension.cc
@@ -58,7 +58,8 @@ constexpr FormatConversionCharSet FormatConversionCharSetInternal::kPointer;
bool FormatSinkImpl::PutPaddedString(string_view value, int width,
int precision, bool left) {
size_t space_remaining = 0;
- if (width >= 0) space_remaining = width;
+ if (width >= 0)
+ space_remaining = static_cast<size_t>(width);
size_t n = value.size();
if (precision >= 0) n = std::min(n, static_cast<size_t>(precision));
string_view shown(value.data(), n);
diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc
index b1c40684..3895001a 100644
--- a/absl/strings/internal/str_format/float_conversion.cc
+++ b/absl/strings/internal/str_format/float_conversion.cc
@@ -92,27 +92,30 @@ class StackArray {
// Calculates `10 * (*v) + carry` and stores the result in `*v` and returns
// the carry.
+// Requires: `0 <= carry <= 9`
template <typename Int>
-inline Int MultiplyBy10WithCarry(Int *v, Int carry) {
+inline char MultiplyBy10WithCarry(Int* v, char carry) {
using BiggerInt = absl::conditional_t<sizeof(Int) == 4, uint64_t, uint128>;
- BiggerInt tmp = 10 * static_cast<BiggerInt>(*v) + carry;
+ BiggerInt tmp =
+ 10 * static_cast<BiggerInt>(*v) + static_cast<BiggerInt>(carry);
*v = static_cast<Int>(tmp);
- return static_cast<Int>(tmp >> (sizeof(Int) * 8));
+ return static_cast<char>(tmp >> (sizeof(Int) * 8));
}
// Calculates `(2^64 * carry + *v) / 10`.
// Stores the quotient in `*v` and returns the remainder.
// Requires: `0 <= carry <= 9`
-inline uint64_t DivideBy10WithCarry(uint64_t *v, uint64_t carry) {
+inline char DivideBy10WithCarry(uint64_t* v, char carry) {
constexpr uint64_t divisor = 10;
// 2^64 / divisor = chunk_quotient + chunk_remainder / divisor
constexpr uint64_t chunk_quotient = (uint64_t{1} << 63) / (divisor / 2);
constexpr uint64_t chunk_remainder = uint64_t{} - chunk_quotient * divisor;
+ const uint64_t carry_u64 = static_cast<uint64_t>(carry);
const uint64_t mod = *v % divisor;
- const uint64_t next_carry = chunk_remainder * carry + mod;
- *v = *v / divisor + carry * chunk_quotient + next_carry / divisor;
- return next_carry % divisor;
+ const uint64_t next_carry = chunk_remainder * carry_u64 + mod;
+ *v = *v / divisor + carry_u64 * chunk_quotient + next_carry / divisor;
+ return static_cast<char>(next_carry % divisor);
}
using MaxFloatType =
@@ -125,11 +128,11 @@ using MaxFloatType =
//
// Requires `0 <= exp` and `exp <= numeric_limits<MaxFloatType>::max_exponent`.
class BinaryToDecimal {
- static constexpr int ChunksNeeded(int exp) {
+ static constexpr size_t ChunksNeeded(int exp) {
// We will left shift a uint128 by `exp` bits, so we need `128+exp` total
// bits. Round up to 32.
// See constructor for details about adding `10%` to the value.
- return (128 + exp + 31) / 32 * 11 / 10;
+ return static_cast<size_t>((128 + exp + 31) / 32 * 11 / 10);
}
public:
@@ -140,7 +143,7 @@ class BinaryToDecimal {
assert(exp > 0);
assert(exp <= std::numeric_limits<MaxFloatType>::max_exponent);
static_assert(
- static_cast<int>(StackArray::kMaxCapacity) >=
+ StackArray::kMaxCapacity >=
ChunksNeeded(std::numeric_limits<MaxFloatType>::max_exponent),
"");
@@ -149,9 +152,9 @@ class BinaryToDecimal {
[=](absl::Span<uint32_t> input) { f(BinaryToDecimal(input, v, exp)); });
}
- int TotalDigits() const {
- return static_cast<int>((decimal_end_ - decimal_start_) * kDigitsPerChunk +
- CurrentDigits().size());
+ size_t TotalDigits() const {
+ return (decimal_end_ - decimal_start_) * kDigitsPerChunk +
+ CurrentDigits().size();
}
// See the current block of digits.
@@ -190,30 +193,31 @@ class BinaryToDecimal {
// the decimal representation is around 7% less efficient in space than the
// binary one. We allocate an extra 10% memory to account for this. See
// ChunksNeeded for this calculation.
- int chunk_index = exp / 32;
+ size_t after_chunk_index = static_cast<size_t>(exp / 32 + 1);
decimal_start_ = decimal_end_ = ChunksNeeded(exp);
const int offset = exp % 32;
// Left shift v by exp bits.
- data_[chunk_index] = static_cast<uint32_t>(v << offset);
+ data_[after_chunk_index - 1] = static_cast<uint32_t>(v << offset);
for (v >>= (32 - offset); v; v >>= 32)
- data_[++chunk_index] = static_cast<uint32_t>(v);
+ data_[++after_chunk_index - 1] = static_cast<uint32_t>(v);
- while (chunk_index >= 0) {
+ while (after_chunk_index > 0) {
// While we have more than one chunk available, go in steps of 1e9.
- // `data_[chunk_index]` holds the highest non-zero binary chunk, so keep
- // the variable updated.
+ // `data_[after_chunk_index - 1]` holds the highest non-zero binary chunk,
+ // so keep the variable updated.
uint32_t carry = 0;
- for (int i = chunk_index; i >= 0; --i) {
- uint64_t tmp = uint64_t{data_[i]} + (uint64_t{carry} << 32);
- data_[i] = static_cast<uint32_t>(tmp / uint64_t{1000000000});
+ for (size_t i = after_chunk_index; i > 0; --i) {
+ uint64_t tmp = uint64_t{data_[i - 1]} + (uint64_t{carry} << 32);
+ data_[i - 1] = static_cast<uint32_t>(tmp / uint64_t{1000000000});
carry = static_cast<uint32_t>(tmp % uint64_t{1000000000});
}
// If the highest chunk is now empty, remove it from view.
- if (data_[chunk_index] == 0) --chunk_index;
+ if (data_[after_chunk_index - 1] == 0)
+ --after_chunk_index;
--decimal_start_;
- assert(decimal_start_ != chunk_index);
+ assert(decimal_start_ != after_chunk_index - 1);
data_[decimal_start_] = carry;
}
@@ -225,13 +229,13 @@ class BinaryToDecimal {
}
private:
- static constexpr int kDigitsPerChunk = 9;
+ static constexpr size_t kDigitsPerChunk = 9;
- int decimal_start_;
- int decimal_end_;
+ size_t decimal_start_;
+ size_t decimal_end_;
char digits_[kDigitsPerChunk];
- int size_ = 0;
+ size_t size_ = 0;
absl::Span<uint32_t> data_;
};
@@ -251,25 +255,26 @@ class FractionalDigitGenerator {
static_assert(StackArray::kMaxCapacity >=
(Limits::digits + 128 - Limits::min_exponent + 31) / 32,
"");
- StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32,
- [=](absl::Span<uint32_t> input) {
- f(FractionalDigitGenerator(input, v, exp));
- });
+ StackArray::RunWithCapacity(
+ static_cast<size_t>((Limits::digits + exp + 31) / 32),
+ [=](absl::Span<uint32_t> input) {
+ f(FractionalDigitGenerator(input, v, exp));
+ });
}
// Returns true if there are any more non-zero digits left.
- bool HasMoreDigits() const { return next_digit_ != 0 || chunk_index_ >= 0; }
+ bool HasMoreDigits() const { return next_digit_ != 0 || after_chunk_index_; }
// Returns true if the remainder digits are greater than 5000...
bool IsGreaterThanHalf() const {
- return next_digit_ > 5 || (next_digit_ == 5 && chunk_index_ >= 0);
+ return next_digit_ > 5 || (next_digit_ == 5 && after_chunk_index_);
}
// Returns true if the remainder digits are exactly 5000...
- bool IsExactlyHalf() const { return next_digit_ == 5 && chunk_index_ < 0; }
+ bool IsExactlyHalf() const { return next_digit_ == 5 && !after_chunk_index_; }
struct Digits {
- int digit_before_nine;
- int num_nines;
+ char digit_before_nine;
+ size_t num_nines;
};
// Get the next set of digits.
@@ -288,35 +293,37 @@ class FractionalDigitGenerator {
private:
// Return the next digit.
- int GetOneDigit() {
- if (chunk_index_ < 0) return 0;
+ char GetOneDigit() {
+ if (!after_chunk_index_)
+ return 0;
- uint32_t carry = 0;
- for (int i = chunk_index_; i >= 0; --i) {
- carry = MultiplyBy10WithCarry(&data_[i], carry);
+ char carry = 0;
+ for (size_t i = after_chunk_index_; i > 0; --i) {
+ carry = MultiplyBy10WithCarry(&data_[i - 1], carry);
}
// If the lowest chunk is now empty, remove it from view.
- if (data_[chunk_index_] == 0) --chunk_index_;
+ if (data_[after_chunk_index_ - 1] == 0)
+ --after_chunk_index_;
return carry;
}
FractionalDigitGenerator(absl::Span<uint32_t> data, uint128 v, int exp)
- : chunk_index_(exp / 32), data_(data) {
+ : after_chunk_index_(static_cast<size_t>(exp / 32 + 1)), data_(data) {
const int offset = exp % 32;
// Right shift `v` by `exp` bits.
- data_[chunk_index_] = static_cast<uint32_t>(v << (32 - offset));
+ data_[after_chunk_index_ - 1] = static_cast<uint32_t>(v << (32 - offset));
v >>= offset;
// Make sure we don't overflow the data. We already calculated that
// non-zero bits fit, so we might not have space for leading zero bits.
- for (int pos = chunk_index_; v; v >>= 32)
+ for (size_t pos = after_chunk_index_ - 1; v; v >>= 32)
data_[--pos] = static_cast<uint32_t>(v);
// Fill next_digit_, as GetDigits expects it to be populated always.
next_digit_ = GetOneDigit();
}
- int next_digit_;
- int chunk_index_;
+ char next_digit_;
+ size_t after_chunk_index_;
absl::Span<uint32_t> data_;
};
@@ -362,7 +369,7 @@ char *PrintIntegralDigitsFromRightFast(uint128 v, char *p) {
auto low = static_cast<uint64_t>(v);
while (high != 0) {
- uint64_t carry = DivideBy10WithCarry(&high, 0);
+ char carry = DivideBy10WithCarry(&high, 0);
carry = DivideBy10WithCarry(&low, carry);
*--p = carry + '0';
}
@@ -373,13 +380,15 @@ char *PrintIntegralDigitsFromRightFast(uint128 v, char *p) {
// shifting.
// Performs rounding if necessary to fit within `precision`.
// Returns the pointer to one after the last character written.
-char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp,
- int precision) {
+char* PrintFractionalDigitsFast(uint64_t v,
+ char* start,
+ int exp,
+ size_t precision) {
char *p = start;
v <<= (64 - exp);
while (precision > 0) {
if (!v) return p;
- *p++ = MultiplyBy10WithCarry(&v, uint64_t{0}) + '0';
+ *p++ = MultiplyBy10WithCarry(&v, 0) + '0';
--precision;
}
@@ -393,8 +402,6 @@ char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp,
RoundToEven(p - 1);
}
- assert(precision == 0);
- // Precision can only be zero here.
return p;
}
@@ -402,8 +409,10 @@ char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp,
// after shifting.
// Performs rounding if necessary to fit within `precision`.
// Returns the pointer to one after the last character written.
-char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
- int precision) {
+char* PrintFractionalDigitsFast(uint128 v,
+ char* start,
+ int exp,
+ size_t precision) {
char *p = start;
v <<= (128 - exp);
auto high = static_cast<uint64_t>(v >> 64);
@@ -412,7 +421,7 @@ char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
// While we have digits to print and `low` is not empty, do the long
// multiplication.
while (precision > 0 && low != 0) {
- uint64_t carry = MultiplyBy10WithCarry(&low, uint64_t{0});
+ char carry = MultiplyBy10WithCarry(&low, 0);
carry = MultiplyBy10WithCarry(&high, carry);
*p++ = carry + '0';
@@ -424,7 +433,7 @@ char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
// above.
while (precision > 0) {
if (!high) return p;
- *p++ = MultiplyBy10WithCarry(&high, uint64_t{0}) + '0';
+ *p++ = MultiplyBy10WithCarry(&high, 0) + '0';
--precision;
}
@@ -438,14 +447,12 @@ char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
RoundToEven(p - 1);
}
- assert(precision == 0);
- // Precision can only be zero here.
return p;
}
struct FormatState {
char sign_char;
- int precision;
+ size_t precision;
const FormatConversionSpecImpl &conv;
FormatSinkImpl *sink;
@@ -455,9 +462,9 @@ struct FormatState {
};
struct Padding {
- int left_spaces;
- int zeros;
- int right_spaces;
+ size_t left_spaces;
+ size_t zeros;
+ size_t right_spaces;
};
Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
@@ -465,7 +472,7 @@ Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
static_cast<size_t>(state.conv.width()) <= total_size) {
return {0, 0, 0};
}
- int missing_chars = state.conv.width() - total_size;
+ size_t missing_chars = static_cast<size_t>(state.conv.width()) - total_size;
if (state.conv.has_left_flag()) {
return {0, 0, missing_chars};
} else if (state.conv.has_zero_flag()) {
@@ -475,8 +482,10 @@ Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
}
}
-void FinalPrint(const FormatState &state, absl::string_view data,
- int padding_offset, int trailing_zeros,
+void FinalPrint(const FormatState& state,
+ absl::string_view data,
+ size_t padding_offset,
+ size_t trailing_zeros,
absl::string_view data_postfix) {
if (state.conv.width() < 0) {
// No width specified. Fast-path.
@@ -487,10 +496,10 @@ void FinalPrint(const FormatState &state, absl::string_view data,
return;
}
- auto padding = ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) +
- data.size() + data_postfix.size() +
- static_cast<size_t>(trailing_zeros),
- state);
+ auto padding =
+ ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + data.size() +
+ data_postfix.size() + trailing_zeros,
+ state);
state.sink->Append(padding.left_spaces, ' ');
if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
@@ -547,15 +556,16 @@ void FormatFFast(Int v, int exp, const FormatState &state) {
if (integral_digits_start[-1] != '0') --integral_digits_start;
}
- size_t size = fractional_digits_end - integral_digits_start;
+ size_t size =
+ static_cast<size_t>(fractional_digits_end - integral_digits_start);
// In `alt` mode (flag #) we keep the `.` even if there are no fractional
// digits. In non-alt mode, we strip it.
if (!state.ShouldPrintDot()) --size;
FinalPrint(state, absl::string_view(integral_digits_start, size),
/*padding_offset=*/0,
- static_cast<int>(state.precision - (fractional_digits_end -
- fractional_digits_start)),
+ state.precision - static_cast<size_t>(fractional_digits_end -
+ fractional_digits_start),
/*data_postfix=*/"");
}
@@ -567,21 +577,22 @@ void FormatFFast(Int v, int exp, const FormatState &state) {
void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) {
BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) {
const size_t total_digits =
- btd.TotalDigits() +
- (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
+ btd.TotalDigits() + (state.ShouldPrintDot() ? state.precision + 1 : 0);
const auto padding = ExtraWidthToPadding(
total_digits + (state.sign_char != '\0' ? 1 : 0), state);
state.sink->Append(padding.left_spaces, ' ');
- if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+ if (state.sign_char != '\0')
+ state.sink->Append(1, state.sign_char);
state.sink->Append(padding.zeros, '0');
do {
state.sink->Append(btd.CurrentDigits());
} while (btd.AdvanceDigits());
- if (state.ShouldPrintDot()) state.sink->Append(1, '.');
+ if (state.ShouldPrintDot())
+ state.sink->Append(1, '.');
state.sink->Append(state.precision, '0');
state.sink->Append(padding.right_spaces, ' ');
});
@@ -594,8 +605,7 @@ void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) {
// digits.
void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {
const size_t total_digits =
- /* 0 */ 1 +
- (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
+ /* 0 */ 1 + (state.ShouldPrintDot() ? state.precision + 1 : 0);
auto padding =
ExtraWidthToPadding(total_digits + (state.sign_char ? 1 : 0), state);
padding.zeros += 1;
@@ -606,7 +616,7 @@ void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {
if (state.ShouldPrintDot()) state.sink->Append(1, '.');
// Print digits
- int digits_to_go = state.precision;
+ size_t digits_to_go = state.precision;
FractionalDigitGenerator::RunConversion(
v, exp, [&](FractionalDigitGenerator digit_gen) {
@@ -666,7 +676,8 @@ void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {
template <typename Int>
void FormatF(Int mantissa, int exp, const FormatState &state) {
if (exp >= 0) {
- const int total_bits = sizeof(Int) * 8 - LeadingZeros(mantissa) + exp;
+ const int total_bits =
+ static_cast<int>(sizeof(Int) * 8) - LeadingZeros(mantissa) + exp;
// Fallback to the slow stack-based approach if we can't do it in a 64 or
// 128 bit state.
@@ -686,9 +697,9 @@ void FormatF(Int mantissa, int exp, const FormatState &state) {
// Grab the group of four bits (nibble) from `n`. E.g., nibble 1 corresponds to
// bits 4-7.
template <typename Int>
-uint8_t GetNibble(Int n, int nibble_index) {
+uint8_t GetNibble(Int n, size_t nibble_index) {
constexpr Int mask_low_nibble = Int{0xf};
- int shift = nibble_index * 4;
+ int shift = static_cast<int>(nibble_index * 4);
n &= mask_low_nibble << shift;
return static_cast<uint8_t>((n >> shift) & 0xf);
}
@@ -696,9 +707,9 @@ uint8_t GetNibble(Int n, int nibble_index) {
// Add one to the given nibble, applying carry to higher nibbles. Returns true
// if overflow, false otherwise.
template <typename Int>
-bool IncrementNibble(int nibble_index, Int *n) {
- constexpr int kShift = sizeof(Int) * 8 - 1;
- constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
+bool IncrementNibble(size_t nibble_index, Int* n) {
+ constexpr size_t kShift = sizeof(Int) * 8 - 1;
+ constexpr size_t kNumNibbles = sizeof(Int) * 8 / 4;
Int before = *n >> kShift;
// Here we essentially want to take the number 1 and move it into the requsted
// nibble, then add it to *n to effectively increment the nibble. However,
@@ -706,28 +717,32 @@ bool IncrementNibble(int nibble_index, Int *n) {
// i.e., if the nibble_index is out of range. So therefore we check for this
// and if we are out of range we just add 0 which leaves *n unchanged, which
// seems like the reasonable thing to do in that case.
- *n += ((nibble_index >= kNumNibbles) ? 0 : (Int{1} << (nibble_index * 4)));
+ *n += ((nibble_index >= kNumNibbles)
+ ? 0
+ : (Int{1} << static_cast<int>(nibble_index * 4)));
Int after = *n >> kShift;
return (before && !after) || (nibble_index >= kNumNibbles);
}
// Return a mask with 1's in the given nibble and all lower nibbles.
template <typename Int>
-Int MaskUpToNibbleInclusive(int nibble_index) {
- constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
+Int MaskUpToNibbleInclusive(size_t nibble_index) {
+ constexpr size_t kNumNibbles = sizeof(Int) * 8 / 4;
static const Int ones = ~Int{0};
- return ones >> std::max(0, 4 * (kNumNibbles - nibble_index - 1));
+ ++nibble_index;
+ return ones >> static_cast<int>(
+ 4 * (std::max(kNumNibbles, nibble_index) - nibble_index));
}
// Return a mask with 1's below the given nibble.
template <typename Int>
-Int MaskUpToNibbleExclusive(int nibble_index) {
- return nibble_index <= 0 ? 0 : MaskUpToNibbleInclusive<Int>(nibble_index - 1);
+Int MaskUpToNibbleExclusive(size_t nibble_index) {
+ return nibble_index == 0 ? 0 : MaskUpToNibbleInclusive<Int>(nibble_index - 1);
}
template <typename Int>
-Int MoveToNibble(uint8_t nibble, int nibble_index) {
- return Int{nibble} << (4 * nibble_index);
+Int MoveToNibble(uint8_t nibble, size_t nibble_index) {
+ return Int{nibble} << static_cast<int>(4 * nibble_index);
}
// Given mantissa size, find optimal # of mantissa bits to put in initial digit.
@@ -744,10 +759,10 @@ Int MoveToNibble(uint8_t nibble, int nibble_index) {
// a multiple of four. Once again, the goal is to have all fractional digits
// represent real precision.
template <typename Float>
-constexpr int HexFloatLeadingDigitSizeInBits() {
+constexpr size_t HexFloatLeadingDigitSizeInBits() {
return std::numeric_limits<Float>::digits % 4 > 0
- ? std::numeric_limits<Float>::digits % 4
- : 4;
+ ? static_cast<size_t>(std::numeric_limits<Float>::digits % 4)
+ : size_t{4};
}
// This function captures the rounding behavior of glibc for hex float
@@ -757,16 +772,17 @@ constexpr int HexFloatLeadingDigitSizeInBits() {
// point that is not followed by 800000..., it disregards the parity and rounds
// up if > 8 and rounds down if < 8.
template <typename Int>
-bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed,
+bool HexFloatNeedsRoundUp(Int mantissa,
+ size_t final_nibble_displayed,
uint8_t leading) {
// If the last nibble (hex digit) to be displayed is the lowest on in the
// mantissa then that means that we don't have any further nibbles to inform
// rounding, so don't round.
- if (final_nibble_displayed <= 0) {
+ if (final_nibble_displayed == 0) {
return false;
}
- int rounding_nibble_idx = final_nibble_displayed - 1;
- constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ size_t rounding_nibble_idx = final_nibble_displayed - 1;
+ constexpr size_t kTotalNibbles = sizeof(Int) * 8 / 4;
assert(final_nibble_displayed <= kTotalNibbles);
Int mantissa_up_to_rounding_nibble_inclusive =
mantissa & MaskUpToNibbleInclusive<Int>(rounding_nibble_idx);
@@ -793,7 +809,7 @@ struct HexFloatTypeParams {
}
int min_exponent;
- int leading_digit_size_bits;
+ size_t leading_digit_size_bits;
};
// Hex Float Rounding. First check if we need to round; if so, then we do that
@@ -803,10 +819,12 @@ struct HexFloatTypeParams {
template <typename Int>
void FormatARound(bool precision_specified, const FormatState &state,
uint8_t *leading, Int *mantissa, int *exp) {
- constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ constexpr size_t kTotalNibbles = sizeof(Int) * 8 / 4;
// Index of the last nibble that we could display given precision.
- int final_nibble_displayed =
- precision_specified ? std::max(0, (kTotalNibbles - state.precision)) : 0;
+ size_t final_nibble_displayed =
+ precision_specified
+ ? (std::max(kTotalNibbles, state.precision) - state.precision)
+ : 0;
if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed, *leading)) {
// Need to round up.
bool overflow = IncrementNibble(final_nibble_displayed, mantissa);
@@ -830,9 +848,9 @@ void FormatARound(bool precision_specified, const FormatState &state,
template <typename Int>
void FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading,
Int *mantissa, int *exp) {
- constexpr int kIntBits = sizeof(Int) * 8;
+ constexpr size_t kIntBits = sizeof(Int) * 8;
static const Int kHighIntBit = Int{1} << (kIntBits - 1);
- const int kLeadDigitBitsCount = float_traits.leading_digit_size_bits;
+ const size_t kLeadDigitBitsCount = float_traits.leading_digit_size_bits;
// Normalize mantissa so that highest bit set is in MSB position, unless we
// get interrupted by the exponent threshold.
while (*mantissa && !(*mantissa & kHighIntBit)) {
@@ -846,18 +864,18 @@ void FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading,
}
// Extract bits for leading digit then shift them away leaving the
// fractional part.
- *leading =
- static_cast<uint8_t>(*mantissa >> (kIntBits - kLeadDigitBitsCount));
- *exp -= (*mantissa != 0) ? kLeadDigitBitsCount : *exp;
- *mantissa <<= kLeadDigitBitsCount;
+ *leading = static_cast<uint8_t>(
+ *mantissa >> static_cast<int>(kIntBits - kLeadDigitBitsCount));
+ *exp -= (*mantissa != 0) ? static_cast<int>(kLeadDigitBitsCount) : *exp;
+ *mantissa <<= static_cast<int>(kLeadDigitBitsCount);
}
template <typename Int>
void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
bool uppercase, const FormatState &state) {
// Int properties.
- constexpr int kIntBits = sizeof(Int) * 8;
- constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ constexpr size_t kIntBits = sizeof(Int) * 8;
+ constexpr size_t kTotalNibbles = sizeof(Int) * 8 / 4;
// Did the user specify a precision explicitly?
const bool precision_specified = state.conv.precision() >= 0;
@@ -903,16 +921,19 @@ void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
}
// ============ Fractional Digits ============
- int digits_emitted = 0;
+ size_t digits_emitted = 0;
while (mantissa > 0) {
*digits_iter++ = digits[GetNibble(mantissa, kTotalNibbles - 1)];
mantissa <<= 4;
++digits_emitted;
}
- int trailing_zeros =
- precision_specified ? state.precision - digits_emitted : 0;
- assert(trailing_zeros >= 0);
- auto digits_result = string_view(digits_buffer, digits_iter - digits_buffer);
+ size_t trailing_zeros = 0;
+ if (precision_specified) {
+ assert(state.precision >= digits_emitted);
+ trailing_zeros = state.precision - digits_emitted;
+ }
+ auto digits_result = string_view(
+ digits_buffer, static_cast<size_t>(digits_iter - digits_buffer));
// =============== Exponent ==================
constexpr size_t kBufSizeForExpDecRepr =
@@ -925,11 +946,11 @@ void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
numbers_internal::FastIntToBuffer(exp < 0 ? -exp : exp, exp_buffer + 2);
// ============ Assemble Result ==============
- FinalPrint(state, //
- digits_result, // 0xN.NNN...
- 2, // offset in `data` to start padding if needed.
- trailing_zeros, // num remaining mantissa padding zeros
- exp_buffer); // exponent
+ FinalPrint(state,
+ digits_result, // 0xN.NNN...
+ 2, // offset of any padding
+ static_cast<size_t>(trailing_zeros), // remaining mantissa padding
+ exp_buffer); // exponent
}
char *CopyStringTo(absl::string_view v, char *out) {
@@ -961,10 +982,10 @@ bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
int n = snprintf(&space[0], space.size(), fmt, w, p, v);
if (n < 0) return false;
if (static_cast<size_t>(n) < space.size()) {
- result = absl::string_view(space.data(), n);
+ result = absl::string_view(space.data(), static_cast<size_t>(n));
break;
}
- space.resize(n + 1);
+ space.resize(static_cast<size_t>(n) + 1);
}
sink->Append(result);
return true;
@@ -972,13 +993,13 @@ bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
// 128-bits in decimal: ceil(128*log(2)/log(10))
// or std::numeric_limits<__uint128_t>::digits10
-constexpr int kMaxFixedPrecision = 39;
+constexpr size_t kMaxFixedPrecision = 39;
-constexpr int kBufferLength = /*sign*/ 1 +
- /*integer*/ kMaxFixedPrecision +
- /*point*/ 1 +
- /*fraction*/ kMaxFixedPrecision +
- /*exponent e+123*/ 5;
+constexpr size_t kBufferLength = /*sign*/ 1 +
+ /*integer*/ kMaxFixedPrecision +
+ /*point*/ 1 +
+ /*fraction*/ kMaxFixedPrecision +
+ /*exponent e+123*/ 5;
struct Buffer {
void push_front(char c) {
@@ -1001,7 +1022,7 @@ struct Buffer {
char last_digit() const { return end[-1] == '.' ? end[-2] : end[-1]; }
- int size() const { return static_cast<int>(end - begin); }
+ size_t size() const { return static_cast<size_t>(end - begin); }
char data[kBufferLength];
char *begin;
@@ -1030,8 +1051,9 @@ bool ConvertNonNumericFloats(char sign_char, Float v,
return false;
}
- return sink->PutPaddedString(string_view(text, ptr - text), conv.width(), -1,
- conv.has_left_flag());
+ return sink->PutPaddedString(
+ string_view(text, static_cast<size_t>(ptr - text)), conv.width(), -1,
+ conv.has_left_flag());
}
// Round up the last digit of the value.
@@ -1068,11 +1090,11 @@ void PrintExponent(int exp, char e, Buffer *out) {
}
// Exponent digits.
if (exp > 99) {
- out->push_back(exp / 100 + '0');
+ out->push_back(static_cast<char>(exp / 100) + '0');
out->push_back(exp / 10 % 10 + '0');
out->push_back(exp % 10 + '0');
} else {
- out->push_back(exp / 10 + '0');
+ out->push_back(static_cast<char>(exp / 10) + '0');
out->push_back(exp % 10 + '0');
}
}
@@ -1115,8 +1137,8 @@ Decomposed<Float> Decompose(Float v) {
// In Fixed mode, we add a '.' at the end.
// In Precision mode, we add a '.' after the first digit.
template <FormatStyle mode, typename Int>
-int PrintIntegralDigits(Int digits, Buffer *out) {
- int printed = 0;
+size_t PrintIntegralDigits(Int digits, Buffer* out) {
+ size_t printed = 0;
if (digits) {
for (; digits; digits /= 10) out->push_front(digits % 10 + '0');
printed = out->size();
@@ -1135,10 +1157,10 @@ int PrintIntegralDigits(Int digits, Buffer *out) {
}
// Back out 'extra_digits' digits and round up if necessary.
-bool RemoveExtraPrecision(int extra_digits, bool has_leftover_value,
- Buffer *out, int *exp_out) {
- if (extra_digits <= 0) return false;
-
+void RemoveExtraPrecision(size_t extra_digits,
+ bool has_leftover_value,
+ Buffer* out,
+ int* exp_out) {
// Back out the extra digits
out->end -= extra_digits;
@@ -1158,15 +1180,17 @@ bool RemoveExtraPrecision(int extra_digits, bool has_leftover_value,
if (needs_to_round_up) {
RoundUp<FormatStyle::Precision>(out, exp_out);
}
- return true;
}
// Print the value into the buffer.
// This will not include the exponent, which will be returned in 'exp_out' for
// Precision mode.
template <typename Int, typename Float, FormatStyle mode>
-bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
- int *exp_out) {
+bool FloatToBufferImpl(Int int_mantissa,
+ int exp,
+ size_t precision,
+ Buffer* out,
+ int* exp_out) {
assert((CanFitMantissa<Float, Int>()));
const int int_bits = std::numeric_limits<Int>::digits;
@@ -1182,14 +1206,16 @@ bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
// The value will overflow the Int
return false;
}
- int digits_printed = PrintIntegralDigits<mode>(int_mantissa << exp, out);
- int digits_to_zero_pad = precision;
+ size_t digits_printed = PrintIntegralDigits<mode>(int_mantissa << exp, out);
+ size_t digits_to_zero_pad = precision;
if (mode == FormatStyle::Precision) {
- *exp_out = digits_printed - 1;
- digits_to_zero_pad -= digits_printed - 1;
- if (RemoveExtraPrecision(-digits_to_zero_pad, false, out, exp_out)) {
+ *exp_out = static_cast<int>(digits_printed - 1);
+ if (digits_to_zero_pad < digits_printed - 1) {
+ RemoveExtraPrecision(digits_printed - 1 - digits_to_zero_pad, false,
+ out, exp_out);
return true;
}
+ digits_to_zero_pad -= digits_printed - 1;
}
for (; digits_to_zero_pad-- > 0;) out->push_back('0');
return true;
@@ -1203,10 +1229,10 @@ bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
const Int mask = (Int{1} << exp) - 1;
// Print the integral part first.
- int digits_printed = PrintIntegralDigits<mode>(int_mantissa >> exp, out);
+ size_t digits_printed = PrintIntegralDigits<mode>(int_mantissa >> exp, out);
int_mantissa &= mask;
- int fractional_count = precision;
+ size_t fractional_count = precision;
if (mode == FormatStyle::Precision) {
if (digits_printed == 0) {
// Find the first non-zero digit, when in Precision mode.
@@ -1222,20 +1248,21 @@ bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
int_mantissa &= mask;
} else {
// We already have a digit, and a '.'
- *exp_out = digits_printed - 1;
- fractional_count -= *exp_out;
- if (RemoveExtraPrecision(-fractional_count, int_mantissa != 0, out,
- exp_out)) {
+ *exp_out = static_cast<int>(digits_printed - 1);
+ if (fractional_count < digits_printed - 1) {
// If we had enough digits, return right away.
// The code below will try to round again otherwise.
+ RemoveExtraPrecision(digits_printed - 1 - fractional_count,
+ int_mantissa != 0, out, exp_out);
return true;
}
+ fractional_count -= digits_printed - 1;
}
}
auto get_next_digit = [&] {
int_mantissa *= 10;
- int digit = static_cast<int>(int_mantissa >> exp);
+ char digit = static_cast<char>(int_mantissa >> exp);
int_mantissa &= mask;
return digit;
};
@@ -1245,7 +1272,7 @@ bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
out->push_back(get_next_digit() + '0');
}
- int next_digit = get_next_digit();
+ char next_digit = get_next_digit();
if (next_digit > 5 ||
(next_digit == 5 && (int_mantissa || out->last_digit() % 2 == 1))) {
RoundUp<mode>(out, exp_out);
@@ -1255,24 +1282,25 @@ bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
}
template <FormatStyle mode, typename Float>
-bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out,
- int *exp) {
+bool FloatToBuffer(Decomposed<Float> decomposed,
+ size_t precision,
+ Buffer* out,
+ int* exp) {
if (precision > kMaxFixedPrecision) return false;
// Try with uint64_t.
if (CanFitMantissa<Float, std::uint64_t>() &&
FloatToBufferImpl<std::uint64_t, Float, mode>(
- static_cast<std::uint64_t>(decomposed.mantissa),
- static_cast<std::uint64_t>(decomposed.exponent), precision, out, exp))
+ static_cast<std::uint64_t>(decomposed.mantissa), decomposed.exponent,
+ precision, out, exp))
return true;
#if defined(ABSL_HAVE_INTRINSIC_INT128)
// If that is not enough, try with __uint128_t.
return CanFitMantissa<Float, __uint128_t>() &&
FloatToBufferImpl<__uint128_t, Float, mode>(
- static_cast<__uint128_t>(decomposed.mantissa),
- static_cast<__uint128_t>(decomposed.exponent), precision, out,
- exp);
+ static_cast<__uint128_t>(decomposed.mantissa), decomposed.exponent,
+ precision, out, exp);
#endif
return false;
}
@@ -1280,12 +1308,15 @@ bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out,
void WriteBufferToSink(char sign_char, absl::string_view str,
const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
- int left_spaces = 0, zeros = 0, right_spaces = 0;
- int missing_chars =
- conv.width() >= 0 ? std::max(conv.width() - static_cast<int>(str.size()) -
- static_cast<int>(sign_char != 0),
- 0)
- : 0;
+ size_t left_spaces = 0, zeros = 0, right_spaces = 0;
+ size_t missing_chars = 0;
+ if (conv.width() >= 0) {
+ const size_t conv_width_size_t = static_cast<size_t>(conv.width());
+ const size_t existing_chars =
+ str.size() + static_cast<size_t>(sign_char != 0);
+ if (conv_width_size_t > existing_chars)
+ missing_chars = conv_width_size_t - existing_chars;
+ }
if (conv.has_left_flag()) {
right_spaces = missing_chars;
} else if (conv.has_zero_flag()) {
@@ -1321,7 +1352,8 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
return true;
}
- int precision = conv.precision() < 0 ? 6 : conv.precision();
+ size_t precision =
+ conv.precision() < 0 ? 6 : static_cast<size_t>(conv.precision());
int exp = 0;
@@ -1348,12 +1380,12 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
&buffer);
} else if (c == FormatConversionCharInternal::g ||
c == FormatConversionCharInternal::G) {
- precision = std::max(0, precision - 1);
+ precision = std::max(precision, size_t{1}) - 1;
if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
&exp)) {
return FallbackToSnprintf(v, conv, sink);
}
- if (precision + 1 > exp && exp >= -4) {
+ if ((exp < 0 || precision + 1 > static_cast<size_t>(exp)) && exp >= -4) {
if (exp < 0) {
// Have 1.23456, needs 0.00123456
// Move the first digit
@@ -1388,9 +1420,11 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
return false;
}
- WriteBufferToSink(sign_char,
- absl::string_view(buffer.begin, buffer.end - buffer.begin),
- conv, sink);
+ WriteBufferToSink(
+ sign_char,
+ absl::string_view(buffer.begin,
+ static_cast<size_t>(buffer.end - buffer.begin)),
+ conv, sink);
return true;
}