void register_libcore_icu_ICU(JNIEnv* env) { std::string path; path = u_getDataDirectory(); path += "/"; path += U_ICUDATA_NAME; path += ".dat"; #define FAIL_WITH_STRERROR(s) \ ALOGE("Couldn't " s " '%s': %s", path.c_str(), strerror(errno)); \ abort(); #define MAYBE_FAIL_WITH_ICU_ERROR(s) \ if (status != U_ZERO_ERROR) {\ ALOGE("Couldn't initialize ICU (" s "): %s (%s)", u_errorName(status), path.c_str()); \ abort(); \ } // Open the file and get its length. ScopedFd fd(open(path.c_str(), O_RDONLY)); if (fd.get() == -1) { FAIL_WITH_STRERROR("open"); } struct stat sb; if (fstat(fd.get(), &sb) == -1) { FAIL_WITH_STRERROR("stat"); } // Map it. void* data = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd.get(), 0); if (data == MAP_FAILED) { FAIL_WITH_STRERROR("mmap"); } // Tell the kernel that accesses are likely to be random rather than sequential. if (madvise(data, sb.st_size, MADV_RANDOM) == -1) { FAIL_WITH_STRERROR("madvise(MADV_RANDOM)"); } // Tell ICU to use our memory-mapped data. UErrorCode status = U_ZERO_ERROR; udata_setCommonData(data, &status); MAYBE_FAIL_WITH_ICU_ERROR("udata_setCommonData"); // Tell ICU it can *only* use our memory-mapped data. udata_setFileAccess(UDATA_NO_FILES, &status); MAYBE_FAIL_WITH_ICU_ERROR("udata_setFileAccess"); // Failures to find the ICU data tend to be somewhat obscure because ICU loads its data on first // use, which can be anywhere. Force initialization up front so we can report a nice clear error // and bail. u_init(&status); MAYBE_FAIL_WITH_ICU_ERROR("u_init"); jniRegisterNativeMethods(env, "libcore/icu/ICU", gMethods, NELEM(gMethods)); }
int register_libcore_icu_ICU(JNIEnv* env) { std::string path; #define FAIL_WITH_STRERROR(s) \ ALOGE("Couldn't " s " '%s': %s", path.c_str(), strerror(errno)); \ abort(); #define MAYBE_FAIL_WITH_ICU_ERROR(s) \ if (status != U_ZERO_ERROR) {\ ALOGE("Couldn't initialize ICU (" s "): %s (%s)", u_errorName(status), path.c_str()); \ abort(); \ } // RoboVM note: Start change. Look for custom ICU data and fall back to builtin minimal data if not found. if (!findCustomICUData(path)) { ALOGI("Using builtin minimal ICU data"); void* data = malloc(out_icudt51l_dat_len); if (!data) { ALOGE("Failed to allocate %d bytes for builtin ICU data", out_icudt51l_dat_len); abort(); } int ret = inflate(out_icudt51l_dat_gz, out_icudt51l_dat_gz_len, data, out_icudt51l_dat_len); if (ret != out_icudt51l_dat_len) { ALOGE("Failed to inflate %d->%d bytes of builtin ICU data: %d", out_icudt51l_dat_gz_len, out_icudt51l_dat_len, ret); abort(); } UErrorCode status = U_ZERO_ERROR; udata_setCommonData(data, &status); MAYBE_FAIL_WITH_ICU_ERROR("udata_setCommonData"); // Tell ICU it can *only* use our data. udata_setFileAccess(UDATA_NO_FILES, &status); MAYBE_FAIL_WITH_ICU_ERROR("udata_setFileAccess"); // Force initialization up front so we can report a nice clear error and bail. u_init(&status); MAYBE_FAIL_WITH_ICU_ERROR("u_init"); return 0; } ALOGI("Using custom ICU data file: '%s'", path.c_str()); // RoboVM note: End change. // Open the file and get its length. ScopedFd fd(open(path.c_str(), O_RDONLY)); if (fd.get() == -1) { FAIL_WITH_STRERROR("open"); } struct stat sb; if (fstat(fd.get(), &sb) == -1) { FAIL_WITH_STRERROR("stat"); } // Map it. void* data = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd.get(), 0); if (data == MAP_FAILED) { FAIL_WITH_STRERROR("mmap"); } // Tell the kernel that accesses are likely to be random rather than sequential. if (madvise(data, sb.st_size, MADV_RANDOM) == -1) { FAIL_WITH_STRERROR("madvise(MADV_RANDOM)"); } // Tell ICU to use our memory-mapped data. UErrorCode status = U_ZERO_ERROR; udata_setCommonData(data, &status); MAYBE_FAIL_WITH_ICU_ERROR("udata_setCommonData"); // Tell ICU it can *only* use our memory-mapped data. udata_setFileAccess(UDATA_NO_FILES, &status); MAYBE_FAIL_WITH_ICU_ERROR("udata_setFileAccess"); // Failures to find the ICU data tend to be somewhat obscure because ICU loads its data on first // use, which can be anywhere. Force initialization up front so we can report a nice clear error // and bail. u_init(&status); MAYBE_FAIL_WITH_ICU_ERROR("u_init"); return 0; }