chromium/third_party/icu/source/i18n/unicode/numberformatter.h

// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

#ifndef __NUMBERFORMATTER_H__
#define __NUMBERFORMATTER_H__

#include "unicode/utypes.h"

#if U_SHOW_CPLUSPLUS_API

#if !UCONFIG_NO_FORMATTING

#include "unicode/appendable.h"
#include "unicode/bytestream.h"
#include "unicode/currunit.h"
#include "unicode/dcfmtsym.h"
#include "unicode/displayoptions.h"
#include "unicode/fieldpos.h"
#include "unicode/fpositer.h"
#include "unicode/measunit.h"
#include "unicode/nounit.h"
#include "unicode/parseerr.h"
#include "unicode/plurrule.h"
#include "unicode/ucurr.h"
#include "unicode/unum.h"
#include "unicode/unumberformatter.h"
#include "unicode/uobject.h"
#include "unicode/unumberoptions.h"
#include "unicode/formattednumber.h"

/**
 * \file
 * \brief C++ API: All-in-one formatter for localized numbers, currencies, and units.
 * 
 * For a full list of options, see icu::number::NumberFormatterSettings.
 *
 * <pre>
 * // Most basic usage:
 * NumberFormatter::withLocale(...).format(123).toString();  // 1,234 in en-US
 *
 * // Custom notation, unit, and rounding precision:
 * NumberFormatter::with()
 *     .notation(Notation::compactShort())
 *     .unit(CurrencyUnit("EUR", status))
 *     .precision(Precision::maxDigits(2))
 *     .locale(...)
 *     .format(1234)
 *     .toString();  // €1.2K in en-US
 *
 * // Create a formatter in a singleton by value for use later:
 * static const LocalizedNumberFormatter formatter = NumberFormatter::withLocale(...)
 *     .unit(NoUnit::percent())
 *     .precision(Precision::fixedFraction(3));
 * formatter.format(5.9831).toString();  // 5.983% in en-US
 *
 * // Create a "template" in a singleton unique_ptr but without setting a locale until the call site:
 * std::unique_ptr<UnlocalizedNumberFormatter> template = NumberFormatter::with()
 *     .sign(UNumberSignDisplay::UNUM_SIGN_ALWAYS)
 *     .unit(MeasureUnit::getMeter())
 *     .unitWidth(UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME)
 *     .clone();
 * template->locale(...).format(1234).toString();  // +1,234 meters in en-US
 * </pre>
 *
 * <p>
 * This API offers more features than DecimalFormat and is geared toward new users of ICU.
 *
 * <p>
 * NumberFormatter instances (i.e., LocalizedNumberFormatter and UnlocalizedNumberFormatter)
 * are immutable and thread safe. This means that invoking a configuration method has no
 * effect on the receiving instance; you must store and use the new number formatter instance it returns instead.
 *
 * <pre>
 * UnlocalizedNumberFormatter formatter = UnlocalizedNumberFormatter::with().notation(Notation::scientific());
 * formatter.precision(Precision.maxFraction(2)); // does nothing!
 * formatter.locale(Locale.getEnglish()).format(9.8765).toString(); // prints "9.8765E0", not "9.88E0"
 * </pre>
 *
 * <p>
 * This API is based on the <em>fluent</em> design pattern popularized by libraries such as Google's Guava. For
 * extensive details on the design of this API, read <a href="https://goo.gl/szi5VB">the design doc</a>.
 *
 * <p>
 * Note: To format monetary/currency values, specify the currency in the `.unit()` function.
 *
 * @author Shane Carr
 */

U_NAMESPACE_BEGIN

// Forward declarations:
class IFixedDecimal;
class FieldPositionIteratorHandler;
class FormattedStringBuilder;

namespace numparse {
namespace impl {

// Forward declarations:
class NumberParserImpl;
class MultiplierParseHandler;

}
}

namespace units {

// Forward declarations:
class UnitsRouter;

} // namespace units

namespace number {  // icu::number

// Forward declarations:
class UnlocalizedNumberFormatter;
class LocalizedNumberFormatter;
class SimpleNumberFormatter;
class FormattedNumber;
class Notation;
class ScientificNotation;
class Precision;
class FractionPrecision;
class CurrencyPrecision;
class IncrementPrecision;
class IntegerWidth;

namespace impl {

// can't be #ifndef U_HIDE_INTERNAL_API; referenced throughout this file in public classes
/**
 * Datatype for minimum/maximum fraction digits. Must be able to hold kMaxIntFracSig.
 *
 * @internal
 */
digits_t;

// can't be #ifndef U_HIDE_INTERNAL_API; needed for struct initialization
/**
 * Use a default threshold of 3. This means that the third time .format() is called, the data structures get built
 * using the "safe" code path. The first two calls to .format() will trigger the unsafe code path.
 *
 * @internal
 */
static constexpr int32_t kInternalDefaultThreshold =;

// Forward declarations:
class Padder;
struct MacroProps;
struct MicroProps;
class DecimalQuantity;
class UFormattedNumberData;
class NumberFormatterImpl;
struct ParsedPatternInfo;
class ScientificModifier;
class MultiplierProducer;
class RoundingImpl;
class ScientificHandler;
class Modifier;
class AffixPatternProvider;
class NumberPropertyMapper;
struct DecimalFormatProperties;
class MultiplierFormatHandler;
class CurrencySymbols;
class GeneratorHelpers;
class DecNum;
class NumberRangeFormatterImpl;
struct RangeMacroProps;
struct UFormattedNumberImpl;
class MutablePatternModifier;
class ImmutablePatternModifier;
struct DecimalFormatWarehouse;
struct SimpleMicroProps;
class AdoptingSignumModifierStore;

/**
 * Used for NumberRangeFormatter and implemented in numrange_fluent.cpp.
 * Declared here so it can be friended.
 *
 * @internal
 */
void touchRangeLocales(impl::RangeMacroProps& macros);

} // namespace impl

/**
 * Extra name reserved in case it is needed in the future.
 *
 * @stable ICU 63
 */
CompactNotation;

/**
 * Extra name reserved in case it is needed in the future.
 *
 * @stable ICU 63
 */
SimpleNotation;

/**
 * A class that defines the notation style to be used when formatting numbers in NumberFormatter.
 *
 * @stable ICU 60
 */
class U_I18N_API Notation : public UMemory {};

/**
 * A class that defines the scientific notation style to be used when formatting numbers in NumberFormatter.
 *
 * <p>
 * To create a ScientificNotation, use one of the factory methods in {@link Notation}.
 *
 * @stable ICU 60
 */
class U_I18N_API ScientificNotation : public Notation {};

/**
 * Extra name reserved in case it is needed in the future.
 *
 * @stable ICU 63
 */
SignificantDigitsPrecision;

/**
 * A class that defines the rounding precision to be used when formatting numbers in NumberFormatter.
 *
 * <p>
 * To create a Precision, use one of the factory methods.
 *
 * @stable ICU 60
 */
class U_I18N_API Precision : public UMemory {};

/**
 * A class that defines a rounding precision based on a number of fraction places and optionally significant digits to be
 * used when formatting numbers in NumberFormatter.
 *
 * <p>
 * To create a FractionPrecision, use one of the factory methods on Precision.
 *
 * @stable ICU 60
 */
class U_I18N_API FractionPrecision : public Precision {};

/**
 * A class that defines a rounding precision parameterized by a currency to be used when formatting numbers in
 * NumberFormatter.
 *
 * <p>
 * To create a CurrencyPrecision, use one of the factory methods on Precision.
 *
 * @stable ICU 60
 */
class U_I18N_API CurrencyPrecision : public Precision {};

/**
 * A class that defines a rounding precision parameterized by a rounding increment to be used when formatting numbers in
 * NumberFormatter.
 *
 * <p>
 * To create an IncrementPrecision, use one of the factory methods on Precision.
 *
 * @stable ICU 60
 */
class U_I18N_API IncrementPrecision : public Precision {};

/**
 * A class that defines the strategy for padding and truncating integers before the decimal separator.
 *
 * <p>
 * To create an IntegerWidth, use one of the factory methods.
 *
 * @stable ICU 60
 * @see NumberFormatter
 */
class U_I18N_API IntegerWidth : public UMemory {};

/**
 * A class that defines a quantity by which a number should be multiplied when formatting.
 *
 * <p>
 * To create a Scale, use one of the factory methods.
 *
 * @stable ICU 62
 */
class U_I18N_API Scale : public UMemory {};

namespace impl {

// Do not enclose entire StringProp with #ifndef U_HIDE_INTERNAL_API, needed for a protected field.
// And do not enclose its class boilerplate within #ifndef U_HIDE_INTERNAL_API.
/**
 * Manages NumberFormatterSettings::usage()'s char* instance on the heap.
 * @internal
 */
class U_I18N_API StringProp : public UMemory {};

// Do not enclose entire SymbolsWrapper with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
/** @internal */
class U_I18N_API SymbolsWrapper : public UMemory {};

// Do not enclose entire Grouper with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
/** @internal */
class U_I18N_API Grouper : public UMemory {};

// Do not enclose entire Padder with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
/** @internal */
class U_I18N_API Padder : public UMemory {};

// Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
/** @internal */
struct U_I18N_API MacroProps : public UMemory {};

} // namespace impl

#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER)
// Ignore MSVC warning 4661. This is generated for NumberFormatterSettings<>::toSkeleton() as this method
// is defined elsewhere (in number_skeletons.cpp). The compiler is warning that the explicit template instantiation
// inside this single translation unit (CPP file) is incomplete, and thus it isn't sure if the template class is
// fully defined. However, since each translation unit explicitly instantiates all the necessary template classes,
// they will all be passed to the linker, and the linker will still find and export all the class members.
#pragma warning(push)
#pragma warning(disable: 4661)
#endif

/**
 * An abstract base class for specifying settings related to number formatting. This class is implemented by
 * {@link UnlocalizedNumberFormatter} and {@link LocalizedNumberFormatter}. This class is not intended for
 * public subclassing.
 */
template<typename Derived>
class U_I18N_API NumberFormatterSettings {};

// Explicit instantiations in source/i18n/number_fluent.cpp.
// (MSVC treats imports/exports of explicit instantiations differently.)
#ifndef _MSC_VER
extern template class NumberFormatterSettings<UnlocalizedNumberFormatter>;
extern template class NumberFormatterSettings<LocalizedNumberFormatter>;
#endif

/**
 * A NumberFormatter that does not yet have a locale. In order to format numbers, a locale must be specified.
 *
 * Instances of this class are immutable and thread-safe.
 *
 * @see NumberFormatter
 * @stable ICU 60
 */
class U_I18N_API UnlocalizedNumberFormatter
        : public NumberFormatterSettings<UnlocalizedNumberFormatter>, public UMemory {};

/**
 * A NumberFormatter that has a locale associated with it; this means .format() methods are available.
 *
 * Instances of this class are immutable and thread-safe.
 *
 * @see NumberFormatter
 * @stable ICU 60
 */
class U_I18N_API LocalizedNumberFormatter
        : public NumberFormatterSettings<LocalizedNumberFormatter>, public UMemory {};

#if (U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(_MSC_VER)
// Warning 4661.
#pragma warning(pop)
#endif

/**
 * See the main description in numberformatter.h for documentation and examples.
 *
 * @stable ICU 60
 */
class U_I18N_API NumberFormatter final {};

}  // namespace number
U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_FORMATTING */

#endif /* U_SHOW_CPLUSPLUS_API */

#endif // __NUMBERFORMATTER_H__