Coverage Report

Created: 2025-06-24 06:43

/src/icu/source/i18n/number_padding.cpp
Line
Count
Source (jump to first uncovered line)
1
// © 2017 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
4
#include "unicode/utypes.h"
5
6
#if !UCONFIG_NO_FORMATTING
7
8
#include "unicode/numberformatter.h"
9
#include "number_types.h"
10
#include "formatted_string_builder.h"
11
#include "number_decimfmtprops.h"
12
13
using namespace icu;
14
using namespace icu::number;
15
using namespace icu::number::impl;
16
17
namespace {
18
19
int32_t
20
addPaddingHelper(UChar32 paddingCp, int32_t requiredPadding, FormattedStringBuilder &string, int32_t index,
21
0
                 UErrorCode &status) {
22
0
    for (int32_t i = 0; i < requiredPadding; i++) {
23
        // TODO: If appending to the end, this will cause actual insertion operations. Improve.
24
0
        string.insertCodePoint(index, paddingCp, kUndefinedField, status);
25
0
    }
26
0
    return U16_LENGTH(paddingCp) * requiredPadding;
27
0
}
28
29
}
30
31
0
Padder::Padder(UChar32 cp, int32_t width, UNumberFormatPadPosition position) : fWidth(width) {
32
    // TODO(13034): Consider making this a string instead of code point.
33
0
    fUnion.padding.fCp = cp;
34
0
    fUnion.padding.fPosition = position;
35
0
}
36
37
0
Padder::Padder(int32_t width) : fWidth(width) {}
38
39
0
Padder Padder::none() {
40
0
    return {-1};
41
0
}
42
43
0
Padder Padder::codePoints(UChar32 cp, int32_t targetWidth, UNumberFormatPadPosition position) {
44
    // TODO: Validate the code point?
45
0
    if (targetWidth >= 0) {
46
0
        return {cp, targetWidth, position};
47
0
    } else {
48
0
        return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
49
0
    }
50
0
}
51
52
0
Padder Padder::forProperties(const DecimalFormatProperties& properties) {
53
0
    UChar32 padCp;
54
0
    if (properties.padString.length() > 0) {
55
0
        padCp = properties.padString.char32At(0);
56
0
    } else {
57
0
        padCp = kFallbackPaddingString[0];
58
0
    }
59
0
    return {padCp, properties.formatWidth, properties.padPosition.getOrDefault(UNUM_PAD_BEFORE_PREFIX)};
60
0
}
61
62
int32_t Padder::padAndApply(const Modifier &mod1, const Modifier &mod2,
63
                            FormattedStringBuilder &string, int32_t leftIndex, int32_t rightIndex,
64
0
                            UErrorCode &status) const {
65
0
    int32_t modLength = mod1.getCodePointCount() + mod2.getCodePointCount();
66
0
    int32_t requiredPadding = fWidth - modLength - string.codePointCount();
67
0
    U_ASSERT(leftIndex == 0 &&
68
0
             rightIndex == string.length()); // fix the previous line to remove this assertion
69
70
0
    int length = 0;
71
0
    if (requiredPadding <= 0) {
72
        // Padding is not required.
73
0
        length += mod1.apply(string, leftIndex, rightIndex, status);
74
0
        length += mod2.apply(string, leftIndex, rightIndex + length, status);
75
0
        return length;
76
0
    }
77
78
0
    PadPosition position = fUnion.padding.fPosition;
79
0
    UChar32 paddingCp = fUnion.padding.fCp;
80
0
    if (position == UNUM_PAD_AFTER_PREFIX) {
81
0
        length += addPaddingHelper(paddingCp, requiredPadding, string, leftIndex, status);
82
0
    } else if (position == UNUM_PAD_BEFORE_SUFFIX) {
83
0
        length += addPaddingHelper(paddingCp, requiredPadding, string, rightIndex + length, status);
84
0
    }
85
0
    length += mod1.apply(string, leftIndex, rightIndex + length, status);
86
0
    length += mod2.apply(string, leftIndex, rightIndex + length, status);
87
0
    if (position == UNUM_PAD_BEFORE_PREFIX) {
88
0
        length += addPaddingHelper(paddingCp, requiredPadding, string, leftIndex, status);
89
0
    } else if (position == UNUM_PAD_AFTER_SUFFIX) {
90
0
        length += addPaddingHelper(paddingCp, requiredPadding, string, rightIndex + length, status);
91
0
    }
92
93
0
    return length;
94
0
}
95
96
#endif /* #if !UCONFIG_NO_FORMATTING */