diff --git a/build/showprogress.sh b/build/showprogress.sh index 59c33509..8338f92d 100755 --- a/build/showprogress.sh +++ b/build/showprogress.sh @@ -29,60 +29,99 @@ C_API_HEADER_NAMES=( ICU_INCLUDE_PATH="$(icu-config --cppflags-searchpath | sed -e 's/-I//' | sed -e 's/ //g')" -for header_basename in ${C_API_HEADER_NAMES[@]}; do - header_fullname="${ICU_INCLUDE_PATH}/unicode/${header_basename}.h" - echo $header_basename: $header_fullname - ctags -x --c-kinds=fp $header_fullname | sed -e 's/ .*$//' \ - | grep -v U_DEFINE | sort | uniq \ - > "${TOP_DIR}/coverage/${header_basename}_all.txt" - - # Extracts all mentions of functions such as "utext_close" for example from - # rust docs of the form "/// Implements `utext_close` ... ". This is - # simplistic but quite enough with a little bit of care. - find . -path "*rust_icu_${header_basename}/src/*.rs" | \ - xargs grep "/// Implements \`" | sed -e 's/.*`\(.*\)`.*$/\1/' | \ - sort | uniq > "${TOP_DIR}/coverage/${header_basename}_implemented.txt" -done - -# Now, write a report out. Again, simplistic, but gets the job done. +# Write a report out as we read the data. REPORT_FILE="${TOP_DIR}/coverage/report.md" -cat < "${REPORT_FILE}" +REPORT_FILE_HEADER="${TOP_DIR}/coverage/report_header.md" +REPORT_FILE_DETAIL="${TOP_DIR}/coverage/report_detail.md" +cat < "${REPORT_FILE_HEADER}" # Implementation coverage report | Header | Implemented | | ------ | ----------- | EOF -for header_basename in ${C_API_HEADER_NAMES[@]}; do - total_functions="$(cat "${TOP_DIR}"/coverage/${header_basename}_all.txt | wc -l)" - implemented_functions="$(cat "${TOP_DIR}"/coverage/${header_basename}_implemented.txt | wc -l)" - printf "| \`%s.h\` | %s / %s | \n" ${header_basename} ${implemented_functions} ${total_functions} >> "${REPORT_FILE}" -done -cat <>"${REPORT_FILE}" + cat <>"${REPORT_FILE_DETAIL}" # Unimplemented functions per header EOF + for header_basename in ${C_API_HEADER_NAMES[@]}; do - cat <>"${REPORT_FILE}" + : > "${TOP_DIR}/coverage/${header_basename}_all.txt" + : > "${TOP_DIR}/coverage/${header_basename}_implemented.txt" + header_fullname="${ICU_INCLUDE_PATH}/unicode/${header_basename}.h" + all=$(ctags -x --c-kinds=fp $header_fullname | sed -e 's/ .*$//' \ + | grep -v U_DEFINE | sort -fs | uniq) + for fn in ${all}; do + printf "%s\n" ${fn} >> "${TOP_DIR}/coverage/${header_basename}_all.txt" + done + + # Extracts all mentions of functions such as "utext_close" for example from + # rust docs of the form "/// Implements `utext_close` ... ". This is + # simplistic but quite enough with a little bit of care. + files=`find . -path "*rust_icu_${header_basename}/src/*.rs"` + impl_fns="" + unimpl_fns="" + for file in ${files}; do + echo $header_basename: $header_fullname ${file} + found_fns="$(grep "/// Implements \`" ${file} | sed -e 's/.*`\(.*\)`.*$/\1/' | sed -e 's/\(.*\)()$/\1/' | sort -fs | uniq)" + # Match the extracted function to a function in the header being processed + # (in case the "/// Implements `" comment is used in another context) + for impl_fn in ${found_fns}; do + for all_fn in ${all}; do + if [ ${impl_fn} = ${all_fn} ] + then + impl_fns="${impl_fns} ${impl_fn}" + break + fi + done + done + done + # Sort again in case we process multiple source files + impl_fns="$(echo ${impl_fns} | sort -fs | uniq)" + for impl_fn in ${impl_fns}; do + printf "%s\n" ${impl_fn} >> "${TOP_DIR}/coverage/${header_basename}_implemented.txt" + done + unimpl_fns="" + for all_fn in ${all}; do + found="false" + for impl_fn in ${impl_fns}; do + if [ ${impl_fn} = ${all_fn} ] + then + found="true" + break + fi + done + if [ "false" = ${found} ] + then + unimpl_fns="${unimpl_fns} ${all_fn}" + fi + done + + total_functions=$(echo ${all} | wc -w) + implemented_functions=$(echo ${impl_fns} | wc -w) + printf "| \`%s.h\` | %s / %s | \n" ${header_basename} ${implemented_functions} ${total_functions} >> "${REPORT_FILE_HEADER}" + + cat <>"${REPORT_FILE_DETAIL}" # Header: \`${header_basename}.h\` | Unimplemented | Implemented | | ------------- | ----------- | EOF - for fun in $(cat "${TOP_DIR}/coverage/${header_basename}_implemented.txt" | sort -fs); do - echo "| | \`${fun}\` |" >>"${REPORT_FILE}" + for impl_fn in ${impl_fns}; do + printf "| | \`%s\` |\n" ${impl_fn} >>"${REPORT_FILE_DETAIL}" done - unimplemented="$(comm -23 \ - "${TOP_DIR}/coverage/${header_basename}_all.txt" \ - "${TOP_DIR}/coverage/${header_basename}_implemented.txt" | sort -fs | uniq)" - for fun in ${unimplemented}; do - echo "| \`${fun}\` | |" >>"${REPORT_FILE}" + for fun in ${unimpl_fns}; do + printf "| \`%s\` | |\n" ${fun} >>"${REPORT_FILE_DETAIL}" done sort -fs -o "${TOP_DIR}/coverage/${header_basename}_all.txt" "${TOP_DIR}/coverage/${header_basename}_all.txt" sort -fs -o "${TOP_DIR}/coverage/${header_basename}_implemented.txt" "${TOP_DIR}/coverage/${header_basename}_implemented.txt" done +cat ${REPORT_FILE_HEADER} ${REPORT_FILE_DETAIL} > ${REPORT_FILE} +rm ${REPORT_FILE_HEADER} +rm ${REPORT_FILE_DETAIL} + diff --git a/coverage/report.md b/coverage/report.md index 45be7aad..d42359dc 100644 --- a/coverage/report.md +++ b/coverage/report.md @@ -5,18 +5,18 @@ | `ubrk.h` | 19 / 23 | | `ucal.h` | 15 / 47 | | `ucol.h` | 8 / 51 | -| `udat.h` | 10 / 38 | -| `udata.h` | 4 / 8 | -| `uenum.h` | 8 / 8 | +| `udat.h` | 5 / 38 | +| `udata.h` | 2 / 8 | +| `uenum.h` | 3 / 8 | | `uformattable.h` | 6 / 13 | | `ulistformatter.h` | 2 / 8 | -| `uloc.h` | 30 / 42 | -| `umsg.h` | 6 / 20 | +| `uloc.h` | 28 / 42 | +| `umsg.h` | 5 / 20 | | `unum.h` | 14 / 32 | -| `unumberformatter.h` | 7 / 6 | +| `unumberformatter.h` | 3 / 6 | | `upluralrules.h` | 3 / 8 | -| `ustring.h` | 3 / 61 | -| `utext.h` | 3 / 28 | +| `ustring.h` | 2 / 61 | +| `utext.h` | 2 / 28 | | `utrans.h` | 10 / 20 | | `unorm2.h` | 8 / 22 | # Unimplemented functions per header @@ -162,11 +162,6 @@ | Unimplemented | Implemented | | ------------- | ----------- | -| | `UDateFormat` | -| | `UDateTimePatternGenerator` | -| | `udatpg_clone` | -| | `udatpg_getBestPattern` | -| | `udatpg_open` | | | `udat_close` | | | `udat_format` | | | `udat_open` | @@ -210,10 +205,8 @@ | Unimplemented | Implemented | | ------------- | ----------- | -| | `UDataMemory` | | | `udata_open` | | | `udata_setCommonData` | -| | `u_setDataDirectory` | | `udata_close` | | | `udata_getInfo` | | | `udata_getMemory` | | @@ -225,14 +218,9 @@ | Unimplemented | Implemented | | ------------- | ----------- | -| | `ucal_openCountryTimeZones` | -| | `ucal_openTimeZoneIDEnumeration` | -| | `ucal_openTimeZones` | -| | `UEnumeration` | | | `uenum_close` | | | `uenum_next` | | | `uenum_openCharStringsEnumeration` | -| | `uloc_openKeywords` | | `uenum_count` | | | `uenum_openFromStringEnumeration` | | | `uenum_openUCharStringsEnumeration` | | @@ -274,8 +262,6 @@ | Unimplemented | Implemented | | ------------- | ----------- | -| | `icu::Locale::getUnicodeKeywords()` | -| | `icu::Locale::getUnicodeKeywordValue()` | | | `uloc_acceptLanguage` | | | `uloc_addLikelySubtags` | | | `uloc_canonicalize` | @@ -292,13 +278,13 @@ | | `uloc_getDisplayName` | | | `uloc_getDisplayScript` | | | `uloc_getDisplayVariant` | -| | `uloc_getKeywordValue()` | +| | `uloc_getKeywordValue` | | | `uloc_getLanguage` | | | `uloc_getName` | | | `uloc_getScript` | | | `uloc_getVariant` | | | `uloc_minimizeSubtags` | -| | `uloc_openKeywords()` | +| | `uloc_openKeywords` | | | `uloc_setDefault` | | | `uloc_toLanguageTag` | | | `uloc_toLegacyKey` | @@ -310,14 +296,12 @@ | `uloc_getISO3Language` | | | `uloc_getISOCountries` | | | `uloc_getISOLanguages` | | -| `uloc_getKeywordValue` | | | `uloc_getLCID` | | | `uloc_getLineOrientation` | | | `uloc_getLocaleForLCID` | | | `uloc_getParent` | | | `uloc_isRightToLeft` | | | `uloc_openAvailableByType` | | -| `uloc_openKeywords` | | | `uloc_setKeywordValue` | | | `uloc_toLegacyType` | | @@ -325,7 +309,6 @@ | Unimplemented | Implemented | | ------------- | ----------- | -| | `UMessageFormat` | | | `umsg_clone` | | | `umsg_close` | | | `umsg_format` | @@ -391,10 +374,6 @@ | | `unumf_formatDecimal` | | | `unumf_openForSkeletonAndLocale` | | | `unumf_openForSkeletonAndLocaleWithError` | -| | `unumf_openResult` | -| | `unumf_resultGetAllFieldPositions` | -| | `unumf_resultNextFieldPosition` | -| | `unumf_resultToString` | | `unumf_close` | | | `unumf_formatDouble` | | | `unumf_formatInt` | | @@ -416,7 +395,6 @@ | Unimplemented | Implemented | | ------------- | ----------- | -| | `UChar*` | | | `u_strFromUTF8` | | | `u_strToUTF8` | | `u_austrcpy` | | @@ -485,7 +463,6 @@ | ------------- | ----------- | | | `utext_clone` | | | `utext_close` | -| | `utext_open` | | `utext_char32At` | | | `utext_copy` | | | `utext_current32` | | diff --git a/coverage/udat_implemented.txt b/coverage/udat_implemented.txt index 75c2b815..2d46bfe4 100644 --- a/coverage/udat_implemented.txt +++ b/coverage/udat_implemented.txt @@ -1,8 +1,3 @@ -UDateFormat -UDateTimePatternGenerator -udatpg_clone -udatpg_getBestPattern -udatpg_open udat_close udat_format udat_open diff --git a/coverage/udata_implemented.txt b/coverage/udata_implemented.txt index 1c4acb57..73bc7ac3 100644 --- a/coverage/udata_implemented.txt +++ b/coverage/udata_implemented.txt @@ -1,4 +1,2 @@ -UDataMemory udata_open udata_setCommonData -u_setDataDirectory diff --git a/coverage/uenum_implemented.txt b/coverage/uenum_implemented.txt index 13874fd8..81fd86ec 100644 --- a/coverage/uenum_implemented.txt +++ b/coverage/uenum_implemented.txt @@ -1,8 +1,3 @@ -ucal_openCountryTimeZones -ucal_openTimeZoneIDEnumeration -ucal_openTimeZones -UEnumeration uenum_close uenum_next uenum_openCharStringsEnumeration -uloc_openKeywords diff --git a/coverage/uloc_implemented.txt b/coverage/uloc_implemented.txt index ae5d5b99..f214e5ce 100644 --- a/coverage/uloc_implemented.txt +++ b/coverage/uloc_implemented.txt @@ -1,5 +1,3 @@ -icu::Locale::getUnicodeKeywords() -icu::Locale::getUnicodeKeywordValue() uloc_acceptLanguage uloc_addLikelySubtags uloc_canonicalize @@ -16,13 +14,13 @@ uloc_getDisplayLanguage uloc_getDisplayName uloc_getDisplayScript uloc_getDisplayVariant -uloc_getKeywordValue() +uloc_getKeywordValue uloc_getLanguage uloc_getName uloc_getScript uloc_getVariant uloc_minimizeSubtags -uloc_openKeywords() +uloc_openKeywords uloc_setDefault uloc_toLanguageTag uloc_toLegacyKey diff --git a/coverage/umsg_implemented.txt b/coverage/umsg_implemented.txt index 70723ed1..18ad92d0 100644 --- a/coverage/umsg_implemented.txt +++ b/coverage/umsg_implemented.txt @@ -1,4 +1,3 @@ -UMessageFormat umsg_clone umsg_close umsg_format diff --git a/coverage/unumberformatter_implemented.txt b/coverage/unumberformatter_implemented.txt index 293892be..e2322d98 100644 --- a/coverage/unumberformatter_implemented.txt +++ b/coverage/unumberformatter_implemented.txt @@ -1,7 +1,3 @@ unumf_formatDecimal unumf_openForSkeletonAndLocale unumf_openForSkeletonAndLocaleWithError -unumf_openResult -unumf_resultGetAllFieldPositions -unumf_resultNextFieldPosition -unumf_resultToString diff --git a/coverage/ustring_implemented.txt b/coverage/ustring_implemented.txt index cedfcebc..bb79bc95 100644 --- a/coverage/ustring_implemented.txt +++ b/coverage/ustring_implemented.txt @@ -1,3 +1,2 @@ -UChar* u_strFromUTF8 u_strToUTF8 diff --git a/coverage/utext_implemented.txt b/coverage/utext_implemented.txt index 2387c45e..f9a99150 100644 --- a/coverage/utext_implemented.txt +++ b/coverage/utext_implemented.txt @@ -1,3 +1,2 @@ utext_clone utext_close -utext_open diff --git a/rust_icu_uenum/src/lib.rs b/rust_icu_uenum/src/lib.rs index ddc0727b..555efc82 100644 --- a/rust_icu_uenum/src/lib.rs +++ b/rust_icu_uenum/src/lib.rs @@ -224,9 +224,8 @@ pub fn open_time_zones() -> Result { } #[doc(hidden)] -/// Implements `uloc_openKeywords`. -// This should be in the `uloc` crate, but this is not possible because of the raw enum -// initialization. Tested in `uloc`. +// This has been moved to the `uloc` crate +#[deprecated(since="4.2.4", note="please use `ULoc::open_keywords` instead")] pub fn uloc_open_keywords(locale: &str) -> Result { let mut status = common::Error::OK_CODE; let asciiz_locale = ffi::CString::new(locale)?; @@ -277,4 +276,21 @@ mod tests { let e = Enumeration::try_from(&vec!["hello", "world", "💖", invalid_utf8][..]); assert!(e.is_err(), "was: {:?}", e); } + + #[test] + fn test_uloc_open_keywords() -> Result<(), common::Error> { + let loc = "az-Cyrl-AZ-u-ca-hebrew-fw-sunday-nu-deva-tz-usnyc"; + #[allow(deprecated)] + let keywords: Vec = uloc_open_keywords(loc).unwrap().map(|result| result.unwrap()).collect(); + assert_eq!( + keywords, + vec![ + "calendar".to_string(), + "fw".to_string(), + "numbers".to_string(), + "timezone".to_string() + ] + ); + Ok(()) + } } diff --git a/rust_icu_uloc/src/lib.rs b/rust_icu_uloc/src/lib.rs index ab8e2f2b..70b227f0 100644 --- a/rust_icu_uloc/src/lib.rs +++ b/rust_icu_uloc/src/lib.rs @@ -416,9 +416,25 @@ impl ULoc { ) } + pub fn open_keywords(&self) -> Result { + let mut status = common::Error::OK_CODE; + let asciiz_locale = self.as_c_str(); + let raw_enum = unsafe { + assert!(common::Error::is_ok(status)); + versioned_function!(uloc_openKeywords)(asciiz_locale.as_ptr(), &mut status) + }; + common::Error::ok_or_warning(status)?; + // "No error but null" means that there are no keywords + if raw_enum.is_null() { + Ok(Enumeration::empty()) + } else { + Ok(unsafe { Enumeration::from_raw_parts(None, raw_enum) }) + } + } + /// Implements `uloc_openKeywords()` from ICU4C. pub fn keywords(&self) -> impl Iterator { - rust_icu_uenum::uloc_open_keywords(&self.repr) + self.open_keywords() .unwrap() .map(|result| result.unwrap()) } @@ -447,7 +463,7 @@ impl ULoc { .map(|value| if value.is_empty() { None } else { Some(value) }) } - /// Implements `icu::Locale::getUnicodeKeywordValue()` from ICU4C. + /// Implements `icu::Locale::getUnicodeKeywordValue()` from the C++ API. pub fn unicode_keyword_value( &self, unicode_keyword: &str,