+static
+uint32_t u_toLargeKana(const UChar *source, const uint32_t sourceLen, UChar *resBuf, const uint32_t resLen, UErrorCode *status) {
+ uint32_t i = 0;
+ UChar c;
+
+ if(U_FAILURE(*status)) {
+ return 0;
+ }
+
+ if(sourceLen > resLen) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return 0;
+ }
+
+ for(i = 0; i < sourceLen; i++) {
+ c = source[i];
+ if(0x3042 < c && c < 0x30ef) { /* Kana range */
+ switch(c - 0x3000) {
+ case 0x41: case 0x43: case 0x45: case 0x47: case 0x49: case 0x63: case 0x83: case 0x85: case 0x8E:
+ case 0xA1: case 0xA3: case 0xA5: case 0xA7: case 0xA9: case 0xC3: case 0xE3: case 0xE5: case 0xEE:
+ c++;
+ break;
+ case 0xF5:
+ c = 0x30AB;
+ break;
+ case 0xF6:
+ c = 0x30B1;
+ break;
+ }
+ }
+ resBuf[i] = c;
+ }
+ return sourceLen;
+}
+
+static
+uint32_t u_toSmallKana(const UChar *source, const uint32_t sourceLen, UChar *resBuf, const uint32_t resLen, UErrorCode *status) {
+ uint32_t i = 0;
+ UChar c;
+
+ if(U_FAILURE(*status)) {
+ return 0;
+ }
+
+ if(sourceLen > resLen) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return 0;
+ }
+
+ for(i = 0; i < sourceLen; i++) {
+ c = source[i];
+ if(0x3042 < c && c < 0x30ef) { /* Kana range */
+ switch(c - 0x3000) {
+ case 0x42: case 0x44: case 0x46: case 0x48: case 0x4A: case 0x64: case 0x84: case 0x86: case 0x8F:
+ case 0xA2: case 0xA4: case 0xA6: case 0xA8: case 0xAA: case 0xC4: case 0xE4: case 0xE6: case 0xEF:
+ c--;
+ break;
+ case 0xAB:
+ c = 0x30F5;
+ break;
+ case 0xB1:
+ c = 0x30F6;
+ break;
+ }
+ }
+ resBuf[i] = c;
+ }
+ return sourceLen;
+}
+
+static
+uint8_t ucol_uprv_getCaseBits(const UCollator *UCA, const UChar *src, uint32_t len, UErrorCode *status) {
+ uint32_t i = 0;
+ UChar n[128];
+ uint32_t nLen = 0;
+ uint32_t uCount = 0, lCount = 0;
+
+ collIterate s;
+ uint32_t order = 0;
+
+ if(U_FAILURE(*status)) {
+ return UCOL_LOWER_CASE;
+ }
+
+ nLen = unorm_normalize(src, len, UNORM_NFKD, 0, n, 128, status);
+ if(U_SUCCESS(*status)) {
+ for(i = 0; i < nLen; i++) {
+ uprv_init_collIterate(UCA, &n[i], 1, &s);
+ order = ucol_getNextCE(UCA, &s, status);
+ if(isContinuation(order)) {
+ *status = U_INTERNAL_PROGRAM_ERROR;
+ return UCOL_LOWER_CASE;
+ }
+ if((order&UCOL_CASE_BIT_MASK)== UCOL_UPPER_CASE) {
+ uCount++;
+ } else {
+ if(u_islower(n[i])) {
+ lCount++;
+ } else {
+ UChar sk[1], lk[1];
+ u_toSmallKana(&n[i], 1, sk, 1, status);
+ u_toLargeKana(&n[i], 1, lk, 1, status);
+ if(sk[0] == n[i] && lk[0] != n[i]) {
+ lCount++;
+ }
+ }
+ }
+ }
+ }
+
+ if(uCount != 0 && lCount != 0) {
+ return UCOL_MIXED_CASE;
+ } else if(uCount != 0) {
+ return UCOL_UPPER_CASE;
+ } else {
+ return UCOL_LOWER_CASE;
+ }
+}
+
+
+U_CFUNC void ucol_doCE(UColTokenParser *src, uint32_t *CEparts, UColToken *tok, UErrorCode *status) {