~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/charset.c

  • Committer: Monty Taylor
  • Date: 2008-09-13 20:24:20 UTC
  • mfrom: (383.1.35 drizzle)
  • Revision ID: monty@inaugust.com-20080913202420-lkj76ewbabl8ljvp
MergedĀ fromĀ trunk.

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>
22
21
 
23
22
 
24
23
/*
46
45
       cs++)
47
46
  {
48
47
    if ( cs[0] && cs[0]->name && 
49
 
         !my_strcasecmp(&my_charset_latin1, cs[0]->name, 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;
117
116
}
118
117
 
119
118
 
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
119
#define MY_MAX_ALLOWED_BUF 1024*1024
346
120
#define MY_CHARSET_INDEX "Index.xml"
347
121
 
349
123
static int charset_initialized=0;
350
124
 
351
125
 
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
126
char *get_charsets_dir(char *buf)
391
127
{
392
128
  const char *sharedir= SHAREDIR;
408
144
}
409
145
 
410
146
CHARSET_INFO *all_charsets[256];
411
 
const CHARSET_INFO *default_charset_info = &my_charset_latin1;
 
147
const CHARSET_INFO *default_charset_info = &my_charset_utf8_general_ci;
412
148
 
413
149
void add_compiled_collation(CHARSET_INFO * cs)
414
150
{
457
193
      }
458
194
      
459
195
      stpcpy(get_charsets_dir(fname), MY_CHARSET_INDEX);
460
 
      error= my_read_charset_file(fname,myflags);
461
196
      charset_initialized=1;
462
197
    }
463
198
    pthread_mutex_unlock(&THR_LOCK_charset);
489
224
       cs++)
490
225
  {
491
226
    if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) &&
492
 
         !my_strcasecmp(&my_charset_latin1, cs[0]->csname, charset_name))
 
227
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->csname, charset_name))
493
228
      return cs[0]->number;
494
229
  }  
495
230
  return 0;
509
244
}
510
245
 
511
246
 
512
 
static const CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
 
247
static const CHARSET_INFO *get_internal_charset(uint cs_number)
513
248
{
514
 
  char  buf[FN_REFLEN];
515
249
  CHARSET_INFO *cs;
516
250
  /*
517
251
    To make things thread safe we are not allowing other threads to interfere
522
256
  {
523
257
    if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED))
524
258
    {
525
 
      strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS);
526
 
      my_read_charset_file(buf,flags);
 
259
      assert(0);
527
260
    }
528
261
    cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
529
262
  }
551
284
  if (!cs_number || cs_number >= array_elements(all_charsets)-1)
552
285
    return NULL;
553
286
  
554
 
  cs=get_internal_charset(cs_number, flags);
 
287
  cs= get_internal_charset(cs_number);
555
288
 
556
289
  if (!cs && (flags & MY_WME))
557
290
  {
571
304
  (void) init_available_charsets(MYF(0));       /* If it isn't initialized */
572
305
 
573
306
  cs_number=get_collation_number(cs_name);
574
 
  cs= cs_number ? get_internal_charset(cs_number,flags) : NULL;
 
307
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
575
308
 
576
309
  if (!cs && (flags & MY_WME))
577
310
  {
594
327
  (void) init_available_charsets(MYF(0));       /* If it isn't initialized */
595
328
 
596
329
  cs_number= get_charset_number(cs_name, cs_flags);
597
 
  cs= cs_number ? get_internal_charset(cs_number, flags) : NULL;
 
330
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
598
331
 
599
332
  if (!cs && (flags & MY_WME))
600
333
  {