OSDN Git Service

bc427add940d6913a4ed68b97bf6f4647af8250a
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / bits / codecvt.h
1 // Locale support (codecvt) -*- C++ -*-
2
3 // Copyright (C) 2000 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING.  If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 // USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30 //
31 // ISO C++ 14882: 22.2.1.5 Template class codecvt
32 //
33
34 // Warning: this file is not meant for user inclusion.  Use <locale>.
35
36 // Written by Benjamin Kosnik <bkoz@cygnus.com>
37
38 #ifndef _CPP_BITS_CODECVT_H
39 #define _CPP_BITS_CODECVT_H     1
40
41 #ifdef _GLIBCPP_USE_WCHAR_T
42 #include <iconv.h>              // For iconv, iconv_t
43 #include <langinfo.h>
44 #endif
45
46 namespace std
47 {
48   // XXX __enc_traits may need to move up the locale header hierarchy,
49   // depending on if ctype ends up using it.
50 #ifdef _GLIBCPP_USE_WCHAR_T
51   // Extensions to use icov for dealing with character encodings,
52   // including conversions and comparisons between various character
53   // sets.  This object encapsulates data that may need to be shared between
54   // char_traits, codecvt and ctype.
55   class __enc_traits
56   {
57   public:
58     // Types: 
59     // NB: A conversion descriptor subsumes and enhances the
60     // functionality of a simple state type such as mbstate_t.
61     typedef iconv_t     __desc_type;
62     
63   protected:
64     // Data Members:
65     // Max size of charset encoding name
66     static const int    _S_max_size = 32;
67     // Name of internal character set encoding.
68     char                _M_intc_enc[_S_max_size];
69     // Name of external character set encoding.
70     char                _M_extc_enc[_S_max_size];
71
72     // Conversion descriptor between external encoding to internal encoding.
73     __desc_type         _M_in_desc;
74     // Conversion descriptor between internal encoding to external encoding.
75     __desc_type         _M_out_desc;
76
77   public:
78     __enc_traits() : _M_in_desc(0), _M_out_desc(0)
79     {
80       // __intc_end = whatever we are using internally, which is
81       // UCS4 (linux) 
82       // UCS2 == UNICODE  (microsoft, java, aix, whatever...)
83       // XXX Currently don't know how to get this data from target system...
84       strcpy(_M_intc_enc, "UCS4");
85
86       // __extc_end = external codeset in current locale
87       strcpy(_M_extc_enc, nl_langinfo(CODESET));
88     }
89
90     __enc_traits(const char* __int, const char* __ext)
91     : _M_in_desc(0), _M_out_desc(0)
92     {
93       strncpy(_M_intc_enc, __int, _S_max_size);
94       strncpy(_M_extc_enc, __ext, _S_max_size);
95     }
96
97     // 21.1.2 traits typedefs
98     // p4
99     // typedef STATE_T state_type
100     // requires: state_type shall meet the requirements of
101     // CopyConstructible types (20.1.3)
102     __enc_traits(const __enc_traits& __obj)
103     {
104       strncpy(_M_intc_enc, __obj._M_intc_enc, _S_max_size);
105       strncpy(_M_extc_enc, __obj._M_extc_enc, _S_max_size);
106     }
107
108     ~__enc_traits()
109     {
110       iconv_close(_M_in_desc);
111       iconv_close(_M_out_desc);
112     } 
113
114     // Initializes
115     void
116     _M_init()
117     {
118       _M_in_desc = iconv_open(_M_intc_enc, _M_extc_enc);
119       _M_out_desc = iconv_open(_M_extc_enc, _M_intc_enc);
120       if (_M_out_desc == iconv_t(-1) || _M_in_desc == iconv_t(-1))
121         {
122           // XXX Extended error checking.
123         }
124     }
125
126     bool
127     _M_good()
128     { 
129       return _M_out_desc && _M_in_desc 
130              && _M_out_desc != iconv_t(-1) && _M_in_desc != iconv_t(-1);
131     }
132
133     const __desc_type* 
134     _M_get_in_descriptor()
135     { return &_M_in_desc; }
136
137     const __desc_type* 
138     _M_get_out_descriptor()
139     { return &_M_out_desc; }
140
141    const char* 
142     _M_get_internal_enc()
143     { return _M_intc_enc; }
144
145     const char* 
146     _M_get_external_enc()
147     { return _M_extc_enc; }
148   };
149 #endif //_GLIBCPP_USE_WCHAR_T
150
151
152   //  22.2.1.5  Template class codecvt
153   class codecvt_base
154   {
155   public:
156     enum result
157     {
158       ok,
159       partial,
160       error,
161       noconv
162     };
163   };
164
165   // Template class __codecvt_abstract_base
166   // NB: An abstract base class that fills in the public inlines, so
167   // that the specializations don't have to re-copy the public
168   // interface.
169   template<typename _InternT, typename _ExternT, typename _StateT>
170     class __codecvt_abstract_base 
171     : public locale::facet, public codecvt_base
172     {
173     public:
174       // Types:
175       typedef codecvt_base::result                      result;
176       typedef _InternT                                  intern_type;
177       typedef _ExternT                                  extern_type;
178       typedef _StateT                                   state_type;
179       
180       // 22.2.1.5.1 codecvt members
181       result
182       out(state_type& __state, const intern_type* __from, 
183           const intern_type* __from_end, const intern_type*& __from_next,
184           extern_type* __to, extern_type* __to_end, 
185           extern_type*& __to_next) const
186       { 
187         return this->do_out(__state, __from, __from_end, __from_next, 
188                             __to, __to_end, __to_next); 
189       }
190
191       result
192       unshift(state_type& __state, extern_type* __to, extern_type* __to_end,
193               extern_type*& __to_next) const
194       { return this->do_unshift(__state, __to,__to_end,__to_next); }
195
196       result
197       in(state_type& __state, const extern_type* __from, 
198          const extern_type* __from_end, const extern_type*& __from_next,
199          intern_type* __to, intern_type* __to_end, 
200          intern_type*& __to_next) const
201       { 
202         return this->do_in(__state, __from, __from_end, __from_next,
203                            __to, __to_end, __to_next); 
204       }
205
206       int 
207       encoding() const throw()
208       { return this->do_encoding(); }
209
210       bool 
211       always_noconv() const throw()
212       { return this->do_always_noconv(); }
213
214       int
215       length(const state_type& __state, const extern_type* __from,
216              const extern_type* __end, size_t __max) const
217       { return this->do_length(__state, __from, __end, __max); }
218
219       int 
220       max_length() const throw()
221       { return this->do_max_length(); }
222
223     protected:
224       explicit 
225       __codecvt_abstract_base(size_t __refs = 0) : locale::facet(__refs) { }
226
227       virtual 
228       ~__codecvt_abstract_base() { }
229
230       virtual result
231       do_out(state_type& __state, const intern_type* __from, 
232              const intern_type* __from_end, const intern_type*& __from_next,
233              extern_type* __to, extern_type* __to_end,
234              extern_type*& __to_next) const = 0;
235
236       virtual result
237       do_unshift(state_type& __state, extern_type* __to, 
238                  extern_type* __to_end, extern_type*& __to_next) const = 0;
239       
240       virtual result
241       do_in(state_type& __state, const extern_type* __from, 
242             const extern_type* __from_end, const extern_type*& __from_next, 
243             intern_type* __to, intern_type* __to_end, 
244             intern_type*& __to_next) const = 0;
245       
246       virtual int 
247       do_encoding() const throw() = 0;
248
249       virtual bool 
250       do_always_noconv() const throw() = 0;
251
252       virtual int 
253       do_length(const state_type&, const extern_type* __from, 
254                 const extern_type* __end, size_t __max) const = 0;
255
256       virtual int 
257       do_max_length() const throw() = 0;
258     };
259
260   // 22.2.1.5 Template class codecvt
261   // NB: Generic, mostly useless implementation.
262   template<typename _InternT, typename _ExternT, typename _StateT>
263     class codecvt 
264     : public __codecvt_abstract_base<_InternT, _ExternT, _StateT>
265     {
266     public:      
267       // Types:
268       typedef codecvt_base::result                      result;
269       typedef _InternT intern_type;
270       typedef _ExternT extern_type;
271       typedef _StateT  state_type;
272
273       // Data Members:
274       static locale::id id;
275
276       explicit 
277       codecvt(size_t __refs = 0) 
278       : __codecvt_abstract_base<_InternT,_ExternT,_StateT> (__refs) { }
279
280     protected:
281       virtual 
282       ~codecvt() { }
283     };
284
285   template<typename _InternT, typename _ExternT, typename _StateT>
286     locale::id codecvt<_InternT, _ExternT, _StateT>::id;
287
288   // partial specialization
289   // This specialization takes advantage of iconv to provide code
290   // conversions between a large number of character encodings.
291   template<typename _InternT, typename _ExternT>
292     class codecvt<_InternT, _ExternT, __enc_traits>
293     : public __codecvt_abstract_base<_InternT, _ExternT, __enc_traits>
294     {
295     public:      
296       // Types:
297       typedef codecvt_base::result                      result;
298       typedef _InternT                                  intern_type;
299       typedef _ExternT                                  extern_type;
300       typedef __enc_traits                              state_type;
301       typedef __enc_traits::__desc_type                 __desc_type;
302       typedef __enc_traits                              __enc_type;
303
304       // Data Members:
305       static locale::id                 id;
306
307       explicit 
308       codecvt(size_t __refs = 0)
309       : __codecvt_abstract_base<intern_type, extern_type, state_type>(__refs)
310       { }
311
312       explicit 
313       codecvt(__enc_type* __enc, size_t __refs = 0)
314       : __codecvt_abstract_base<intern_type, extern_type, state_type>(__refs)
315       { }
316
317     protected:
318       virtual 
319       ~codecvt() { }
320
321       virtual result
322       do_out(state_type& __state, const intern_type* __from, 
323              const intern_type* __from_end, const intern_type*& __from_next,
324              extern_type* __to, extern_type* __to_end,
325              extern_type*& __to_next) const;
326
327       virtual result
328       do_unshift(state_type& __state, extern_type* __to, 
329                  extern_type* __to_end, extern_type*& __to_next) const;
330
331       virtual result
332       do_in(state_type& __state, const extern_type* __from, 
333             const extern_type* __from_end, const extern_type*& __from_next,
334             intern_type* __to, intern_type* __to_end, 
335             intern_type*& __to_next) const;
336
337       virtual int 
338       do_encoding() const throw();
339
340       virtual bool 
341       do_always_noconv() const throw();
342
343       virtual int 
344       do_length(const state_type&, const extern_type* __from, 
345                 const extern_type* __end, size_t __max) const;
346
347       virtual int 
348       do_max_length() const throw();
349     };
350
351   template<typename _InternT, typename _ExternT>
352     locale::id 
353     codecvt<_InternT, _ExternT, __enc_traits>::id;
354
355   template<typename _InternT, typename _ExternT>
356     codecvt_base::result
357     codecvt<_InternT, _ExternT, __enc_traits>::
358     do_out(state_type& __state, const intern_type* __from, 
359            const intern_type* __from_end, const intern_type*& __from_next,
360            extern_type* __to, extern_type* __to_end,
361            extern_type*& __to_next) const
362     {
363       result __ret = error;
364       if (__state._M_good())
365         {
366           typedef state_type::__desc_type       __desc_type;
367           const __desc_type* __desc = __state._M_get_out_descriptor();
368           const size_t __fmultiple = sizeof(intern_type) / sizeof(char);
369           size_t __flen = __fmultiple * (__from_end - __from);
370           const size_t __tmultiple = sizeof(extern_type) / sizeof(char);
371           size_t __tlen = __tmultiple * (__to_end - __to); 
372           
373           // Argument list for iconv specifies a byte sequence. Thus,
374           // all to/from arrays must be brutally casted to char*.
375           const char* __cfrom = reinterpret_cast<const char*>(__from);
376           char* __cto = reinterpret_cast<char*>(__to);
377           size_t __conv = iconv(*__desc, &__cfrom, &__flen, &__cto, &__tlen); 
378           
379           if (__conv != size_t(-1))
380             {
381               __from_next = reinterpret_cast<const intern_type*>(__cfrom);
382               __to_next = reinterpret_cast<extern_type*>(__cto);
383               __ret = ok;
384             }
385           else 
386             {
387               if (__flen < __from_end - __from)
388                 {
389                   __from_next = reinterpret_cast<const intern_type*>(__cfrom);
390                   __to_next = reinterpret_cast<extern_type*>(__cto);
391                   __ret = partial;
392                 }
393               else
394                 __ret = error;
395             }
396         }
397       return __ret; 
398     }
399
400   template<typename _InternT, typename _ExternT>
401     codecvt_base::result
402     codecvt<_InternT, _ExternT, __enc_traits>::
403     do_unshift(state_type& __state, extern_type* __to, 
404                extern_type* __to_end, extern_type*& __to_next) const
405     {
406       result __ret = error;
407       if (__state._M_good())
408         {
409           typedef state_type::__desc_type       __desc_type;
410           const __desc_type* __desc = __state._M_get_in_descriptor();
411           const size_t __tmultiple = sizeof(intern_type) / sizeof(char);
412           size_t __tlen = __tmultiple * (__to_end - __to); 
413           
414           // Argument list for iconv specifies a byte sequence. Thus,
415           // all to/from arrays must be brutally casted to char*.
416           char* __cto = reinterpret_cast<char*>(__to);
417           size_t __conv = iconv(*__desc, NULL, NULL, &__cto, &__tlen); 
418           
419           if (__conv != size_t(-1))
420             {
421               __to_next = reinterpret_cast<extern_type*>(__cto);
422               if (__tlen == __tmultiple * (__to_end - __to))
423                 __ret = noconv;
424               else if (__tlen == 0)
425                 __ret = ok;
426               else
427                 __ret = partial;
428             }
429           else 
430             __ret = error;
431         }
432       return __ret; 
433     }
434    
435   template<typename _InternT, typename _ExternT>
436     codecvt_base::result
437     codecvt<_InternT, _ExternT, __enc_traits>::
438     do_in(state_type& __state, const extern_type* __from, 
439           const extern_type* __from_end, const extern_type*& __from_next,
440           intern_type* __to, intern_type* __to_end, 
441           intern_type*& __to_next) const
442     { 
443       result __ret = error;
444       if (__state._M_good())
445         {
446           typedef state_type::__desc_type       __desc_type;
447           const __desc_type* __desc = __state._M_get_in_descriptor();
448           const size_t __fmultiple = sizeof(extern_type) / sizeof(char);
449           size_t __flen = __fmultiple * (__from_end - __from);
450           const size_t __tmultiple = sizeof(intern_type) / sizeof(char);
451           size_t __tlen = __tmultiple * (__to_end - __to); 
452           
453           // Argument list for iconv specifies a byte sequence. Thus,
454           // all to/from arrays must be brutally casted to char*.
455           const char* __cfrom = reinterpret_cast<const char*>(__from);
456           char* __cto = reinterpret_cast<char*>(__to);
457           size_t __conv = iconv(*__desc, &__cfrom, &__flen, &__cto, &__tlen); 
458           
459           if (__conv != size_t(-1))
460             {
461               __from_next = reinterpret_cast<const extern_type*>(__cfrom);
462               __to_next = reinterpret_cast<intern_type*>(__cto);
463               __ret = ok;
464             }
465           else 
466             {
467               if (__flen < __from_end - __from)
468                 {
469                   __from_next = reinterpret_cast<const extern_type*>(__cfrom);
470                   __to_next = reinterpret_cast<intern_type*>(__cto);
471                   __ret = partial;
472                 }
473               else
474                 __ret = error;
475             }
476         }
477       return __ret; 
478     }
479   
480   template<typename _InternT, typename _ExternT>
481     int 
482     codecvt<_InternT, _ExternT, __enc_traits>::
483     do_encoding() const throw()
484     { return 0; }
485   
486   template<typename _InternT, typename _ExternT>
487     bool 
488     codecvt<_InternT, _ExternT, __enc_traits>::
489     do_always_noconv() const throw()
490     { return false; }
491   
492   template<typename _InternT, typename _ExternT>
493     int 
494     codecvt<_InternT, _ExternT, __enc_traits>::
495     do_length(const state_type& __state, const extern_type* __from, 
496               const extern_type* __end, size_t __max) const
497     { return min(__max, static_cast<size_t>(__end - __from)); }
498
499 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
500 // 74.  Garbled text for codecvt::do_max_length
501   template<typename _InternT, typename _ExternT>
502     int 
503     codecvt<_InternT, _ExternT, __enc_traits>::
504     do_max_length() const throw()
505     { return 1; }
506 #endif
507
508   // codecvt<char, char, mbstate_t> required specialization
509   template<>
510     class codecvt<char, char, mbstate_t> 
511     : public __codecvt_abstract_base<char, char, mbstate_t>
512     {
513     public:      
514       // Types:
515       typedef char      intern_type;
516       typedef char      extern_type;
517       typedef mbstate_t state_type;
518
519       // Data Members:
520       static locale::id id;
521
522       explicit 
523       codecvt(size_t __refs = 0);
524
525     protected:
526       virtual 
527       ~codecvt();
528
529       virtual result
530       do_out(state_type& __state, const intern_type* __from, 
531              const intern_type* __from_end, const intern_type*& __from_next,
532              extern_type* __to, extern_type* __to_end,
533              extern_type*& __to_next) const;
534
535       virtual result
536       do_unshift(state_type& __state, extern_type* __to, 
537                  extern_type* __to_end, extern_type*& __to_next) const;
538
539       virtual result
540       do_in(state_type& __state, const extern_type* __from, 
541             const extern_type* __from_end, const extern_type*& __from_next,
542             intern_type* __to, intern_type* __to_end, 
543             intern_type*& __to_next) const;
544
545       virtual int 
546       do_encoding() const throw();
547
548       virtual bool 
549       do_always_noconv() const throw();
550
551       virtual int 
552       do_length(const state_type&, const extern_type* __from, 
553                 const extern_type* __end, size_t __max) const;
554
555       virtual int 
556       do_max_length() const throw();
557   };
558
559 #ifdef _GLIBCPP_USE_WCHAR_T
560   // codecvt<wchar_t, char, mbstate_t> required specialization
561   template<>
562     class codecvt<wchar_t, char, mbstate_t> 
563     : public __codecvt_abstract_base<wchar_t, char, mbstate_t>
564     {
565     public:
566       // Types:
567       typedef wchar_t   intern_type;
568       typedef char      extern_type;
569       typedef mbstate_t state_type;
570
571       // Data Members:
572       static locale::id id;
573
574       explicit 
575       codecvt(size_t __refs = 0);
576
577     protected:
578       virtual 
579       ~codecvt();
580
581       virtual result
582       do_out(state_type& __state, const intern_type* __from, 
583              const intern_type* __from_end, const intern_type*& __from_next,
584              extern_type* __to, extern_type* __to_end,
585              extern_type*& __to_next) const;
586
587       virtual result
588       do_unshift(state_type& __state,
589                  extern_type* __to, extern_type* __to_end,
590                  extern_type*& __to_next) const;
591
592       virtual result
593       do_in(state_type& __state,
594              const extern_type* __from, const extern_type* __from_end,
595              const extern_type*& __from_next,
596              intern_type* __to, intern_type* __to_end,
597              intern_type*& __to_next) const;
598
599       virtual 
600       int do_encoding() const throw();
601
602       virtual 
603       bool do_always_noconv() const throw();
604
605       virtual 
606       int do_length(const state_type&, const extern_type* __from,
607                     const extern_type* __end, size_t __max) const;
608
609       virtual int 
610       do_max_length() const throw();
611     };
612 #endif //_GLIBCPP_USE_WCHAR_T
613
614   // 22.2.1.6  Template class codecvt_byname
615   template<typename _InternT, typename _ExternT, typename _StateT>
616     class codecvt_byname : public codecvt<_InternT, _ExternT, _StateT>
617     {
618     public:
619       explicit 
620       codecvt_byname(const char*, size_t __refs = 0) 
621       : codecvt<_InternT,_ExternT,_StateT> (__refs) { }
622     protected:
623       virtual 
624       ~codecvt_byname() { }
625     };
626
627   template<>
628     class codecvt_byname<char, char, mbstate_t>
629     : public codecvt<char, char, mbstate_t>
630     {
631     public:
632       explicit 
633       codecvt_byname(const char*, size_t __refs = 0);
634
635     protected:
636       virtual 
637       ~codecvt_byname();
638     };
639   
640 #ifdef _GLIBCPP_USE_WCHAR_T
641   template<>
642     class codecvt_byname<wchar_t, char, mbstate_t>
643       : public codecvt<wchar_t, char, mbstate_t>
644     {
645     public:
646       explicit 
647       codecvt_byname(const char*, size_t __refs = 0);
648
649     protected:
650       virtual 
651       ~codecvt_byname();
652     };
653 #endif
654
655 } // namespace std
656
657 #endif // _CPP_BITS_CODECVT_H
658
659 // Local Variables:
660 // mode:c++
661 // End:
662