Bug 1735352 - Part 3: Add wrapper for ICU4C specific library functions. r=platform-i18n-reviewers,gregtatum

Adds abstractions for `u_init()`, `u_cleanup()`, and `u_setMemoryFunctions()`,
and additionally a method to retrieve `U_ICU_VERSION`.

Because these methods are unlikely to replaceable with ICU4X, the class was
named "ICU4CLibrary" to make clear that the functionality is specific to ICU4C.

Differential Revision: https://phabricator.services.mozilla.com/D128228
This commit is contained in:
André Bargull 2021-10-12 17:09:04 +00:00
Родитель e5bef00d2b
Коммит 2c8cb57da2
5 изменённых файлов: 128 добавлений и 27 удалений

Просмотреть файл

@ -10,6 +10,7 @@ EXPORTS.mozilla.intl = [
"src/DateTimeFormat.h",
"src/DateTimePatternGenerator.h",
"src/ICU4CGlue.h",
"src/ICU4CLibrary.h",
"src/ICUError.h",
"src/ListFormat.h",
"src/Locale.h",
@ -32,6 +33,7 @@ UNIFIED_SOURCES += [
"src/DateTimeFormat.cpp",
"src/DateTimePatternGenerator.cpp",
"src/ICU4CGlue.cpp",
"src/ICU4CLibrary.cpp",
"src/ListFormat.cpp",
"src/LocaleCanonicalizer.cpp",
"src/MeasureUnit.cpp",

Просмотреть файл

@ -0,0 +1,41 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/intl/ICU4CLibrary.h"
#include "unicode/putil.h"
#include "unicode/uclean.h"
#include "unicode/utypes.h"
#include "unicode/uversion.h"
namespace mozilla::intl {
ICUResult ICU4CLibrary::Initialize() {
#if !MOZ_SYSTEM_ICU
// Explicitly set the data directory to its default value, but only when we're
// sure that we use our in-tree ICU copy. See bug 1527879 and ICU bug
// report <https://unicode-org.atlassian.net/browse/ICU-20491>.
u_setDataDirectory("");
#endif
UErrorCode status = U_ZERO_ERROR;
u_init(&status);
return ToICUResult(status);
}
void ICU4CLibrary::Cleanup() { u_cleanup(); }
ICUResult ICU4CLibrary::SetMemoryFunctions(MemoryFunctions aMemoryFunctions) {
UErrorCode status = U_ZERO_ERROR;
u_setMemoryFunctions(/* context = */ nullptr, aMemoryFunctions.mAllocFn,
aMemoryFunctions.mReallocFn, aMemoryFunctions.mFreeFn,
&status);
return ToICUResult(status);
}
Span<const char> ICU4CLibrary::GetVersion() {
return MakeStringSpan(U_ICU_VERSION);
}
} // namespace mozilla::intl

Просмотреть файл

@ -0,0 +1,74 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef intl_components_ICU4CLibrary_h
#define intl_components_ICU4CLibrary_h
#include "mozilla/intl/ICU4CGlue.h"
#include "mozilla/Span.h"
#include <stddef.h>
namespace mozilla::intl {
/**
* Wrapper around non-portable, ICU4C specific functions.
*/
class ICU4CLibrary final {
public:
ICU4CLibrary() = delete;
/**
* Initializes the ICU4C library.
*
* Note: This function should only be called once.
*/
static ICUResult Initialize();
/**
* Releases any memory held by ICU. Any open ICU objects and resources are
* left in an undefined state after this operation.
*
* NOTE: This function is not thread-safe.
*/
static void Cleanup();
struct MemoryFunctions {
// These are equivalent to ICU's |UMemAllocFn|, |UMemReallocFn|, and
// |UMemFreeFn| types. The first argument (called |context| in the ICU
// docs) will always be nullptr and should be ignored.
using AllocFn = void* (*)(const void*, size_t);
using ReallocFn = void* (*)(const void*, void*, size_t);
using FreeFn = void (*)(const void*, void*);
/**
* Function called when allocating memory.
*/
AllocFn mAllocFn = nullptr;
/**
* Function called when reallocating memory.
*/
ReallocFn mReallocFn = nullptr;
/**
* Function called when freeing memory.
*/
FreeFn mFreeFn = nullptr;
};
/**
* Sets the ICU memory functions.
*
* This function can only be called before the initial call to Initialize()!
*/
static ICUResult SetMemoryFunctions(MemoryFunctions aMemoryFunctions);
/**
* Return the ICU version number.
*/
static Span<const char> GetVersion();
};
} // namespace mozilla::intl
#endif

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/Casting.h"
#include "mozilla/FloatingPoint.h"
#ifdef JS_HAS_INTL_API
# include "mozilla/intl/ICU4CLibrary.h"
# include "mozilla/intl/Locale.h"
# include "mozilla/intl/String.h"
# include "mozilla/intl/TimeZone.h"
@ -103,9 +104,6 @@
#include "js/Vector.h"
#include "js/Wrapper.h"
#include "threading/CpuCount.h"
#ifdef JS_HAS_INTL_API
# include "unicode/uversion.h"
#endif
#include "util/DifferentialTesting.h"
#include "util/StringBuffer.h"
#include "util/Text.h"
@ -7321,7 +7319,7 @@ static bool GetICUOptions(JSContext* cx, unsigned argc, Value* vp) {
#ifdef JS_HAS_INTL_API
RootedString str(cx);
str = NewStringCopyZ<CanGC>(cx, U_ICU_VERSION);
str = NewStringCopy<CanGC>(cx, mozilla::intl::ICU4CLibrary::GetVersion());
if (!str || !JS_DefineProperty(cx, info, "version", str, JSPROP_ENUMERATE)) {
return false;
}

Просмотреть файл

@ -9,6 +9,9 @@
#include "js/Initialization.h"
#include "mozilla/Assertions.h"
#if JS_HAS_INTL_API
# include "mozilla/intl/ICU4CLibrary.h"
#endif
#include "mozilla/TextUtils.h"
#include "jstypes.h"
@ -22,13 +25,6 @@
#include "jit/JitCommon.h"
#include "jit/ProcessExecutableMemory.h"
#include "js/Utility.h"
#if JS_HAS_INTL_API
# include "unicode/putil.h"
# include "unicode/uclean.h"
# include "unicode/utypes.h"
#endif // JS_HAS_INTL_API
#include "threading/ProtectedData.h" // js::AutoNoteSingleThreadedRegion
#include "util/Poison.h"
#include "vm/ArrayBufferObject.h"
@ -193,17 +189,8 @@ JS_PUBLIC_API const char* JS::detail::InitWithFailureDiagnostic(
RETURN_IF_FAIL(js::jit::AtomicOperations::Initialize());
#if JS_HAS_INTL_API
# if !MOZ_SYSTEM_ICU
// Explicitly set the data directory to its default value, but only when we're
// sure that we use our in-tree ICU copy. See bug 1527879 and ICU bug
// report <https://unicode-org.atlassian.net/browse/ICU-20491>.
u_setDataDirectory("");
# endif
UErrorCode err = U_ZERO_ERROR;
u_init(&err);
if (U_FAILURE(err)) {
return "u_init() failed";
if (mozilla::intl::ICU4CLibrary::Initialize().isErr()) {
return "ICU4CLibrary::Initialize() failed";
}
#endif // JS_HAS_INTL_API
@ -310,7 +297,7 @@ JS_PUBLIC_API void JS_ShutDown(void) {
PRMJ_NowShutdown();
#if JS_HAS_INTL_API
u_cleanup();
mozilla::intl::ICU4CLibrary::Cleanup();
#endif // JS_HAS_INTL_API
#ifdef MOZ_VTUNE
@ -337,10 +324,9 @@ JS_PUBLIC_API bool JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn,
"operation (including JS_Init)");
#if JS_HAS_INTL_API
UErrorCode status = U_ZERO_ERROR;
u_setMemoryFunctions(/* context = */ nullptr, allocFn, reallocFn, freeFn,
&status);
return U_SUCCESS(status);
return mozilla::intl::ICU4CLibrary::SetMemoryFunctions(
{allocFn, reallocFn, freeFn})
.isOk();
#else
return true;
#endif