Line data Source code
1 : /*
2 : Copyright (c) 2007, Adobe Systems, Incorporated
3 : All rights reserved.
4 :
5 : Redistribution and use in source and binary forms, with or without
6 : modification, are permitted provided that the following conditions are
7 : met:
8 :
9 : * Redistributions of source code must retain the above copyright
10 : notice, this list of conditions and the following disclaimer.
11 :
12 : * Redistributions in binary form must reproduce the above copyright
13 : notice, this list of conditions and the following disclaimer in the
14 : documentation and/or other materials provided with the distribution.
15 :
16 : * Neither the name of Adobe Systems, Network Resonance nor the names of its
17 : contributors may be used to endorse or promote products derived from
18 : this software without specific prior written permission.
19 :
20 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : */
32 :
33 :
34 : #ifdef LINUX
35 : #define _GNU_SOURCE 1
36 : #endif
37 : #include <string.h>
38 :
39 : #include <errno.h>
40 : #include <csi_platform.h>
41 :
42 : #include <assert.h>
43 : #include <locale.h>
44 : #include <stdlib.h>
45 : #include <wchar.h>
46 : #if defined(DARWIN) || defined(__DragonFly__) || defined(__FreeBSD__)
47 : #define HAVE_XLOCALE
48 : #endif
49 :
50 : #ifdef HAVE_XLOCALE
51 : #include <xlocale.h>
52 : #endif /* HAVE_XLOCALE */
53 :
54 : #include "nr_api.h"
55 : #include "mbslen.h"
56 :
57 : /* get number of characters in a mult-byte character string */
58 : int
59 0 : mbslen(const char *s, size_t *ncharsp)
60 : {
61 : #ifdef HAVE_XLOCALE
62 : static locale_t loc = 0;
63 : static int initialized = 0;
64 : #endif /* HAVE_XLOCALE */
65 : #ifdef WIN32
66 : char *my_locale=0;
67 : unsigned int i;
68 : #endif /* WIN32 */
69 : int _status;
70 : size_t nbytes;
71 : int nchars;
72 : mbstate_t mbs;
73 :
74 : #ifdef HAVE_XLOCALE
75 : if (! initialized) {
76 : initialized = 1;
77 : loc = newlocale(LC_CTYPE_MASK, "UTF-8", LC_GLOBAL_LOCALE);
78 : }
79 :
80 : if (loc == 0) {
81 : /* unable to create the UTF-8 locale */
82 : assert(loc != 0); /* should never happen */
83 : #endif /* HAVE_XLOCALE */
84 :
85 : #ifdef WIN32
86 : if (!setlocale(LC_CTYPE, 0))
87 : ABORT(R_INTERNAL);
88 :
89 : if (!(my_locale = r_strdup(setlocale(LC_CTYPE, 0))))
90 : ABORT(R_NO_MEMORY);
91 :
92 : for (i=0; i<strlen(my_locale); i++)
93 : my_locale[i] = toupper(my_locale[i]);
94 :
95 : if (!strstr(my_locale, "UTF-8") && !strstr(my_locale, "UTF8"))
96 : ABORT(R_NOT_FOUND);
97 : #else
98 : /* can't count UTF-8 characters with mbrlen if the locale isn't UTF-8 */
99 : /* null-checking setlocale is required because Android */
100 0 : char *locale = setlocale(LC_CTYPE, 0);
101 : /* some systems use "utf8" instead of "UTF-8" like Fedora 17 */
102 0 : if (!locale || (!strcasestr(locale, "UTF-8") && !strcasestr(locale, "UTF8")))
103 0 : ABORT(R_NOT_FOUND);
104 : #endif
105 :
106 : #ifdef HAVE_XLOCALE
107 : }
108 : #endif /* HAVE_XLOCALE */
109 :
110 0 : memset(&mbs, 0, sizeof(mbs));
111 0 : nchars = 0;
112 :
113 : #ifdef HAVE_XLOCALE
114 : while (*s != '\0' && (nbytes = mbrlen_l(s, strlen(s), &mbs, loc)) != 0)
115 : #else
116 0 : while (*s != '\0' && (nbytes = mbrlen(s, strlen(s), &mbs)) != 0)
117 : #endif /* HAVE_XLOCALE */
118 : {
119 0 : if (nbytes == (size_t)-1) /* should never happen */ {
120 0 : ABORT(R_INTERNAL);
121 : }
122 0 : if (nbytes == (size_t)-2) /* encoding error */ {
123 0 : ABORT(R_BAD_DATA);
124 : }
125 :
126 0 : s += nbytes;
127 0 : ++nchars;
128 : }
129 :
130 0 : *ncharsp = nchars;
131 :
132 0 : _status = 0;
133 : abort:
134 : #ifdef WIN32
135 : RFREE(my_locale);
136 : #endif
137 0 : return _status;
138 : }
139 :
|