~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/charset.c

  • Committer: Monty Taylor
  • Date: 2008-08-04 19:37:18 UTC
  • mto: (261.2.2 codestyle)
  • mto: This revision was merged to the branch mainline in revision 262.
  • Revision ID: monty@inaugust.com-20080804193718-f0rz13uli4429ozb
Changed gettext_noop() to N_()

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
#include <mystrings/m_ctype.h>
19
19
#include <mystrings/m_string.h>
20
20
#include <my_dir.h>
 
21
#include <mystrings/my_xml.h>
21
22
 
22
23
 
23
24
/*
45
46
       cs++)
46
47
  {
47
48
    if ( cs[0] && cs[0]->name && 
48
 
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->name, name))
 
49
         !my_strcasecmp(&my_charset_latin1, cs[0]->name, name))
49
50
      return cs[0]->number;
50
51
  }  
51
52
  return 0;
54
55
 
55
56
static bool init_state_maps(CHARSET_INFO *cs)
56
57
{
57
 
  uint32_t i;
58
 
  unsigned char *state_map;
59
 
  unsigned char *ident_map;
 
58
  uint i;
 
59
  uchar *state_map;
 
60
  uchar *ident_map;
60
61
 
61
 
  if (!(cs->state_map= (unsigned char*) my_once_alloc(256, MYF(MY_WME))))
 
62
  if (!(cs->state_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
62
63
    return 1;
63
64
    
64
 
  if (!(cs->ident_map= (unsigned char*) my_once_alloc(256, MYF(MY_WME))))
 
65
  if (!(cs->ident_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
65
66
    return 1;
66
67
 
67
68
  state_map= cs->state_map;
71
72
  for (i=0; i < 256 ; i++)
72
73
  {
73
74
    if (my_isalpha(cs,i))
74
 
      state_map[i]=(unsigned char) MY_LEX_IDENT;
 
75
      state_map[i]=(uchar) MY_LEX_IDENT;
75
76
    else if (my_isdigit(cs,i))
76
 
      state_map[i]=(unsigned char) MY_LEX_NUMBER_IDENT;
 
77
      state_map[i]=(uchar) MY_LEX_NUMBER_IDENT;
77
78
#if defined(USE_MB) && defined(USE_MB_IDENT)
78
79
    else if (my_mbcharlen(cs, i)>1)
79
 
      state_map[i]=(unsigned char) MY_LEX_IDENT;
 
80
      state_map[i]=(uchar) MY_LEX_IDENT;
80
81
#endif
81
82
    else if (my_isspace(cs,i))
82
 
      state_map[i]=(unsigned char) MY_LEX_SKIP;
 
83
      state_map[i]=(uchar) MY_LEX_SKIP;
83
84
    else
84
 
      state_map[i]=(unsigned char) MY_LEX_CHAR;
 
85
      state_map[i]=(uchar) MY_LEX_CHAR;
85
86
  }
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;
 
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;
102
103
 
103
104
  /*
104
105
    Create a second map to make it faster to find identifiers
105
106
  */
106
107
  for (i=0; i < 256 ; i++)
107
108
  {
108
 
    ident_map[i]= (unsigned char) (state_map[i] == MY_LEX_IDENT ||
 
109
    ident_map[i]= (uchar) (state_map[i] == MY_LEX_IDENT ||
109
110
                           state_map[i] == MY_LEX_NUMBER_IDENT);
110
111
  }
111
112
 
112
113
  /* Special handling of hex and binary strings */
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
 
 
 
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((void*)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
119
346
#define MY_CHARSET_INDEX "Index.xml"
120
347
 
121
348
const char *charsets_dir= NULL;
122
349
static int charset_initialized=0;
123
350
 
124
351
 
 
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
 
125
390
char *get_charsets_dir(char *buf)
126
391
{
127
392
  const char *sharedir= SHAREDIR;
133
398
  {
134
399
    if (test_if_hard_path(sharedir) ||
135
400
        is_prefix(sharedir, DEFAULT_CHARSET_HOME))
136
 
      strxmov(buf, sharedir, "/", CHARSET_DIR, NULL);
 
401
      strxmov(buf, sharedir, "/", CHARSET_DIR, NullS);
137
402
    else
138
403
      strxmov(buf, DEFAULT_CHARSET_HOME, "/", sharedir, "/", CHARSET_DIR,
139
 
              NULL);
 
404
              NullS);
140
405
  }
141
 
  res= convert_dirname(buf,buf,NULL);
 
406
  res= convert_dirname(buf,buf,NullS);
142
407
  return(res);
143
408
}
144
409
 
145
410
CHARSET_INFO *all_charsets[256];
146
 
const CHARSET_INFO *default_charset_info = &my_charset_utf8_general_ci;
 
411
CHARSET_INFO *default_charset_info = &my_charset_latin1;
147
412
 
148
 
void add_compiled_collation(CHARSET_INFO * cs)
 
413
void add_compiled_collation(CHARSET_INFO *cs)
149
414
{
150
415
  all_charsets[cs->number]= cs;
151
416
  cs->state|= MY_CS_AVAILABLE;
191
456
        }
192
457
      }
193
458
      
194
 
      my_stpcpy(get_charsets_dir(fname), MY_CHARSET_INDEX);
 
459
      strmov(get_charsets_dir(fname), MY_CHARSET_INDEX);
 
460
      error= my_read_charset_file(fname,myflags);
195
461
      charset_initialized=1;
196
462
    }
197
463
    pthread_mutex_unlock(&THR_LOCK_charset);
206
472
}
207
473
 
208
474
 
209
 
uint32_t get_collation_number(const char *name)
 
475
uint get_collation_number(const char *name)
210
476
{
211
477
  init_available_charsets(MYF(0));
212
478
  return get_collation_number_internal(name);
213
479
}
214
480
 
215
481
 
216
 
uint32_t get_charset_number(const char *charset_name, uint32_t cs_flags)
 
482
uint get_charset_number(const char *charset_name, uint cs_flags)
217
483
{
218
484
  CHARSET_INFO **cs;
219
485
  init_available_charsets(MYF(0));
223
489
       cs++)
224
490
  {
225
491
    if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) &&
226
 
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->csname, charset_name))
 
492
         !my_strcasecmp(&my_charset_latin1, cs[0]->csname, charset_name))
227
493
      return cs[0]->number;
228
494
  }  
229
495
  return 0;
230
496
}
231
497
 
232
498
 
233
 
const char *get_charset_name(uint32_t charset_number)
 
499
const char *get_charset_name(uint charset_number)
234
500
{
235
 
  const CHARSET_INFO *cs;
 
501
  CHARSET_INFO *cs;
236
502
  init_available_charsets(MYF(0));
237
503
 
238
504
  cs=all_charsets[charset_number];
243
509
}
244
510
 
245
511
 
246
 
static const CHARSET_INFO *get_internal_charset(uint32_t cs_number)
 
512
static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
247
513
{
 
514
  char  buf[FN_REFLEN];
248
515
  CHARSET_INFO *cs;
249
516
  /*
250
517
    To make things thread safe we are not allowing other threads to interfere
255
522
  {
256
523
    if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED))
257
524
    {
258
 
      assert(0);
 
525
      strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS);
 
526
      my_read_charset_file(buf,flags);
259
527
    }
260
528
    cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
261
529
  }
272
540
}
273
541
 
274
542
 
275
 
const CHARSET_INFO *get_charset(uint32_t cs_number, myf flags)
 
543
CHARSET_INFO *get_charset(uint cs_number, myf flags)
276
544
{
277
 
  const CHARSET_INFO *cs;
 
545
  CHARSET_INFO *cs;
278
546
  if (cs_number == default_charset_info->number)
279
547
    return default_charset_info;
280
548
 
283
551
  if (!cs_number || cs_number >= array_elements(all_charsets)-1)
284
552
    return NULL;
285
553
  
286
 
  cs= get_internal_charset(cs_number);
 
554
  cs=get_internal_charset(cs_number, flags);
287
555
 
288
556
  if (!cs && (flags & MY_WME))
289
557
  {
290
558
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)], cs_string[23];
291
 
    my_stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
 
559
    strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX);
292
560
    cs_string[0]='#';
293
561
    int10_to_str(cs_number, cs_string+1, 10);
294
562
    my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_string, index_file);
296
564
  return cs;
297
565
}
298
566
 
299
 
const CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
 
567
CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
300
568
{
301
 
  uint32_t cs_number;
302
 
  const CHARSET_INFO *cs;
 
569
  uint cs_number;
 
570
  CHARSET_INFO *cs;
303
571
  (void) init_available_charsets(MYF(0));       /* If it isn't initialized */
304
572
 
305
573
  cs_number=get_collation_number(cs_name);
306
 
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
 
574
  cs= cs_number ? get_internal_charset(cs_number,flags) : NULL;
307
575
 
308
576
  if (!cs && (flags & MY_WME))
309
577
  {
310
578
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
311
 
    my_stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
 
579
    strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX);
312
580
    my_error(EE_UNKNOWN_COLLATION, MYF(ME_BELL), cs_name, index_file);
313
581
  }
314
582
 
316
584
}
317
585
 
318
586
 
319
 
const CHARSET_INFO *get_charset_by_csname(const char *cs_name,
320
 
                                    uint32_t cs_flags,
 
587
CHARSET_INFO *get_charset_by_csname(const char *cs_name,
 
588
                                    uint cs_flags,
321
589
                                    myf flags)
322
590
{
323
 
  uint32_t cs_number;
324
 
  const CHARSET_INFO *cs;
 
591
  uint cs_number;
 
592
  CHARSET_INFO *cs;
325
593
 
326
594
  (void) init_available_charsets(MYF(0));       /* If it isn't initialized */
327
595
 
328
596
  cs_number= get_charset_number(cs_name, cs_flags);
329
 
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
 
597
  cs= cs_number ? get_internal_charset(cs_number, flags) : NULL;
330
598
 
331
599
  if (!cs && (flags & MY_WME))
332
600
  {
333
601
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
334
 
    my_stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
 
602
    strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX);
335
603
    my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file);
336
604
  }
337
605
 
356
624
*/
357
625
 
358
626
bool resolve_charset(const char *cs_name,
359
 
                     const CHARSET_INFO *default_cs,
360
 
                     const CHARSET_INFO **cs)
 
627
                        CHARSET_INFO *default_cs,
 
628
                        CHARSET_INFO **cs)
361
629
{
362
630
  *cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0));
363
631
 
388
656
*/
389
657
 
390
658
bool resolve_collation(const char *cl_name,
391
 
                       const CHARSET_INFO *default_cl,
392
 
                       const CHARSET_INFO **cl)
 
659
                          CHARSET_INFO *default_cl,
 
660
                          CHARSET_INFO **cl)
393
661
{
394
662
  *cl= get_charset_by_name(cl_name, MYF(0));
395
663
 
403
671
}
404
672
 
405
673
 
 
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
 
406
789
#ifdef BACKSLASH_MBTAIL
407
790
static CHARSET_INFO *fs_cset_cache= NULL;
408
791
 
449
832
    mean "big enough"
450
833
 
451
834
  RETURN VALUES
452
 
    UINT32_MAX  The escaped string did not fit in the to buffer
 
835
    ~0          The escaped string did not fit in the to buffer
453
836
    >=0         The length of the escaped string
454
837
*/
455
838
 
506
889
    }
507
890
  }
508
891
  *to= 0;
509
 
  return overflow ? UINT32_MAX : (uint32_t) (to - to_start);
 
892
  return overflow ? (ulong)~0 : (ulong) (to - to_start);
510
893
}