diff options
Diffstat (limited to 'intl/icu_capi/cpp/examples')
33 files changed, 1488 insertions, 0 deletions
diff --git a/intl/icu_capi/cpp/examples/bidi/.gitignore b/intl/icu_capi/cpp/examples/bidi/.gitignore new file mode 100644 index 0000000000..cb34c546b3 --- /dev/null +++ b/intl/icu_capi/cpp/examples/bidi/.gitignore @@ -0,0 +1,2 @@ +a.out +a.out.dSYM diff --git a/intl/icu_capi/cpp/examples/bidi/Makefile b/intl/icu_capi/cpp/examples/bidi/Makefile new file mode 100644 index 0000000000..594ca66c37 --- /dev/null +++ b/intl/icu_capi/cpp/examples/bidi/Makefile @@ -0,0 +1,28 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +.DEFAULT_GOAL := test +.PHONY: build test +FORCE: + +ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../c/include/*.h) + +CXX?=g++ + +$(ALL_HEADERS): + +../../../../../target/debug/libicu_capi_staticlib.a: FORCE + cargo build -p icu_capi_staticlib --features compiled_data + +a.out: ../../../../../target/debug/libicu_capi_staticlib.a $(ALL_HEADERS) test.cpp + $(CXX) -std=c++17 test.cpp ../../../../../target/debug/libicu_capi_staticlib.a -ldl -lpthread -lm -g + +build: a.out + +test: build + ./a.out + +clean: + git clean -xf * + rm -f ../../../../../target/debug/libicu_capi_staticlib.a diff --git a/intl/icu_capi/cpp/examples/bidi/test.cpp b/intl/icu_capi/cpp/examples/bidi/test.cpp new file mode 100644 index 0000000000..629cf752ce --- /dev/null +++ b/intl/icu_capi/cpp/examples/bidi/test.cpp @@ -0,0 +1,93 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#include "../../include/ICU4XDataProvider.hpp" +#include "../../include/ICU4XBidi.hpp" +#include "../../include/ICU4XLogger.hpp" + +#include <iostream> + +int main() { + ICU4XDataProvider dp = ICU4XDataProvider::create_compiled(); + auto bidi = ICU4XBidi::create(dp).ok().value(); + + // Written char-by-char to avoid messing up certain text editors. + std::string_view str = + "א" + "ב" + "ג" + "a" + "b" + "c" + "\n" + "a" + "b" + "c" + "א" + "ב" + "ג"; + + // reordered string is same for both lines + std::string_view reordered_expected = + "a" + "b" + "c" + "ג" + "ב" + "א"; + auto bidi_info = bidi.for_text(str, ICU4XBidi::level_ltr()); + auto n_para = bidi_info.paragraph_count(); + if (n_para != 2) { + std::cout << "Expected 2 paragraphs, found " << n_para << std::endl; + return 1; + } + + auto para = bidi_info.paragraph_at(0).value(); + + auto size = para.size(); + if (size != 10) { + std::cout << "Expected paragraph of size 10, found " << size << std::endl; + return 1; + } + + // The first paragraph's first strongly directional character is RTL + uint8_t level = para.level_at(0); + std::cout << "Level of first paragraph at index 0 is " << unsigned(level) << std::endl; + if (!ICU4XBidi::level_is_rtl(level)) { + std::cout << "Expected level at index 0 to be RTL" << std::endl; + return 1; + } + + + std::string reordered = para.reorder_line(0, 9).ok().value(); + std::cout << "Reordered paragraph: " << reordered << std::endl; + + if (reordered != reordered) { + std::cout << "Found incorrect reordering, expected: " << reordered << std::endl; + } + + para.set_paragraph_in_text(1).ok().value(); + + size = para.size(); + if (size != 9) { + std::cout << "Expected paragraph of size 9, found " << size << std::endl; + return 1; + } + + // The second paragraph's first strongly directional character is LTR + level = para.level_at(0); + std::cout << "Level of second paragraph at index 0 is " << unsigned(level) << std::endl; + if (!ICU4XBidi::level_is_ltr(level)) { + std::cout << "Expected level at index 0 to be LTR" << std::endl; + return 1; + } + reordered = para.reorder_line(10, 19).ok().value(); + std::cout << "Reordered paragraph: " << reordered << std::endl; + + if (reordered != reordered) { + std::cout << "Found incorrect reordering, expected: " << reordered << std::endl; + } + + return 0; +} diff --git a/intl/icu_capi/cpp/examples/casemapping/.gitignore b/intl/icu_capi/cpp/examples/casemapping/.gitignore new file mode 100644 index 0000000000..cb34c546b3 --- /dev/null +++ b/intl/icu_capi/cpp/examples/casemapping/.gitignore @@ -0,0 +1,2 @@ +a.out +a.out.dSYM diff --git a/intl/icu_capi/cpp/examples/casemapping/Makefile b/intl/icu_capi/cpp/examples/casemapping/Makefile new file mode 100644 index 0000000000..57a9c06943 --- /dev/null +++ b/intl/icu_capi/cpp/examples/casemapping/Makefile @@ -0,0 +1,28 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +.DEFAULT_GOAL := test +.PHONY: build test +FORCE: + +ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../c/include/*.h) + +CXX?=g++ + +$(ALL_HEADERS): + +../../../../../target/debug/libicu_capi_staticlib.a: FORCE + cargo build -p icu_capi_staticlib + +a.out: ../../../../../target/debug/libicu_capi_staticlib.a $(ALL_HEADERS) test.cpp + $(CXX) -std=c++17 test.cpp ../../../../../target/debug/libicu_capi_staticlib.a -ldl -lpthread -lm -g + +build: a.out + +test: build + ./a.out + +clean: + git clean -xf * + rm -f ../../../../../target/debug/libicu_capi_staticlib.a diff --git a/intl/icu_capi/cpp/examples/casemapping/test.cpp b/intl/icu_capi/cpp/examples/casemapping/test.cpp new file mode 100644 index 0000000000..3559c5435d --- /dev/null +++ b/intl/icu_capi/cpp/examples/casemapping/test.cpp @@ -0,0 +1,109 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#include "../../include/ICU4XCaseMapper.hpp" +#include "../../include/ICU4XLogger.hpp" +#include "../../include/ICU4XDataProvider.hpp" +#include "../../include/ICU4XCodePointSetBuilder.hpp" +#include "../../include/ICU4XTitlecaseOptionsV1.hpp" + +#include <iostream> + +int main() { + ICU4XLogger::init_simple_logger(); + ICU4XLocale und = ICU4XLocale::create_from_string("und").ok().value(); + ICU4XLocale greek = ICU4XLocale::create_from_string("el").ok().value(); + ICU4XLocale turkish = ICU4XLocale::create_from_string("tr").ok().value(); + ICU4XDataProvider dp = ICU4XDataProvider::create_compiled(); + + ICU4XCaseMapper cm = ICU4XCaseMapper::create(dp).ok().value(); + + ICU4XTitlecaseOptionsV1 tc_options = ICU4XTitlecaseOptionsV1::default_options(); + + std::string out = cm.lowercase("hEllO WorLd", und).ok().value(); + std::cout << "Lowercased value is " << out << std::endl; + if (out != "hello world") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + out = cm.uppercase("hEllO WorLd", und).ok().value(); + std::cout << "Uppercased value is " << out << std::endl; + if (out != "HELLO WORLD") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + out = cm.titlecase_segment_with_only_case_data_v1("hEllO WorLd", und, tc_options).ok().value(); + std::cout << "Titlecased value is " << out << std::endl; + if (out != "Hello world") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + + // locale-specific behavior + + out = cm.uppercase("Γειά σου Κόσμε", und).ok().value(); + std::cout << "Uppercased value is " << out << std::endl; + if (out != "ΓΕΙΆ ΣΟΥ ΚΌΣΜΕ") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + out = cm.uppercase("Γειά σου Κόσμε", greek).ok().value(); + std::cout << "Uppercased value is " << out << std::endl; + if (out != "ΓΕΙΑ ΣΟΥ ΚΟΣΜΕ") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + out = cm.uppercase("istanbul", und).ok().value(); + std::cout << "Uppercased value is " << out << std::endl; + if (out != "ISTANBUL") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + out = cm.uppercase("istanbul", turkish).ok().value(); + std::cout << "Uppercased value is " << out << std::endl; + if (out != "İSTANBUL") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + + out = cm.fold("ISTANBUL").ok().value(); + std::cout << "Folded value is " << out << std::endl; + if (out != "istanbul") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + out = cm.fold_turkic("ISTANBUL").ok().value(); + std::cout << "Turkic-folded value is " << out << std::endl; + if (out != "ıstanbul") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + ICU4XCodePointSetBuilder builder = ICU4XCodePointSetBuilder::create(); + + cm.add_case_closure_to('s', builder); + + auto set = builder.build(); + + if (set.contains('s')) { + std::cout << "Set contains 's', which was not expected" << std::endl; + return 1; + } + if (!set.contains('S')) { + std::cout << "Set does not 'S', which was not expected" << std::endl; + return 1; + } + if (!set.contains(U'ſ')) { + std::cout << "Set does not 'S', which was not expected" << std::endl; + return 1; + } + return 0; +} diff --git a/intl/icu_capi/cpp/examples/collator/.gitignore b/intl/icu_capi/cpp/examples/collator/.gitignore new file mode 100644 index 0000000000..cb34c546b3 --- /dev/null +++ b/intl/icu_capi/cpp/examples/collator/.gitignore @@ -0,0 +1,2 @@ +a.out +a.out.dSYM diff --git a/intl/icu_capi/cpp/examples/collator/Makefile b/intl/icu_capi/cpp/examples/collator/Makefile new file mode 100644 index 0000000000..57a9c06943 --- /dev/null +++ b/intl/icu_capi/cpp/examples/collator/Makefile @@ -0,0 +1,28 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +.DEFAULT_GOAL := test +.PHONY: build test +FORCE: + +ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../c/include/*.h) + +CXX?=g++ + +$(ALL_HEADERS): + +../../../../../target/debug/libicu_capi_staticlib.a: FORCE + cargo build -p icu_capi_staticlib + +a.out: ../../../../../target/debug/libicu_capi_staticlib.a $(ALL_HEADERS) test.cpp + $(CXX) -std=c++17 test.cpp ../../../../../target/debug/libicu_capi_staticlib.a -ldl -lpthread -lm -g + +build: a.out + +test: build + ./a.out + +clean: + git clean -xf * + rm -f ../../../../../target/debug/libicu_capi_staticlib.a diff --git a/intl/icu_capi/cpp/examples/collator/test.cpp b/intl/icu_capi/cpp/examples/collator/test.cpp new file mode 100644 index 0000000000..20cd0d1315 --- /dev/null +++ b/intl/icu_capi/cpp/examples/collator/test.cpp @@ -0,0 +1,67 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#include "../../include/ICU4XCollator.hpp" +#include "../../include/ICU4XDataProvider.hpp" +#include "../../include/ICU4XLocale.hpp" +#include "../../include/ICU4XLogger.hpp" +#include "../../include/ICU4XOrdering.hpp" + +#include <iostream> +#include <string_view> + +int main() { + ICU4XLogger::init_simple_logger(); + ICU4XDataProvider dp = ICU4XDataProvider::create_compiled(); + + // test 01 - basic collation example, default CollatorOptions + + std::string_view manna{ "manna" }; + std::string_view manana{ "mañana" }; + + ICU4XLocale locale = ICU4XLocale::create_from_string("en").ok().value(); + ICU4XCollatorOptionsV1 options = {}; + ICU4XCollator collator = ICU4XCollator::create_v1(dp, locale, options).ok().value(); + ICU4XOrdering actual = collator.compare(manna, manana); + + if (actual != ICU4XOrdering::Greater) { + std::cout << "Expected manna > mañana for locale " << locale.to_string().ok().value() << std::endl; + return 1; + } + + locale = ICU4XLocale::create_from_string("es").ok().value(); + collator = ICU4XCollator::create_v1(dp, locale, options).ok().value(); + actual = collator.compare(manna, manana); + + if (actual != ICU4XOrdering::Less) { + std::cout << "Expected manna < mañana for locale " << locale.to_string().ok().value()<< std::endl; + return 1; + } + + // test 02 - collation strength example, requires non-default CollatorOptions + + std::string_view as{ "as" }; + std::string_view graveAs{ "às" }; + + locale = ICU4XLocale::create_from_string("en").ok().value(); + options.strength = ICU4XCollatorStrength::Primary; + collator = ICU4XCollator::create_v1(dp, locale, options).ok().value(); + actual = collator.compare(as, graveAs); + + if (actual != ICU4XOrdering::Equal) { + std::cout << "Expected as = às for primary strength, locale " << locale.to_string().ok().value()<< std::endl; + return 1; + } + + options.strength = ICU4XCollatorStrength::Secondary; + collator = ICU4XCollator::create_v1(dp, locale, options).ok().value(); + actual = collator.compare(as, graveAs); + + if (actual != ICU4XOrdering::Less) { + std::cout << "Expected as < às for secondary strength, locale " << locale.to_string().ok().value()<< std::endl; + return 1; + } + + return 0; +} diff --git a/intl/icu_capi/cpp/examples/datetime/.gitignore b/intl/icu_capi/cpp/examples/datetime/.gitignore new file mode 100644 index 0000000000..cb34c546b3 --- /dev/null +++ b/intl/icu_capi/cpp/examples/datetime/.gitignore @@ -0,0 +1,2 @@ +a.out +a.out.dSYM diff --git a/intl/icu_capi/cpp/examples/datetime/Makefile b/intl/icu_capi/cpp/examples/datetime/Makefile new file mode 100644 index 0000000000..57a9c06943 --- /dev/null +++ b/intl/icu_capi/cpp/examples/datetime/Makefile @@ -0,0 +1,28 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +.DEFAULT_GOAL := test +.PHONY: build test +FORCE: + +ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../c/include/*.h) + +CXX?=g++ + +$(ALL_HEADERS): + +../../../../../target/debug/libicu_capi_staticlib.a: FORCE + cargo build -p icu_capi_staticlib + +a.out: ../../../../../target/debug/libicu_capi_staticlib.a $(ALL_HEADERS) test.cpp + $(CXX) -std=c++17 test.cpp ../../../../../target/debug/libicu_capi_staticlib.a -ldl -lpthread -lm -g + +build: a.out + +test: build + ./a.out + +clean: + git clean -xf * + rm -f ../../../../../target/debug/libicu_capi_staticlib.a diff --git a/intl/icu_capi/cpp/examples/datetime/test.cpp b/intl/icu_capi/cpp/examples/datetime/test.cpp new file mode 100644 index 0000000000..4e86e86e52 --- /dev/null +++ b/intl/icu_capi/cpp/examples/datetime/test.cpp @@ -0,0 +1,116 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#include "../../include/ICU4XGregorianDateFormatter.hpp" +#include "../../include/ICU4XGregorianDateTimeFormatter.hpp" +#include "../../include/ICU4XDateTimeFormatter.hpp" +#include "../../include/ICU4XTimeFormatter.hpp" +#include "../../include/ICU4XDataStruct.hpp" +#include "../../include/ICU4XLogger.hpp" +#include "../../include/ICU4XCustomTimeZone.hpp" +#include "../../include/ICU4XIanaToBcp47Mapper.hpp" +#include "../../include/ICU4XBcp47ToIanaMapper.hpp" +#include "../../include/ICU4XGregorianZonedDateTimeFormatter.hpp" +#include "../../include/ICU4XZonedDateTimeFormatter.hpp" + +#include <atomic> +#include <iostream> +#include <array> + +int main() { + ICU4XLogger::init_simple_logger(); + ICU4XLocale locale = ICU4XLocale::create_from_string("es").ok().value(); + std::cout << "Running test for locale " << locale.to_string().ok().value() << std::endl; + ICU4XDataProvider dp = ICU4XDataProvider::create_compiled(); + + ICU4XIsoDateTime date = ICU4XIsoDateTime::create(2022, 07, 11, 13, 06, 42, 0).ok().value(); + + ICU4XTimeFormatter tf = ICU4XTimeFormatter::create_with_length(dp, locale, ICU4XTimeLength::Short).ok().value(); + std::string out = tf.format_iso_datetime(date).ok().value(); + std::cout << "Formatted value is " << out << std::endl; + if (out != "13:06") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + ICU4XGregorianDateFormatter df = ICU4XGregorianDateFormatter::create_with_length(dp, locale, ICU4XDateLength::Full).ok().value(); + out = df.format_iso_datetime(date).ok().value(); + std::cout << "Formatted value is " << out << std::endl; + if (out != "lunes, 11 de julio de 2022") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + ICU4XGregorianDateTimeFormatter dtf = ICU4XGregorianDateTimeFormatter::create_with_lengths(dp, locale, ICU4XDateLength::Medium, ICU4XTimeLength::Short).ok().value(); + out = dtf.format_iso_datetime(date).ok().value(); + std::cout << "Formatted value is " << out << std::endl; + if (out != "11 jul 2022, 13:06") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + locale = ICU4XLocale::create_from_string("en-u-ca-japanese").ok().value(); + ICU4XCalendar cal = ICU4XCalendar::create_for_locale(dp, locale).ok().value(); + ICU4XDateTime any_date = ICU4XDateTime::create_from_iso_in_calendar(2020, 10, 5, 13, 33, 15, 0, cal).ok().value(); + ICU4XDateTimeFormatter any_dtf = ICU4XDateTimeFormatter::create_with_lengths(dp, locale, ICU4XDateLength::Medium, ICU4XTimeLength::Short).ok().value(); + out = any_dtf.format_datetime(any_date).ok().value(); + std::cout << "Formatted value is " << out << std::endl; + if (out != "Oct 5, 2 Reiwa, 1:33\u202fPM") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + ICU4XCustomTimeZone time_zone = ICU4XCustomTimeZone::create_from_string("-06:00").ok().value(); + int32_t offset = time_zone.gmt_offset_seconds().ok().value(); + if (offset != -21600) { + std::cout << "GMT offset doesn't parse" << std::endl; + return 1; + } + ICU4XMetazoneCalculator mzcalc = ICU4XMetazoneCalculator::create(dp).ok().value(); + ICU4XIanaToBcp47Mapper mapper = ICU4XIanaToBcp47Mapper::create(dp).ok().value(); + time_zone.try_set_iana_time_zone_id(mapper, "america/chicago").ok().value(); + std::string time_zone_id_return = time_zone.time_zone_id().ok().value(); + if (time_zone_id_return != "uschi") { + std::cout << "Time zone ID does not roundtrip: " << time_zone_id_return << std::endl; + return 1; + } + ICU4XBcp47ToIanaMapper reverse_mapper = ICU4XBcp47ToIanaMapper::create(dp).ok().value(); + std::string recovered_iana_id = reverse_mapper.get("uschi").ok().value(); + if (recovered_iana_id != "America/Chicago") { + std::cout << "Time zone ID does not canonicalize to IANA: " << recovered_iana_id << std::endl; + return 1; + } + ICU4XIsoDateTime local_datetime = ICU4XIsoDateTime::create(2022, 8, 25, 0, 0, 0, 0).ok().value(); + time_zone.maybe_calculate_metazone(mzcalc, local_datetime); + std::string metazone_id_return = time_zone.metazone_id().ok().value(); + if (metazone_id_return != "amce") { + std::cout << "Metazone ID not calculated correctly; got " << metazone_id_return << std::endl; + return 1; + } + // Note: The daylight time switch should normally come from TZDB calculations. + time_zone.set_daylight_time(); + std::string zone_variant_return = time_zone.zone_variant().ok().value(); + if (zone_variant_return != "dt") { + std::cout << "Zone variant not calculated correctly; got " << zone_variant_return << std::endl; + return 1; + } + + ICU4XGregorianZonedDateTimeFormatter gzdtf = ICU4XGregorianZonedDateTimeFormatter::create_with_lengths(dp, locale, ICU4XDateLength::Full, ICU4XTimeLength::Full).ok().value(); + out = gzdtf.format_iso_datetime_with_custom_time_zone(date, time_zone).ok().value(); + std::cout << "Formatted value is " << out << std::endl; + if (out != "Monday, July 11, 2022, 1:06:42\u202fPM Central Daylight Time") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + ICU4XZonedDateTimeFormatter zdtf = ICU4XZonedDateTimeFormatter::create_with_lengths(dp, locale, ICU4XDateLength::Full, ICU4XTimeLength::Full).ok().value(); + out = zdtf.format_datetime_with_custom_time_zone(any_date, time_zone).ok().value(); + std::cout << "Formatted value is " << out << std::endl; + if (out != "Monday, October 5, 2 Reiwa, 1:33:15\u202fPM Central Daylight Time") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + return 0; +} diff --git a/intl/icu_capi/cpp/examples/fixeddecimal/.gitignore b/intl/icu_capi/cpp/examples/fixeddecimal/.gitignore new file mode 100644 index 0000000000..cb34c546b3 --- /dev/null +++ b/intl/icu_capi/cpp/examples/fixeddecimal/.gitignore @@ -0,0 +1,2 @@ +a.out +a.out.dSYM diff --git a/intl/icu_capi/cpp/examples/fixeddecimal/Makefile b/intl/icu_capi/cpp/examples/fixeddecimal/Makefile new file mode 100644 index 0000000000..57a9c06943 --- /dev/null +++ b/intl/icu_capi/cpp/examples/fixeddecimal/Makefile @@ -0,0 +1,28 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +.DEFAULT_GOAL := test +.PHONY: build test +FORCE: + +ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../c/include/*.h) + +CXX?=g++ + +$(ALL_HEADERS): + +../../../../../target/debug/libicu_capi_staticlib.a: FORCE + cargo build -p icu_capi_staticlib + +a.out: ../../../../../target/debug/libicu_capi_staticlib.a $(ALL_HEADERS) test.cpp + $(CXX) -std=c++17 test.cpp ../../../../../target/debug/libicu_capi_staticlib.a -ldl -lpthread -lm -g + +build: a.out + +test: build + ./a.out + +clean: + git clean -xf * + rm -f ../../../../../target/debug/libicu_capi_staticlib.a diff --git a/intl/icu_capi/cpp/examples/fixeddecimal/test.cpp b/intl/icu_capi/cpp/examples/fixeddecimal/test.cpp new file mode 100644 index 0000000000..365d3972c5 --- /dev/null +++ b/intl/icu_capi/cpp/examples/fixeddecimal/test.cpp @@ -0,0 +1,127 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#include "../../include/ICU4XFixedDecimalFormatter.hpp" +#include "../../include/ICU4XDataStruct.hpp" +#include "../../include/ICU4XLogger.hpp" + +#include <iostream> +#include <array> + +int main() { + ICU4XLogger::init_simple_logger(); + ICU4XLocale locale = ICU4XLocale::create_from_string("bn").ok().value(); + std::cout << "Running test for locale " << locale.to_string().ok().value() << std::endl; + ICU4XDataProvider dp = ICU4XDataProvider::create_compiled(); + ICU4XFixedDecimalFormatter fdf = ICU4XFixedDecimalFormatter::create_with_grouping_strategy( + dp, locale, ICU4XFixedDecimalGroupingStrategy::Auto).ok().value(); + + ICU4XFixedDecimal decimal = ICU4XFixedDecimal::create_from_u64(1000007); + std::string out = fdf.format(decimal).ok().value(); + std::cout << "Formatted value is " << out << std::endl; + if (out != "১০,০০,০০৭") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + std::string out2; + fdf.format_to_writeable(decimal, out2); + std::cout << "Formatted writeable value is " << out2 << std::endl; + if (out2 != "১০,০০,০০৭") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + decimal.multiply_pow10(2); + decimal.set_sign(ICU4XFixedDecimalSign::Negative); + out = fdf.format(decimal).ok().value(); + std::cout << "Value x100 and negated is " << out << std::endl; + if (out != "-১০,০০,০০,৭০০") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + decimal = ICU4XFixedDecimal::create_from_f64_with_floating_precision(100.01).ok().value(); + out = fdf.format(decimal).ok().value(); + std::cout << "Formatted float value is " << out << std::endl; + if (out != "১০০.০১") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + decimal.pad_end(-4); + out = fdf.format(decimal).ok().value(); + std::cout << "Formatted left-padded float value is " << out << std::endl; + if (out != "১০০.০১০০") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + decimal.pad_start(4); + out = fdf.format(decimal).ok().value(); + std::cout << "Formatted right-padded float value is " << out << std::endl; + if (out != "০,১০০.০১০০") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + decimal.set_max_position(3); + out = fdf.format(decimal).ok().value(); + std::cout << "Formatted truncated float value is " << out << std::endl; + if (out != "১০০.০১০০") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + decimal = ICU4XFixedDecimal::create_from_f64_with_lower_magnitude(100.0006, -2).ok().value(); + out = fdf.format(decimal).ok().value(); + std::cout << "Formatted float value from precision 2 is " << out << std::endl; + if (out != "১০০.০০") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + decimal = ICU4XFixedDecimal::create_from_f64_with_significant_digits(100.0006, 5).ok().value(); + out = fdf.format(decimal).ok().value(); + std::cout << "Formatted float value with 5 digits is " << out << std::endl; + if (out != "১০০.০০") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + std::array<char32_t, 10> digits = {U'a', U'b', U'c', U'd', U'e', U'f', U'g', U'h', U'i', U'j'}; + + auto data = ICU4XDataStruct::create_decimal_symbols_v1("+", "", "-", "", "/", "_", 4, 2, 4, digits).ok().value(); + + fdf = ICU4XFixedDecimalFormatter::create_with_decimal_symbols_v1(data, ICU4XFixedDecimalGroupingStrategy::Auto).ok().value(); + + decimal = ICU4XFixedDecimal::create_from_f64_with_floating_precision(123456.8901).ok().value(); + out = fdf.format(decimal).ok().value(); + std::cout << "Formatted float value for custom numeric system is " << out << std::endl; + if (out != "bcdefg/ijab") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + decimal = ICU4XFixedDecimal::create_from_f64_with_floating_precision(123451234567.8901).ok().value(); + out = fdf.format(decimal).ok().value(); + std::cout << "Formatted float value for custom numeric system is " << out << std::endl; + if (out != "bc_de_fb_cd_efgh/ijab") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + locale = ICU4XLocale::create_from_string("th-u-nu-thai").ok().value(); + std::cout << "Running test for locale " << locale.to_string().ok().value() << std::endl; + fdf = ICU4XFixedDecimalFormatter::create_with_grouping_strategy( + dp, locale, ICU4XFixedDecimalGroupingStrategy::Auto).ok().value(); + + decimal = ICU4XFixedDecimal::create_from_f64_with_floating_precision(123456.8901).ok().value(); + out = fdf.format(decimal).ok().value(); + std::cout << "Formatted value is " << out << std::endl; + if (out != "๑๒๓,๔๕๖.๘๙๐๑") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + return 0; +} diff --git a/intl/icu_capi/cpp/examples/fixeddecimal_wasm/.gitignore b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/.gitignore new file mode 100644 index 0000000000..100536298e --- /dev/null +++ b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/.gitignore @@ -0,0 +1,9 @@ +web-version.html +web-version.wasm +web-version.js +node-version.js +node-version.wasm +package-lock.json +node_modules +a.out +a.out.dSYM diff --git a/intl/icu_capi/cpp/examples/fixeddecimal_wasm/Makefile b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/Makefile new file mode 100644 index 0000000000..b2c0a018cf --- /dev/null +++ b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/Makefile @@ -0,0 +1,53 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +.DEFAULT_GOAL := build +.PHONY: build test clean serve build-host test-host +FORCE: + +ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../c/include/*.h) +ICU4X_NIGHTLY_TOOLCHAIN ?= "nightly-2022-12-26" + +CXX?=g++ +EMCC?=emcc + +$(ALL_HEADERS): + +crate/target/debug/libcrate.a: FORCE + cd crate && cargo build + +a.out: crate/target/debug/libcrate.a $(ALL_HEADERS) test.cpp + $(CXX) -std=c++17 test.cpp crate/target/debug/libcrate.a -ldl -lpthread -lm -g + +crate/target/wasm32-unknown-emscripten/release/libcrate.a: FORCE + rustup toolchain install ${ICU4X_NIGHTLY_TOOLCHAIN} + rustup component add rust-src --toolchain ${ICU4X_NIGHTLY_TOOLCHAIN} + RUSTFLAGS="-Cpanic=abort -Copt-level=s -Clto -Cembed-bitcode" \ + cd crate && cargo +${ICU4X_NIGHTLY_TOOLCHAIN} build --release --target wasm32-unknown-emscripten -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort + +web-version.html: crate/target/wasm32-unknown-emscripten/release/libcrate.a $(ALL_HEADERS) test.cpp + $(EMCC) -std=c++17 test.cpp crate/target/wasm32-unknown-emscripten/release/libcrate.a -ldl -lpthread -lm -g -o web-version.html --bind --emrun -sENVIRONMENT=web -sWASM=1 -sEXPORT_ES6=1 -sMODULARIZE=1 + +node-version.js: crate/target/wasm32-unknown-emscripten/release/libcrate.a $(ALL_HEADERS) test.cpp + $(EMCC) -std=c++17 test.cpp crate/target/wasm32-unknown-emscripten/release/libcrate.a -ldl -lpthread -lm -g -o node-version.js --bind -sWASM=1 -sENVIRONMENT=node -sWASM_ASYNC_COMPILATION=0 -DNOMAIN + +build: web-version.html node-version.js + +test: node-version.js + exec node ./node-test.js + +serve: web-version.html + emrun web-version.html + +# These make it possible to ensure that the C++ code is up to date with the bindings +# without needing to set up emsdk. This way `make test-ffi` works without emsdk. +build-host: a.out + +test-host: build-host + ./a.out + +clean: + git clean -xf * + rm -f crate/target/wasm32-unknown-emscripten/release/libcrate.a + rm -f crate/target/debug/libcrate.a diff --git a/intl/icu_capi/cpp/examples/fixeddecimal_wasm/README b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/README new file mode 100644 index 0000000000..1299d40bf0 --- /dev/null +++ b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/README @@ -0,0 +1,7 @@ +This folder contains a test for calling ICU4X from C++ compiled to WASM (via emscripten). + +You need the [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html) downloaded and sourced into your environment to run this. + +There are two ways to run the test. Firstly, you can call `make test`, which runs `node node-test.js` after building the appropriate WASM files. This runs a CLI test with the fixed decimal example in test.cpp. + +The other way is to run `make serve`, which will open a web page running test.cpp in your browser.
\ No newline at end of file diff --git a/intl/icu_capi/cpp/examples/fixeddecimal_wasm/node-test.js b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/node-test.js new file mode 100644 index 0000000000..d4a7a99d41 --- /dev/null +++ b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/node-test.js @@ -0,0 +1,6 @@ +wasm = require("./node-version.js"); + +const exitCode = wasm.runFixedDecimal(); +if (exitCode !== 0) { + throw new Error(`Test failed with exit code ${exitCode}`) +} diff --git a/intl/icu_capi/cpp/examples/fixeddecimal_wasm/package.json b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/package.json new file mode 100644 index 0000000000..5567954da2 --- /dev/null +++ b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/package.json @@ -0,0 +1,6 @@ +{ + "type": "commonjs", + "scripts": { + "test": "node node-test.js" + } +} diff --git a/intl/icu_capi/cpp/examples/fixeddecimal_wasm/test.cpp b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/test.cpp new file mode 100644 index 0000000000..e9bca35216 --- /dev/null +++ b/intl/icu_capi/cpp/examples/fixeddecimal_wasm/test.cpp @@ -0,0 +1,70 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#ifdef __EMSCRIPTEN__ +#include <emscripten/bind.h> +#endif + +#include "../../include/ICU4XFixedDecimalFormatter.hpp" +#include "../../include/ICU4XLogger.hpp" + +#include <iostream> + +extern "C" void diplomat_init(); +extern "C" void log_js(char* s, u_int len) { + std::cout<<"LOG: " << std::string_view(s, len) <<std::endl; +} +extern "C" void warn_js(char* s, u_int len) { + std::cout<<"WARN: " << std::string_view(s, len) <<std::endl; +} + +int runFixedDecimal() { +#ifdef __EMSCRIPTEN__ + diplomat_init(); + ICU4XLogger::init_console_logger(); +#endif + ICU4XLocale locale = ICU4XLocale::create_from_string("bn").ok().value(); + std::cout << "Running test for locale " << locale.to_string().ok().value() << std::endl; + ICU4XDataProvider dp = ICU4XDataProvider::create_compiled(); + ICU4XFixedDecimalFormatter fdf = ICU4XFixedDecimalFormatter::create_with_grouping_strategy( + dp, locale, ICU4XFixedDecimalGroupingStrategy::Auto).ok().value(); + + ICU4XFixedDecimal decimal = ICU4XFixedDecimal::create_from_u64(1000007); + std::string out = fdf.format(decimal).ok().value(); + std::cout << "Formatted value is " << out << std::endl; + if (out != "১০,০০,০০৭") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + std::string out2; + fdf.format_to_writeable(decimal, out2); + std::cout << "Formatted writeable value is " << out2 << std::endl; + if (out2 != "১০,০০,০০৭") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + + decimal.multiply_pow10(2); + decimal.set_sign(ICU4XFixedDecimalSign::Negative); + out = fdf.format(decimal).ok().value(); + std::cout << "Value x100 and negated is " << out << std::endl; + if (out != "-১০,০০,০০,৭০০") { + std::cout << "Output does not match expected output" << std::endl; + return 1; + } + return 0; +} + +#ifdef __EMSCRIPTEN__ +EMSCRIPTEN_BINDINGS(testFixedDecimal) { + emscripten::function("runFixedDecimal", &runFixedDecimal); +} +#endif + +#ifndef NOMAIN +int main() { + return runFixedDecimal(); +} +#endif diff --git a/intl/icu_capi/cpp/examples/locale/.gitignore b/intl/icu_capi/cpp/examples/locale/.gitignore new file mode 100644 index 0000000000..cb34c546b3 --- /dev/null +++ b/intl/icu_capi/cpp/examples/locale/.gitignore @@ -0,0 +1,2 @@ +a.out +a.out.dSYM diff --git a/intl/icu_capi/cpp/examples/locale/Makefile b/intl/icu_capi/cpp/examples/locale/Makefile new file mode 100644 index 0000000000..57a9c06943 --- /dev/null +++ b/intl/icu_capi/cpp/examples/locale/Makefile @@ -0,0 +1,28 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +.DEFAULT_GOAL := test +.PHONY: build test +FORCE: + +ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../c/include/*.h) + +CXX?=g++ + +$(ALL_HEADERS): + +../../../../../target/debug/libicu_capi_staticlib.a: FORCE + cargo build -p icu_capi_staticlib + +a.out: ../../../../../target/debug/libicu_capi_staticlib.a $(ALL_HEADERS) test.cpp + $(CXX) -std=c++17 test.cpp ../../../../../target/debug/libicu_capi_staticlib.a -ldl -lpthread -lm -g + +build: a.out + +test: build + ./a.out + +clean: + git clean -xf * + rm -f ../../../../../target/debug/libicu_capi_staticlib.a diff --git a/intl/icu_capi/cpp/examples/locale/test.cpp b/intl/icu_capi/cpp/examples/locale/test.cpp new file mode 100644 index 0000000000..b2bba0ceff --- /dev/null +++ b/intl/icu_capi/cpp/examples/locale/test.cpp @@ -0,0 +1,107 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#include "../../include/ICU4XLocale.hpp" +#include "../../include/ICU4XLogger.hpp" + +#include <iostream> + +static bool test_locale(ICU4XLocale &locale, std::string_view expectedString, + const char *message) { + std::string actualString = locale.to_string().ok().value(); + std::cout << message << ": \"" << actualString << "\"" << std::endl; + if (actualString != expectedString) { + std::cout << "Locale did not match expected: \"" << expectedString << "\"" + << std::endl; + return false; + } + return true; +} + +static bool test_string(std::string_view actualString, + std::string_view expectedString, const char *message) { + std::cout << message << ": \"" << actualString << "\"" << std::endl; + if (actualString != expectedString) { + std::cout << "String did not match expected: \"" << expectedString << "\"" + << std::endl; + return false; + } + return true; +} + +int main() { + ICU4XLogger::init_simple_logger(); + ICU4XLocale locale = ICU4XLocale::create_from_string("es-ES").ok().value(); + if (!test_locale(locale, "es-ES", "Created a locale")) { + return 1; + } + + locale.set_language("en").ok(); + if (!test_locale(locale, "en-ES", "The language can be updated")) { + return 1; + } + + locale.set_region("US").ok(); + if (!test_locale(locale, "en-US", "The region can be updated")) { + return 1; + } + + locale.set_script("Latn").ok(); + if (!test_locale(locale, "en-Latn-US", "The script can be updated")) { + return 1; + } + + if (!test_string(locale.language().ok().value(), "en", + "The language can be accessed")) { + return 1; + } + if (!test_string(locale.region().ok().value(), "US", + "The region can be accessed")) { + return 1; + } + if (!test_string(locale.script().ok().value(), "Latn", + "The script can be accessed")) { + return 1; + } + + locale.set_language("").ok(); + if (!test_locale(locale, "und-Latn-US", "Removed the language")) { + return 1; + } + + locale.set_region("").ok(); + if (locale.region().is_ok()) { + std::cout << "Expected region to be an err" << std::endl; + return 1; + } + if (!test_locale(locale, "und-Latn", "Removed the region")) { + return 1; + } + + locale.set_script("").ok(); + if (locale.script().is_ok()) { + std::cout << "Expected script to be an err" << std::endl; + return 1; + } + if (!test_locale(locale, "und", "Removed the script")) { + return 1; + } + + locale = ICU4XLocale::create_from_string("en-US-u-hc-h12").ok().value(); + if (!test_string(locale.get_unicode_extension("hc").ok().value(), "h12", + "The unicode extension can be accessed")) { + return 1; + } + if (!test_string(locale.basename().ok().value(), "en-US", + "The basename can be accessed")) { + return 1; + } + + locale = ICU4XLocale::create_und(); + if (!test_locale(locale, "und", "Created an undefined locale")) { + return 1; + } + + return 0; +} diff --git a/intl/icu_capi/cpp/examples/pluralrules/.gitignore b/intl/icu_capi/cpp/examples/pluralrules/.gitignore new file mode 100644 index 0000000000..cba7efc8ef --- /dev/null +++ b/intl/icu_capi/cpp/examples/pluralrules/.gitignore @@ -0,0 +1 @@ +a.out diff --git a/intl/icu_capi/cpp/examples/pluralrules/Makefile b/intl/icu_capi/cpp/examples/pluralrules/Makefile new file mode 100644 index 0000000000..fd43d93d00 --- /dev/null +++ b/intl/icu_capi/cpp/examples/pluralrules/Makefile @@ -0,0 +1,28 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +.DEFAULT_GOAL := test +.PHONY: build test +FORCE: + +ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../c/include/*.h) + +CXX?=g++ + +$(ALL_HEADERS): + +../../../../../target/debug/libicu_capi_staticlib.a: FORCE + cargo build -p icu_capi_staticlib -p icu_provider --features provider_fs,deserialize_json + +a.out: ../../../../../target/debug/libicu_capi_staticlib.a $(ALL_HEADERS) test.cpp + $(CXX) -std=c++17 test.cpp ../../../../../target/debug/libicu_capi_staticlib.a -ldl -lpthread -lm -g + +build: a.out + +test: build + ./a.out + +clean: + git clean -xf * + rm -f ../../../../../target/debug/libicu_capi_staticlib.a diff --git a/intl/icu_capi/cpp/examples/pluralrules/test.cpp b/intl/icu_capi/cpp/examples/pluralrules/test.cpp new file mode 100644 index 0000000000..254e96ecef --- /dev/null +++ b/intl/icu_capi/cpp/examples/pluralrules/test.cpp @@ -0,0 +1,38 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#include "../../include/ICU4XPluralRules.hpp" +#include "../../include/ICU4XLogger.hpp" + +#include <iostream> + +const std::string_view path = "../../../../../provider/datagen/tests/data/json/"; + +int main() { + ICU4XLogger::init_simple_logger(); + ICU4XLocale locale = ICU4XLocale::create_from_string("ar").ok().value(); + std::cout << "Running test for locale " << locale.to_string().ok().value() << std::endl; + ICU4XDataProvider dp = ICU4XDataProvider::create_fs(path).ok().value(); + ICU4XPluralRules pr = ICU4XPluralRules::create_cardinal(dp, locale).ok().value(); + + ICU4XPluralOperands op = ICU4XPluralOperands::create_from_string("3").ok().value(); + ICU4XPluralCategory cat = pr.category_for(op); + + std::cout << "Category is " << static_cast<int32_t>(cat) + << " (should be " << static_cast<int32_t>(ICU4XPluralCategory::Few) << ")" + << std::endl; + if (cat != ICU4XPluralCategory::Few) { + return 1; + } + + op = ICU4XPluralOperands::create_from_string("1011.0").ok().value(); + cat = pr.category_for(op); + std::cout << "Category is " << static_cast<int32_t>(cat) + << " (should be " << static_cast<int32_t>(ICU4XPluralCategory::Many) << ")" + << std::endl; + if (cat != ICU4XPluralCategory::Many) { + return 1; + } + return 0; +} diff --git a/intl/icu_capi/cpp/examples/properties/.gitignore b/intl/icu_capi/cpp/examples/properties/.gitignore new file mode 100644 index 0000000000..cb34c546b3 --- /dev/null +++ b/intl/icu_capi/cpp/examples/properties/.gitignore @@ -0,0 +1,2 @@ +a.out +a.out.dSYM diff --git a/intl/icu_capi/cpp/examples/properties/Makefile b/intl/icu_capi/cpp/examples/properties/Makefile new file mode 100644 index 0000000000..57a9c06943 --- /dev/null +++ b/intl/icu_capi/cpp/examples/properties/Makefile @@ -0,0 +1,28 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +.DEFAULT_GOAL := test +.PHONY: build test +FORCE: + +ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../c/include/*.h) + +CXX?=g++ + +$(ALL_HEADERS): + +../../../../../target/debug/libicu_capi_staticlib.a: FORCE + cargo build -p icu_capi_staticlib + +a.out: ../../../../../target/debug/libicu_capi_staticlib.a $(ALL_HEADERS) test.cpp + $(CXX) -std=c++17 test.cpp ../../../../../target/debug/libicu_capi_staticlib.a -ldl -lpthread -lm -g + +build: a.out + +test: build + ./a.out + +clean: + git clean -xf * + rm -f ../../../../../target/debug/libicu_capi_staticlib.a diff --git a/intl/icu_capi/cpp/examples/properties/test.cpp b/intl/icu_capi/cpp/examples/properties/test.cpp new file mode 100644 index 0000000000..24583041df --- /dev/null +++ b/intl/icu_capi/cpp/examples/properties/test.cpp @@ -0,0 +1,251 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#include "../../include/ICU4XCodePointSetData.hpp" +#include "../../include/ICU4XUnicodeSetData.hpp" +#include "../../include/ICU4XCodePointMapData16.hpp" +#include "../../include/ICU4XCodePointMapData8.hpp" +#include "../../include/ICU4XPropertyValueNameToEnumMapper.hpp" +#include "../../include/ICU4XGeneralCategoryNameToMaskMapper.hpp" +#include "../../include/ICU4XLogger.hpp" + +#include <iostream> + +int test_set_property(ICU4XCodePointSetData data, char32_t included, char32_t excluded) { + bool contains1 = data.contains(included); + bool contains2 = data.contains(excluded); + std::cout << std::hex; // print hex for U+#### + if (contains1 && !contains2) { + std::cout << "Set correctly contains U+" << included << " and not U+" << excluded << std::endl; + } else { + std::cout << "Set returns wrong result on U+" << included << " or U+" << excluded << std::endl; + return 1; + } + return 0; +} + +int test_map_16_property(ICU4XCodePointMapData16 data, char32_t sample, uint32_t expected) { + uint32_t actual = data.get(sample); + std::cout << std::hex; // print hex for U+#### + if (actual == expected) { + std::cout << "Code point U+" << sample << " correctly mapped to 0x" << actual << std::endl; + } else { + std::cout << "Code point U+" << sample << " incorrectly mapped to 0x" << actual << std::endl; + return 1; + } + return 0; +} + +int test_map_8_property(ICU4XCodePointMapData8 data, char32_t sample, uint32_t expected) { + uint32_t actual = data.get(sample); + std::cout << std::hex; // print hex for U+#### + if (actual == expected) { + std::cout << "Code point U+" << sample << " correctly mapped to 0x" << actual << std::endl; + } else { + std::cout << "Code point U+" << sample << " incorrectly mapped to 0x" << actual << std::endl; + return 1; + } + return 0; +} + +int main() { + ICU4XLogger::init_simple_logger(); + ICU4XDataProvider dp = ICU4XDataProvider::create_compiled(); + int result; + + result = test_set_property( + ICU4XCodePointSetData::load_ascii_hex_digit(dp).ok().value(), + u'3', + u'੩' + ); + if (result != 0) { + return result; + } + + result = test_map_16_property( + ICU4XCodePointMapData16::load_script(dp).ok().value(), + u'木', + 17 // Script::Han + ); + if (result != 0) { + return result; + } + + result = test_map_8_property( + ICU4XCodePointMapData8::load_general_category(dp).ok().value(), + u'木', + 5 // GeneralCategory::OtherLetter + ); + if (result != 0) { + return result; + } + + result = test_map_8_property( + ICU4XCodePointMapData8::load_bidi_class(dp).ok().value(), + u'ع', + 13 // GeneralCategory::ArabicLetter + ); + if (result != 0) { + return result; + } + + ICU4XUnicodeSetData basic_emoji = ICU4XUnicodeSetData::load_basic_emoji(dp).ok().value(); + std::string letter = u8"hello"; + + if (!basic_emoji.contains_char(U'🔥')) { + std::cout << "Character 🔥 not found in Basic_Emoji set" << std::endl; + result = 1; + } + + if (!basic_emoji.contains(u8"🗺️")) { + std::cout << "String \"🗺️\" (U+1F5FA U+FE0F) not found in Basic_Emoji set" << std::endl; + result = 1; + } + if (basic_emoji.contains_char(U'a')) { + std::cout << "Character a found in Basic_Emoji set" << std::endl; + result = 1; + } + + if (basic_emoji.contains(u8"aa")) { + std::cout << "String \"aa\" found in Basic_Emoji set" << std::endl; + result = 1; + } + + if (result != 0) { + return result; + } else { + std::cout << "Basic_Emoji set contains appropriate characters" << std::endl; + } + ICU4XLocale locale = ICU4XLocale::create_from_string("bn").ok().value(); + ICU4XUnicodeSetData exemplars = ICU4XUnicodeSetData::load_exemplars_main(dp, locale).ok().value(); + if (!exemplars.contains_char(U'ব')) { + std::cout << "Character 'ব' not found in Bangla exemplar chars set" << std::endl; + result = 1; + } + + if (!exemplars.contains(u8"ক্ষ")) { + std::cout << "String \"ক্ষ\" (U+0995U+09CDU+09B7) not found in Bangla exemplar chars set" << std::endl; + result = 1; + } + if (exemplars.contains_char(U'a')) { + std::cout << "Character a found in Bangla exemplar chars set" << std::endl; + result = 1; + } + + if (exemplars.contains(u8"aa")) { + std::cout << "String \"aa\" not found in Bangla exemplar chars set" << std::endl; + result = 1; + } + if (result != 0) { + return result; + } else { + std::cout << "Bangla exemplar chars set contains appropriate characters" << std::endl; + } + + + ICU4XPropertyValueNameToEnumMapper mapper = ICU4XPropertyValueNameToEnumMapper::load_script(dp).ok().value(); + int32_t script = mapper.get_strict("Brah"); + if (script != 65) { + std::cout << "Expected discriminant 64 for script name `Brah`, found " << script << std::endl; + result = 1; + } + script = mapper.get_strict("Brahmi"); + if (script != 65) { + std::cout << "Expected discriminant 64 for script name `Brahmi`, found " << script << std::endl; + result = 1; + } + script = mapper.get_loose("brah"); + if (script != 65) { + std::cout << "Expected discriminant 64 for (loose matched) script name `brah`, found " << script << std::endl; + result = 1; + } + script = mapper.get_strict("Linear_Z"); + if (script != -1) { + std::cout << "Expected no value for fake script name `Linear_Z`, found " << script << std::endl; + result = 1; + } + if (result != 0) { + return result; + } else { + std::cout << "Script name mapper returns correct values" << std::endl; + } + + ICU4XGeneralCategoryNameToMaskMapper mask_mapper = ICU4XGeneralCategoryNameToMaskMapper::load(dp).ok().value(); + int32_t mask = mask_mapper.get_strict("Lu"); + if (mask != 0x02) { + std::cout << "Expected discriminant 0x02 for mask name `Lu`, found " << mask << std::endl; + result = 1; + } + mask = mask_mapper.get_strict("L"); + if (mask != 0x3e) { + std::cout << "Expected discriminant 0x3e for mask name `Lu`, found " << mask << std::endl; + result = 1; + } + mask = mask_mapper.get_strict("Letter"); + if (mask != 0x3e) { + std::cout << "Expected discriminant 0x3e for mask name `Letter`, found " << mask << std::endl; + result = 1; + } + mask = mask_mapper.get_loose("l"); + if (mask != 0x3e) { + std::cout << "Expected discriminant 0x3e for mask name `l`, found " << mask << std::endl; + result = 1; + } + mask = mask_mapper.get_strict("letter"); + if (mask != 0) { + std::cout << "Expected no mask for (strict matched) name `letter`, found " << mask << std::endl; + result = 1; + } + mask = mask_mapper.get_strict("EverythingLol"); + if (mask != 0) { + std::cout << "Expected no mask for nonexistant name `EverythingLol`, found " << mask << std::endl; + result = 1; + } + + + if (result != 0) { + return result; + } else { + std::cout << "Mask name mapper returns correct values" << std::endl; + } + + + mask = mask_mapper.get_strict("Lu"); + ICU4XCodePointMapData8 gc = ICU4XCodePointMapData8::load_general_category(dp).ok().value(); + auto ranges = gc.iter_ranges_for_mask(mask); + auto next = ranges.next(); + if (next.done) { + std::cout << "Got empty iterator!"; + result = 1; + } + if (next.start != U'A' || next.end != U'Z') { + std::cout << "Expected range [" << U'A' << ", " << U'Z' << "], got range [" << next.start << ", " << next.end << "]" << std::endl; + result = 1; + } + + // Test iteration to completion for a small set + mask = mask_mapper.get_strict("Control"); + ranges = gc.iter_ranges_for_mask(mask); + next = ranges.next(); + + if (next.start != 0 || next.end != 0x1f) { + std::cout << "Expected range [0, 0x1f], got range [" << next.start << ", " << next.end << "]" << std::endl; + result = 1; + } + + std::cout << "Found ranges for gc=Control:"; + while (!next.done) { + std::cout << " [" << next.start << ", " << next.end << "]"; + + next = ranges.next(); + } + std::cout << std::endl; + + if (result != 0) { + return result; + } else { + std::cout << "Ranges iterator works" << std::endl; + } + return 0; +} diff --git a/intl/icu_capi/cpp/examples/segmenter/.gitignore b/intl/icu_capi/cpp/examples/segmenter/.gitignore new file mode 100644 index 0000000000..cb34c546b3 --- /dev/null +++ b/intl/icu_capi/cpp/examples/segmenter/.gitignore @@ -0,0 +1,2 @@ +a.out +a.out.dSYM diff --git a/intl/icu_capi/cpp/examples/segmenter/Makefile b/intl/icu_capi/cpp/examples/segmenter/Makefile new file mode 100644 index 0000000000..57a9c06943 --- /dev/null +++ b/intl/icu_capi/cpp/examples/segmenter/Makefile @@ -0,0 +1,28 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +.DEFAULT_GOAL := test +.PHONY: build test +FORCE: + +ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../c/include/*.h) + +CXX?=g++ + +$(ALL_HEADERS): + +../../../../../target/debug/libicu_capi_staticlib.a: FORCE + cargo build -p icu_capi_staticlib + +a.out: ../../../../../target/debug/libicu_capi_staticlib.a $(ALL_HEADERS) test.cpp + $(CXX) -std=c++17 test.cpp ../../../../../target/debug/libicu_capi_staticlib.a -ldl -lpthread -lm -g + +build: a.out + +test: build + ./a.out + +clean: + git clean -xf * + rm -f ../../../../../target/debug/libicu_capi_staticlib.a diff --git a/intl/icu_capi/cpp/examples/segmenter/test.cpp b/intl/icu_capi/cpp/examples/segmenter/test.cpp new file mode 100644 index 0000000000..cfe0899f76 --- /dev/null +++ b/intl/icu_capi/cpp/examples/segmenter/test.cpp @@ -0,0 +1,160 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#include "../../include/ICU4XDataProvider.hpp" +#include "../../include/ICU4XGraphemeClusterSegmenter.hpp" +#include "../../include/ICU4XLineSegmenter.hpp" +#include "../../include/ICU4XSentenceSegmenter.hpp" +#include "../../include/ICU4XWordSegmenter.hpp" +#include "../../include/ICU4XLogger.hpp" + +#include <iostream> +#include <string_view> + +using std::cout; +using std::endl; + +void print_ruler(size_t str_len) { + for (size_t i = 0; i < str_len; i++) { + if (i % 10 == 0) { + cout << "0"; + } else if (i % 5 == 0) { + cout << "5"; + } else { + cout << "."; + } + } + cout << endl; +} + +template <typename Iterator> +void iterate_breakpoints(Iterator& iterator) { + while (true) { + int32_t breakpoint = iterator.next(); + if (breakpoint == -1) { + break; + } + cout << " " << breakpoint; + } + cout << endl; +} + +template <typename Iterator> +void iterate_word_breakpoints(Iterator& iterator) { + while (true) { + int32_t breakpoint = iterator.next(); + if (breakpoint == -1) { + break; + } + cout << " " << breakpoint; + switch (iterator.word_type()) { + case ICU4XSegmenterWordType::None: + cout << " (none"; + break; + case ICU4XSegmenterWordType::Number: + cout << " (number"; + break; + case ICU4XSegmenterWordType::Letter: + cout << " (letter"; + break; + default: + cout << " (unknown status"; + break; + } + if (iterator.is_word_like()) { + cout << ", word-like"; + } + cout << ")"; + } + cout << endl; +} + +void test_line(const std::string_view& str) { + const auto provider = ICU4XDataProvider::create_compiled(); + const auto segmenter_auto = + ICU4XLineSegmenter::create_auto(provider).ok().value(); + const auto segmenter_lstm = + ICU4XLineSegmenter::create_lstm(provider).ok().value(); + const auto segmenter_dictionary = + ICU4XLineSegmenter::create_dictionary(provider).ok().value(); + + const ICU4XLineSegmenter* segmenters[] = {&segmenter_auto, &segmenter_lstm, + &segmenter_dictionary}; + for (const auto* segmenter : segmenters) { + cout << "Finding line breakpoints in string:" << endl << str << endl; + print_ruler(str.size()); + + cout << "Line breakpoints:"; + auto iterator = segmenter->segment_utf8(str); + iterate_breakpoints(iterator); + } +} + +void test_grapheme(const std::string_view& str) { + const auto provider = ICU4XDataProvider::create_compiled(); + const auto segmenter = ICU4XGraphemeClusterSegmenter::create(provider).ok().value(); + cout << "Finding grapheme cluster breakpoints in string:" << endl + << str << endl; + print_ruler(str.size()); + + cout << "Grapheme cluster breakpoints:"; + auto iterator = segmenter.segment_utf8(str); + iterate_breakpoints(iterator); +} + +void test_word(const std::string_view& str) { + const auto provider = ICU4XDataProvider::create_compiled(); + const auto segmenter_auto = + ICU4XWordSegmenter::create_auto(provider).ok().value(); + const auto segmenter_lstm = + ICU4XWordSegmenter::create_lstm(provider).ok().value(); + const auto segmenter_dictionary = + ICU4XWordSegmenter::create_dictionary(provider).ok().value(); + + const ICU4XWordSegmenter* segmenters[] = {&segmenter_auto, &segmenter_lstm, + &segmenter_dictionary}; + for (const auto* segmenter : segmenters) { + cout << "Finding word breakpoints in string:" << endl << str << endl; + print_ruler(str.size()); + + cout << "Word breakpoints:"; + auto iterator = segmenter->segment_utf8(str); + iterate_word_breakpoints(iterator); + } +} + +void test_sentence(const std::string_view& str) { + const auto provider = ICU4XDataProvider::create_compiled(); + const auto segmenter = ICU4XSentenceSegmenter::create(provider).ok().value(); + cout << "Finding sentence breakpoints in string:" << endl + << str << endl; + print_ruler(str.size()); + + cout << "Sentence breakpoints:"; + auto iterator = segmenter.segment_utf8(str); + iterate_breakpoints(iterator); +} + +int main(int argc, char* argv[]) { + ICU4XLogger::init_simple_logger(); + std::string_view str; + if (argc >= 2) { + str = argv[1]; + } else { + str = "The 101 quick brown foxes jump over the lazy dog."; + } + + test_line(str); + cout << endl; + + test_grapheme(str); + cout << endl; + + test_word(str); + cout << endl; + + test_sentence(str); + cout << endl; + return 0; +} |