add option for generating partial collation key
diff --git a/UTS10/collation_key.c b/UTS10/collation_key.c index 8d3ed62..c1ffa9a 100644 --- a/UTS10/collation_key.c +++ b/UTS10/collation_key.c
@@ -50,12 +50,23 @@ return (collation | UNICOLL_CONTRACTIONS_MASK); } +/* If PARTIAL_KEY_ENABLED is non-zero, u*_make_collation_key does not + re-allocate RESULTBUF and will return a partial key (null-terminated) + if the full result would be longer than *LENGTHP bytes. */ +Collation_choice unicoll_enable_partial (Collation_choice collation, + int partial_key_enabled) +{ + if (!partial_key_enabled) + return (collation & ~UNICOLL_PARTIAL_MASK); + else + return (collation | UNICOLL_PARTIAL_MASK); +} + /* forward declaration */ static char *make_key_internal (char *psort_key, - struct collation_unit *elements, - size_t elements_count, - int variable_shifted_or_blanked, - int variable_shifted); + struct collation_unit *elements, size_t elements_count, + int variable_shifted_or_blanked, int variable_shifted, + char *limit); char * u32_make_collation_key (Collation_choice collation, @@ -78,6 +89,8 @@ int disable_sequence_lookup = (collation & UNICOLL_CONTRACTIONS_MASK); + int fix_length = 0; + char32_t *codepoints; size_t length; @@ -199,21 +212,31 @@ sort_key = resultbuf; else { - sort_key = malloc (sort_key_alloc); - if (!sort_key) + int partial_key_enabled = (collation & UNICOLL_PARTIAL_MASK); + if (!partial_key_enabled) { - errno = ENOMEM; - return 0; + sort_key = malloc (sort_key_alloc); + if (!sort_key) + { + errno = ENOMEM; + return 0; + } + } + else + { + sort_key = resultbuf; + fix_length = 1; } } psort_key = sort_key; psort_key = make_key_internal (psort_key, elements, elements_count, variable_shifted_or_blanked, - variable_shifted); + variable_shifted, + fix_length ? &sort_key[*lengthp] : NULL); *psort_key = '\0'; - *lengthp = psort_key - sort_key; + *lengthp = psort_key - sort_key + 1; free (elements); free (codepoints); @@ -225,11 +248,16 @@ make_key_internal (char *psort_key, struct collation_unit *elements, size_t elements_count, - int variable_shifted_or_blanked, - int variable_shifted) + int variable_shifted_or_blanked, int variable_shifted, + char *limit) { -#define cat(c) (*psort_key++ = (c)) +#define cat(c) { \ + if (psort_key == limit) return psort_key; \ + else *psort_key++ = (c); \ +} + /* Note that we do not call malloc in this function so no clean-up + is required at function exit. */ /* Output collation key without any null bytes. See UTS#10 s.9.4 "Avoiding Zero Bytes". */ @@ -397,6 +425,7 @@ } } return psort_key; +#undef cat } char *
diff --git a/UTS10/collation_key.h b/UTS10/collation_key.h index f1b735a..1be02f8 100644 --- a/UTS10/collation_key.h +++ b/UTS10/collation_key.h
@@ -11,6 +11,7 @@ #define UNICOLL_VARIABLE_MASK 0x3 #define UNICOLL_NORMALIZATION_MASK 0x4 #define UNICOLL_CONTRACTIONS_MASK 0x8 +#define UNICOLL_PARTIAL_MASK 0x10 typedef uint_fast32_t Collation_choice; @@ -21,6 +22,8 @@ int normalization_on); Collation_choice unicoll_set_contractions (Collation_choice collation, int use_contractions); +Collation_choice unicoll_enable_partial (Collation_choice collation, + int partial_key_enabled); char *u8_make_collation_key (Collation_choice collation,