1 // © 2017 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 #include "unicode/utypes.h"
6 #if !UCONFIG_NO_FORMATTING
8 #include "unicode/numberformatter.h"
9 #include "number_types.h"
10 #include "number_stringbuilder.h"
11 #include "number_decimfmtprops.h"
14 using namespace icu::number
;
15 using namespace icu::number::impl
;
20 addPaddingHelper(UChar32 paddingCp
, int32_t requiredPadding
, NumberStringBuilder
&string
, int32_t index
,
22 for (int32_t i
= 0; i
< requiredPadding
; i
++) {
23 // TODO: If appending to the end, this will cause actual insertion operations. Improve.
24 string
.insertCodePoint(index
, paddingCp
, UNUM_FIELD_COUNT
, status
);
26 return U16_LENGTH(paddingCp
) * requiredPadding
;
31 Padder::Padder(UChar32 cp
, int32_t width
, UNumberFormatPadPosition position
) : fWidth(width
) {
32 // TODO(13034): Consider making this a string instead of code point.
33 fUnion
.padding
.fCp
= cp
;
34 fUnion
.padding
.fPosition
= position
;
37 Padder::Padder(int32_t width
) : fWidth(width
) {}
39 Padder
Padder::none() {
43 Padder
Padder::codePoints(UChar32 cp
, int32_t targetWidth
, UNumberFormatPadPosition position
) {
44 // TODO: Validate the code point?
45 if (targetWidth
>= 0) {
46 return {cp
, targetWidth
, position
};
48 return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR
};
52 Padder
Padder::forProperties(const DecimalFormatProperties
& properties
) {
54 if (properties
.padString
.length() > 0) {
55 padCp
= properties
.padString
.char32At(0);
57 padCp
= kFallbackPaddingString
[0];
59 return {padCp
, properties
.formatWidth
, properties
.padPosition
.getOrDefault(UNUM_PAD_BEFORE_PREFIX
)};
62 int32_t Padder::padAndApply(const Modifier
&mod1
, const Modifier
&mod2
,
63 NumberStringBuilder
&string
, int32_t leftIndex
, int32_t rightIndex
,
64 UErrorCode
&status
) const {
65 int32_t modLength
= mod1
.getCodePointCount(status
) + mod2
.getCodePointCount(status
);
66 int32_t requiredPadding
= fWidth
- modLength
- string
.codePointCount();
67 U_ASSERT(leftIndex
== 0 &&
68 rightIndex
== string
.length()); // fix the previous line to remove this assertion
71 if (requiredPadding
<= 0) {
72 // Padding is not required.
73 length
+= mod1
.apply(string
, leftIndex
, rightIndex
, status
);
74 length
+= mod2
.apply(string
, leftIndex
, rightIndex
+ length
, status
);
78 PadPosition position
= fUnion
.padding
.fPosition
;
79 UChar32 paddingCp
= fUnion
.padding
.fCp
;
80 if (position
== UNUM_PAD_AFTER_PREFIX
) {
81 length
+= addPaddingHelper(paddingCp
, requiredPadding
, string
, leftIndex
, status
);
82 } else if (position
== UNUM_PAD_BEFORE_SUFFIX
) {
83 length
+= addPaddingHelper(paddingCp
, requiredPadding
, string
, rightIndex
+ length
, status
);
85 length
+= mod1
.apply(string
, leftIndex
, rightIndex
+ length
, status
);
86 length
+= mod2
.apply(string
, leftIndex
, rightIndex
+ length
, status
);
87 if (position
== UNUM_PAD_BEFORE_PREFIX
) {
88 length
+= addPaddingHelper(paddingCp
, requiredPadding
, string
, leftIndex
, status
);
89 } else if (position
== UNUM_PAD_AFTER_SUFFIX
) {
90 length
+= addPaddingHelper(paddingCp
, requiredPadding
, string
, rightIndex
+ length
, status
);
96 #endif /* #if !UCONFIG_NO_FORMATTING */