]> git.saurik.com Git - wxWidgets.git/blob - src/common/wxchar.cpp
glibc2.1 chokes on null input to wcstombs()
[wxWidgets.git] / src / common / wxchar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wxchar.cpp
3 // Purpose: wxChar implementation
4 // Author: Ove Kåven
5 // Modified by:
6 // Created: 09/04/99
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWindows copyright
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "wxchar.h"
14 #endif
15
16 // ===========================================================================
17 // headers, declarations, constants
18 // ===========================================================================
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #define _ISOC9X_SOURCE 1 // to get vsscanf()
28 #define _BSD_SOURCE 1 // to still get strdup()
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <locale.h>
34
35 #ifndef WX_PRECOMP
36 #include "wx/defs.h"
37 #include "wx/wxchar.h"
38 #include "wx/string.h"
39 #include "wx/hash.h"
40 #endif
41
42 size_t wxMB2WC(wchar_t *buf, const char *psz, size_t n)
43 {
44 if (buf) {
45 if (!n || !*psz) {
46 if (n) *buf = _T('\0');
47 return 0;
48 }
49 return mbstowcs(buf, psz, n);
50 }
51
52 // NB: GNU libc5 wcstombs() is completely broken, don't use it (it doesn't
53 // honor the 3rd parameter, thus it will happily crash here).
54 #if wxUSE_WCSRTOMBS
55 // don't know if it's really needed (or if we can pass NULL), but better safe
56 // than quick
57 mbstate_t mbstate;
58 return mbsrtowcs((wchar_t *) NULL, &psz, 0, &mbstate);
59 #else // !GNU libc
60 return mbstowcs((wchar_t *) NULL, psz, 0);
61 #endif // GNU
62 }
63
64 size_t wxWC2MB(char *buf, const wchar_t *pwz, size_t n)
65 {
66 if (buf) {
67 if (!n || !*pwz) {
68 // glibc2.1 chokes on null input
69 if (n) *buf = '\0';
70 return 0;
71 }
72 return wcstombs(buf, pwz, n);
73 }
74
75 // NB: GNU libc5 wcstombs() is completely broken, don't use it (it doesn't
76 // honor the 3rd parameter, thus it will happily crash here).
77 #if wxUSE_WCSRTOMBS
78 // don't know if it's really needed (or if we can pass NULL), but better safe
79 // than quick
80 mbstate_t mbstate;
81 return wcsrtombs((char *) NULL, &pwz, 0, &mbstate);
82 #else // !GNU libc
83 return wcstombs((char *) NULL, pwz, 0);
84 #endif // GNU
85 }
86
87 #ifndef wxStrdup
88 wxChar * WXDLLEXPORT wxStrdup(const wxChar *psz)
89 {
90 size_t size = (wxStrlen(psz) + 1) * sizeof(wxChar);
91 wxChar *ret = (wxChar *) malloc(size);
92 memcpy(ret, psz, size);
93 return ret;
94 }
95 #endif
96
97 #ifndef wxStrtok
98 wxChar * WXDLLEXPORT wxStrtok(wxChar *psz, const wxChar *delim, wxChar **save_ptr)
99 {
100 if (!psz) psz = *save_ptr;
101 psz += wxStrspn(psz, delim);
102 if (!*psz) {
103 *save_ptr = (wxChar *)NULL;
104 return (wxChar *)NULL;
105 }
106 wxChar *ret = psz;
107 psz = wxStrpbrk(psz, delim);
108 if (!psz) *save_ptr = (wxChar*)NULL;
109 else {
110 *psz = _T('\0');
111 *save_ptr = psz + 1;
112 }
113 return ret;
114 }
115 #endif
116
117 #ifndef wxSetlocale
118 wxChar * WXDLLEXPORT wxSetlocale(int category, const wxChar *locale)
119 {
120 setlocale(category, wxConv_libc.cWX2MB(locale));
121 // FIXME
122 return (wxChar *)NULL;
123 }
124 #endif
125
126 #ifdef wxNEED_WX_STDIO_H
127 int WXDLLEXPORT wxPrintf(const wxChar *fmt, ...)
128 {
129 va_list argptr;
130 int ret;
131
132 va_start(argptr, fmt);
133 ret = wxVprintf(fmt, argptr);
134 va_end(argptr);
135 return ret;
136 }
137
138 int WXDLLEXPORT wxVprintf(const wxChar *fmt, va_list argptr)
139 {
140 wxString str;
141 str.PrintfV(fmt,argptr);
142 printf("%s", (const char*)str.mb_str());
143 return str.Len();
144 }
145
146 int WXDLLEXPORT wxFprintf(FILE *stream, const wxChar *fmt, ...)
147 {
148 va_list argptr;
149 int ret;
150
151 va_start(argptr, fmt);
152 ret = wxVfprintf(stream, fmt, argptr);
153 va_end(argptr);
154 return ret;
155 }
156
157 int WXDLLEXPORT wxVfprintf(FILE *stream, const wxChar *fmt, va_list argptr)
158 {
159 wxString str;
160 str.PrintfV(fmt,argptr);
161 fprintf(stream, "%s", (const char*)str.mb_str());
162 return str.Len();
163 }
164
165 int WXDLLEXPORT wxSprintf(wxChar *buf, const wxChar *fmt, ...)
166 {
167 va_list argptr;
168 int ret;
169
170 va_start(argptr, fmt);
171 ret = wxVsprintf(buf, fmt, argptr);
172 va_end(argptr);
173 return ret;
174 }
175
176 int WXDLLEXPORT wxVsprintf(wxChar *buf, const wxChar *fmt, va_list argptr)
177 {
178 // this might be sort of inefficient, but it doesn't matter since
179 // we'd prefer people to use wxString::Printf directly instead anyway
180 wxString str;
181 str.PrintfV(fmt,argptr);
182 wxStrcpy(buf,str.c_str());
183 return str.Len();
184 }
185
186 int WXDLLEXPORT wxSscanf(const wxChar *buf, const wxChar *fmt, ...)
187 {
188 va_list argptr;
189 int ret;
190
191 va_start(argptr, fmt);
192 ret = wxVsscanf(buf, fmt, argptr);
193 va_end(argptr);
194 return ret;
195 }
196
197 int WXDLLEXPORT wxVsscanf(const wxChar *buf, const wxChar *fmt, va_list argptr)
198 {
199 int ret;
200 // this will work only for numeric conversion! Strings will not be converted correctly
201 // hopefully this is all we'll need
202 ret = vsscanf(wxConv_libc.cWX2MB(buf), wxConv_libc.cWX2MB(fmt), argptr);
203 return ret;
204 }
205 #endif
206
207 #ifndef wxAtof
208 double WXDLLEXPORT wxAtof(const wxChar *psz)
209 {
210 return atof(wxConv_libc.cWX2MB(psz));
211 }
212 #endif
213
214 #ifdef wxNEED_WX_STDLIB_H
215 int WXDLLEXPORT wxAtoi(const wxChar *psz)
216 {
217 return atoi(wxConv_libc.cWX2MB(psz));
218 }
219
220 long WXDLLEXPORT wxAtol(const wxChar *psz)
221 {
222 return atol(wxConv_libc.cWX2MB(psz));
223 }
224
225 wxChar * WXDLLEXPORT wxGetenv(const wxChar *name)
226 {
227 static wxHashTable env;
228 // check if we already have stored the converted env var
229 wxObject *data = env.Get(name);
230 if (!data) {
231 // nope, retrieve it,
232 const char *val = getenv(wxConv_libc.cWX2MB(name));
233 if (!val) return (wxChar *)NULL;
234 // convert it,
235 data = (wxObject *)new wxString(val);
236 // and store it
237 env.Put(name, data);
238 }
239 // return converted env var
240 return (wxChar *)((wxString *)data)->c_str();
241 }
242
243 int WXDLLEXPORT wxSystem(const wxChar *psz)
244 {
245 return system(wxConv_libc.cWX2MB(psz));
246 }
247
248 #endif