Mercurial > hg > octave-lojdl > gnulib-hg
diff lib/wcsxfrm-impl.h @ 14294:b19db9397852
New module 'wcsxfrm'.
* modules/wcsxfrm: New file.
* lib/wchar.in.h (wcsxfrm): New declaration.
* lib/wcsxfrm.c: New file.
* lib/wcsxfrm-impl.h: New file.
* m4/wcsxfrm.m4: New file.
* m4/wchar_h.m4 (gl_WCHAR_H): Test whether wcsxfrm is declared.
(gl_WCHAR_H_DEFAULTS): Initialize GNULIB_WCSXFRM, HAVE_WCSXFRM.
* modules/wchar (Makefile.am): Substitute GNULIB_WCSXFRM, HAVE_WCSXFRM.
* tests/test-wchar-c++.cc: Test the declaration of wcsxfrm.
* doc/posix-functions/wcsxfrm.texi: Mention the new module.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sun, 06 Feb 2011 13:30:53 +0100 (2011-02-06) |
parents | |
children | 8250f2777afc |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/lib/wcsxfrm-impl.h @@ -0,0 +1,96 @@ +/* Transform wide string for comparison using the current locale. + Copyright (C) 2011 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +size_t +wcsxfrm (wchar_t *s1, const wchar_t *s2, size_t n) +{ + char mbbuf2[1024]; + char *mbs2; + + { + int saved_errno = errno; + size_t result; + + /* Convert s2 to a multibyte string, trying to avoid malloc(). */ + { + size_t ret; + + ret = wcstombs (mbbuf2, s2, sizeof (mbbuf2)); + if (ret == (size_t)-1) + goto failed; + if (ret < sizeof (mbbuf2)) + mbs2 = mbbuf2; + else + { + size_t need = wcstombs (NULL, s2, 0); + if (need == (size_t)-1) + goto failed; + mbs2 = (char *) malloc (need + 1); + if (mbs2 == NULL) + goto out_of_memory; + ret = wcstombs (mbs2, s2, need + 1); + if (ret != need) + abort (); + } + } + + /* Transform the multibyte string. */ + errno = 0; + result = strxfrm ((char *)s1, mbs2, n); + if (errno != 0) + { + /* An error occurred. */ + if (mbs2 != mbbuf2) + { + saved_errno = errno; + free (mbs2); + errno = saved_errno; + } + return 0; + } + + if (result < n) + { + /* Convert the result by mapping char[] -> wchar_t[]. + Since strcmp() compares the elements as 'unsigned char' values, + whereas wcscmp() compares the elements as 'wchar_t' values, we need + to map 1 'unsigned char' to 1 'wchar_t'. (We could also map 2 + consecutive 'unsigned char' values to 1 'wchar_t' value, but this is + not needed. */ + wchar_t *wcp = s1 + n; + char *cp = (char *)s1 + n; + + while (wcp > s1) + *--wcp = (wchar_t) (unsigned char) *--cp; + } + + if (mbs2 != mbbuf2) + free (mbs2); + + /* No error. */ + errno = saved_errno; + return result; + } + + out_of_memory: + errno = ENOMEM; + return 0; + + failed: + errno = EILSEQ; + return 0; +}