~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/charset.cc

  • Committer: Brian Aker
  • Date: 2009-01-21 05:53:36 UTC
  • mto: This revision was merged to the branch mainline in revision 801.
  • Revision ID: brian@tangent.org-20090121055336-fxoz6wfzreo8gi9x
Removed purge

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
#include "mysys_err.h"
18
18
#include <mystrings/m_ctype.h>
19
19
#include <mystrings/m_string.h>
20
 
#include <my_dir.h>
21
 
#include <mystrings/my_xml.h>
 
20
#include <drizzled/configmake.h>
22
21
 
23
22
 
24
23
/*
25
24
  The code below implements this functionality:
26
 
  
 
25
 
27
26
    - Initializing charset related structures
28
27
    - Loading dynamic charsets
29
 
    - Searching for a proper CHARSET_INFO 
 
28
    - Searching for a proper CHARSET_INFO
30
29
      using charset name, collation name or collation ID
31
30
    - Setting server default character set
32
31
*/
45
44
       cs < all_charsets+array_elements(all_charsets)-1 ;
46
45
       cs++)
47
46
  {
48
 
    if ( cs[0] && cs[0]->name && 
49
 
         !my_strcasecmp(&my_charset_latin1, cs[0]->name, name))
 
47
    if ( cs[0] && cs[0]->name &&
 
48
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->name, name))
50
49
      return cs[0]->number;
51
 
  }  
 
50
  }
52
51
  return 0;
53
52
}
54
53
 
55
54
 
56
55
static bool init_state_maps(CHARSET_INFO *cs)
57
56
{
58
 
  uint i;
59
 
  uchar *state_map;
60
 
  uchar *ident_map;
 
57
  uint32_t i;
 
58
  unsigned char *state_map;
 
59
  unsigned char *ident_map;
61
60
 
62
 
  if (!(cs->state_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
 
61
  if (!(cs->state_map= (unsigned char*) malloc(256)))
63
62
    return 1;
64
63
    
65
 
  if (!(cs->ident_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
 
64
  if (!(cs->ident_map= (unsigned char*) malloc(256)))
66
65
    return 1;
67
66
 
68
67
  state_map= cs->state_map;
69
68
  ident_map= cs->ident_map;
70
 
  
 
69
 
71
70
  /* Fill state_map with states to get a faster parser */
72
71
  for (i=0; i < 256 ; i++)
73
72
  {
74
73
    if (my_isalpha(cs,i))
75
 
      state_map[i]=(uchar) MY_LEX_IDENT;
 
74
      state_map[i]=(unsigned char) MY_LEX_IDENT;
76
75
    else if (my_isdigit(cs,i))
77
 
      state_map[i]=(uchar) MY_LEX_NUMBER_IDENT;
 
76
      state_map[i]=(unsigned char) MY_LEX_NUMBER_IDENT;
78
77
#if defined(USE_MB) && defined(USE_MB_IDENT)
79
78
    else if (my_mbcharlen(cs, i)>1)
80
 
      state_map[i]=(uchar) MY_LEX_IDENT;
 
79
      state_map[i]=(unsigned char) MY_LEX_IDENT;
81
80
#endif
82
81
    else if (my_isspace(cs,i))
83
 
      state_map[i]=(uchar) MY_LEX_SKIP;
 
82
      state_map[i]=(unsigned char) MY_LEX_SKIP;
84
83
    else
85
 
      state_map[i]=(uchar) MY_LEX_CHAR;
 
84
      state_map[i]=(unsigned char) MY_LEX_CHAR;
86
85
  }
87
 
  state_map[(uchar)'_']=state_map[(uchar)'$']=(uchar) MY_LEX_IDENT;
88
 
  state_map[(uchar)'\'']=(uchar) MY_LEX_STRING;
89
 
  state_map[(uchar)'.']=(uchar) MY_LEX_REAL_OR_POINT;
90
 
  state_map[(uchar)'>']=state_map[(uchar)'=']=state_map[(uchar)'!']= (uchar) MY_LEX_CMP_OP;
91
 
  state_map[(uchar)'<']= (uchar) MY_LEX_LONG_CMP_OP;
92
 
  state_map[(uchar)'&']=state_map[(uchar)'|']=(uchar) MY_LEX_BOOL;
93
 
  state_map[(uchar)'#']=(uchar) MY_LEX_COMMENT;
94
 
  state_map[(uchar)';']=(uchar) MY_LEX_SEMICOLON;
95
 
  state_map[(uchar)':']=(uchar) MY_LEX_SET_VAR;
96
 
  state_map[0]=(uchar) MY_LEX_EOL;
97
 
  state_map[(uchar)'\\']= (uchar) MY_LEX_ESCAPE;
98
 
  state_map[(uchar)'/']= (uchar) MY_LEX_LONG_COMMENT;
99
 
  state_map[(uchar)'*']= (uchar) MY_LEX_END_LONG_COMMENT;
100
 
  state_map[(uchar)'@']= (uchar) MY_LEX_USER_END;
101
 
  state_map[(uchar) '`']= (uchar) MY_LEX_USER_VARIABLE_DELIMITER;
102
 
  state_map[(uchar)'"']= (uchar) MY_LEX_STRING_OR_DELIMITER;
 
86
  state_map[(unsigned char)'_']=state_map[(unsigned char)'$']=(unsigned char) MY_LEX_IDENT;
 
87
  state_map[(unsigned char)'\'']=(unsigned char) MY_LEX_STRING;
 
88
  state_map[(unsigned char)'.']=(unsigned char) MY_LEX_REAL_OR_POINT;
 
89
  state_map[(unsigned char)'>']=state_map[(unsigned char)'=']=state_map[(unsigned char)'!']= (unsigned char) MY_LEX_CMP_OP;
 
90
  state_map[(unsigned char)'<']= (unsigned char) MY_LEX_LONG_CMP_OP;
 
91
  state_map[(unsigned char)'&']=state_map[(unsigned char)'|']=(unsigned char) MY_LEX_BOOL;
 
92
  state_map[(unsigned char)'#']=(unsigned char) MY_LEX_COMMENT;
 
93
  state_map[(unsigned char)';']=(unsigned char) MY_LEX_SEMICOLON;
 
94
  state_map[(unsigned char)':']=(unsigned char) MY_LEX_SET_VAR;
 
95
  state_map[0]=(unsigned char) MY_LEX_EOL;
 
96
  state_map[(unsigned char)'\\']= (unsigned char) MY_LEX_ESCAPE;
 
97
  state_map[(unsigned char)'/']= (unsigned char) MY_LEX_LONG_COMMENT;
 
98
  state_map[(unsigned char)'*']= (unsigned char) MY_LEX_END_LONG_COMMENT;
 
99
  state_map[(unsigned char)'@']= (unsigned char) MY_LEX_USER_END;
 
100
  state_map[(unsigned char) '`']= (unsigned char) MY_LEX_USER_VARIABLE_DELIMITER;
 
101
  state_map[(unsigned char)'"']= (unsigned char) MY_LEX_STRING_OR_DELIMITER;
103
102
 
104
103
  /*
105
104
    Create a second map to make it faster to find identifiers
106
105
  */
107
106
  for (i=0; i < 256 ; i++)
108
107
  {
109
 
    ident_map[i]= (uchar) (state_map[i] == MY_LEX_IDENT ||
 
108
    ident_map[i]= (unsigned char) (state_map[i] == MY_LEX_IDENT ||
110
109
                           state_map[i] == MY_LEX_NUMBER_IDENT);
111
110
  }
112
111
 
113
112
  /* Special handling of hex and binary strings */
114
 
  state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) MY_LEX_IDENT_OR_HEX;
115
 
  state_map[(uchar)'b']= state_map[(uchar)'B']= (uchar) MY_LEX_IDENT_OR_BIN;
116
 
  return 0;
117
 
}
118
 
 
119
 
 
120
 
static void simple_cs_init_functions(CHARSET_INFO *cs)
121
 
{
122
 
  if (cs->state & MY_CS_BINSORT)
123
 
    cs->coll= &my_collation_8bit_bin_handler;
124
 
  else
125
 
    cs->coll= &my_collation_8bit_simple_ci_handler;
126
 
  
127
 
  cs->cset= &my_charset_8bit_handler;
128
 
}
129
 
 
130
 
 
131
 
 
132
 
static int cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
133
 
{
134
 
  to->number= from->number ? from->number : to->number;
135
 
 
136
 
  if (from->csname)
137
 
    if (!(to->csname= my_once_strdup(from->csname,MYF(MY_WME))))
138
 
      goto err;
139
 
  
140
 
  if (from->name)
141
 
    if (!(to->name= my_once_strdup(from->name,MYF(MY_WME))))
142
 
      goto err;
143
 
  
144
 
  if (from->comment)
145
 
    if (!(to->comment= my_once_strdup(from->comment,MYF(MY_WME))))
146
 
      goto err;
147
 
  
148
 
  if (from->ctype)
149
 
  {
150
 
    if (!(to->ctype= (uchar*) my_once_memdup((char*) from->ctype,
151
 
                                             MY_CS_CTYPE_TABLE_SIZE,
152
 
                                             MYF(MY_WME))))
153
 
      goto err;
154
 
    if (init_state_maps(to))
155
 
      goto err;
156
 
  }
157
 
  if (from->to_lower)
158
 
    if (!(to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower,
159
 
                                                MY_CS_TO_LOWER_TABLE_SIZE,
160
 
                                                MYF(MY_WME))))
161
 
      goto err;
162
 
 
163
 
  if (from->to_upper)
164
 
    if (!(to->to_upper= (uchar*) my_once_memdup((char*) from->to_upper,
165
 
                                                MY_CS_TO_UPPER_TABLE_SIZE,
166
 
                                                MYF(MY_WME))))
167
 
      goto err;
168
 
  if (from->sort_order)
169
 
  {
170
 
    if (!(to->sort_order= (uchar*) my_once_memdup((char*) from->sort_order,
171
 
                                                  MY_CS_SORT_ORDER_TABLE_SIZE,
172
 
                                                  MYF(MY_WME))))
173
 
      goto err;
174
 
 
175
 
  }
176
 
  if (from->tab_to_uni)
177
 
  {
178
 
    uint sz= MY_CS_TO_UNI_TABLE_SIZE*sizeof(uint16_t);
179
 
    if (!(to->tab_to_uni= (uint16_t*)  my_once_memdup((char*)from->tab_to_uni,
180
 
                                                    sz, MYF(MY_WME))))
181
 
      goto err;
182
 
  }
183
 
  if (from->tailoring)
184
 
    if (!(to->tailoring= my_once_strdup(from->tailoring,MYF(MY_WME))))
185
 
      goto err;
186
 
 
187
 
  return 0;
188
 
 
189
 
err:
190
 
  return 1;
191
 
}
192
 
 
193
 
 
194
 
 
195
 
static bool simple_cs_is_full(CHARSET_INFO *cs)
196
 
{
197
 
  return ((cs->csname && cs->tab_to_uni && cs->ctype && cs->to_upper &&
198
 
           cs->to_lower) &&
199
 
          (cs->number && cs->name &&
200
 
          (cs->sort_order || (cs->state & MY_CS_BINSORT) )));
201
 
}
202
 
 
203
 
 
204
 
static void
205
 
copy_uca_collation(CHARSET_INFO *to, CHARSET_INFO *from)
206
 
{
207
 
  to->cset= from->cset;
208
 
  to->coll= from->coll;
209
 
  to->strxfrm_multiply= from->strxfrm_multiply;
210
 
  to->min_sort_char= from->min_sort_char;
211
 
  to->max_sort_char= from->max_sort_char;
212
 
  to->mbminlen= from->mbminlen;
213
 
  to->mbmaxlen= from->mbmaxlen;
214
 
}
215
 
 
216
 
 
217
 
static int add_collation(CHARSET_INFO *cs)
218
 
{
219
 
  if (cs->name && (cs->number ||
220
 
                   (cs->number=get_collation_number_internal(cs->name))))
221
 
  {
222
 
    if (!all_charsets[cs->number])
223
 
    {
224
 
      if (!(all_charsets[cs->number]=
225
 
         (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),MYF(0))))
226
 
        return MY_XML_ERROR;
227
 
      memset(all_charsets[cs->number], 0, sizeof(CHARSET_INFO));
228
 
    }
229
 
    
230
 
    if (cs->primary_number == cs->number)
231
 
      cs->state |= MY_CS_PRIMARY;
232
 
      
233
 
    if (cs->binary_number == cs->number)
234
 
      cs->state |= MY_CS_BINSORT;
235
 
    
236
 
    all_charsets[cs->number]->state|= cs->state;
237
 
    
238
 
    if (!(all_charsets[cs->number]->state & MY_CS_COMPILED))
239
 
    {
240
 
      CHARSET_INFO *newcs= all_charsets[cs->number];
241
 
      if (cs_copy_data(all_charsets[cs->number],cs))
242
 
        return MY_XML_ERROR;
243
 
 
244
 
      newcs->levels_for_compare= 1;
245
 
      newcs->levels_for_order= 1;
246
 
      
247
 
      if (!strcmp(cs->csname,"ucs2") )
248
 
      {
249
 
#if defined(HAVE_CHARSET_ucs2) && defined(HAVE_UCA_COLLATIONS)
250
 
        copy_uca_collation(newcs, &my_charset_ucs2_unicode_ci);
251
 
        newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII;
252
 
#endif        
253
 
      }
254
 
      else if (!strcmp(cs->csname, "utf8"))
255
 
      {
256
 
#if defined (HAVE_CHARSET_utf8mb3) && defined(HAVE_UCA_COLLATIONS)
257
 
        copy_uca_collation(newcs, &my_charset_utf8mb4_unicode_ci);
258
 
        newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED;
259
 
#endif
260
 
      }
261
 
      else if (!strcmp(cs->csname, "utf8mb3"))
262
 
      {
263
 
#if defined (HAVE_CHARSET_utf8mb3) && defined(HAVE_UCA_COLLATIONS)
264
 
        copy_uca_collation(newcs, &my_charset_utf8mb3_unicode_ci);
265
 
        newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED;
266
 
#endif
267
 
      }
268
 
      else if (!strcmp(cs->csname, "utf16"))
269
 
      {
270
 
#if defined (HAVE_CHARSET_utf16) && defined(HAVE_UCA_COLLATIONS)
271
 
        copy_uca_collation(newcs, &my_charset_utf16_unicode_ci);
272
 
        newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII;
273
 
#endif
274
 
      }
275
 
      else if (!strcmp(cs->csname, "utf32"))
276
 
      {
277
 
#if defined (HAVE_CHARSET_utf32) && defined(HAVE_UCA_COLLATIONS)
278
 
        copy_uca_collation(newcs, &my_charset_utf32_unicode_ci);
279
 
        newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII;
280
 
#endif
281
 
      }
282
 
      else
283
 
      {
284
 
        uchar *sort_order= all_charsets[cs->number]->sort_order;
285
 
        simple_cs_init_functions(all_charsets[cs->number]);
286
 
        newcs->mbminlen= 1;
287
 
        newcs->mbmaxlen= 1;
288
 
        if (simple_cs_is_full(all_charsets[cs->number]))
289
 
        {
290
 
          all_charsets[cs->number]->state |= MY_CS_LOADED;
291
 
        }
292
 
        all_charsets[cs->number]->state|= MY_CS_AVAILABLE;
293
 
        
294
 
        /*
295
 
          Check if case sensitive sort order: A < a < B.
296
 
          We need MY_CS_FLAG for regex library, and for
297
 
          case sensitivity flag for 5.0 client protocol,
298
 
          to support isCaseSensitive() method in JDBC driver 
299
 
        */
300
 
        if (sort_order && sort_order['A'] < sort_order['a'] &&
301
 
                          sort_order['a'] < sort_order['B'])
302
 
          all_charsets[cs->number]->state|= MY_CS_CSSORT; 
303
 
 
304
 
        if (my_charset_is_8bit_pure_ascii(all_charsets[cs->number]))
305
 
          all_charsets[cs->number]->state|= MY_CS_PUREASCII;
306
 
        if (!my_charset_is_ascii_compatible(cs))
307
 
          all_charsets[cs->number]->state|= MY_CS_NONASCII;
308
 
      }
309
 
    }
310
 
    else
311
 
    {
312
 
      /*
313
 
        We need the below to make get_charset_name()
314
 
        and get_charset_number() working even if a
315
 
        character set has not been really incompiled.
316
 
        The above functions are used for example
317
 
        in error message compiler extra/comp_err.c.
318
 
        If a character set was compiled, this information
319
 
        will get lost and overwritten in add_compiled_collation().
320
 
      */
321
 
      CHARSET_INFO *dst= all_charsets[cs->number];
322
 
      dst->number= cs->number;
323
 
      if (cs->comment)
324
 
        if (!(dst->comment= my_once_strdup(cs->comment,MYF(MY_WME))))
325
 
          return MY_XML_ERROR;
326
 
      if (cs->csname && !dst->csname)
327
 
        if (!(dst->csname= my_once_strdup(cs->csname,MYF(MY_WME))))
328
 
          return MY_XML_ERROR;
329
 
      if (cs->name && !dst->name)
330
 
        if (!(dst->name= my_once_strdup(cs->name,MYF(MY_WME))))
331
 
          return MY_XML_ERROR;
332
 
    }
333
 
    cs->number= 0;
334
 
    cs->primary_number= 0;
335
 
    cs->binary_number= 0;
336
 
    cs->name= NULL;
337
 
    cs->state= 0;
338
 
    cs->sort_order= NULL;
339
 
    cs->state= 0;
340
 
  }
341
 
  return MY_XML_OK;
342
 
}
343
 
 
344
 
 
345
 
#define MY_MAX_ALLOWED_BUF 1024*1024
 
113
  state_map[(unsigned char)'x']= state_map[(unsigned char)'X']= (unsigned char) MY_LEX_IDENT_OR_HEX;
 
114
  state_map[(unsigned char)'b']= state_map[(unsigned char)'B']= (unsigned char) MY_LEX_IDENT_OR_BIN;
 
115
  return 0;
 
116
}
 
117
 
 
118
 
346
119
#define MY_CHARSET_INDEX "Index.xml"
347
120
 
348
121
const char *charsets_dir= NULL;
349
122
static int charset_initialized=0;
350
123
 
351
124
 
352
 
static bool my_read_charset_file(const char *filename, myf myflags)
353
 
{
354
 
  uchar *buf;
355
 
  int  fd;
356
 
  uint len, tmp_len;
357
 
  struct stat stat_info;
358
 
  
359
 
  if (stat(filename, &stat_info) ||
360
 
       ((len= (uint)stat_info.st_size) > MY_MAX_ALLOWED_BUF) ||
361
 
       !(buf= (uchar*) my_malloc(len,myflags)))
362
 
    return true;
363
 
  
364
 
  if ((fd=my_open(filename,O_RDONLY,myflags)) < 0)
365
 
    goto error;
366
 
  tmp_len=my_read(fd, buf, len, myflags);
367
 
  my_close(fd,myflags);
368
 
  if (tmp_len != len)
369
 
    goto error;
370
 
  
371
 
  if (my_parse_charset_xml((char*) buf,len,add_collation))
372
 
  {
373
 
#ifdef NOT_YET
374
 
    printf("ERROR at line %d pos %d '%s'\n",
375
 
           my_xml_error_lineno(&p)+1,
376
 
           my_xml_error_pos(&p),
377
 
           my_xml_error_string(&p));
378
 
#endif
379
 
  }
380
 
  
381
 
  my_free(buf, myflags);
382
 
  return false;
383
 
 
384
 
error:
385
 
  my_free(buf, myflags);
386
 
  return true;
387
 
}
388
 
 
389
 
 
390
125
char *get_charsets_dir(char *buf)
391
126
{
392
 
  const char *sharedir= SHAREDIR;
393
127
  char *res;
394
128
 
395
129
  if (charsets_dir != NULL)
396
 
    strmake(buf, charsets_dir, FN_REFLEN-1);
 
130
    strncpy(buf, charsets_dir, FN_REFLEN-1);
397
131
  else
398
132
  {
399
 
    if (test_if_hard_path(sharedir) ||
400
 
        is_prefix(sharedir, DEFAULT_CHARSET_HOME))
401
 
      strxmov(buf, sharedir, "/", CHARSET_DIR, NullS);
 
133
    if (test_if_hard_path(PKGDATADIR) ||
 
134
        is_prefix(PKGDATADIR, PREFIX))
 
135
      sprintf(buf,"%s/%s",PKGDATADIR,CHARSET_DIR);
402
136
    else
403
 
      strxmov(buf, DEFAULT_CHARSET_HOME, "/", sharedir, "/", CHARSET_DIR,
404
 
              NullS);
 
137
      sprintf(buf,"%s/%s/%s",PREFIX,PKGDATADIR,CHARSET_DIR);
405
138
  }
406
 
  res= convert_dirname(buf,buf,NullS);
 
139
  res= convert_dirname(buf,buf,NULL);
407
140
  return(res);
408
141
}
409
142
 
410
143
CHARSET_INFO *all_charsets[256];
411
 
const CHARSET_INFO *default_charset_info = &my_charset_latin1;
 
144
const CHARSET_INFO *default_charset_info = &my_charset_utf8_general_ci;
412
145
 
413
146
void add_compiled_collation(CHARSET_INFO * cs)
414
147
{
416
149
  cs->state|= MY_CS_AVAILABLE;
417
150
}
418
151
 
419
 
static void *cs_alloc(size_t size)
 
152
void *cs_alloc(size_t size)
420
153
{
421
 
  return my_once_alloc(size, MYF(MY_WME));
 
154
  return malloc(size);
422
155
}
423
156
 
424
157
 
442
175
    {
443
176
      memset(&all_charsets, 0, sizeof(all_charsets));
444
177
      init_compiled_charsets(myflags);
445
 
      
 
178
 
446
179
      /* Copy compiled charsets */
447
180
      for (cs=all_charsets;
448
181
           cs < all_charsets+array_elements(all_charsets)-1 ;
455
188
              *cs= NULL;
456
189
        }
457
190
      }
458
 
      
459
 
      stpcpy(get_charsets_dir(fname), MY_CHARSET_INDEX);
460
 
      error= my_read_charset_file(fname,myflags);
 
191
 
 
192
      strcpy(get_charsets_dir(fname), MY_CHARSET_INDEX);
461
193
      charset_initialized=1;
462
194
    }
463
195
    pthread_mutex_unlock(&THR_LOCK_charset);
472
204
}
473
205
 
474
206
 
475
 
uint get_collation_number(const char *name)
 
207
uint32_t get_collation_number(const char *name)
476
208
{
477
209
  init_available_charsets(MYF(0));
478
210
  return get_collation_number_internal(name);
479
211
}
480
212
 
481
213
 
482
 
uint get_charset_number(const char *charset_name, uint cs_flags)
 
214
uint32_t get_charset_number(const char *charset_name, uint32_t cs_flags)
483
215
{
484
216
  CHARSET_INFO **cs;
485
217
  init_available_charsets(MYF(0));
486
 
  
 
218
 
487
219
  for (cs= all_charsets;
488
220
       cs < all_charsets+array_elements(all_charsets)-1 ;
489
221
       cs++)
490
222
  {
491
223
    if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) &&
492
 
         !my_strcasecmp(&my_charset_latin1, cs[0]->csname, charset_name))
 
224
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->csname, charset_name))
493
225
      return cs[0]->number;
494
 
  }  
 
226
  }
495
227
  return 0;
496
228
}
497
229
 
498
230
 
499
 
const char *get_charset_name(uint charset_number)
 
231
const char *get_charset_name(uint32_t charset_number)
500
232
{
501
233
  const CHARSET_INFO *cs;
502
234
  init_available_charsets(MYF(0));
504
236
  cs=all_charsets[charset_number];
505
237
  if (cs && (cs->number == charset_number) && cs->name )
506
238
    return (char*) cs->name;
507
 
  
 
239
 
508
240
  return (char*) "?";   /* this mimics find_type() */
509
241
}
510
242
 
511
243
 
512
 
static const CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
 
244
static const CHARSET_INFO *get_internal_charset(uint32_t cs_number)
513
245
{
514
 
  char  buf[FN_REFLEN];
515
246
  CHARSET_INFO *cs;
516
247
  /*
517
248
    To make things thread safe we are not allowing other threads to interfere
522
253
  {
523
254
    if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED))
524
255
    {
525
 
      strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS);
526
 
      my_read_charset_file(buf,flags);
 
256
      assert(0);
527
257
    }
528
258
    cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
529
259
  }
540
270
}
541
271
 
542
272
 
543
 
const const CHARSET_INFO *get_charset(uint cs_number, myf flags)
 
273
const CHARSET_INFO *get_charset(uint32_t cs_number, myf flags)
544
274
{
545
275
  const CHARSET_INFO *cs;
546
276
  if (cs_number == default_charset_info->number)
547
277
    return default_charset_info;
548
278
 
549
279
  (void) init_available_charsets(MYF(0));       /* If it isn't initialized */
550
 
  
 
280
 
551
281
  if (!cs_number || cs_number >= array_elements(all_charsets)-1)
552
282
    return NULL;
553
 
  
554
 
  cs=get_internal_charset(cs_number, flags);
 
283
 
 
284
  cs= get_internal_charset(cs_number);
555
285
 
556
286
  if (!cs && (flags & MY_WME))
557
287
  {
558
288
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)], cs_string[23];
559
 
    stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
 
289
    strcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
560
290
    cs_string[0]='#';
561
291
    int10_to_str(cs_number, cs_string+1, 10);
562
292
    my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_string, index_file);
566
296
 
567
297
const CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
568
298
{
569
 
  uint cs_number;
 
299
  uint32_t cs_number;
570
300
  const CHARSET_INFO *cs;
571
301
  (void) init_available_charsets(MYF(0));       /* If it isn't initialized */
572
302
 
573
303
  cs_number=get_collation_number(cs_name);
574
 
  cs= cs_number ? get_internal_charset(cs_number,flags) : NULL;
 
304
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
575
305
 
576
306
  if (!cs && (flags & MY_WME))
577
307
  {
578
308
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
579
 
    stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
 
309
    strcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
580
310
    my_error(EE_UNKNOWN_COLLATION, MYF(ME_BELL), cs_name, index_file);
581
311
  }
582
312
 
585
315
 
586
316
 
587
317
const CHARSET_INFO *get_charset_by_csname(const char *cs_name,
588
 
                                    uint cs_flags,
 
318
                                    uint32_t cs_flags,
589
319
                                    myf flags)
590
320
{
591
 
  uint cs_number;
 
321
  uint32_t cs_number;
592
322
  const CHARSET_INFO *cs;
593
323
 
594
324
  (void) init_available_charsets(MYF(0));       /* If it isn't initialized */
595
325
 
596
326
  cs_number= get_charset_number(cs_name, cs_flags);
597
 
  cs= cs_number ? get_internal_charset(cs_number, flags) : NULL;
 
327
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
598
328
 
599
329
  if (!cs && (flags & MY_WME))
600
330
  {
601
331
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
602
 
    stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
 
332
    strcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
603
333
    my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file);
604
334
  }
605
335
 
671
401
}
672
402
 
673
403
 
674
 
/*
675
 
  Escape string with backslashes (\)
676
 
 
677
 
  SYNOPSIS
678
 
    escape_string_for_drizzle()
679
 
    charset_info        Charset of the strings
680
 
    to                  Buffer for escaped string
681
 
    to_length           Length of destination buffer, or 0
682
 
    from                The string to escape
683
 
    length              The length of the string to escape
684
 
 
685
 
  DESCRIPTION
686
 
    This escapes the contents of a string by adding backslashes before special
687
 
    characters, and turning others into specific escape sequences, such as
688
 
    turning newlines into \n and null bytes into \0.
689
 
 
690
 
  NOTE
691
 
    To maintain compatibility with the old C API, to_length may be 0 to mean
692
 
    "big enough"
693
 
 
694
 
  RETURN VALUES
695
 
    (size_t) -1 The escaped string did not fit in the to buffer
696
 
    #           The length of the escaped string
697
 
*/
698
 
 
699
 
size_t escape_string_for_drizzle(const CHARSET_INFO *charset_info,
700
 
                                 char *to, size_t to_length,
701
 
                                 const char *from, size_t length)
702
 
{
703
 
  const char *to_start= to;
704
 
  const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
705
 
  bool overflow= false;
706
 
#ifdef USE_MB
707
 
  bool use_mb_flag= use_mb(charset_info);
708
 
#endif
709
 
  for (end= from + length; from < end; from++)
710
 
  {
711
 
    char escape= 0;
712
 
#ifdef USE_MB
713
 
    int tmp_length;
714
 
    if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
715
 
    {
716
 
      if (to + tmp_length > to_end)
717
 
      {
718
 
        overflow= true;
719
 
        break;
720
 
      }
721
 
      while (tmp_length--)
722
 
        *to++= *from++;
723
 
      from--;
724
 
      continue;
725
 
    }
726
 
    /*
727
 
     If the next character appears to begin a multi-byte character, we
728
 
     escape that first byte of that apparent multi-byte character. (The
729
 
     character just looks like a multi-byte character -- if it were actually
730
 
     a multi-byte character, it would have been passed through in the test
731
 
     above.)
732
 
 
733
 
     Without this check, we can create a problem by converting an invalid
734
 
     multi-byte character into a valid one. For example, 0xbf27 is not
735
 
     a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \)
736
 
    */
737
 
    if (use_mb_flag && (tmp_length= my_mbcharlen(charset_info, *from)) > 1)
738
 
      escape= *from;
739
 
    else
740
 
#endif
741
 
    switch (*from) {
742
 
    case 0:                             /* Must be escaped for 'mysql' */
743
 
      escape= '0';
744
 
      break;
745
 
    case '\n':                          /* Must be escaped for logs */
746
 
      escape= 'n';
747
 
      break;
748
 
    case '\r':
749
 
      escape= 'r';
750
 
      break;
751
 
    case '\\':
752
 
      escape= '\\';
753
 
      break;
754
 
    case '\'':
755
 
      escape= '\'';
756
 
      break;
757
 
    case '"':                           /* Better safe than sorry */
758
 
      escape= '"';
759
 
      break;
760
 
    case '\032':                        /* This gives problems on Win32 */
761
 
      escape= 'Z';
762
 
      break;
763
 
    }
764
 
    if (escape)
765
 
    {
766
 
      if (to + 2 > to_end)
767
 
      {
768
 
        overflow= true;
769
 
        break;
770
 
      }
771
 
      *to++= '\\';
772
 
      *to++= escape;
773
 
    }
774
 
    else
775
 
    {
776
 
      if (to + 1 > to_end)
777
 
      {
778
 
        overflow= true;
779
 
        break;
780
 
      }
781
 
      *to++= *from;
782
 
    }
783
 
  }
784
 
  *to= 0;
785
 
  return overflow ? (size_t) -1 : (size_t) (to - to_start);
786
 
}
787
 
 
788
 
 
789
404
#ifdef BACKSLASH_MBTAIL
790
405
static CHARSET_INFO *fs_cset_cache= NULL;
791
406
 
832
447
    mean "big enough"
833
448
 
834
449
  RETURN VALUES
835
 
    ~0          The escaped string did not fit in the to buffer
 
450
    UINT32_MAX  The escaped string did not fit in the to buffer
836
451
    >=0         The length of the escaped string
837
452
*/
838
453
 
889
504
    }
890
505
  }
891
506
  *to= 0;
892
 
  return overflow ? (uint32_t)~0 : (uint32_t) (to - to_start);
 
507
  return overflow ? UINT32_MAX : (uint32_t) (to - to_start);
893
508
}