OSDN Git Service

2002-08-19 Jonathan Wakely <jw@kayari.org>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / docs / html / 22_locale / codecvt.html
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2 <html>
3 <head>
4   <title>
5   Notes on the codecvt implementation.
6   </title>
7 </head>
8 <body>
9   <h1>
10   Notes on the codecvt implementation.
11   </h1>
12 <p>
13 <I>
14 prepared by Benjamin Kosnik (bkoz@redhat.com) on August 28, 2000
15 </I>
16
17 <h2>
18 1. Abstract
19 </h2>
20 <p>
21 The standard class codecvt attempts to address conversions between
22 different character encoding schemes. In particular, the standard
23 attempts to detail conversions between the implementation-defined wide
24 characters (hereafter referred to as wchar_t) and the standard type
25 char that is so beloved in classic &quot;C&quot; (which can now be referred to
26 as narrow characters.)  This document attempts to describe how the GNU
27 libstdc++-v3 implementation deals with the conversion between wide and
28 narrow characters, and also presents a framework for dealing with the
29 huge number of other encodings that iconv can convert, including
30 Unicode and UTF8. Design issues and requirements are addressed, and
31 examples of correct usage for both the required specializations for
32 wide and narrow characters and the implementation-provided extended
33 functionality are given.
34 </p>
35
36 <p>
37 <h2>
38 2. What the standard says
39 </h2>
40 Around page 425 of the C++ Standard, this charming heading comes into view:
41
42 <BLOCKQUOTE>
43 22.2.1.5 - Template class codecvt [lib.locale.codecvt]
44 </BLOCKQUOTE>
45
46 The text around the codecvt definition gives some clues:
47
48 <BLOCKQUOTE>
49 <I>
50 -1- The class codecvt&lt;internT,externT,stateT&gt; is for use when
51 converting from one codeset to another, such as from wide characters
52 to multibyte characters, between wide character encodings such as
53 Unicode and EUC. 
54 </I>
55 </BLOCKQUOTE>
56
57 <p> 
58 Hmm. So, in some unspecified way, Unicode encodings and
59 translations between other character sets should be handled by this
60 class.  
61 </p>
62
63 <BLOCKQUOTE>
64 <I>
65 -2- The stateT argument selects the pair of codesets being mapped between. 
66 </I>
67 </BLOCKQUOTE>
68
69 <p>
70 Ah ha! Another clue...
71 </p>
72
73 <BLOCKQUOTE>
74 <I>
75 -3- The instantiations required in the Table ??
76 (lib.locale.category), namely codecvt&lt;wchar_t,char,mbstate_t&gt; and
77 codecvt&lt;char,char,mbstate_t&gt;, convert the implementation-defined
78 native character set. codecvt&lt;char,char,mbstate_t&gt; implements a
79 degenerate conversion; it does not convert at
80 all. codecvt&lt;wchar_t,char,mbstate_t&gt; converts between the native
81 character sets for tiny and wide characters. Instantiations on
82 mbstate_t perform conversion between encodings known to the library
83 implementor.  Other encodings can be converted by specializing on a
84 user-defined stateT type. The stateT object can contain any state that
85 is useful to communicate to or from the specialized do_convert member.
86 </I>
87 </BLOCKQUOTE>
88
89 <p>
90 At this point, a couple points become clear:
91
92 <p>
93 One: The standard clearly implies that attempts to add non-required
94 (yet useful and widely used) conversions need to do so through the
95 third template parameter, stateT.</p>
96
97 <p>
98 Two: The required conversions, by specifying mbstate_t as the third
99 template parameter, imply an implementation strategy that is mostly
100 (or wholly) based on the underlying C library, and the functions
101 mcsrtombs and wcsrtombs in particular.</p>
102
103 <p>
104 <h2>
105 3. Some thoughts on what would be useful
106 </h2>
107 Probably the most frequently asked question about code conversion is:
108 &quot;So dudes, what's the deal with Unicode strings?&quot; The dude part is
109 optional, but apparently the usefulness of Unicode strings is pretty
110 widely appreciated. Sadly, this specific encoding (And other useful
111 encodings like UTF8, UCS4, ISO 8859-10, etc etc etc) are not mentioned
112 in the C++ standard.
113
114 <p>
115 In particular, the simple implementation detail of wchar_t's size
116 seems to repeatedly confound people. Many systems use a two byte,
117 unsigned integral type to represent wide characters, and use an
118 internal encoding of Unicode or UCS2. (See AIX, Microsoft NT, Java,
119 others.) Other systems, use a four byte, unsigned integral type to
120 represent wide characters, and use an internal encoding of
121 UCS4. (GNU/Linux systems using glibc, in particular.) The C
122 programming language (and thus C++) does not specify a specific size
123 for the type wchar_t.
124
125 <p>
126 Thus, portable C++ code cannot assume a byte size (or endianness) either.
127
128 <p>
129 Getting back to the frequently asked question: What about Unicode strings?
130
131 <p>
132 What magic spell will do this conversion?
133
134 <p>
135 A couple of comments:
136 </p>
137
138 <p>
139 The thought that all one needs to convert between two arbitrary
140 codesets is two types and some kind of state argument is
141 unfortunate. In particular, encodings may be stateless. The naming of
142 the third parameter as stateT is unfortunate, as what is really needed
143 is some kind of generalized type that accounts for the issues that
144 abstract encodings will need. The minimum information that is required
145 includes:
146 </p>
147
148 <ul>
149 <li>
150 <p>
151  Identifiers for each of the codesets involved in the conversion. For
152 example, using the iconv family of functions from the Single Unix
153 Specification (what used to be called X/Open) hosted on the GNU/Linux
154 operating system allows bi-directional mapping between far more than
155 the following tantalizing possibilities: 
156
157 <p>
158 (An edited list taken from <code>`iconv --list`</code> on a Red Hat 6.2/Intel system:
159
160 <BLOCKQUOTE>
161 <PRE>
162 8859_1, 8859_9, 10646-1:1993, 10646-1:1993/UCS4, ARABIC, ARABIC7,
163 ASCII, EUC-CN, EUC-JP, EUC-KR, EUC-TW, GREEK-CCIcode, GREEK, GREEK7-OLD,
164 GREEK7, GREEK8, HEBREW, ISO-8859-1, ISO-8859-2, ISO-8859-3,
165 ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8,
166 ISO-8859-9, ISO-8859-10, ISO-8859-11, ISO-8859-13, ISO-8859-14,
167 ISO-8859-15, ISO-10646, ISO-10646/UCS2, ISO-10646/UCS4,
168 ISO-10646/UTF-8, ISO-10646/UTF8, SHIFT-JIS, SHIFT_JIS, UCS-2, UCS-4,
169 UCS2, UCS4, UNICODE, UNICODEBIG, UNICODELIcodeLE, US-ASCII, US, UTF-8,
170 UTF-16, UTF8, UTF16).
171 </PRE>
172 </BLOCKQUOTE>
173
174 <p>
175 For iconv-based implementations, string literals for each of the
176 encodings (ie. &quot;UCS-2&quot; and &quot;UTF-8&quot;) are necessary,
177 although for other,
178 non-iconv implementations a table of enumerated values or some other
179 mechanism may be required.
180
181 <li>
182  Maximum length of the identifying string literal.
183
184 <li>
185  Some encodings are require explicit endian-ness. As such, some kind
186   of endian marker or other byte-order marker will be necessary. See
187   &quot;Footnotes for C/C++ developers&quot; in Haible for more information on
188   UCS-2/Unicode endian issues. (Summary: big endian seems most likely,
189   however implementations, most notably Microsoft, vary.)
190
191 <li>
192  Types representing the conversion state, for conversions involving
193   the machinery in the &quot;C&quot; library, or the conversion descriptor, for
194   conversions using iconv (such as the type iconv_t.)  Note that the
195   conversion descriptor encodes more information than a simple encoding
196   state type.
197
198 <li>
199  Conversion descriptors for both directions of encoding. (ie, both
200   UCS-2 to UTF-8 and UTF-8 to UCS-2.)
201
202 <li>
203  Something to indicate if the conversion requested if valid.
204
205 <li>
206  Something to represent if the conversion descriptors are valid.
207
208 <li>
209  Some way to enforce strict type checking on the internal and
210   external types. As part of this, the size of the internal and
211   external types will need to be known.
212 </ul>
213
214 <p>
215 <h2>
216 4. Problems with &quot;C&quot; code conversions : thread safety, global
217 locales, termination.
218 </h2>
219
220 In addition, multi-threaded and multi-locale environments also impact
221 the design and requirements for code conversions. In particular, they
222 affect the required specialization codecvt&lt;wchar_t, char, mbstate_t&gt;
223 when implemented using standard &quot;C&quot; functions.
224
225 <p>
226 Three problems arise, one big, one of medium importance, and one small. 
227
228 <p>
229 First, the small: mcsrtombs and wcsrtombs may not be multithread-safe
230 on all systems required by the GNU tools. For GNU/Linux and glibc,
231 this is not an issue.
232
233 <p>
234 Of medium concern, in the grand scope of things, is that the functions
235 used to implement this specialization work on null-terminated
236 strings. Buffers, especially file buffers, may not be null-terminated,
237 thus giving conversions that end prematurely or are otherwise
238 incorrect. Yikes!
239
240 <p>
241 The last, and fundamental problem, is the assumption of a global
242 locale for all the &quot;C&quot; functions referenced above. For something like
243 C++ iostreams (where codecvt is explicitly used) the notion of
244 multiple locales is fundamental. In practice, most users may not run
245 into this limitation. However, as a quality of implementation issue,
246 the GNU C++ library would like to offer a solution that allows
247 multiple locales and or simultaneous usage with computationally
248 correct results. In short, libstdc++-v3 is trying to offer, as an
249 option, a high-quality implementation, damn the additional complexity!
250
251 <p>
252 For the required specialization codecvt&lt;wchar_t, char, mbstate_t&gt; ,
253 conversions are made between the internal character set (always UCS4
254 on GNU/Linux) and whatever the currently selected locale for the
255 LC_CTYPE category implements.
256
257 <p>
258 <h2>
259 5. Design
260 </h2>
261 The two required specializations are implemented as follows:
262
263 <p>
264 <code>
265 codecvt&lt;char, char, mbstate_t&gt;
266 </code>
267 <p>
268 This is a degenerate (ie, does nothing) specialization. Implementing
269 this was a piece of cake.
270
271 <p>
272 <code>
273 codecvt&lt;char, wchar_t, mbstate_t&gt;
274 </code>
275 <p>
276 This specialization, by specifying all the template parameters, pretty
277 much ties the hands of implementors. As such, the implementation is
278 straightforward, involving mcsrtombs for the conversions between char
279 to wchar_t and wcsrtombs for conversions between wchar_t and char.
280
281 <p>
282 Neither of these two required specializations deals with Unicode
283 characters. As such, libstdc++-v3 implements a partial specialization
284 of the codecvt class with and iconv wrapper class, __enc_traits as the
285 third template parameter.
286
287 <p>
288 This implementation should be standards conformant. First of all, the
289 standard explicitly points out that instantiations on the third
290 template parameter, stateT, are the proper way to implement
291 non-required conversions. Second of all, the standard says (in Chapter
292 17) that partial specializations of required classes are a-ok. Third
293 of all, the requirements for the stateT type elsewhere in the standard
294 (see 21.1.2 traits typedefs) only indicate that this type be copy
295 constructible.
296
297 <p>
298 As such, the type __enc_traits is defined as a non-templatized, POD
299 type to be used as the third type of a codecvt instantiation. This
300 type is just a wrapper class for iconv, and provides an easy interface
301 to iconv functionality.
302
303 <p>
304 There are two constructors for __enc_traits:
305
306 <p>
307 <code> 
308 __enc_traits() : __in_desc(0), __out_desc(0)
309 </code>
310 <p>
311 This default constructor sets the internal encoding to some default
312 (currently UCS4) and the external encoding to whatever is returned by
313 nl_langinfo(CODESET).
314
315 <p>
316 <code> 
317 __enc_traits(const char* __int, const char* __ext)
318 </code>
319 <p>
320 This constructor takes as parameters string literals that indicate the
321 desired internal and external encoding. There are no defaults for
322 either argument.
323
324 <p>
325 One of the issues with iconv is that the string literals identifying
326 conversions are not standardized. Because of this, the thought of
327 mandating and or enforcing some set of pre-determined valid
328 identifiers seems iffy: thus, a more practical (and non-migraine
329 inducing) strategy was implemented: end-users can specify any string
330 (subject to a pre-determined length qualifier, currently 32 bytes) for
331 encodings. It is up to the user to make sure that these strings are
332 valid on the target system.
333   
334 <p>
335 <code> 
336 void
337 _M_init()
338 </code>
339 <p>
340 Strangely enough, this member function attempts to open conversion
341 descriptors for a given __enc_traits object. If the conversion
342 descriptors are not valid, the conversion descriptors returned will
343 not be valid and the resulting calls to the codecvt conversion
344 functions will return error.
345
346 <p>
347 <code> 
348 bool
349 _M_good()
350 </code>
351 <p>
352 Provides a way to see if the given __enc_traits object has been
353 properly initialized. If the string literals describing the desired
354 internal and external encoding are not valid, initialization will
355 fail, and this will return false. If the internal and external
356 encodings are valid, but iconv_open could not allocate conversion
357 descriptors, this will also return false. Otherwise, the object is
358 ready to convert and will return true.
359
360 <p>
361 <code> 
362 __enc_traits(const __enc_traits&amp;)
363 </code>
364 <p>
365 As iconv allocates memory and sets up conversion descriptors, the copy
366 constructor can only copy the member data pertaining to the internal
367 and external code conversions, and not the conversion descriptors
368 themselves.
369
370 <p>
371 Definitions for all the required codecvt member functions are provided
372 for this specialization, and usage of codecvt&lt;internal character type,
373 external character type, __enc_traits&gt; is consistent with other
374 codecvt usage.
375
376 <p>
377 <h2>
378 6.  Examples
379 </h2>
380
381 <ul>
382         <li>
383         a. conversions involving string literals
384
385 <pre>
386   typedef codecvt_base::result                  result;
387   typedef unsigned short                        unicode_t;
388   typedef unicode_t                             int_type;
389   typedef char                                  ext_type;
390   typedef __enc_traits                          enc_type;
391   typedef codecvt&lt;int_type, ext_type, enc_type&gt;   unicode_codecvt;
392
393   const ext_type*       e_lit = "black pearl jasmine tea";
394   int                   size = strlen(e_lit);
395   int_type              i_lit_base[24] = 
396   { 25088, 27648, 24832, 25344, 27392, 8192, 28672, 25856, 24832, 29184, 
397     27648, 8192, 27136, 24832, 29440, 27904, 26880, 28160, 25856, 8192, 29696,
398     25856, 24832, 2560
399   };
400   const int_type*       i_lit = i_lit_base;
401   const ext_type*       efrom_next;
402   const int_type*       ifrom_next;
403   ext_type*             e_arr = new ext_type[size + 1];
404   ext_type*             eto_next;
405   int_type*             i_arr = new int_type[size + 1];
406   int_type*             ito_next;
407
408   // construct a locale object with the specialized facet.
409   locale                loc(locale::classic(), new unicode_codecvt);
410   // sanity check the constructed locale has the specialized facet.
411   VERIFY( has_facet&lt;unicode_codecvt&gt;(loc) );
412   const unicode_codecvt&amp; cvt = use_facet&lt;unicode_codecvt&gt;(loc); 
413   // convert between const char* and unicode strings
414   unicode_codecvt::state_type state01("UNICODE", "ISO_8859-1");
415   initialize_state(state01);
416   result r1 = cvt.in(state01, e_lit, e_lit + size, efrom_next, 
417                      i_arr, i_arr + size, ito_next);
418   VERIFY( r1 == codecvt_base::ok );
419   VERIFY( !int_traits::compare(i_arr, i_lit, size) ); 
420   VERIFY( efrom_next == e_lit + size );
421   VERIFY( ito_next == i_arr + size );
422 </pre>
423         <li>
424         b. conversions involving std::string
425         <li>
426         c. conversions involving std::filebuf and std::ostream
427 </ul>
428
429 More information can be found in the following testcases:
430 <ul>
431 <li> testsuite/22_locale/codecvt_char_char.cc  
432 <li> testsuite/22_locale/codecvt_unicode_wchar_t.cc
433 <li> testsuite/22_locale/codecvt_unicode_char.cc  
434 <li> testsuite/22_locale/codecvt_wchar_t_char.cc
435 </ul>
436
437 <p>
438 <h2>
439 7.  Unresolved Issues
440 </h2>
441 <ul>
442 <li>
443         a. things that are sketchy, or remain unimplemented:
444                 do_encoding, max_length and length member functions
445                 are only weakly implemented. I have no idea how to do
446                 this correctly, and in a generic manner.  Nathan?
447
448 <li>
449         b. conversions involving std::string
450
451         <ul>
452                 <li>
453                 how should operators != and == work for string of
454                 different/same encoding?
455
456                 <li>
457                 what is equal? A byte by byte comparison or an
458                 encoding then byte comparison?
459                 
460                 <li>
461                 conversions between narrow, wide, and unicode strings
462         </ul>
463 <li>
464         c. conversions involving std::filebuf and std::ostream
465         <ul>
466                 <li>
467                 how to initialize the state object in a
468                 standards-conformant manner?
469
470                 <li>
471                 how to synchronize the &quot;C&quot; and &quot;C++&quot;
472         conversion information?
473
474                 <li>
475                 wchar_t/char internal buffers and conversions between
476                 internal/external buffers?
477         </ul>
478 </ul>
479
480 <p>
481 <h2>
482 8. Acknowledgments
483 </h2>
484 Ulrich Drepper for the iconv suggestions and patient answering of
485 late-night questions, Jason Merrill for the template partial
486 specialization hints, language clarification, and wchar_t fixes.
487
488 <p>
489 <h2>
490 9. Bibliography / Referenced Documents
491 </h2>
492
493 Drepper, Ulrich, GNU libc (glibc) 2.2 manual. In particular, Chapters &quot;6. Character Set Handling&quot; and &quot;7 Locales and Internationalization&quot;
494
495 <p>
496 Drepper, Ulrich, Numerous, late-night email correspondence
497
498 <p>
499 Feather, Clive, &quot;A brief description of Normative Addendum 1,&quot; in particular the parts on Extended Character Sets
500 http://www.lysator.liu.se/c/na1.html
501
502 <p>
503 Haible, Bruno, &quot;The Unicode HOWTO&quot; v0.18, 4 August 2000
504 ftp://ftp.ilog.fr/pub/Users/haible/utf8/Unicode-HOWTO.html
505
506 <p>
507 ISO/IEC 14882:1998 Programming languages - C++
508
509 <p>
510 ISO/IEC 9899:1999 Programming languages - C
511
512 <p>
513 Khun, Markus, &quot;UTF-8 and Unicode FAQ for Unix/Linux&quot;
514 http://www.cl.cam.ac.uk/~mgk25/unicode.html
515
516 <p>
517 Langer, Angelika and Klaus Kreft, Standard C++ IOStreams and Locales, Advanced Programmer's Guide and Reference, Addison Wesley Longman, Inc. 2000
518
519 <p>
520 Stroustrup, Bjarne, Appendix D, The C++ Programming Language, Special Edition, Addison Wesley, Inc. 2000
521
522 <p>
523 System Interface Definitions, Issue 6 (IEEE Std. 1003.1-200x)
524 The Open Group/The Institute of Electrical and Electronics Engineers, Inc.
525 http://www.opennc.org/austin/docreg.html
526
527 </body>
528 </html>