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