BNumberFormat: cache ICU formatters
For performance reasons, it is a good idea to keep the formatters instanciated, instead of re-creating them each time we need to format a number.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2014, Haiku, Inc.
|
* Copyright 2003-2017, Haiku, Inc.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _B_NUMBER_FORMAT_H_
|
#ifndef _B_NUMBER_FORMAT_H_
|
||||||
@@ -16,30 +16,31 @@ enum BNumberElement {
|
|||||||
B_NUMBER_ELEMENT_CURRENCY
|
B_NUMBER_ELEMENT_CURRENCY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BNumberFormatImpl;
|
||||||
|
|
||||||
|
|
||||||
class BNumberFormat : public BFormat {
|
class BNumberFormat : public BFormat {
|
||||||
public:
|
public:
|
||||||
BNumberFormat();
|
BNumberFormat();
|
||||||
BNumberFormat(const BNumberFormat &other);
|
|
||||||
~BNumberFormat();
|
~BNumberFormat();
|
||||||
|
|
||||||
// formatting
|
|
||||||
|
|
||||||
ssize_t Format(char* string, size_t maxSize,
|
ssize_t Format(char* string, size_t maxSize,
|
||||||
const double value) const;
|
const double value);
|
||||||
status_t Format(BString& string, const double value)
|
status_t Format(BString& string, const double value);
|
||||||
const;
|
|
||||||
ssize_t Format(char* string, size_t maxSize,
|
ssize_t Format(char* string, size_t maxSize,
|
||||||
const int32 value) const;
|
const int32 value);
|
||||||
status_t Format(BString& string, const int32 value)
|
status_t Format(BString& string, const int32 value);
|
||||||
const;
|
|
||||||
|
|
||||||
// monetary
|
|
||||||
|
|
||||||
ssize_t FormatMonetary(char* string, size_t maxSize,
|
ssize_t FormatMonetary(char* string, size_t maxSize,
|
||||||
const double value) const;
|
const double value);
|
||||||
status_t FormatMonetary(BString& string,
|
status_t FormatMonetary(BString& string,
|
||||||
const double value) const;
|
const double value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BNumberFormat(const BNumberFormat &other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BNumberFormatImpl* fPrivateData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,20 +18,122 @@
|
|||||||
#include <unicode/numfmt.h>
|
#include <unicode/numfmt.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BNumberFormatImpl {
|
||||||
|
public:
|
||||||
|
BNumberFormatImpl();
|
||||||
|
~BNumberFormatImpl();
|
||||||
|
|
||||||
|
NumberFormat* GetInteger(BFormattingConventions* convention);
|
||||||
|
NumberFormat* GetFloat(BFormattingConventions* convention);
|
||||||
|
NumberFormat* GetCurrency(BFormattingConventions* convention);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NumberFormat* fIntegerFormat;
|
||||||
|
NumberFormat* fFloatFormat;
|
||||||
|
NumberFormat* fCurrencyFormat;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
BNumberFormatImpl::BNumberFormatImpl()
|
||||||
|
{
|
||||||
|
// They are initialized lazily as needed
|
||||||
|
fIntegerFormat = NULL;
|
||||||
|
fFloatFormat = NULL;
|
||||||
|
fCurrencyFormat = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BNumberFormatImpl::~BNumberFormatImpl()
|
||||||
|
{
|
||||||
|
delete fIntegerFormat;
|
||||||
|
delete fFloatFormat;
|
||||||
|
delete fCurrencyFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NumberFormat*
|
||||||
|
BNumberFormatImpl::GetInteger(BFormattingConventions* convention)
|
||||||
|
{
|
||||||
|
if (fIntegerFormat == NULL) {
|
||||||
|
UErrorCode err = U_ZERO_ERROR;
|
||||||
|
fIntegerFormat = NumberFormat::createInstance(
|
||||||
|
*BFormattingConventions::Private(convention).ICULocale(),
|
||||||
|
UNUM_DECIMAL, err);
|
||||||
|
|
||||||
|
if (fIntegerFormat == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (U_FAILURE(err)) {
|
||||||
|
delete fIntegerFormat;
|
||||||
|
fIntegerFormat = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fIntegerFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NumberFormat*
|
||||||
|
BNumberFormatImpl::GetFloat(BFormattingConventions* convention)
|
||||||
|
{
|
||||||
|
if (fFloatFormat == NULL) {
|
||||||
|
UErrorCode err = U_ZERO_ERROR;
|
||||||
|
fFloatFormat = NumberFormat::createInstance(
|
||||||
|
*BFormattingConventions::Private(convention).ICULocale(),
|
||||||
|
UNUM_DECIMAL, err);
|
||||||
|
|
||||||
|
if (fFloatFormat == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (U_FAILURE(err)) {
|
||||||
|
delete fFloatFormat;
|
||||||
|
fFloatFormat = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fFloatFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NumberFormat*
|
||||||
|
BNumberFormatImpl::GetCurrency(BFormattingConventions* convention)
|
||||||
|
{
|
||||||
|
if (fCurrencyFormat == NULL) {
|
||||||
|
UErrorCode err = U_ZERO_ERROR;
|
||||||
|
fCurrencyFormat = NumberFormat::createCurrencyInstance(
|
||||||
|
*BFormattingConventions::Private(convention).ICULocale(),
|
||||||
|
err);
|
||||||
|
|
||||||
|
if (fCurrencyFormat == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (U_FAILURE(err)) {
|
||||||
|
delete fCurrencyFormat;
|
||||||
|
fCurrencyFormat = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fCurrencyFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BNumberFormat::BNumberFormat()
|
BNumberFormat::BNumberFormat()
|
||||||
: BFormat()
|
: BFormat()
|
||||||
{
|
{
|
||||||
|
fPrivateData = new BNumberFormatImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BNumberFormat::BNumberFormat(const BNumberFormat &other)
|
BNumberFormat::BNumberFormat(const BNumberFormat &other)
|
||||||
: BFormat(other)
|
: BFormat(other)
|
||||||
{
|
{
|
||||||
|
fPrivateData = new BNumberFormatImpl(*other.fPrivateData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BNumberFormat::~BNumberFormat()
|
BNumberFormat::~BNumberFormat()
|
||||||
{
|
{
|
||||||
|
delete fPrivateData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -39,7 +141,7 @@ BNumberFormat::~BNumberFormat()
|
|||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
BNumberFormat::Format(char* string, size_t maxSize, const double value) const
|
BNumberFormat::Format(char* string, size_t maxSize, const double value)
|
||||||
{
|
{
|
||||||
BString fullString;
|
BString fullString;
|
||||||
status_t status = Format(fullString, value);
|
status_t status = Format(fullString, value);
|
||||||
@@ -51,20 +153,15 @@ BNumberFormat::Format(char* string, size_t maxSize, const double value) const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BNumberFormat::Format(BString& string, const double value) const
|
BNumberFormat::Format(BString& string, const double value)
|
||||||
{
|
{
|
||||||
UErrorCode err = U_ZERO_ERROR;
|
NumberFormat* formatter = fPrivateData->GetFloat(&fConventions);
|
||||||
ObjectDeleter<NumberFormat> numberFormatter(NumberFormat::createInstance(
|
|
||||||
*BFormattingConventions::Private(&fConventions).ICULocale(),
|
|
||||||
UNUM_DECIMAL, err));
|
|
||||||
|
|
||||||
if (numberFormatter.Get() == NULL)
|
if (formatter == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
if (U_FAILURE(err))
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
UnicodeString icuString;
|
UnicodeString icuString;
|
||||||
numberFormatter->format(value, icuString);
|
formatter->format(value, icuString);
|
||||||
|
|
||||||
string.Truncate(0);
|
string.Truncate(0);
|
||||||
BStringByteSink stringConverter(&string);
|
BStringByteSink stringConverter(&string);
|
||||||
@@ -75,7 +172,7 @@ BNumberFormat::Format(BString& string, const double value) const
|
|||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
BNumberFormat::Format(char* string, size_t maxSize, const int32 value) const
|
BNumberFormat::Format(char* string, size_t maxSize, const int32 value)
|
||||||
{
|
{
|
||||||
BString fullString;
|
BString fullString;
|
||||||
status_t status = Format(fullString, value);
|
status_t status = Format(fullString, value);
|
||||||
@@ -87,20 +184,15 @@ BNumberFormat::Format(char* string, size_t maxSize, const int32 value) const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BNumberFormat::Format(BString& string, const int32 value) const
|
BNumberFormat::Format(BString& string, const int32 value)
|
||||||
{
|
{
|
||||||
UErrorCode err = U_ZERO_ERROR;
|
NumberFormat* formatter = fPrivateData->GetInteger(&fConventions);
|
||||||
ObjectDeleter<NumberFormat> numberFormatter(NumberFormat::createInstance(
|
|
||||||
*BFormattingConventions::Private(&fConventions).ICULocale(),
|
|
||||||
UNUM_DECIMAL, err));
|
|
||||||
|
|
||||||
if (numberFormatter.Get() == NULL)
|
if (formatter == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
if (U_FAILURE(err))
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
UnicodeString icuString;
|
UnicodeString icuString;
|
||||||
numberFormatter->format((int32_t)value, icuString);
|
formatter->format((int32_t)value, icuString);
|
||||||
|
|
||||||
string.Truncate(0);
|
string.Truncate(0);
|
||||||
BStringByteSink stringConverter(&string);
|
BStringByteSink stringConverter(&string);
|
||||||
@@ -112,7 +204,6 @@ BNumberFormat::Format(BString& string, const int32 value) const
|
|||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
BNumberFormat::FormatMonetary(char* string, size_t maxSize, const double value)
|
BNumberFormat::FormatMonetary(char* string, size_t maxSize, const double value)
|
||||||
const
|
|
||||||
{
|
{
|
||||||
BString fullString;
|
BString fullString;
|
||||||
status_t status = FormatMonetary(fullString, value);
|
status_t status = FormatMonetary(fullString, value);
|
||||||
@@ -124,24 +215,15 @@ BNumberFormat::FormatMonetary(char* string, size_t maxSize, const double value)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BNumberFormat::FormatMonetary(BString& string, const double value) const
|
BNumberFormat::FormatMonetary(BString& string, const double value)
|
||||||
{
|
{
|
||||||
if (string == NULL)
|
NumberFormat* formatter = fPrivateData->GetCurrency(&fConventions);
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
UErrorCode err = U_ZERO_ERROR;
|
if (formatter == NULL)
|
||||||
ObjectDeleter<NumberFormat> numberFormatter(
|
|
||||||
NumberFormat::createCurrencyInstance(
|
|
||||||
*BFormattingConventions::Private(&fConventions).ICULocale(),
|
|
||||||
err));
|
|
||||||
|
|
||||||
if (numberFormatter.Get() == NULL)
|
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
if (U_FAILURE(err))
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
UnicodeString icuString;
|
UnicodeString icuString;
|
||||||
numberFormatter->format(value, icuString);
|
formatter->format(value, icuString);
|
||||||
|
|
||||||
string.Truncate(0);
|
string.Truncate(0);
|
||||||
BStringByteSink stringConverter(&string);
|
BStringByteSink stringConverter(&string);
|
||||||
|
|||||||
Reference in New Issue
Block a user