]> git.saurik.com Git - wxWidgets.git/blame - docs/doxygen/overviews/unicode.h
add very simple (but already exposing many problems) wxIPC benchmark
[wxWidgets.git] / docs / doxygen / overviews / unicode.h
CommitLineData
15b6757b 1/////////////////////////////////////////////////////////////////////////////
2cd3cc94 2// Name: unicode.h
15b6757b
FM
3// Purpose: topic overview
4// Author: wxWidgets team
5// RCS-ID: $Id$
6// Licence: wxWindows license
7/////////////////////////////////////////////////////////////////////////////
8
880efa2a 9/**
36c9828f 10
2cd3cc94
BP
11@page overview_unicode Unicode Support in wxWidgets
12
cc506697
VZ
13This section describes how does wxWidgets support Unicode and how can it affect
14your programs.
36c9828f 15
cc506697
VZ
16Notice that Unicode support has changed radically in wxWidgets 3.0 and a lot of
17existing material pertaining to the previous versions of the library is not
18correct any more. Please see @ref overview_changes_unicode for the details of
19these changes.
20
21You can skip the first two sections if you're already familiar with Unicode and
22wish to jump directly in the details of its support in the library:
2cd3cc94 23@li @ref overview_unicode_what
cc506697 24@li @ref overview_unicode_encodings
2cd3cc94 25@li @ref overview_unicode_supportin
cc506697 26@li @ref overview_unicode_pitfalls
2cd3cc94
BP
27@li @ref overview_unicode_supportout
28@li @ref overview_unicode_settings
36c9828f 29
2cd3cc94 30<hr>
36c9828f
FM
31
32
2cd3cc94
BP
33@section overview_unicode_what What is Unicode?
34
cc506697
VZ
35Unicode is a standard for character encoding which addresses the shortcomings
36of the previous, 8 bit standards, by using at least 16 (and possibly 32) bits
37for encoding each character. This allows to have at least 65536 characters
38(in what is called the BMP, or basic multilingual plane) and possible 2^32 of
39them instead of the usual 256 and is sufficient to encode all of the world
40languages at once. More details about Unicode may be found at
41http://www.unicode.org/.
42
43From a practical point of view, using Unicode is almost a requirement when
44writing applications for international audience. Moreover, any application
45reading files which it didn't produce or receiving data from the network from
46other services should be ready to deal with Unicode.
47
48
49@section overview_unicode_encodings Unicode Representations
50
51Unicode provides a unique code to identify every character, however in practice
52these codes are not always used directly but encoded using one of the standard
53UTF or Unicode Transformation Formats which are algorithms mapping the Unicode
54codes to byte code sequences. The simplest of them is UTF-32 which simply maps
55the Unicode code to a 4 byte sequence representing this 32 bit number (although
56this is still not completely trivial as the mapping is different for little and
57big-endian architectures). UTF-32 is commonly used under Unix systems for
58internal representation of Unicode strings. Another very widespread standard is
59UTF-16 which is used by Microsoft Windows: it encodes the first (approximately)
6064 thousands of Unicode characters using only 2 bytes and uses a pair of 16-bit
61codes to encode the characters beyond this. Finally, the most widespread
62encoding used for the external Unicode storage (e.g. files and network
63protocols) is UTF-8 which is byte-oriented and so avoids the endianness
64ambiguities of UTF-16 and UTF-32. However UTF-8 uses a variable number of bytes
65for representing Unicode characters which makes it less efficient than UTF-32
66for internal representation.
67
68From the C/C++ programmer perspective the situation is further complicated by
69the fact that the standard type @c wchar_t which is used to represent the
70Unicode ("wide") strings in C/C++ doesn't have the same size on all platforms.
71It is 4 bytes under Unix systems, corresponding to the tradition of using
72UTF-32, but only 2 bytes under Windows which is required by compatibility with
73the OS which uses UTF-16.
2cd3cc94 74
2cd3cc94 75
cc506697 76@section overview_unicode_supportin Unicode Support in wxWidgets
2cd3cc94 77
cc506697
VZ
78Since wxWidgets 3.0 Unicode support is always enabled and building the library
79without it is not recommended any longer and will cease to be supported in the
80near future. This means that internally only Unicode strings are used and that,
81under Microsoft Windows, Unicode system API is used which means that wxWidgets
82programs require the Microsoft Layer for Unicode to run on Windows 95/98/ME.
83
84However, unlike Unicode build mode in the previous versions of wxWidgets, this
85support is mostly transparent: you can still continue to work with the narrow
86(i.e. @c char*) strings even if wide (i.e. @c wchar_t*) strings are also
87supported. Any wxWidgets function accepts arguments of either type as both
88kinds of strings are implicitly converted to wxString, so both
89@code
90wxMessageBox("Hello, world!");
91@endcode
92and somewhat less usual
93@code
94wxMessageBox(L"Salut \u00e0 toi!"); // 00E0 is "Latin Small Letter a with Grave"
95@endcode
96work as expected.
2cd3cc94 97
cc506697
VZ
98Notice that the narrow strings used with wxWidgets are @e always assumed to be
99in the current locale encoding, so writing
100@code
101wxMessageBox("Salut à toi!");
102@endcode
103wouldn't work if the encoding used on the user system is incompatible with
f99af6c0
VS
104ISO-8859-1 (or even if the sources were compiled under different locale
105in the case of gcc). In particular, the most common encoding used under
106modern Unix systems is UTF-8 and as the string above is not a valid UTF-8 byte
107sequence, nothing would be displayed at all in this case. Thus it is important
108to never use 8 bit characters directly in the program source but use wide
109strings or, alternatively, write
cc506697
VZ
110@code
111wxMessageBox(wxString::FromUTF8("Salut \xc3\xa0 toi!"));
112@endcode
2cd3cc94 113
cc506697
VZ
114In a similar way, wxString provides access to its contents as either wchar_t or
115char character buffer. Of course, the latter only works if the string contains
116data representable in the current locale encoding. This will always be the case
117if the string had been initially constructed from a narrow string or if it
118contains only 7-bit ASCII data but otherwise this conversion is not guaranteed
119to succeed. And as with @c FromUTF8() example above, you can always use @c
120ToUTF8() to retrieve the string contents in UTF-8 encoding -- this, unlike
121converting to @c char* using the current locale, never fails
122
123To summarize, Unicode support in wxWidgets is mostly transparent for the
124application and if you use wxString objects for storing all the character data
125in your program there is really nothing special to do. However you should be
126aware of the potential problems covered by the following section.
127
128
129@section overview_unicode_pitfalls Potential Unicode Pitfalls
130
131The problems can be separated into three broad classes:
132
133@subsection overview_unicode_compilation_errors Unicode-Related Compilation Errors
134
135Because of the need to support implicit conversions to both @c char and @c
136wchar_t, wxString implementation is rather involved and many of its operators
137don't return the types which they could be naively expected to return. For
138example, the @c operator[] doesn't return neither a @c char nor a @c wchar_t
139but an object of a helper class wxUniChar or wxUniCharRef which is implicitly
140convertible to either. Usually you don't need to worry about this as the
141conversions do their work behind the scenes however in some cases it doesn't
142work. Here are some examples, using a wxString object @c s and some integer @c
143n:
144
145 - Writing @code switch ( s[n] ) @endcode doesn't work because the argument of
146 the switch statement must an integer expression so you need to replace
147 @c s[n] with @code s[n].GetValue() @endcode. You may also force the
148 conversion to char or wchar_t by using an explicit cast but beware that
149 converting the value to char uses the conversion to current locale and may
150 return 0 if it fails. Finally notice that writing @code (wxChar)s[n] @endcode
151 works both with wxWidgets 3.0 and previous library versions and so should be
152 used for writing code which should be compatible with both 2.8 and 3.0.
153
154 - Similarly, @code &s[n] @endcode doesn't yield a pointer to char so you may
155 not pass it to functions expecting @c char* or @c wchar_t*. Consider using
156 string iterators instead if possible or replace this expression with
157 @code s.c_str() + n @endcode otherwise.
158
159Another class of problems is related to the fact that the value returned by @c
160c_str() itself is also not just a pointer to a buffer but a value of helper
161class wxCStrData which is implicitly convertible to both narrow and wide
162strings. Again, this mostly will be unnoticeable but can result in some
163problems:
164
165 - You shouldn't pass @c c_str() result to vararg functions such as standard
166 @c printf(). Some compilers (notably g++) warn about this but even if they
167 don't, this @code printf("Hello, %s", s.c_str()) @endcode is not going to
168 work. It can be corrected in one of the following ways:
169
170 - Preferred: @code wxPrintf("Hello, %s", s) @endcode (notice the absence
171 of @c c_str(), it is not needed at all with wxWidgets functions)
172 - Compatible with wxWidgets 2.8: @code wxPrintf("Hello, %s", s.c_str()) @endcode
173 - Using an explicit conversion to narrow, multibyte, string:
f99af6c0 174 @code printf("Hello, %s", (const char *)s.mb_str()) @endcode
cc506697
VZ
175 - Using a cast to force the issue (listed only for completeness):
176 @code printf("Hello, %s", (const char *)s.c_str()) @endcode
177
178 - The result of @c c_str() can not be cast to @c char* but only to @c const @c
179 @c char*. Of course, modifying the string via the pointer returned by this
180 method has never been possible but unfortunately it was occasionally useful
181 to use a @c const_cast here to pass the value to const-incorrect functions.
182 This can be done either using new wxString::char_str() (and matching
183 wchar_str()) method or by writing a double cast:
184 @code (char *)(const char *)s.c_str() @endcode
185
186 - One of the unfortunate consequences of the possibility to pass wxString to
187 @c wxPrintf() without using @c c_str() is that it is now impossible to pass
188 the elements of unnamed enumerations to @c wxPrintf() and other similar
189 vararg functions, i.e.
190 @code
191 enum { Red, Green, Blue };
192 wxPrintf("Red is %d", Red);
193 @endcode
194 doesn't compile. The easiest workaround is to give a name to the enum.
195
196Other unexpected compilation errors may arise but they should happen even more
197rarely than the above-mentioned ones and the solution should usually be quite
198simple: just use the explicit methods of wxUniChar and wxCStrData classes
199instead of relying on their implicit conversions if the compiler can't choose
200among them.
201
202
203@subsection overview_unicode_data_loss Data Loss due To Unicode Conversion Errors
204
205wxString API provides implicit conversion of the internal Unicode string
206contents to narrow, char strings. This can be very convenient and is absolutely
207necessary for backwards compatibility with the existing code using wxWidgets
208however it is a rather dangerous operation as it can easily give unexpected
209results if the string contents isn't convertible to the current locale.
210
211To be precise, the conversion will always succeed if the string was created
212from a narrow string initially. It will also succeed if the current encoding is
213UTF-8 as all Unicode strings are representable in this encoding. However
214initializing the string using FromUTF8() method and then accessing it as a char
215string via its c_str() method is a recipe for disaster as the program may work
216perfectly well during testing on Unix systems using UTF-8 locale but completely
217fail under Windows where UTF-8 locales are never used because c_str() would
218return an empty string.
219
220The simplest way to ensure that this doesn't happen is to avoid conversions to
221@c char* completely by using wxString throughout your program. However if the
222program never manipulates 8 bit strings internally, using @c char* pointers is
223safe as well. So the existing code needs to be reviewed when upgrading to
224wxWidgets 3.0 and the new code should be used with this in mind and ideally
225avoiding implicit conversions to @c char*.
226
227
228@subsection overview_unicode_performance Unicode Performance Implications
229
230Under Unix systems wxString class uses variable-width UTF-8 encoding for
231internal representation and this implies that it can't guarantee constant-time
232access to N-th element of the string any longer as to find the position of this
233character in the string we have to examine all the preceding ones. Usually this
234doesn't matter much because most algorithms used on the strings examine them
a6919a6a
RR
235sequentially anyhow and because wxString implements a cache for iterating over
236the string by index but it can have serious consequences for algorithms
237using random access to string elements as they typically acquire O(N^2) time
cc506697
VZ
238complexity instead of O(N) where N is the length of the string.
239
a6919a6a 240Even despite caching the index, indexed access should be replaced with
cc506697 241sequential access using string iterators. For example a typical loop:
7b74e828 242@code
cc506697
VZ
243wxString s("hello");
244for ( size_t i = 0; i < s.length(); i++ )
7b74e828 245{
cc506697 246 wchar_t ch = s[i];
7b74e828
RR
247
248 // do something with it
249}
250@endcode
cc506697 251should be rewritten as
2cd3cc94 252@code
cc506697
VZ
253wxString s("hello");
254for ( wxString::const_iterator i = s.begin(); i != s.end(); ++i )
7b74e828 255{
cc506697 256 wchar_t ch = *i
7b74e828
RR
257
258 // do something with it
259}
2cd3cc94
BP
260@endcode
261
cc506697 262Another, similar, alternative is to use pointer arithmetic:
7b74e828 263@code
cc506697
VZ
264wxString s("hello");
265for ( const wchar_t *p = s.wc_str(); *p; p++ )
7b74e828 266{
cc506697
VZ
267 wchar_t ch = *i
268
269 // do something with it
7b74e828
RR
270}
271@endcode
cc506697
VZ
272however this doesn't work correctly for strings with embedded @c NUL characters
273and the use of iterators is generally preferred as they provide some run-time
274checks (at least in debug build) unlike the raw pointers. But if you do use
275them, it is better to use wchar_t pointers rather than char ones to avoid the
276data loss problems due to conversion as discussed in the previous section.
2cd3cc94 277
2cd3cc94 278
cc506697 279@section overview_unicode_supportout Unicode and the Outside World
2cd3cc94 280
cc506697
VZ
281Even though wxWidgets always uses Unicode internally, not all the other
282libraries and programs do and even those that do use Unicode may use a
283different encoding of it. So you need to be able to convert the data to various
284representations and the wxString methods ToAscii(), ToUTF8() (or its synonym
285utf8_str()), mb_str(), c_str() and wc_str() can be used for this. The first of
286them should be only used for the string containing 7-bit ASCII characters only,
287anything else will be replaced by some substitution character. mb_str()
288converts the string to the encoding used by the current locale and so can
289return an empty string if the string contains characters not representable in
290it as explained in @ref overview_unicode_data_loss. The same applies to c_str()
291if its result is used as a narrow string. Finally, ToUTF8() and wc_str()
292functions never fail and always return a pointer to char string containing the
293UTF-8 representation of the string or wchar_t string.
294
295wxString also provides two convenience functions: From8BitData() and
296To8BitData(). They can be used to create wxString from arbitrary binary data
297without supposing that it is in current locale encoding, and then get it back,
298again, without any conversion or, rather, undoing the conversion used by
299From8BitData(). Because of this you should only use From8BitData() for the
300strings created using To8BitData(). Also notice that in spite of the
301availability of these functions, wxString is not the ideal class for storing
302arbitrary binary data as they can take up to 4 times more space than needed
303(when using @c wchar_t internal representation on the systems where size of
304wide characters is 4 bytes) and you should consider using wxMemoryBuffer
305instead.
306
307Final word of caution: most of these functions may return either directly the
308pointer to internal string buffer or a temporary wxCharBuffer or wxWCharBuffer
309object. Such objects are implicitly convertible to char and wchar_t pointers,
310respectively, and so the result of, for example, ToUTF8() can always be passed
311directly to a function taking @c const @c char*. However code such as
7b74e828 312@code
cc506697
VZ
313const char *p = s.ToUTF8();
314...
315puts(p); // or call any other function taking const char *
7b74e828 316@endcode
cc506697
VZ
317does @b not work because the temporary buffer returned by ToUTF8() is destroyed
318and @c p is left pointing nowhere. To correct this you may use
7b74e828 319@code
cc506697
VZ
320wxCharBuffer p(s.ToUTF8());
321puts(p);
7b74e828 322@endcode
cc506697
VZ
323which does work but results in an unnecessary copy of string data in the build
324configurations when ToUTF8() returns the pointer to internal string buffer. If
325this inefficiency is important you may write
2cd3cc94 326@code
cc506697
VZ
327const wxUTF8Buf p(s.ToUTF8());
328puts(p);
2cd3cc94 329@endcode
cc506697
VZ
330where @c wxUTF8Buf is the type corresponding to the real return type of
331ToUTF8(). Similarly, wxWX2WCbuf can be used for the return type of wc_str().
332But, once again, none of these cryptic types is really needed if you just pass
333the return value of any of the functions mentioned in this section to another
334function directly.
2cd3cc94
BP
335
336@section overview_unicode_settings Unicode Related Compilation Settings
337
cc506697
VZ
338@c wxUSE_UNICODE is now defined as 1 by default to indicate Unicode support.
339If UTF-8 is used for the internal storage in wxString, @c wxUSE_UNICODE_UTF8 is
340also defined, otherwise @c wxUSE_UNICODE_WCHAR is.
2cd3cc94
BP
341
342*/
343