97 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| // © 2017 and later: Unicode, Inc. and others.
 | |
| // License & terms of use: http://www.unicode.org/copyright.html
 | |
| 
 | |
| #include "unicode/utypes.h"
 | |
| 
 | |
| #if !UCONFIG_NO_FORMATTING
 | |
| 
 | |
| #include "unicode/numberformatter.h"
 | |
| #include "number_types.h"
 | |
| #include "formatted_string_builder.h"
 | |
| #include "number_decimfmtprops.h"
 | |
| 
 | |
| using namespace icu;
 | |
| using namespace icu::number;
 | |
| using namespace icu::number::impl;
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| int32_t
 | |
| addPaddingHelper(UChar32 paddingCp, int32_t requiredPadding, FormattedStringBuilder &string, int32_t index,
 | |
|                  UErrorCode &status) {
 | |
|     for (int32_t i = 0; i < requiredPadding; i++) {
 | |
|         // TODO: If appending to the end, this will cause actual insertion operations. Improve.
 | |
|         string.insertCodePoint(index, paddingCp, kUndefinedField, status);
 | |
|     }
 | |
|     return U16_LENGTH(paddingCp) * requiredPadding;
 | |
| }
 | |
| 
 | |
| }
 | |
| 
 | |
| Padder::Padder(UChar32 cp, int32_t width, UNumberFormatPadPosition position) : fWidth(width) {
 | |
|     // TODO(13034): Consider making this a string instead of code point.
 | |
|     fUnion.padding.fCp = cp;
 | |
|     fUnion.padding.fPosition = position;
 | |
| }
 | |
| 
 | |
| Padder::Padder(int32_t width) : fWidth(width) {}
 | |
| 
 | |
| Padder Padder::none() {
 | |
|     return {-1};
 | |
| }
 | |
| 
 | |
| Padder Padder::codePoints(UChar32 cp, int32_t targetWidth, UNumberFormatPadPosition position) {
 | |
|     // TODO: Validate the code point?
 | |
|     if (targetWidth >= 0) {
 | |
|         return {cp, targetWidth, position};
 | |
|     } else {
 | |
|         return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
 | |
|     }
 | |
| }
 | |
| 
 | |
| Padder Padder::forProperties(const DecimalFormatProperties& properties) {
 | |
|     UChar32 padCp;
 | |
|     if (properties.padString.length() > 0) {
 | |
|         padCp = properties.padString.char32At(0);
 | |
|     } else {
 | |
|         padCp = kFallbackPaddingString[0];
 | |
|     }
 | |
|     return {padCp, properties.formatWidth, properties.padPosition.getOrDefault(UNUM_PAD_BEFORE_PREFIX)};
 | |
| }
 | |
| 
 | |
| int32_t Padder::padAndApply(const Modifier &mod1, const Modifier &mod2,
 | |
|                             FormattedStringBuilder &string, int32_t leftIndex, int32_t rightIndex,
 | |
|                             UErrorCode &status) const {
 | |
|     int32_t modLength = mod1.getCodePointCount() + mod2.getCodePointCount();
 | |
|     int32_t requiredPadding = fWidth - modLength - string.codePointCount();
 | |
|     U_ASSERT(leftIndex == 0 &&
 | |
|              rightIndex == string.length()); // fix the previous line to remove this assertion
 | |
| 
 | |
|     int length = 0;
 | |
|     if (requiredPadding <= 0) {
 | |
|         // Padding is not required.
 | |
|         length += mod1.apply(string, leftIndex, rightIndex, status);
 | |
|         length += mod2.apply(string, leftIndex, rightIndex + length, status);
 | |
|         return length;
 | |
|     }
 | |
| 
 | |
|     PadPosition position = fUnion.padding.fPosition;
 | |
|     UChar32 paddingCp = fUnion.padding.fCp;
 | |
|     if (position == UNUM_PAD_AFTER_PREFIX) {
 | |
|         length += addPaddingHelper(paddingCp, requiredPadding, string, leftIndex, status);
 | |
|     } else if (position == UNUM_PAD_BEFORE_SUFFIX) {
 | |
|         length += addPaddingHelper(paddingCp, requiredPadding, string, rightIndex + length, status);
 | |
|     }
 | |
|     length += mod1.apply(string, leftIndex, rightIndex + length, status);
 | |
|     length += mod2.apply(string, leftIndex, rightIndex + length, status);
 | |
|     if (position == UNUM_PAD_BEFORE_PREFIX) {
 | |
|         length += addPaddingHelper(paddingCp, requiredPadding, string, leftIndex, status);
 | |
|     } else if (position == UNUM_PAD_AFTER_SUFFIX) {
 | |
|         length += addPaddingHelper(paddingCp, requiredPadding, string, rightIndex + length, status);
 | |
|     }
 | |
| 
 | |
|     return length;
 | |
| }
 | |
| 
 | |
| #endif /* #if !UCONFIG_NO_FORMATTING */
 |