1/* Test whether case matters for a Unicode string. 2 Copyright (C) 2009-2010 Free Software Foundation, Inc. 3 Written by Bruno Haible <bruno@clisp.org>, 2009. 4 5 This program is free software: you can redistribute it and/or modify it 6 under the terms of the GNU Lesser General Public License as published 7 by the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18int 19FUNC (const UNIT *s, size_t n, const char *iso639_language, 20 bool *resultp) 21{ 22 UNIT normsbuf[2048 / sizeof (UNIT)]; 23 UNIT *norms; 24 size_t norms_length; 25 UNIT mappedbuf[2048 / sizeof (UNIT)]; 26 UNIT *mapped_toupper; 27 UNIT *mapped_tolower; 28 UNIT *mapped_totitle; 29 size_t mapped_length; 30 31 /* Apply canonical decomposition to S. */ 32 norms_length = sizeof (normsbuf) / sizeof (UNIT); 33 norms = U_NORMALIZE (UNINORM_NFD, s, n, normsbuf, &norms_length); 34 if (norms == NULL) 35 /* errno is set here. */ 36 return -1; 37 38 mapped_length = sizeof (mappedbuf) / sizeof (UNIT); 39 40 /* Apply toupper mapping. */ 41 mapped_toupper = U_TOUPPER (norms, norms_length, iso639_language, NULL, 42 mappedbuf, &mapped_length); 43 if (mapped_toupper == NULL) 44 goto fail; 45 46 /* Compare. */ 47 if (!(mapped_length == norms_length 48 && U_CMP (mapped_toupper, norms, norms_length) == 0)) 49 { 50 if (mapped_toupper != mappedbuf) 51 free (mapped_toupper); 52 goto yes; 53 } 54 55 /* Apply tolower mapping. */ 56 mapped_tolower = U_TOLOWER (norms, norms_length, iso639_language, NULL, 57 mapped_toupper, &mapped_length); 58 if (mapped_tolower == NULL) 59 { 60 if (mapped_toupper != mappedbuf) 61 { 62 int saved_errno = errno; 63 free (mapped_toupper); 64 errno = saved_errno; 65 } 66 goto fail; 67 } 68 69 if (mapped_toupper != mapped_tolower && mapped_toupper != mappedbuf) 70 free (mapped_toupper); 71 72 /* Compare. */ 73 if (!(mapped_length == norms_length 74 && U_CMP (mapped_tolower, norms, norms_length) == 0)) 75 { 76 if (mapped_tolower != mappedbuf) 77 free (mapped_tolower); 78 goto yes; 79 } 80 81 /* Apply totitle mapping. */ 82 mapped_totitle = U_TOTITLE (norms, norms_length, iso639_language, NULL, 83 mapped_tolower, &mapped_length); 84 if (mapped_totitle == NULL) 85 { 86 if (mapped_tolower != mappedbuf) 87 { 88 int saved_errno = errno; 89 free (mapped_tolower); 90 errno = saved_errno; 91 } 92 goto fail; 93 } 94 95 if (mapped_tolower != mapped_totitle && mapped_tolower != mappedbuf) 96 free (mapped_tolower); 97 98 /* Compare. */ 99 if (!(mapped_length == norms_length 100 && U_CMP (mapped_totitle, norms, norms_length) == 0)) 101 { 102 if (mapped_totitle != mappedbuf) 103 free (mapped_totitle); 104 goto yes; 105 } 106 107 if (mapped_totitle != mappedbuf) 108 free (mapped_totitle); 109 if (norms != normsbuf) 110 free (norms); 111 *resultp = false; 112 return 0; 113 114 yes: 115 if (norms != normsbuf) 116 free (norms); 117 *resultp = true; 118 return 0; 119 120 fail: 121 if (norms != normsbuf) 122 { 123 int saved_errno = errno; 124 free (norms); 125 errno = saved_errno; 126 } 127 return -1; 128} 129