blob: fb6cf07bbd800d3ef99f91a170c2f10042eec373 [file] [log] [blame]
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
* Copyright (C) 2015, International Business Machines
* Corporation and others. All Rights Reserved.
*
* file name: smallintformatter.cpp
*/
#include "unicode/unistr.h"
#include "smallintformatter.h"
// Maximal number of decimal digits that can be generated by the ::format()
// method below.
static constexpr int kMaxDigits = 6;
// The corresponding decimal limit, anything greater or equal than this
// value cannot be fast-formatted. Must be 10^kMaxDigits.
static constexpr int32_t kMaxFastInt = 1000000;
// Return the number of decimal digits needed to print |value|.
// Results are only guaranteed if |value| in in [0..kMaxFastInt) range.
static constexpr int digitCount(int32_t value) {
// NOTE: The following expressions generates the smallest and fastest
// machine code for this function on 32-bit ARM.
return (value >= 1000) ? (4 + (value >= 10000) + (value >= 100000)) :
(1 + (value >= 10) + (value >= 100));
}
static_assert(digitCount(0) == 1, "digitCount() is invalid");
static_assert(digitCount(1) == 1, "digitCount() is invalid");
static_assert(digitCount(9) == 1, "digitCount() is invalid");
static_assert(digitCount(10) == 2, "digitCount() is invalid");
static_assert(digitCount(99) == 2, "digitCount() is invalid");
static_assert(digitCount(100) == 3, "digitCount() is invalid");
static_assert(digitCount(999) == 3, "digitCount() is invalid");
static_assert(digitCount(1000) == 4, "digitCount() is invalid");
static_assert(digitCount(9999) == 4, "digitCount() is invalid");
static_assert(digitCount(10000) == 5, "digitCount() is invalid");
static_assert(digitCount(99999) == 5, "digitCount() is invalid");
static_assert(digitCount(100000) == 6, "digitCount() is invalid");
static_assert(digitCount(999999) == 6, "digitCount() is invalid");
U_NAMESPACE_BEGIN
IntDigitCountRange::IntDigitCountRange(int32_t min, int32_t max) {
fMin = min < 0 ? 0 : min;
fMax = max < fMin ? fMin : max;
}
int32_t
IntDigitCountRange::pin(int32_t digitCount) const {
return digitCount < fMin ? fMin : (digitCount < fMax ? digitCount : fMax);
}
int32_t
SmallIntFormatter::estimateDigitCount(
int32_t positiveValue, const IntDigitCountRange &range) {
if (positiveValue >= kMaxFastInt) {
return range.getMax();
}
return range.pin(digitCount(positiveValue));
}
UBool
SmallIntFormatter::canFormat(
int32_t positiveValue, const IntDigitCountRange &range) {
return (positiveValue < kMaxFastInt && range.getMin() <= kMaxDigits);
}
UnicodeString &
SmallIntFormatter::format(
int32_t smallPositiveValue,
const IntDigitCountRange &range,
UnicodeString &appendTo) {
int digits = range.pin(digitCount(smallPositiveValue));
// Always emit at least '0'
if (digits == 0) {
return appendTo.append((UChar) 0x30);
}
// Sanity check
if (digits > kMaxDigits) {
digits = kMaxDigits;
}
// Write up to kMaxDigits digits in |chars| array, from the end of the
// array so that the result doesn't need reversal.
UChar chars[kMaxDigits];
for (int n = 0; n < digits; ++n) {
chars[kMaxDigits - 1 - n] = (UChar)(0x30 + smallPositiveValue % 10);
smallPositiveValue /= 10;
}
return appendTo.append(chars, kMaxDigits - digits, digits);
}
U_NAMESPACE_END