MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CharsetMap.cpp
1 /*
2  Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 /*
19  * CharsetMap.cpp
20  */
21 
22 #include "CharsetMap.hpp"
23 #include "CharsetMapImpl.h"
24 #include "my_global.h"
25 #include "mysql.h"
26 #include "my_sys.h"
27 
28 bool m_false_result = false;
29 bool m_true_result = true;
30 
31 /* _map is a static pointer visible only within the scope of this file.
32  A singleton CharsetMapImpl serves every instance of CharsetMap.
33 */
34 static CharsetMapImpl *_map = 0;
35 
36 
37 /* Initialization allocates the CharsetMapImpl and initializes its mutex.
38  But we defer building the map of charset names, so as not to create
39  any sort of ordering dependency that would require mysql_init() to
40  be run first.
41  */
42 
44 {
45  if(_map == 0) _map = new CharsetMapImpl;
46 }
47 
48 
49 /* Free the CharsetMapImpl at shutdown time.
50 */
52 {
53  delete _map;
54  _map = 0;
55 }
56 
57 
58 /* On the first invocation of the CharsetMap constructor, it completes the
59  initialization of the CharsetMapImpl by building the map of character set
60  names.
61 */
62 CharsetMap::CharsetMap()
63 {
64  _map->lock();
65  if(_map->ready == 0) _map->build_map();
66  _map->unlock();
67 }
68 
69 
70 const char * CharsetMap::getName(int csnum) const
71 {
72  return _map->getName(csnum);
73 }
74 
75 
76 const char * CharsetMap::getMysqlName(int csnum) const
77 {
78  CHARSET_INFO *cs = get_charset(csnum, MYF(0));
79  return cs ? cs->csname : 0;
80 }
81 
82 
84 {
85  return _map->UTF8Charset;
86 }
87 
88 
90 {
91  return _map->UTF16Charset;
92 }
93 
94 
95 int CharsetMap::getCharsetNumber(const char *name) const
96 {
97  return get_charset_number(name, MY_CS_AVAILABLE);
98 }
99 
100 const bool * CharsetMap::isMultibyte(int cs_number) const
101 {
102  CHARSET_INFO * cset = get_charset(cs_number, MYF(0));
103  if(cset == 0) return 0;
104  return use_mb(cset) ? & m_true_result : & m_false_result;
105 }
106 
107 
108 CharsetMap::RecodeStatus CharsetMap::recode(int32_t *lengths, int From, int To,
109  const void *void_src,
110  void *void_dest) const
111 {
112  int32_t &total_read = lengths[0]; // IN/OUT
113  int32_t &total_written = lengths[1]; // IN/OUT
114  my_wc_t wide;
115  my_wc_t mystery_char = '?'; // used in place of unmappable characters
116  const unsigned char * src = (const unsigned char *) void_src;
117  unsigned char * dest = (unsigned char *) void_dest;
118  CHARSET_INFO * csFrom = get_charset(From, MYF(0));
119  CHARSET_INFO * csTo = get_charset(To, MYF(0));
120 
121  if(! (csTo && csFrom)) return RECODE_BAD_CHARSET;
122 
123  int32_t src_len = lengths[0];
124  int32_t dest_len = lengths[1];
125  const unsigned char * src_end = src + src_len;
126  unsigned char * dest_end = dest + dest_len;
127  total_read = 0 ; // i.e. lengths[0] = 0;
128  total_written = 0; // i.e. lengths[1] = 0;
129 
130  while(src < src_end) {
131  /* First recode from source character to 32-bit wide character */
132  int nread = csFrom->cset->mb_wc(csFrom, &wide, src, src_end);
133  if(nread < 0) return RECODE_BUFF_TOO_SMALL;
134  if(nread == 0) return RECODE_BAD_SRC;
135 
136  /* Then recode from wide character to target character */
137  int nwritten = csTo->cset->wc_mb(csTo, wide, dest, dest_end);
138  if(nwritten == MY_CS_ILUNI) {
139  /* Character does not exist in target charset */
140  nwritten = csTo->cset->wc_mb(csTo, mystery_char, dest, dest_end);
141  }
142  if(nwritten < 0) return RECODE_BUFF_TOO_SMALL;
143 
144  total_read += nread; src += nread;
145  total_written += nwritten; dest += nwritten;
146  }
147 
148  return RECODE_OK;
149 }