[DO-981] qt package (!15)

Co-authored-by: aleksandr.vodyanov <aleksandr.vodyanov@avroid.tech>
Reviewed-on: https://git.avroid.tech/Conan/conan_build/pulls/15
This commit is contained in:
Aleksandr Vodyanov
2025-02-13 12:25:48 +03:00
parent 60445ac09e
commit 3759e1163f
228 changed files with 16106 additions and 12 deletions

View File

@@ -0,0 +1,49 @@
sources:
"76.1":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-76-1/icu4c-76_1-src.tgz"
sha256: "dfacb46bfe4747410472ce3e1144bf28a102feeaa4e3875bac9b4c6cf30f4f3e"
"75.1":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-75-1/icu4c-75_1-src.tgz"
sha256: "cb968df3e4d2e87e8b11c49a5d01c787bd13b9545280fc6642f826527618caef"
"74.2":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-74-2/icu4c-74_2-src.tgz"
sha256: "68db082212a96d6f53e35d60f47d38b962e9f9d207a74cfac78029ae8ff5e08c"
"74.1":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-74-1/icu4c-74_1-src.tgz"
sha256: "86ce8e60681972e60e4dcb2490c697463fcec60dd400a5f9bffba26d0b52b8d0"
"73.2":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-73-2/icu4c-73_2-src.tgz"
sha256: "818a80712ed3caacd9b652305e01afc7fa167e6f2e94996da44b90c2ab604ce1"
"73.1":
url: "https://nexus.avroid.tech/repository/devops-raw-proxy-github/unicode-org/icu/releases/download/release-73-1/icu4c-73_1-src.tgz"
sha256: "a457431de164b4aa7eca00ed134d00dfbf88a77c6986a10ae7774fc076bb8c45"
patches:
"76.1":
- patch_file: "patches/0001-76.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"
"75.1":
- patch_file: "patches/0001-69.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"
"74.2":
- patch_file: "patches/0001-69.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"
- patch_file: "patches/0002-74.2-fix-emscripten.patch"
patch_description: "Add config file for wasm-emscripten platform"
patch_type: "portability"
patch_source: "https://gerrit.libreoffice.org/c/core/+/111130/9/external/icu/icu4c-emscripten-cross.patch.1"
"74.1":
- patch_file: "patches/0001-69.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"
"73.2":
- patch_file: "patches/0001-69.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"
"73.1":
- patch_file: "patches/0001-69.1-fix-mingw.patch"
patch_description: "support mingw"
patch_type: "portability"

View File

@@ -0,0 +1,374 @@
import glob
import hashlib
import os
import shutil
from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.apple import is_apple_os
from conan.tools.build import cross_building, stdcpp_library, check_min_cppstd
from conan.tools.env import Environment, VirtualBuildEnv
from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, mkdir, rename, replace_in_file, rm, rmdir, save
from conan.tools.gnu import Autotools, AutotoolsToolchain
from conan.tools.layout import basic_layout
from conan.tools.microsoft import check_min_vs, is_msvc, unix_path
from conan.tools.scm import Version
required_conan_version = ">=1.57.0"
class ICUConan(ConanFile):
name = "icu"
homepage = "http://site.icu-project.org"
license = "ICU"
description = "ICU is a mature, widely used set of C/C++ and Java libraries " \
"providing Unicode and Globalization support for software applications."
url = "https://github.com/conan-io/conan-center-index"
topics = ("icu4c", "i see you", "unicode")
package_type = "library"
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
"data_packaging": ["files", "archive", "library", "static"],
"with_dyload": [True, False],
"dat_package_file": [None, "ANY"],
"with_icuio": [True, False],
"with_extras": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
"data_packaging": "archive",
"with_dyload": True,
"dat_package_file": None,
"with_icuio": True,
"with_extras": False,
}
@property
def _min_cppstd(self):
return 17
@property
def _compilers_minimum_version(self):
return {
"gcc": "8",
"clang": "7",
"apple-clang": "12",
"Visual Studio": "16",
"msvc": "192",
}
@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)
@property
def _enable_icu_tools(self):
return self.settings.os not in ["iOS", "tvOS", "watchOS", "Emscripten"]
@property
def _with_unit_tests(self):
return not self.conf.get("tools.build:skip_test", default=True, check_type=bool)
def export_sources(self):
export_conandata_patches(self)
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
del self.options.data_packaging
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
if Version(self.version) >= "74.1":
self.license = "Unicode-3.0"
def validate(self):
if self.options.dat_package_file:
if not os.path.exists(str(self.options.dat_package_file)):
raise ConanInvalidConfiguration("Non-existent dat_package_file specified")
if Version(self.version) >= "75.1":
if self.settings.compiler.cppstd:
check_min_cppstd(self, self._min_cppstd)
minimum_version = self._compilers_minimum_version.get(str(self.settings.compiler), False)
if minimum_version and Version(self.settings.compiler.version) < minimum_version:
raise ConanInvalidConfiguration(
f"{self.ref} requires C++{self._min_cppstd}, which your compiler does not support."
)
def layout(self):
basic_layout(self, src_folder="src")
@staticmethod
def _sha256sum(file_path):
m = hashlib.sha256()
with open(file_path, "rb") as fh:
for data in iter(lambda: fh.read(8192), b""):
m.update(data)
return m.hexdigest()
def package_id(self):
if self.info.options.dat_package_file:
self.info.options.dat_package_file = self._sha256sum(str(self.info.options.dat_package_file))
def build_requirements(self):
if self._settings_build.os == "Windows":
self.win_bash = True
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
self.tool_requires("msys2/cci.latest")
if cross_building(self) and hasattr(self, "settings_build"):
self.tool_requires(str(self.ref))
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def generate(self):
env = VirtualBuildEnv(self)
env.generate()
tc = AutotoolsToolchain(self)
if check_min_vs(self, "180", raise_invalid=False):
tc.extra_cflags.append("-FS")
tc.extra_cxxflags.append("-FS")
if Version(self.version) >= "75.1" and not self.settings.compiler.cppstd and is_msvc(self):
tc.extra_cxxflags.append(f"-std:c++{self._min_cppstd}")
if not self.options.shared:
tc.extra_defines.append("U_STATIC_IMPLEMENTATION")
if is_apple_os(self):
tc.extra_defines.append("_DARWIN_C_SOURCE")
yes_no = lambda v: "yes" if v else "no"
tc.configure_args.extend([
"--datarootdir=${prefix}/lib", # do not use share
f"--enable-release={yes_no(self.settings.build_type != 'Debug')}",
f"--enable-debug={yes_no(self.settings.build_type == 'Debug')}",
f"--enable-dyload={yes_no(self.options.with_dyload)}",
f"--enable-extras={yes_no(self.options.with_extras)}",
f"--enable-icuio={yes_no(self.options.with_icuio)}",
"--disable-layoutex",
"--disable-layout",
f"--enable-tools={yes_no(self._enable_icu_tools)}",
f"--enable-tests={yes_no(self._with_unit_tests)}",
"--disable-samples",
])
if cross_building(self):
base_path = unix_path(self, self.dependencies.build["icu"].package_folder)
tc.configure_args.append(f"--with-cross-build={base_path}")
if self.settings.os in ["iOS", "tvOS", "watchOS"]:
# ICU build scripts interpret all Apple platforms as 'darwin'.
# Since this can coincide with the `build` triple, we need to tweak
# the build triple to avoid the collision and ensure the scripts
# know we are cross-building.
host_triplet = f"{str(self.settings.arch)}-apple-darwin"
build_triplet = f"{str(self._settings_build.arch)}-apple"
tc.update_configure_args({"--host": host_triplet,
"--build": build_triplet})
else:
arch64 = ["x86_64", "sparcv9", "ppc64", "ppc64le", "armv8", "armv8.3", "mips64"]
bits = "64" if self.settings.arch in arch64 else "32"
tc.configure_args.append(f"--with-library-bits={bits}")
if self.settings.os != "Windows":
# http://userguide.icu-project.org/icudata
# This is the only directly supported behavior on Windows builds.
tc.configure_args.append(f"--with-data-packaging={self.options.data_packaging}")
tc.generate()
if is_msvc(self):
env = Environment()
env.define("CC", "cl -nologo")
env.define("CXX", "cl -nologo")
if cross_building(self):
env.define("icu_cv_host_frag", "mh-msys-msvc")
env.vars(self).save_script("conanbuild_icu_msvc")
def _patch_sources(self):
apply_conandata_patches(self)
if not self._with_unit_tests:
# Prevent any call to python during configuration, it's only needed for unit tests
replace_in_file(
self,
os.path.join(self.source_folder, "source", "configure"),
"if test -z \"$PYTHON\"",
"if true",
)
if self._settings_build.os == "Windows":
# https://unicode-org.atlassian.net/projects/ICU/issues/ICU-20545
makeconv_cpp = os.path.join(self.source_folder, "source", "tools", "makeconv", "makeconv.cpp")
replace_in_file(self, makeconv_cpp,
"pathBuf.appendPathPart(arg, localError);",
"pathBuf.append(\"/\", localError); pathBuf.append(arg, localError);")
# relocatable shared libs on macOS
mh_darwin = os.path.join(self.source_folder, "source", "config", "mh-darwin")
replace_in_file(self, mh_darwin, "-install_name $(libdir)/$(notdir", "-install_name @rpath/$(notdir")
replace_in_file(self,
mh_darwin,
"-install_name $(notdir $(MIDDLE_SO_TARGET)) $(PKGDATA_TRAILING_SPACE)",
"-install_name @rpath/$(notdir $(MIDDLE_SO_TARGET))",
)
# workaround for https://unicode-org.atlassian.net/browse/ICU-20531
mkdir(self, os.path.join(self.build_folder, "data", "out", "tmp"))
# workaround for "No rule to make target 'out/tmp/dirs.timestamp'"
save(self, os.path.join(self.build_folder, "data", "out", "tmp", "dirs.timestamp"), "")
def build(self):
self._patch_sources()
if self.options.dat_package_file:
dat_package_file = glob.glob(os.path.join(self.source_folder, "source", "data", "in", "*.dat"))
if dat_package_file:
shutil.copy(str(self.options.dat_package_file), dat_package_file[0])
autotools = Autotools(self)
autotools.configure(build_script_folder=os.path.join(self.source_folder, "source"))
autotools.make()
if self._with_unit_tests:
autotools.make(target="check")
@property
def _data_filename(self):
vtag = Version(self.version).major
return f"icudt{vtag}l.dat"
@property
def _data_path(self):
data_dir_name = "icu"
if self.settings.os == "Windows" and self.settings.build_type == "Debug":
data_dir_name += "d"
data_dir = os.path.join(self.package_folder, "lib", data_dir_name, str(self.version))
return os.path.join(data_dir, self._data_filename)
def package(self):
copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
autotools = Autotools(self)
autotools.install()
dll_files = glob.glob(os.path.join(self.package_folder, "lib", "*.dll"))
if dll_files:
bin_dir = os.path.join(self.package_folder, "bin")
mkdir(self, bin_dir)
for dll in dll_files:
dll_name = os.path.basename(dll)
rm(self, dll_name, bin_dir)
rename(self, src=dll, dst=os.path.join(bin_dir, dll_name))
if self.settings.os != "Windows" and self.options.data_packaging in ["files", "archive"]:
mkdir(self, os.path.join(self.package_folder, "res"))
rename(self, src=self._data_path, dst=os.path.join(self.package_folder, "res", self._data_filename))
# Copy some files required for cross-compiling
config_dir = os.path.join(self.package_folder, "config")
copy(self, "icucross.mk", src=os.path.join(self.build_folder, "config"), dst=config_dir)
copy(self, "icucross.inc", src=os.path.join(self.build_folder, "config"), dst=config_dir)
rmdir(self, os.path.join(self.package_folder, "lib", "icu"))
rmdir(self, os.path.join(self.package_folder, "lib", "man"))
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rmdir(self, os.path.join(self.package_folder, "share"))
def package_info(self):
self.cpp_info.set_property("cmake_find_mode", "both")
self.cpp_info.set_property("cmake_file_name", "ICU")
prefix = "s" if self.settings.os == "Windows" and not self.options.shared else ""
suffix = "d" if self.settings.os == "Windows" and self.settings.build_type == "Debug" else ""
# icudata
self.cpp_info.components["icu-data"].set_property("cmake_target_name", "ICU::data")
icudata_libname = "icudt" if self.settings.os == "Windows" else "icudata"
self.cpp_info.components["icu-data"].libs = [f"{prefix}{icudata_libname}{suffix}"]
if not self.options.shared:
self.cpp_info.components["icu-data"].defines.append("U_STATIC_IMPLEMENTATION")
# icu uses c++, so add the c++ runtime
libcxx = stdcpp_library(self)
if libcxx:
self.cpp_info.components["icu-data"].system_libs.append(libcxx)
# Alias of data CMake component
self.cpp_info.components["icu-data-alias"].set_property("cmake_target_name", "ICU::dt")
self.cpp_info.components["icu-data-alias"].requires = ["icu-data"]
# icuuc
self.cpp_info.components["icu-uc"].set_property("cmake_target_name", "ICU::uc")
self.cpp_info.components["icu-uc"].set_property("pkg_config_name", "icu-uc")
self.cpp_info.components["icu-uc"].libs = [f"{prefix}icuuc{suffix}"]
self.cpp_info.components["icu-uc"].requires = ["icu-data"]
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["icu-uc"].system_libs = ["m", "pthread"]
if self.options.with_dyload:
self.cpp_info.components["icu-uc"].system_libs.append("dl")
elif self.settings.os == "Windows":
self.cpp_info.components["icu-uc"].system_libs = ["advapi32"]
# icui18n
self.cpp_info.components["icu-i18n"].set_property("cmake_target_name", "ICU::i18n")
self.cpp_info.components["icu-i18n"].set_property("pkg_config_name", "icu-i18n")
icui18n_libname = "icuin" if self.settings.os == "Windows" else "icui18n"
self.cpp_info.components["icu-i18n"].libs = [f"{prefix}{icui18n_libname}{suffix}"]
self.cpp_info.components["icu-i18n"].requires = ["icu-uc"]
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["icu-i18n"].system_libs = ["m"]
# Alias of i18n CMake component
self.cpp_info.components["icu-i18n-alias"].set_property("cmake_target_name", "ICU::in")
self.cpp_info.components["icu-i18n-alias"].requires = ["icu-i18n"]
# icuio
if self.options.with_icuio:
self.cpp_info.components["icu-io"].set_property("cmake_target_name", "ICU::io")
self.cpp_info.components["icu-io"].set_property("pkg_config_name", "icu-io")
self.cpp_info.components["icu-io"].libs = [f"{prefix}icuio{suffix}"]
self.cpp_info.components["icu-io"].requires = ["icu-i18n", "icu-uc"]
if self.settings.os != "Windows" and self.options.data_packaging in ["files", "archive"]:
self.cpp_info.components["icu-data"].resdirs = ["res"]
data_path = os.path.join(self.package_folder, "res", self._data_filename).replace("\\", "/")
self.runenv_info.prepend_path("ICU_DATA", data_path)
if self._enable_icu_tools or self.options.with_extras:
self.buildenv_info.prepend_path("ICU_DATA", data_path)
if self._enable_icu_tools:
# icutu
self.cpp_info.components["icu-tu"].set_property("cmake_target_name", "ICU::tu")
self.cpp_info.components["icu-tu"].libs = [f"{prefix}icutu{suffix}"]
self.cpp_info.components["icu-tu"].requires = ["icu-i18n", "icu-uc"]
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["icu-tu"].system_libs = ["pthread"]
# icutest
self.cpp_info.components["icu-test"].set_property("cmake_target_name", "ICU::test")
self.cpp_info.components["icu-test"].libs = [f"{prefix}icutest{suffix}"]
self.cpp_info.components["icu-test"].requires = ["icu-tu", "icu-uc"]
# TODO: to remove after conan v2
self.cpp_info.names["cmake_find_package"] = "ICU"
self.cpp_info.names["cmake_find_package_multi"] = "ICU"
self.cpp_info.components["icu-data"].names["cmake_find_package"] = "data"
self.cpp_info.components["icu-data"].names["cmake_find_package_multi"] = "data"
self.cpp_info.components["icu-data-alias"].names["cmake_find_package"] = "dt"
self.cpp_info.components["icu-data-alias"].names["cmake_find_package_multi"] = "dt"
self.cpp_info.components["icu-uc"].names["cmake_find_package"] = "uc"
self.cpp_info.components["icu-uc"].names["cmake_find_package_multi"] = "uc"
self.cpp_info.components["icu-i18n"].names["cmake_find_package"] = "i18n"
self.cpp_info.components["icu-i18n"].names["cmake_find_package_multi"] = "i18n"
self.cpp_info.components["icu-i18n-alias"].names["cmake_find_package"] = "in"
self.cpp_info.components["icu-i18n-alias"].names["cmake_find_package_multi"] = "in"
if self.options.with_icuio:
self.cpp_info.components["icu-io"].names["cmake_find_package"] = "io"
self.cpp_info.components["icu-io"].names["cmake_find_package_multi"] = "io"
if self.settings.os != "Windows" and self.options.data_packaging in ["files", "archive"]:
self.env_info.ICU_DATA.append(data_path)
if self._enable_icu_tools:
self.cpp_info.components["icu-tu"].names["cmake_find_package"] = "tu"
self.cpp_info.components["icu-tu"].names["cmake_find_package_multi"] = "tu"
self.cpp_info.components["icu-test"].names["cmake_find_package"] = "test"
self.cpp_info.components["icu-test"].names["cmake_find_package_multi"] = "test"
if self._enable_icu_tools or self.options.with_extras:
self.env_info.PATH.append(os.path.join(self.package_folder, "bin"))

View File

@@ -0,0 +1,43 @@
--- source/config/mh-mingw64
+++ source/config/mh-mingw64
@@ -94,7 +94,7 @@
# This is also for backwards compatibility.
DATA_STUBNAME = dt
I18N_STUBNAME = in
-LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
+#LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
#SH### copied from Makefile.inc
#SH## for icu-config to test with
@@ -102,13 +102,13 @@
#SH#ICULIBS_COMMON_LIB_NAME_A="${LIBICU}${COMMON_STUBNAME}${ICULIBSUFFIX}.${A}"
#SH#ICULIBS_DATA="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_DT="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_I18N="-l$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_LX="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(LAYOUTEX_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_IO="-l$(ICUPREFIX)$(IO_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_UC="-l$(ICUPREFIX)$(COMMON_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_CTESTFW="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(CTESTFW_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_TOOLUTIL="-l$(ICUPREFIX)tu$(ICULIBSUFFIX)"
+#ICULIBS_DT="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)""
+#ICULIBS_I18N="-l$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_LX="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(LAYOUTEX_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_IO="-l$(ICUPREFIX)$(IO_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_UC="-l$(ICUPREFIX)$(COMMON_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_CTESTFW="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(CTESTFW_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_TOOLUTIL="-l$(ICUPREFIX)tu$(ICULIBSUFFIX)"
#SH#
#SH## ICULIBS is the set of libraries your application should link
#SH## with usually. Many applications will want to add ${ICULIBS_I18N} as well.
--- source/data/Makefile.in
+++ source/data/Makefile.in
@@ -207,7 +207,7 @@
ifneq ($(ICUDATA_SOURCE_IS_NATIVE_TARGET),YES)
# For MinGW, do we want the DLL to go in the bin location?
ifeq ($(MINGW_MOVEDLLSTOBINDIR),YES)
- $(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(DESTDIR)$(bindir)
+ $(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(ICUPKGDATA_INSTALL_DIR)
else
$(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(ICUPKGDATA_INSTALL_DIR)
endif

View File

@@ -0,0 +1,47 @@
diff --git a/source/config/mh-mingw64 b/source/config/mh-mingw64
index fb64c56..ff8922c 100644
--- a/source/config/mh-mingw64
+++ b/source/config/mh-mingw64
@@ -94,7 +94,7 @@ LIBPREFIX=
# This is also for backwards compatibility.
DATA_STUBNAME = dt
I18N_STUBNAME = in
-LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
+#LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
#SH### copied from Makefile.inc
#SH## for icu-config to test with
@@ -102,13 +102,13 @@ LIBICU = $(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)
#SH#ICULIBS_COMMON_LIB_NAME_A="${LIBICU}${COMMON_STUBNAME}${ICULIBSUFFIX}.${A}"
#SH#ICULIBS_DATA="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_DT="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_I18N="-l$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_LX="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(LAYOUTEX_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_IO="-l$(ICUPREFIX)$(IO_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_UC="-l$(ICUPREFIX)$(COMMON_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_CTESTFW="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(CTESTFW_STUBNAME)$(ICULIBSUFFIX)"
-ICULIBS_TOOLUTIL="-l$(ICUPREFIX)tu$(ICULIBSUFFIX)"
+#ICULIBS_DT="-l$(ICUPREFIX)$(DATA_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_I18N="-l$(ICUPREFIX)$(I18N_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_LX="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(LAYOUTEX_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_IO="-l$(ICUPREFIX)$(IO_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_UC="-l$(ICUPREFIX)$(COMMON_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_CTESTFW="-l$(STATIC_PREFIX_WHEN_USED)$(ICUPREFIX)$(CTESTFW_STUBNAME)$(ICULIBSUFFIX)"
+#ICULIBS_TOOLUTIL="-l$(ICUPREFIX)tu$(ICULIBSUFFIX)"
#SH#
#SH## ICULIBS is the set of libraries your application should link
#SH## with usually. Many applications will want to add ${ICULIBS_I18N} as well.
diff --git a/source/data/Makefile.in b/source/data/Makefile.in
index 266ad7a..8e3be4f 100644
--- a/source/data/Makefile.in
+++ b/source/data/Makefile.in
@@ -193,7 +193,7 @@ endif
ifneq ($(ICUDATA_SOURCE_IS_NATIVE_TARGET),YES)
# For MinGW, do we want the DLL to go in the bin location?
ifeq ($(MINGW_MOVEDLLSTOBINDIR),YES)
- $(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(DESTDIR)$(bindir)
+ $(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(ICUPKGDATA_INSTALL_DIR)
else
$(PKGDATA_INVOKE) $(PKGDATA) -m $(PKGDATA_MODE) $(PKGDATA_VERSIONING) -e $(ICUDATA_ENTRY_POINT) -T $(OUTTMPDIR) -s $(BUILDDIR) -p $(ICUDATA_NAME) $(PKGDATA_LIBNAME) $(PKGDATA_LIST) -I $(ICUPKGDATA_INSTALL_DIR)
endif

View File

@@ -0,0 +1,109 @@
--- a/source/acinclude.m4
+++ b/source/acinclude.m4
@@ -85,6 +85,7 @@ powerpc*-apple-darwin*) icu_cv_host_frag=mh-darwin-ppc ;;
*-dec-osf*) icu_cv_host_frag=mh-alpha-osf ;;
*-*-nto*) icu_cv_host_frag=mh-qnx ;;
*-ncr-*) icu_cv_host_frag=mh-mpras ;;
+wasm*-*-emscripten*) icu_cv_host_frag=mh-emscripten ;;
*) icu_cv_host_frag=mh-unknown ;;
esac
]
--- /dev/null
+++ b/source/config/mh-emscripten
@@ -0,0 +1,86 @@
+## Emscripten-specific setup
+## Copyright (c) 1999-2013, International Business Machines Corporation and
+## others. All Rights Reserved.
+## Commands to generate dependency files
+GEN_DEPS.c= $(CC) -E -MM $(DEFS) $(CPPFLAGS)
+GEN_DEPS.cc= $(CXX) -E -MM $(DEFS) $(CPPFLAGS) $(CXXFLAGS)
+
+## Flags for position independent code
+SHAREDLIBCFLAGS = -fPIC
+SHAREDLIBCXXFLAGS = -fPIC
+SHAREDLIBCPPFLAGS = -DPIC
+
+## Additional flags when building libraries and with threads
+THREADSCPPFLAGS = -D_REENTRANT
+LIBCPPFLAGS =
+
+## Compiler switch to embed a runtime search path
+LD_RPATH= -Wl,-zorigin,-rpath,'$$'ORIGIN
+LD_RPATH_PRE = -Wl,-rpath,
+
+## Force RPATH=$ORIGIN to locate own dependencies w/o need for LD_LIBRARY_PATH:
+ENABLE_RPATH=YES
+RPATHLDFLAGS=${LD_RPATH_PRE}'$$ORIGIN'
+
+## These are the library specific LDFLAGS
+#LDFLAGSICUDT=-nodefaultlibs -nostdlib
+# Debian change: linking icudata as data only causes too many problems.
+LDFLAGSICUDT=
+
+## Compiler switch to embed a library name
+# The initial tab in the next line is to prevent icu-config from reading it.
+ LD_SONAME = -Wl,-soname -Wl,$(notdir $(MIDDLE_SO_TARGET))
+#SH# # We can't depend on MIDDLE_SO_TARGET being set.
+#SH# LD_SONAME=
+
+## Shared library options
+LD_SOOPTIONS= -Wl,-Bsymbolic-functions
+
+## Shared object suffix
+SO = so
+## Non-shared intermediate object suffix
+STATIC_O = o
+
+## Compilation rules
+# WASM needs -pthread for atomics support
+%.$(STATIC_O): $(srcdir)/%.c
+ $(call SILENT_COMPILE,$(strip $(COMPILE.c) $(STATICCPPFLAGS) $(STATICCFLAGS)) -pthread -o $@ $<)
+
+%.$(STATIC_O): $(srcdir)/%.cpp
+ $(call SILENT_COMPILE,$(strip $(COMPILE.cc) $(STATICCPPFLAGS) $(STATICCXXFLAGS)) -pthread -o $@ $<)
+
+
+## Dependency rules
+%.d: $(srcdir)/%.c
+ $(call ICU_MSG,(deps)) $<
+ @$(SHELL) -ec '$(GEN_DEPS.c) $< \
+ | sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \
+ [ -s $@ ] || rm -f $@'
+
+%.d: $(srcdir)/%.cpp
+ $(call ICU_MSG,(deps)) $<
+ @$(SHELL) -ec '$(GEN_DEPS.cc) $< \
+ | sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \
+ [ -s $@ ] || rm -f $@'
+
+## Versioned libraries rules
+
+%.$(SO).$(SO_TARGET_VERSION_MAJOR): %.$(SO).$(SO_TARGET_VERSION)
+ $(RM) $@ && ln -s ${<F} $@
+%.$(SO): %.$(SO).$(SO_TARGET_VERSION_MAJOR)
+ $(RM) $@ && ln -s ${*F}.$(SO).$(SO_TARGET_VERSION) $@
+
+## Bind internal references
+
+# LDflags that pkgdata will use
+BIR_LDFLAGS= -Wl,-Bsymbolic
+
+# Dependencies [i.e. map files] for the final library
+BIR_DEPS=
+
+## Remove shared library 's'
+STATIC_PREFIX_WHEN_USED =
+STATIC_PREFIX =
+
+## without assembly
+PKGDATA_OPTS = -O $(top_builddir)/data/icupkg.inc -w
--- a/source/configure
+++ b/source/configure
@@ -5342,6 +5342,7 @@ powerpc*-apple-darwin*) icu_cv_host_frag=mh-darwin-ppc ;;
*-dec-osf*) icu_cv_host_frag=mh-alpha-osf ;;
*-*-nto*) icu_cv_host_frag=mh-qnx ;;
*-ncr-*) icu_cv_host_frag=mh-mpras ;;
+wasm*-*-emscripten*) icu_cv_host_frag=mh-emscripten ;;
*) icu_cv_host_frag=mh-unknown ;;
esac

View File

@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.8)
project(test_package LANGUAGES CXX)
find_package(ICU REQUIRED uc)
add_executable(${PROJECT_NAME} test_package.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE ICU::uc)
if(ICU_VERSION VERSION_LESS "75.1")
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11)
else()
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)
endif()

View File

@@ -0,0 +1,9 @@
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"build/gcc-12-x86_64-gnu17-release/generators/CMakePresets.json"
]
}

View File

@@ -0,0 +1,26 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import CMake, cmake_layout
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeToolchain", "CMakeDeps", "VirtualRunEnv"
test_type = "explicit"
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires(self.tested_reference_str)
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
if can_run(self):
bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
self.run(bin_path, env="conanrun")

View File

@@ -0,0 +1,623 @@
// This is taken from ICU samples: source/samples/ustring
/*
*******************************************************************************
*
* © 2016 and later: Unicode, Inc. and others.
* License & terms of use: http://www.unicode.org/copyright.html#License
*
*******************************************************************************
*******************************************************************************
*
* Copyright (C) 2000-2014, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: ustring.c
* encoding: UTF-8
* tab size: 8 (not used)
* indentation:4
*
* created on: 2000aug15
* created by: Markus W. Scherer
*
* This file contains sample code that illustrates the use of Unicode strings
* with ICU.
*/
#include <stdio.h>
#define U_DEFINE_FALSE_AND_TRUE 1
#include "unicode/utypes.h"
#include "unicode/uchar.h"
#include "unicode/locid.h"
#include "unicode/ustring.h"
#include "unicode/ucnv.h"
#include "unicode/unistr.h"
#ifndef UPRV_LENGTHOF
#define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
#endif
// helper functions -------------------------------------------------------- ***
// default converter for the platform encoding
static UConverter *cnv=NULL;
using namespace icu;
static void
printUString(const char *announce, const UChar *s, int32_t length) {
static char out[200];
UChar32 c;
int32_t i;
UErrorCode errorCode=U_ZERO_ERROR;
/*
* Convert to the "platform encoding". See notes in printUnicodeString().
* ucnv_fromUChars(), like most ICU APIs understands length==-1
* to mean that the string is NUL-terminated.
*/
ucnv_fromUChars(cnv, out, sizeof(out), s, length, &errorCode);
if(U_FAILURE(errorCode) || errorCode==U_STRING_NOT_TERMINATED_WARNING) {
printf("%sproblem converting string from Unicode: %s\n", announce, u_errorName(errorCode));
return;
}
printf("%s%s {", announce, out);
/* output the code points (not code units) */
if(length>=0) {
/* s is not NUL-terminated */
for(i=0; i<length; /* U16_NEXT post-increments */) {
U16_NEXT(s, i, length, c);
printf(" %04x", c);
}
} else {
/* s is NUL-terminated */
for(i=0; /* condition in loop body */; /* U16_NEXT post-increments */) {
U16_NEXT(s, i, length, c);
if(c==0) {
break;
}
printf(" %04x", c);
}
}
printf(" }\n");
}
static void
printUnicodeString(const char *announce, const UnicodeString &s) {
static char out[200];
int32_t i, length;
// output the string, converted to the platform encoding
// Note for Windows: The "platform encoding" defaults to the "ANSI codepage",
// which is different from the "OEM codepage" in the console window.
// However, if you pipe the output into a file and look at it with Notepad
// or similar, then "ANSI" characters will show correctly.
// Production code should be aware of what encoding is required,
// and use a UConverter or at least a charset name explicitly.
out[s.extract(0, 99, out)]=0;
printf("%s%s {", announce, out);
// output the code units (not code points)
length=s.length();
for(i=0; i<length; ++i) {
printf(" %04x", s.charAt(i));
}
printf(" }\n");
}
// sample code for utf.h macros -------------------------------------------- ***
static void
demo_utf_h_macros() {
static UChar input[]={ 0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062 };
UChar32 c;
int32_t i;
UBool isError;
printf("\n* demo_utf_h_macros() -------------- ***\n\n");
printUString("iterate forward through: ", input, UPRV_LENGTHOF(input));
for(i=0; i<UPRV_LENGTHOF(input); /* U16_NEXT post-increments */) {
/* Iterating forwards
Codepoint at offset 0: U+0061
Codepoint at offset 1: U+10000
Codepoint at offset 3: U+10ffff
Codepoint at offset 5: U+0062
*/
printf("Codepoint at offset %d: U+", i);
U16_NEXT(input, i, UPRV_LENGTHOF(input), c);
printf("%04x\n", c);
}
puts("");
isError=FALSE;
i=1; /* write position, gets post-incremented so needs to be in an l-value */
U16_APPEND(input, i, UPRV_LENGTHOF(input), 0x0062, isError);
printUString("iterate backward through: ", input, UPRV_LENGTHOF(input));
for(i=UPRV_LENGTHOF(input); i>0; /* U16_PREV pre-decrements */) {
U16_PREV(input, 0, i, c);
/* Iterating backwards
Codepoint at offset 5: U+0062
Codepoint at offset 3: U+10ffff
Codepoint at offset 2: U+dc00 -- unpaired surrogate because lead surr. overwritten
Codepoint at offset 1: U+0062 -- by this BMP code point
Codepoint at offset 0: U+0061
*/
printf("Codepoint at offset %d: U+%04x\n", i, c);
}
}
// sample code for Unicode strings in C ------------------------------------ ***
static void demo_C_Unicode_strings() {
printf("\n* demo_C_Unicode_strings() --------- ***\n\n");
static const UChar text[]={ 0x41, 0x42, 0x43, 0 }; /* "ABC" */
static const UChar appendText[]={ 0x61, 0x62, 0x63, 0 }; /* "abc" */
static const UChar cmpText[]={ 0x61, 0x53, 0x73, 0x43, 0 }; /* "aSsC" */
UChar buffer[32];
int32_t compare;
int32_t length=u_strlen(text); /* length=3 */
/* simple ANSI C-style functions */
buffer[0]=0; /* empty, NUL-terminated string */
u_strncat(buffer, text, 1); /* append just n=1 character ('A') */
u_strcat(buffer, appendText); /* buffer=="Aabc" */
length=u_strlen(buffer); /* length=4 */
printUString("should be \"Aabc\": ", buffer, -1);
/* bitwise comparing buffer with text */
compare=u_strcmp(buffer, text);
if(compare<=0) {
printf("String comparison error, expected \"Aabc\" > \"ABC\"\n");
}
/* Build "A<sharp s>C" in the buffer... */
u_strcpy(buffer, text);
buffer[1]=0xdf; /* sharp s, case-compares equal to "ss" */
printUString("should be \"A<sharp s>C\": ", buffer, -1);
/* Compare two strings case-insensitively using full case folding */
compare=u_strcasecmp(buffer, cmpText, U_FOLD_CASE_DEFAULT);
if(compare!=0) {
printf("String case insensitive comparison error, expected \"AbC\" to be equal to \"ABC\"\n");
}
}
// sample code for case mappings with C APIs -------------------------------- ***
static void demoCaseMapInC() {
/*
* input=
* "aB<capital sigma>"
* "iI<small dotless i><capital dotted I> "
* "<sharp s> <small lig. ffi>"
* "<small final sigma><small sigma><capital sigma>"
*/
static const UChar input[]={
0x61, 0x42, 0x3a3,
0x69, 0x49, 0x131, 0x130, 0x20,
0xdf, 0x20, 0xfb03,
0x3c2, 0x3c3, 0x3a3, 0
};
UChar buffer[32];
UErrorCode errorCode;
UChar32 c;
int32_t i, j, length;
UBool isError;
printf("\n* demoCaseMapInC() ----------------- ***\n\n");
/*
* First, use simple case mapping functions which provide
* 1:1 code point mappings without context/locale ID.
*
* Note that some mappings will not be "right" because some "real"
* case mappings require context, depend on the locale ID,
* and/or result in a change in the number of code points.
*/
printUString("input string: ", input, -1);
/* uppercase */
isError=FALSE;
for(i=j=0; j<UPRV_LENGTHOF(buffer) && !isError; /* U16_NEXT post-increments */) {
U16_NEXT(input, i, INT32_MAX, c); /* without length because NUL-terminated */
if(c==0) {
break; /* stop at terminating NUL, no need to terminate buffer */
}
c=u_toupper(c);
U16_APPEND(buffer, j, UPRV_LENGTHOF(buffer), c, isError);
}
printUString("simple-uppercased: ", buffer, j);
/* lowercase */
isError=FALSE;
for(i=j=0; j<UPRV_LENGTHOF(buffer) && !isError; /* U16_NEXT post-increments */) {
U16_NEXT(input, i, INT32_MAX, c); /* without length because NUL-terminated */
if(c==0) {
break; /* stop at terminating NUL, no need to terminate buffer */
}
c=u_tolower(c);
U16_APPEND(buffer, j, UPRV_LENGTHOF(buffer), c, isError);
}
printUString("simple-lowercased: ", buffer, j);
/* titlecase */
isError=FALSE;
for(i=j=0; j<UPRV_LENGTHOF(buffer) && !isError; /* U16_NEXT post-increments */) {
U16_NEXT(input, i, INT32_MAX, c); /* without length because NUL-terminated */
if(c==0) {
break; /* stop at terminating NUL, no need to terminate buffer */
}
c=u_totitle(c);
U16_APPEND(buffer, j, UPRV_LENGTHOF(buffer), c, isError);
}
printUString("simple-titlecased: ", buffer, j);
/* case-fold/default */
isError=FALSE;
for(i=j=0; j<UPRV_LENGTHOF(buffer) && !isError; /* U16_NEXT post-increments */) {
U16_NEXT(input, i, INT32_MAX, c); /* without length because NUL-terminated */
if(c==0) {
break; /* stop at terminating NUL, no need to terminate buffer */
}
c=u_foldCase(c, U_FOLD_CASE_DEFAULT);
U16_APPEND(buffer, j, UPRV_LENGTHOF(buffer), c, isError);
}
printUString("simple-case-folded/default: ", buffer, j);
/* case-fold/Turkic */
isError=FALSE;
for(i=j=0; j<UPRV_LENGTHOF(buffer) && !isError; /* U16_NEXT post-increments */) {
U16_NEXT(input, i, INT32_MAX, c); /* without length because NUL-terminated */
if(c==0) {
break; /* stop at terminating NUL, no need to terminate buffer */
}
c=u_foldCase(c, U_FOLD_CASE_EXCLUDE_SPECIAL_I);
U16_APPEND(buffer, j, UPRV_LENGTHOF(buffer), c, isError);
}
printUString("simple-case-folded/Turkic: ", buffer, j);
/*
* Second, use full case mapping functions which provide
* 1:n code point mappings (n can be 0!) and are sensitive to context and locale ID.
*
* Note that lower/upper/titlecasing take a locale ID while case-folding
* has bit flag options instead, by design of the Unicode SpecialCasing.txt UCD file.
*
* Also, string titlecasing requires a BreakIterator to find starts of words.
* The sample code here passes in a NULL pointer; u_strToTitle() will open and close a default
* titlecasing BreakIterator automatically.
* For production code where many strings are titlecased it would be more efficient
* to open a BreakIterator externally and pass it in.
*/
printUString("\ninput string: ", input, -1);
/* lowercase/English */
errorCode=U_ZERO_ERROR;
length=u_strToLower(buffer, UPRV_LENGTHOF(buffer), input, -1, "en", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-lowercased/en: ", buffer, length);
} else {
printf("error in u_strToLower(en)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* lowercase/Turkish */
errorCode=U_ZERO_ERROR;
length=u_strToLower(buffer, UPRV_LENGTHOF(buffer), input, -1, "tr", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-lowercased/tr: ", buffer, length);
} else {
printf("error in u_strToLower(tr)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* uppercase/English */
errorCode=U_ZERO_ERROR;
length=u_strToUpper(buffer, UPRV_LENGTHOF(buffer), input, -1, "en", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-uppercased/en: ", buffer, length);
} else {
printf("error in u_strToUpper(en)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* uppercase/Turkish */
errorCode=U_ZERO_ERROR;
length=u_strToUpper(buffer, UPRV_LENGTHOF(buffer), input, -1, "tr", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-uppercased/tr: ", buffer, length);
} else {
printf("error in u_strToUpper(tr)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* titlecase/English */
errorCode=U_ZERO_ERROR;
length=u_strToTitle(buffer, UPRV_LENGTHOF(buffer), input, -1, NULL, "en", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-titlecased/en: ", buffer, length);
} else {
printf("error in u_strToTitle(en)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* titlecase/Turkish */
errorCode=U_ZERO_ERROR;
length=u_strToTitle(buffer, UPRV_LENGTHOF(buffer), input, -1, NULL, "tr", &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-titlecased/tr: ", buffer, length);
} else {
printf("error in u_strToTitle(tr)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* case-fold/default */
errorCode=U_ZERO_ERROR;
length=u_strFoldCase(buffer, UPRV_LENGTHOF(buffer), input, -1, U_FOLD_CASE_DEFAULT, &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-case-folded/default: ", buffer, length);
} else {
printf("error in u_strFoldCase(default)=%ld error=%s\n", length, u_errorName(errorCode));
}
/* case-fold/Turkic */
errorCode=U_ZERO_ERROR;
length=u_strFoldCase(buffer, UPRV_LENGTHOF(buffer), input, -1, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode);
if(U_SUCCESS(errorCode)) {
printUString("full-case-folded/Turkic: ", buffer, length);
} else {
printf("error in u_strFoldCase(Turkic)=%ld error=%s\n", length, u_errorName(errorCode));
}
}
// sample code for case mappings with C++ APIs ------------------------------ ***
static void demoCaseMapInCPlusPlus() {
/*
* input=
* "aB<capital sigma>"
* "iI<small dotless i><capital dotted I> "
* "<sharp s> <small lig. ffi>"
* "<small final sigma><small sigma><capital sigma>"
*/
static const UChar input[]={
0x61, 0x42, 0x3a3,
0x69, 0x49, 0x131, 0x130, 0x20,
0xdf, 0x20, 0xfb03,
0x3c2, 0x3c3, 0x3a3, 0
};
printf("\n* demoCaseMapInCPlusPlus() --------- ***\n\n");
UnicodeString s(input), t;
const Locale &en=Locale::getEnglish();
Locale tr("tr");
/*
* Full case mappings as in demoCaseMapInC(), using UnicodeString functions.
* These functions modify the string object itself.
* Since we want to keep the input string around, we copy it each time
* and case-map the copy.
*/
printUnicodeString("input string: ", s);
/* lowercase/English */
printUnicodeString("full-lowercased/en: ", (t=s).toLower(en));
/* lowercase/Turkish */
printUnicodeString("full-lowercased/tr: ", (t=s).toLower(tr));
/* uppercase/English */
printUnicodeString("full-uppercased/en: ", (t=s).toUpper(en));
/* uppercase/Turkish */
printUnicodeString("full-uppercased/tr: ", (t=s).toUpper(tr));
/* titlecase/English */
printUnicodeString("full-titlecased/en: ", (t=s).toTitle(NULL, en));
/* titlecase/Turkish */
printUnicodeString("full-titlecased/tr: ", (t=s).toTitle(NULL, tr));
/* case-folde/default */
printUnicodeString("full-case-folded/default: ", (t=s).foldCase(U_FOLD_CASE_DEFAULT));
/* case-folde/Turkic */
printUnicodeString("full-case-folded/Turkic: ", (t=s).foldCase(U_FOLD_CASE_EXCLUDE_SPECIAL_I));
}
// sample code for UnicodeString storage models ----------------------------- ***
static const UChar readonly[]={
0x61, 0x31, 0x20ac
};
static UChar writeable[]={
0x62, 0x32, 0xdbc0, 0xdc01 // includes a surrogate pair for a supplementary code point
};
static char out[100];
static void
demoUnicodeStringStorage() {
// These sample code lines illustrate how to use UnicodeString, and the
// comments tell what happens internally. There are no APIs to observe
// most of this programmatically, except for stepping into the code
// with a debugger.
// This is by design to hide such details from the user.
int32_t i;
printf("\n* demoUnicodeStringStorage() ------- ***\n\n");
// * UnicodeString with internally stored contents
// instantiate a UnicodeString from a single code point
// the few (2) UChars will be stored in the object itself
UnicodeString one((UChar32)0x24001);
// this copies the few UChars into the "two" object
UnicodeString two=one;
printf("length of short string copy: %d\n", two.length());
// set "one" to contain the 3 UChars from readonly
// this setTo() variant copies the characters
one.setTo(readonly, UPRV_LENGTHOF(readonly));
// * UnicodeString with allocated contents
// build a longer string that will not fit into the object's buffer
one+=UnicodeString(writeable, UPRV_LENGTHOF(writeable));
one+=one;
one+=one;
printf("length of longer string: %d\n", one.length());
// copying will use the same allocated buffer and increment the reference
// counter
two=one;
printf("length of longer string copy: %d\n", two.length());
// * UnicodeString using readonly-alias to a const UChar array
// construct a string that aliases a readonly buffer
UnicodeString three(FALSE, readonly, UPRV_LENGTHOF(readonly));
printUnicodeString("readonly-alias string: ", three);
// copy-on-write: any modification to the string results in
// a copy to either the internal buffer or to a newly allocated one
three.setCharAt(1, 0x39);
printUnicodeString("readonly-aliasing string after modification: ", three);
// the aliased array is not modified
for(i=0; i<three.length(); ++i) {
printf("readonly buffer[%d] after modifying its string: 0x%lx\n",
i, readonly[i]);
}
// setTo() readonly alias
one.setTo(FALSE, writeable, UPRV_LENGTHOF(writeable));
// copying the readonly-alias object with fastCopyFrom() (new in ICU 2.4)
// will readonly-alias the same buffer
two.fastCopyFrom(one);
printUnicodeString("fastCopyFrom(readonly alias of \"writeable\" array): ", two);
printf("verify that a fastCopyFrom(readonly alias) uses the same buffer pointer: %d (should be 1)\n",
one.getBuffer()==two.getBuffer());
// a normal assignment will clone the contents (new in ICU 2.4)
two=one;
printf("verify that a regular copy of a readonly alias uses a different buffer pointer: %d (should be 0)\n",
one.getBuffer()==two.getBuffer());
// * UnicodeString using writeable-alias to a non-const UChar array
UnicodeString four(writeable, UPRV_LENGTHOF(writeable), UPRV_LENGTHOF(writeable));
printUnicodeString("writeable-alias string: ", four);
// a modification writes through to the buffer
four.setCharAt(1, 0x39);
for(i=0; i<four.length(); ++i) {
printf("writeable-alias backing buffer[%d]=0x%lx "
"after modification\n", i, writeable[i]);
}
// a copy will not alias any more;
// instead, it will get a copy of the contents into allocated memory
two=four;
two.setCharAt(1, 0x21);
for(i=0; i<two.length(); ++i) {
printf("writeable-alias backing buffer[%d]=0x%lx after "
"modification of string copy\n", i, writeable[i]);
}
// setTo() writeable alias, capacity==length
one.setTo(writeable, UPRV_LENGTHOF(writeable), UPRV_LENGTHOF(writeable));
// grow the string - it will not fit into the backing buffer any more
// and will get copied before modification
one.append((UChar)0x40);
// shrink it back so it would fit
one.truncate(one.length()-1);
// we still operate on the copy
one.setCharAt(1, 0x25);
printf("string after growing too much and then shrinking[1]=0x%lx\n"
" backing store for this[1]=0x%lx\n",
one.charAt(1), writeable[1]);
// if we need it in the original buffer, then extract() to it
// extract() does not do anything if the string aliases that same buffer
// i=min(one.length(), length of array)
if(one.length()<UPRV_LENGTHOF(writeable)) {
i=one.length();
} else {
i=UPRV_LENGTHOF(writeable);
}
one.extract(0, i, writeable);
for(i=0; i<UPRV_LENGTHOF(writeable); ++i) {
printf("writeable-alias backing buffer[%d]=0x%lx after re-extract\n",
i, writeable[i]);
}
}
// sample code for UnicodeString instantiations ----------------------------- ***
static void
demoUnicodeStringInit() {
// *** Make sure to read about invariant characters in utypes.h! ***
// Initialization of Unicode strings from C literals works _only_ for
// invariant characters!
printf("\n* demoUnicodeStringInit() ---------- ***\n\n");
// the string literal is 32 chars long - this must be counted for the macro
UnicodeString invariantOnly=UNICODE_STRING("such characters are safe 123 %-.", 32);
/*
* In C, we need two macros: one to declare the UChar[] array, and
* one to populate it; the second one is a noop on platforms where
* wchar_t is compatible with UChar and ASCII-based.
* The length of the string literal must be counted for both macros.
*/
/* declare the invString array for the string */
U_STRING_DECL(invString, "such characters are safe 123 %-.", 32);
/* populate it with the characters */
U_STRING_INIT(invString, "such characters are safe 123 %-.", 32);
// compare the C and C++ strings
printf("C and C++ Unicode strings are equal: %d\n", invariantOnly==UnicodeString(TRUE, invString, 32));
/*
* convert between char * and UChar * strings that
* contain only invariant characters
*/
static const char *cs1="such characters are safe 123 %-.";
static UChar us1[40];
static char cs2[40];
u_charsToUChars(cs1, us1, 33); /* include the terminating NUL */
u_UCharsToChars(us1, cs2, 33);
printf("char * -> UChar * -> char * with only "
"invariant characters: \"%s\"\n",
cs2);
// initialize a UnicodeString from a string literal that contains
// escape sequences written with invariant characters
// do not forget to duplicate the backslashes for ICU to see them
// then, count each double backslash only once!
UnicodeString german=UNICODE_STRING(
"Sch\\u00f6nes Auto: \\u20ac 11240.\\fPrivates Zeichen: \\U00102345\\n", 64).
unescape();
printUnicodeString("german UnicodeString from unescaping:\n ", german);
/*
* C: convert and unescape a char * string with only invariant
* characters to fill a UChar * string
*/
UChar buffer[200];
int32_t length;
length=u_unescape(
"Sch\\u00f6nes Auto: \\u20ac 11240.\\fPrivates Zeichen: \\U00102345\\n",
buffer, UPRV_LENGTHOF(buffer));
printf("german C Unicode string from char * unescaping: (length %d)\n ", length);
printUnicodeString("", UnicodeString(buffer));
}
extern int
main(int argc, const char *argv[]) {
UErrorCode errorCode=U_ZERO_ERROR;
// Note: Using a global variable for any object is not exactly thread-safe...
// You can change this call to e.g. ucnv_open("UTF-8", &errorCode) if you pipe
// the output to a file and look at it with a Unicode-capable editor.
// This will currently affect only the printUString() function, see the code above.
// printUnicodeString() could use this, too, by changing to an extract() overload
// that takes a UConverter argument.
cnv=ucnv_open(NULL, &errorCode);
if(U_FAILURE(errorCode)) {
fprintf(stderr, "error %s opening the default converter\n", u_errorName(errorCode));
return errorCode;
}
ucnv_setFromUCallBack(cnv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_C, NULL, NULL, &errorCode);
if(U_FAILURE(errorCode)) {
fprintf(stderr, "error %s setting the escape callback in the default converter\n", u_errorName(errorCode));
ucnv_close(cnv);
return errorCode;
}
demo_utf_h_macros();
demo_C_Unicode_strings();
demoCaseMapInC();
demoCaseMapInCPlusPlus();
demoUnicodeStringStorage();
demoUnicodeStringInit();
ucnv_close(cnv);
return 0;
}