ICU-5316 Increase the performance of sprintf/sscanf

X-SVN-Rev: 20050
This commit is contained in:
George Rhoten 2006-08-12 09:47:38 +00:00
parent 13a2bd3fbb
commit 2a806e34dc
6 changed files with 153 additions and 9 deletions

View file

@ -1,6 +1,6 @@
#******************************************************************************
#
# Copyright (C) 1999-2005, International Business Machines
# Copyright (C) 1999-2006, International Business Machines
# Corporation and others. All Rights Reserved.
#
#******************************************************************************
@ -61,7 +61,7 @@ LIBS = $(LIBICUUC) $(LIBICUI18N) $(DEFAULT_LIBS)
OBJECTS = locbund.o ufile.o ufmt_cmn.o uprintf.o uprntf_p.o \
uscanf.o uscanf_p.o ustdio.o sprintf.o sscanf.o \
ustream.o
ustream.o ucln_io.o
## Header files to install
HEADERS = $(srcdir)/unicode/*.h

View file

@ -160,6 +160,9 @@
<File
RelativePath=".\sscanf.c">
</File>
<File
RelativePath=".\ucln_io.c">
</File>
<File
RelativePath=".\ufile.c">
</File>
@ -203,6 +206,9 @@
<File
RelativePath=".\locbund.h">
</File>
<File
RelativePath=".\ucln_io.h">
</File>
<File
RelativePath=".\ufile.h">
</File>

View file

@ -24,9 +24,51 @@
#include "cmemory.h"
#include "cstring.h"
#include "ucln_io.h"
#include "umutex.h"
#include "unicode/ustring.h"
#include "unicode/uloc.h"
static UBool isFormatsInitialized = FALSE;
static UNumberFormat *gPosixNumberFormat[ULOCALEBUNDLE_NUMBERFORMAT_COUNT];
U_CDECL_BEGIN
static UBool U_CALLCONV locbund_cleanup(void) {
int32_t style;
for (style = 0; style < ULOCALEBUNDLE_NUMBERFORMAT_COUNT; style++) {
unum_close(gPosixNumberFormat[style]);
gPosixNumberFormat[style] = NULL;
}
isFormatsInitialized = FALSE;
return TRUE;
}
U_CDECL_END
static U_INLINE UNumberFormat * copyInvariantFormatter(ULocaleBundle *result, UNumberFormatStyle style) {
if (result->fNumberFormat[style-1] == NULL) {
UErrorCode status = U_ZERO_ERROR;
UBool needsInit;
UMTX_CHECK(NULL, gPosixNumberFormat[style-1] == NULL, needsInit);
if (needsInit) {
UNumberFormat *formatAlias = unum_open(style, NULL, 0, "en_US_POSIX", NULL, &status);
/* Cache upon first request. */
if (U_SUCCESS(status)) {
umtx_lock(NULL);
gPosixNumberFormat[style-1] = formatAlias;
ucln_io_registerCleanup(UCLN_IO_LOCBUND, locbund_cleanup);
umtx_unlock(NULL);
}
}
/* Copy the needed formatter. */
result->fNumberFormat[style-1] = unum_clone(gPosixNumberFormat[style-1], &status);
}
return result->fNumberFormat[style-1];
}
ULocaleBundle*
u_locbund_init(ULocaleBundle *result, const char *loc)
{
@ -49,6 +91,8 @@ u_locbund_init(ULocaleBundle *result, const char *loc)
uprv_strcpy(result->fLocale, loc);
result->isInvariantLocale = uprv_strcmp(result->fLocale, "en_US_POSIX") == 0;
return result;
}
@ -121,14 +165,19 @@ u_locbund_getNumberFormat(ULocaleBundle *bundle, UNumberFormatStyle style)
if (style >= UNUM_IGNORE) {
formatAlias = bundle->fNumberFormat[style-1];
if (formatAlias == NULL) {
UErrorCode status = U_ZERO_ERROR;
formatAlias = unum_open(style, NULL, 0, bundle->fLocale, NULL, &status);
if (U_FAILURE(status)) {
unum_close(formatAlias);
formatAlias = NULL;
if (bundle->isInvariantLocale) {
formatAlias = copyInvariantFormatter(bundle, style);
}
else {
bundle->fNumberFormat[style-1] = formatAlias;
UErrorCode status = U_ZERO_ERROR;
formatAlias = unum_open(style, NULL, 0, bundle->fLocale, NULL, &status);
if (U_FAILURE(status)) {
unum_close(formatAlias);
formatAlias = NULL;
}
else {
bundle->fNumberFormat[style-1] = formatAlias;
}
}
}
}

View file

@ -1,7 +1,7 @@
/*
*******************************************************************************
*
* Copyright (C) 1998-2004, International Business Machines
* Copyright (C) 1998-2006s, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
@ -31,6 +31,7 @@ typedef struct ULocaleBundle {
char *fLocale;
UNumberFormat *fNumberFormat[ULOCALEBUNDLE_NUMBERFORMAT_COUNT];
UBool isInvariantLocale;
} ULocaleBundle;

51
icu4c/source/io/ucln_io.c Normal file
View file

@ -0,0 +1,51 @@
/*
******************************************************************************
* *
* Copyright (C) 2001-2006, International Business Machines *
* Corporation and others. All Rights Reserved. *
* *
******************************************************************************
* file name: ucln_io.c
* encoding: US-ASCII
* tab size: 8 (not used)
* indentation:4
*
* created on: 2006August11
* created by: George Rhoten
*/
#include "ucln.h"
#include "ucln_io.h"
#include "umutex.h"
#include "uassert.h"
/* Leave this copyright notice here! It needs to go somewhere in this library. */
static const char copyright[] = U_COPYRIGHT_STRING;
static cleanupFunc *gCleanupFunctions[UCLN_IO_COUNT];
static UBool io_cleanup(void)
{
ECleanupIOType libType;
for (libType = UCLN_IO_START+1; libType<UCLN_IO_COUNT; libType++) {
if (gCleanupFunctions[libType])
{
gCleanupFunctions[libType]();
gCleanupFunctions[libType] = NULL;
}
}
return TRUE;
}
void ucln_io_registerCleanup(ECleanupIOType type,
cleanupFunc *func)
{
U_ASSERT(UCLN_IO_START < type && type < UCLN_IO_COUNT);
ucln_registerCleanup(UCLN_IO, io_cleanup);
if (UCLN_IO_START < type && type < UCLN_IO_COUNT)
{
gCleanupFunctions[type] = func;
}
}

37
icu4c/source/io/ucln_io.h Normal file
View file

@ -0,0 +1,37 @@
/*
******************************************************************************
* *
* Copyright (C) 2001-2006, International Business Machines *
* Corporation and others. All Rights Reserved. *
* *
******************************************************************************
* file name: ucln_io.h
* encoding: US-ASCII
* tab size: 8 (not used)
* indentation:4
*
* created on: 2006August11
* created by: George Rhoten
*/
#ifndef __UCLN_IO_H__
#define __UCLN_IO_H__
#include "unicode/utypes.h"
#include "ucln.h"
/*
Please keep the order of enums declared in same order
as the functions are suppose to be called. */
typedef enum ECleanupIOType {
UCLN_IO_START = -1,
UCLN_IO_LOCBUND,
UCLN_IO_COUNT /* This must be last */
} ECleanupIOType;
/* Main library cleanup registration function. */
/* See common/ucln.h for details on adding a cleanup function. */
U_CFUNC void U_EXPORT2 ucln_io_registerCleanup(ECleanupIOType type,
cleanupFunc *func);
#endif