105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Multibyte character data type.
205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Copyright (C) 2001, 2005-2007, 2009-2012 Free Software Foundation, Inc.
305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is free software: you can redistribute it and/or modify
505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   it under the terms of the GNU General Public License as published by
605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   the Free Software Foundation; either version 3 of the License, or
705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   (at your option) any later version.
805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is distributed in the hope that it will be useful,
1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   but WITHOUT ANY WARRANTY; without even the implied warranty of
1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   GNU General Public License for more details.
1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   You should have received a copy of the GNU General Public License
1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Written by Bruno Haible <bruno@clisp.org>.  */
1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* A multibyte character is a short subsequence of a char* string,
2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   representing a single wide character.
2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   We use multibyte characters instead of wide characters because of
2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   the following goals:
2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   1) correct multibyte handling, i.e. operate according to the LC_CTYPE
2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      locale,
2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   2) ease of maintenance, i.e. the maintainer needs not know all details
2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      of the ISO C 99 standard,
2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   3) don't fail grossly if the input is not in the encoding set by the
2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      locale, because often different encodings are in use in the same
3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      countries (ISO-8859-1/UTF-8, EUC-JP/Shift_JIS, ...),
3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   4) fast in the case of ASCII characters,
3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   5) portability, i.e. don't make unportable assumptions about wchar_t.
3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Multibyte characters are only accessed through the mb* macros.
3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_ptr (mbc)
3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang     return a pointer to the beginning of the multibyte sequence.
3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_len (mbc)
4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns the number of bytes occupied by the multibyte sequence.
4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     Always > 0.
4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_iseq (mbc, sc)
4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is the standard ASCII character sc.
4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isnul (mbc)
4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is the nul character.
4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_cmp (mbc1, mbc2)
5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns a positive, zero, or negative value depending on whether mbc1
5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     sorts after, same or before mbc2.
5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_casecmp (mbc1, mbc2)
5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns a positive, zero, or negative value depending on whether mbc1
5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang     sorts after, same or before mbc2, modulo upper/lowercase conversion.
5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_equal (mbc1, mbc2)
5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc1 and mbc2 are equal.
5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_caseequal (mbc1, mbc2)
6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc1 and mbc2 are equal modulo upper/lowercase conversion.
6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isalnum (mbc)
6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is alphanumeric.
6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isalpha (mbc)
6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is alphabetic.
6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isascii(mbc)
7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is plain ASCII.
7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isblank (mbc)
7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is a blank.
7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_iscntrl (mbc)
7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is a control character.
7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isdigit (mbc)
7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is a decimal digit.
8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isgraph (mbc)
8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is a graphic character.
8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_islower (mbc)
8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is lowercase.
8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isprint (mbc)
8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is a printable character.
8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_ispunct (mbc)
9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is a punctuation character.
9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isspace (mbc)
9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is a space character.
9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isupper (mbc)
9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is uppercase.
9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_isxdigit (mbc)
10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns true if mbc is a hexadecimal digit.
10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_width (mbc)
10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang     returns the number of columns on the output device occupied by mbc.
10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang     Always >= 0.
10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_putc (mbc, stream)
10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang     outputs mbc on stream, a byte oriented FILE stream opened for output.
10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_setascii (&mbc, sc)
11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     assigns the standard ASCII character sc to mbc.
11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   mb_copy (&destmbc, &srcmbc)
11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang     copies srcmbc to destmbc.
11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Here are the function prototypes of the macros.
11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern const char *  mb_ptr (const mbchar_t mbc);
11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern size_t        mb_len (const mbchar_t mbc);
11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_iseq (const mbchar_t mbc, char sc);
12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isnul (const mbchar_t mbc);
12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern int           mb_cmp (const mbchar_t mbc1, const mbchar_t mbc2);
12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern int           mb_casecmp (const mbchar_t mbc1, const mbchar_t mbc2);
12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_equal (const mbchar_t mbc1, const mbchar_t mbc2);
12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_caseequal (const mbchar_t mbc1, const mbchar_t mbc2);
12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isalnum (const mbchar_t mbc);
12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isalpha (const mbchar_t mbc);
12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isascii (const mbchar_t mbc);
12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isblank (const mbchar_t mbc);
12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_iscntrl (const mbchar_t mbc);
13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isdigit (const mbchar_t mbc);
13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isgraph (const mbchar_t mbc);
13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_islower (const mbchar_t mbc);
13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isprint (const mbchar_t mbc);
13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_ispunct (const mbchar_t mbc);
13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isspace (const mbchar_t mbc);
13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isupper (const mbchar_t mbc);
13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern bool          mb_isxdigit (const mbchar_t mbc);
13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern int           mb_width (const mbchar_t mbc);
13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern void          mb_putc (const mbchar_t mbc, FILE *stream);
14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern void          mb_setascii (mbchar_t *new, char sc);
14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   extern void          mb_copy (mbchar_t *new, const mbchar_t *old);
14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang */
14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef _MBCHAR_H
14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define _MBCHAR_H 1
14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdbool.h>
14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <string.h>
14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   <wchar.h>.
15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   <wchar.h>.  */
15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdio.h>
15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <time.h>
15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <wchar.h>
15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <wctype.h>
15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang_GL_INLINE_HEADER_BEGIN
16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef MBCHAR_INLINE
16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define MBCHAR_INLINE _GL_INLINE
16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define MBCHAR_BUF_SIZE 24
16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
16605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstruct mbchar
16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  const char *ptr;      /* pointer to current character */
16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t bytes;         /* number of bytes of current character, > 0 */
17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  bool wc_valid;        /* true if wc is a valid wide character */
17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  wchar_t wc;           /* if wc_valid: the current character */
17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char buf[MBCHAR_BUF_SIZE]; /* room for the bytes, used for file input only */
17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang};
17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* EOF (not a real character) is represented with bytes = 0 and
17605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   wc_valid = false.  */
17705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
17805436638acc7c010349a69c3395f1a57c642dc62Ying Wangtypedef struct mbchar mbchar_t;
17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Access the current character.  */
18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_ptr(mbc) ((mbc).ptr)
18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_len(mbc) ((mbc).bytes)
18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Comparison of characters.  */
18505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_iseq(mbc, sc) ((mbc).wc_valid && (mbc).wc == (sc))
18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isnul(mbc) ((mbc).wc_valid && (mbc).wc == 0)
18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_cmp(mbc1, mbc2) \
18805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((mbc1).wc_valid                                                      \
18905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   ? ((mbc2).wc_valid                                                   \
19005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      ? (int) (mbc1).wc - (int) (mbc2).wc                               \
19105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      : -1)                                                             \
19205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   : ((mbc2).wc_valid                                                   \
19305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      ? 1                                                               \
19405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      : (mbc1).bytes == (mbc2).bytes                                    \
19505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes)                 \
19605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        : (mbc1).bytes < (mbc2).bytes                                   \
19705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \
19805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1)))
19905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_casecmp(mbc1, mbc2) \
20005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((mbc1).wc_valid                                                      \
20105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   ? ((mbc2).wc_valid                                                   \
20205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      ? (int) towlower ((mbc1).wc) - (int) towlower ((mbc2).wc)         \
20305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      : -1)                                                             \
20405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   : ((mbc2).wc_valid                                                   \
20505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      ? 1                                                               \
20605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      : (mbc1).bytes == (mbc2).bytes                                    \
20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes)                 \
20805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        : (mbc1).bytes < (mbc2).bytes                                   \
20905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \
21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1)))
21105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_equal(mbc1, mbc2) \
21205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((mbc1).wc_valid && (mbc2).wc_valid                                   \
21305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   ? (mbc1).wc == (mbc2).wc                                             \
21405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   : (mbc1).bytes == (mbc2).bytes                                       \
21505436638acc7c010349a69c3395f1a57c642dc62Ying Wang     && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0)
21605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_caseequal(mbc1, mbc2) \
21705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((mbc1).wc_valid && (mbc2).wc_valid                                   \
21805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   ? towlower ((mbc1).wc) == towlower ((mbc2).wc)                       \
21905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   : (mbc1).bytes == (mbc2).bytes                                       \
22005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0)
22105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
22205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* <ctype.h>, <wctype.h> classification.  */
22305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isascii(mbc) \
22405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((mbc).wc_valid && (mbc).wc >= 0 && (mbc).wc <= 127)
22505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isalnum(mbc) ((mbc).wc_valid && iswalnum ((mbc).wc))
22605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isalpha(mbc) ((mbc).wc_valid && iswalpha ((mbc).wc))
22705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isblank(mbc) ((mbc).wc_valid && iswblank ((mbc).wc))
22805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_iscntrl(mbc) ((mbc).wc_valid && iswcntrl ((mbc).wc))
22905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isdigit(mbc) ((mbc).wc_valid && iswdigit ((mbc).wc))
23005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isgraph(mbc) ((mbc).wc_valid && iswgraph ((mbc).wc))
23105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_islower(mbc) ((mbc).wc_valid && iswlower ((mbc).wc))
23205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isprint(mbc) ((mbc).wc_valid && iswprint ((mbc).wc))
23305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_ispunct(mbc) ((mbc).wc_valid && iswpunct ((mbc).wc))
23405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isspace(mbc) ((mbc).wc_valid && iswspace ((mbc).wc))
23505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isupper(mbc) ((mbc).wc_valid && iswupper ((mbc).wc))
23605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_isxdigit(mbc) ((mbc).wc_valid && iswxdigit ((mbc).wc))
23705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
23805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Extra <wchar.h> function.  */
23905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
24005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Unprintable characters appear as a small box of width 1.  */
24105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define MB_UNPRINTABLE_WIDTH 1
24205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
24305436638acc7c010349a69c3395f1a57c642dc62Ying WangMBCHAR_INLINE int
24405436638acc7c010349a69c3395f1a57c642dc62Ying Wangmb_width_aux (wint_t wc)
24505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
24605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int w = wcwidth (wc);
24705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* For unprintable characters, arbitrarily return 0 for control characters
24805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     and MB_UNPRINTABLE_WIDTH otherwise.  */
24905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return (w >= 0 ? w : iswcntrl (wc) ? 0 : MB_UNPRINTABLE_WIDTH);
25005436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
25105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
25205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_width(mbc) \
25305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((mbc).wc_valid ? mb_width_aux ((mbc).wc) : MB_UNPRINTABLE_WIDTH)
25405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
25505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Output.  */
25605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_putc(mbc, stream)  fwrite ((mbc).ptr, 1, (mbc).bytes, (stream))
25705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
25805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Assignment.  */
25905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define mb_setascii(mbc, sc) \
26005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((mbc)->ptr = (mbc)->buf, (mbc)->bytes = 1, (mbc)->wc_valid = 1, \
26105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   (mbc)->wc = (mbc)->buf[0] = (sc))
26205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
26305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Copying a character.  */
26405436638acc7c010349a69c3395f1a57c642dc62Ying WangMBCHAR_INLINE void
26505436638acc7c010349a69c3395f1a57c642dc62Ying Wangmb_copy (mbchar_t *new_mbc, const mbchar_t *old_mbc)
26605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
26705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (old_mbc->ptr == &old_mbc->buf[0])
26805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
26905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      memcpy (&new_mbc->buf[0], &old_mbc->buf[0], old_mbc->bytes);
27005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      new_mbc->ptr = &new_mbc->buf[0];
27105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
27205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
27305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    new_mbc->ptr = old_mbc->ptr;
27405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  new_mbc->bytes = old_mbc->bytes;
27505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if ((new_mbc->wc_valid = old_mbc->wc_valid))
27605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    new_mbc->wc = old_mbc->wc;
27705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
27805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
27905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
28005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* is_basic(c) tests whether the single-byte character c is in the
28105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   ISO C "basic character set".
28205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This is a convenience function, and is in this file only to share code
28305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   between mbiter_multi.h and mbfile_multi.h.  */
28405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
28505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
28605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
28705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
28805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
28905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
29005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
29105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
29205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
29305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
29405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
29505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
29605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
29705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
29805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
29905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
30005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
30105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
30205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
30305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
30405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
30505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
30605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
30705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* The character set is ISO-646, not EBCDIC. */
30805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define IS_BASIC_ASCII 1
30905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
31005436638acc7c010349a69c3395f1a57c642dc62Ying Wangextern const unsigned int is_basic_table[];
31105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
31205436638acc7c010349a69c3395f1a57c642dc62Ying WangMBCHAR_INLINE bool
31305436638acc7c010349a69c3395f1a57c642dc62Ying Wangis_basic (char c)
31405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
31505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return (is_basic_table [(unsigned char) c >> 5] >> ((unsigned char) c & 31))
31605436638acc7c010349a69c3395f1a57c642dc62Ying Wang         & 1;
31705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
31805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
31905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
32005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
32105436638acc7c010349a69c3395f1a57c642dc62Ying WangMBCHAR_INLINE bool
32205436638acc7c010349a69c3395f1a57c642dc62Ying Wangis_basic (char c)
32305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
32405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  switch (c)
32505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
32605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case '\t': case '\v': case '\f':
32705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case ' ': case '!': case '"': case '#': case '%':
32805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case '&': case '\'': case '(': case ')': case '*':
32905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case '+': case ',': case '-': case '.': case '/':
33005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case '0': case '1': case '2': case '3': case '4':
33105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case '5': case '6': case '7': case '8': case '9':
33205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case ':': case ';': case '<': case '=': case '>':
33305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case '?':
33405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'A': case 'B': case 'C': case 'D': case 'E':
33505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'F': case 'G': case 'H': case 'I': case 'J':
33605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'K': case 'L': case 'M': case 'N': case 'O':
33705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'P': case 'Q': case 'R': case 'S': case 'T':
33805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'U': case 'V': case 'W': case 'X': case 'Y':
33905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'Z':
34005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case '[': case '\\': case ']': case '^': case '_':
34105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'a': case 'b': case 'c': case 'd': case 'e':
34205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'f': case 'g': case 'h': case 'i': case 'j':
34305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'k': case 'l': case 'm': case 'n': case 'o':
34405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'p': case 'q': case 'r': case 's': case 't':
34505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'u': case 'v': case 'w': case 'x': case 'y':
34605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'z': case '{': case '|': case '}': case '~':
34705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      return 1;
34805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    default:
34905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      return 0;
35005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
35105436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
35205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
35305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
35405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
35505436638acc7c010349a69c3395f1a57c642dc62Ying Wang_GL_INLINE_HEADER_END
35605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
35705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif /* _MBCHAR_H */
358