~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/charset.cc

  • Committer: Eric Day
  • Date: 2009-08-27 07:26:22 UTC
  • mto: This revision was merged to the branch mainline in revision 1131.
  • Revision ID: eday@oddments.org-20090827072622-72te13ua0wdlc2ky
Reworked listen interface to not require binding of TCP ports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
   along with this program; if not, write to the Free Software
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
 
#include "mysys_priv.h"
17
 
#include "mysys_err.h"
 
16
#include "mysys/mysys_priv.h"
 
17
#include "mysys/mysys_err.h"
18
18
#include <mystrings/m_ctype.h>
19
19
#include <mystrings/m_string.h>
20
 
#include <my_dir.h>
21
 
 
 
20
#include <drizzled/configmake.h>
 
21
#include <vector>
 
22
 
 
23
using namespace std;
 
24
 
 
25
 
 
26
/*
 
27
  We collect memory in this vector that we free on delete.
 
28
*/
 
29
static vector<void *>memory_vector;
22
30
 
23
31
/*
24
32
  The code below implements this functionality:
25
 
  
 
33
 
26
34
    - Initializing charset related structures
27
35
    - Loading dynamic charsets
28
 
    - Searching for a proper CHARSET_INFO 
 
36
    - Searching for a proper CHARSET_INFO
29
37
      using charset name, collation name or collation ID
30
38
    - Setting server default character set
31
39
*/
44
52
       cs < all_charsets+array_elements(all_charsets)-1 ;
45
53
       cs++)
46
54
  {
47
 
    if ( cs[0] && cs[0]->name && 
 
55
    if ( cs[0] && cs[0]->name &&
48
56
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->name, name))
49
57
      return cs[0]->number;
50
 
  }  
 
58
  }
51
59
  return 0;
52
60
}
53
61
 
58
66
  unsigned char *state_map;
59
67
  unsigned char *ident_map;
60
68
 
61
 
  if (!(cs->state_map= (unsigned char*) my_once_alloc(256, MYF(MY_WME))))
 
69
  if (!(cs->state_map= (unsigned char*) cs_alloc(256)))
62
70
    return 1;
63
71
    
64
 
  if (!(cs->ident_map= (unsigned char*) my_once_alloc(256, MYF(MY_WME))))
 
72
  if (!(cs->ident_map= (unsigned char*) cs_alloc(256)))
65
73
    return 1;
66
74
 
67
75
  state_map= cs->state_map;
68
76
  ident_map= cs->ident_map;
69
 
  
 
77
 
70
78
  /* Fill state_map with states to get a faster parser */
71
79
  for (i=0; i < 256 ; i++)
72
80
  {
74
82
      state_map[i]=(unsigned char) MY_LEX_IDENT;
75
83
    else if (my_isdigit(cs,i))
76
84
      state_map[i]=(unsigned char) MY_LEX_NUMBER_IDENT;
77
 
#if defined(USE_MB) && defined(USE_MB_IDENT)
78
85
    else if (my_mbcharlen(cs, i)>1)
79
86
      state_map[i]=(unsigned char) MY_LEX_IDENT;
80
 
#endif
81
87
    else if (my_isspace(cs,i))
82
88
      state_map[i]=(unsigned char) MY_LEX_SKIP;
83
89
    else
116
122
}
117
123
 
118
124
 
119
 
#define MY_MAX_ALLOWED_BUF 1024*1024
120
 
#define MY_CHARSET_INDEX "Index.xml"
121
 
 
122
 
const char *charsets_dir= NULL;
123
 
static int charset_initialized=0;
124
 
 
125
 
 
126
 
char *get_charsets_dir(char *buf)
127
 
{
128
 
  const char *sharedir= SHAREDIR;
129
 
  char *res;
130
 
 
131
 
  if (charsets_dir != NULL)
132
 
    strmake(buf, charsets_dir, FN_REFLEN-1);
133
 
  else
134
 
  {
135
 
    if (test_if_hard_path(sharedir) ||
136
 
        is_prefix(sharedir, DEFAULT_CHARSET_HOME))
137
 
      strxmov(buf, sharedir, "/", CHARSET_DIR, NULL);
138
 
    else
139
 
      strxmov(buf, DEFAULT_CHARSET_HOME, "/", sharedir, "/", CHARSET_DIR,
140
 
              NULL);
141
 
  }
142
 
  res= convert_dirname(buf,buf,NULL);
143
 
  return(res);
144
 
}
 
125
static bool charset_initialized= false;
145
126
 
146
127
CHARSET_INFO *all_charsets[256];
147
128
const CHARSET_INFO *default_charset_info = &my_charset_utf8_general_ci;
152
133
  cs->state|= MY_CS_AVAILABLE;
153
134
}
154
135
 
155
 
static void *cs_alloc(size_t size)
 
136
void *cs_alloc(size_t size)
156
137
{
157
 
  return my_once_alloc(size, MYF(MY_WME));
 
138
  void *ptr= malloc(size);
 
139
 
 
140
  memory_vector.push_back(ptr);
 
141
 
 
142
  return ptr;
158
143
}
159
144
 
160
145
 
161
146
static bool init_available_charsets(myf myflags)
162
147
{
163
 
  char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
164
 
  bool error=false;
 
148
  bool error= false;
165
149
  /*
166
150
    We have to use charset_initialized to not lock on THR_LOCK_charset
167
151
    inside get_internal_charset...
168
152
  */
169
 
  if (!charset_initialized)
 
153
  if (charset_initialized == false)
170
154
  {
171
155
    CHARSET_INFO **cs;
172
 
    /*
173
 
      To make things thread safe we are not allowing other threads to interfere
174
 
      while we may changing the cs_info_table
175
 
    */
176
 
    pthread_mutex_lock(&THR_LOCK_charset);
177
 
    if (!charset_initialized)
 
156
    memset(&all_charsets, 0, sizeof(all_charsets));
 
157
    init_compiled_charsets(myflags);
 
158
 
 
159
    /* Copy compiled charsets */
 
160
    for (cs=all_charsets;
 
161
         cs < all_charsets+array_elements(all_charsets)-1 ;
 
162
         cs++)
178
163
    {
179
 
      memset(&all_charsets, 0, sizeof(all_charsets));
180
 
      init_compiled_charsets(myflags);
181
 
      
182
 
      /* Copy compiled charsets */
183
 
      for (cs=all_charsets;
184
 
           cs < all_charsets+array_elements(all_charsets)-1 ;
185
 
           cs++)
 
164
      if (*cs)
186
165
      {
187
 
        if (*cs)
188
 
        {
189
 
          if (cs[0]->ctype)
190
 
            if (init_state_maps(*cs))
191
 
              *cs= NULL;
192
 
        }
 
166
        if (cs[0]->ctype)
 
167
          if (init_state_maps(*cs))
 
168
            *cs= NULL;
193
169
      }
194
 
      
195
 
      my_stpcpy(get_charsets_dir(fname), MY_CHARSET_INDEX);
196
 
      charset_initialized=1;
197
170
    }
198
 
    pthread_mutex_unlock(&THR_LOCK_charset);
 
171
 
 
172
    charset_initialized= true;
199
173
  }
 
174
  assert(charset_initialized);
 
175
 
200
176
  return error;
201
177
}
202
178
 
203
179
 
204
180
void free_charsets(void)
205
181
{
206
 
  charset_initialized=0;
 
182
  charset_initialized= true;
 
183
 
 
184
  while (memory_vector.empty() == false)
 
185
  {
 
186
    void *ptr= memory_vector.back();
 
187
    memory_vector.pop_back();
 
188
    free(ptr);
 
189
  }
 
190
  memory_vector.clear();
 
191
 
207
192
}
208
193
 
209
194
 
218
203
{
219
204
  CHARSET_INFO **cs;
220
205
  init_available_charsets(MYF(0));
221
 
  
 
206
 
222
207
  for (cs= all_charsets;
223
208
       cs < all_charsets+array_elements(all_charsets)-1 ;
224
209
       cs++)
226
211
    if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) &&
227
212
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->csname, charset_name))
228
213
      return cs[0]->number;
229
 
  }  
 
214
  }
230
215
  return 0;
231
216
}
232
217
 
239
224
  cs=all_charsets[charset_number];
240
225
  if (cs && (cs->number == charset_number) && cs->name )
241
226
    return (char*) cs->name;
242
 
  
 
227
 
243
228
  return (char*) "?";   /* this mimics find_type() */
244
229
}
245
230
 
251
236
    To make things thread safe we are not allowing other threads to interfere
252
237
    while we may changing the cs_info_table
253
238
  */
254
 
  pthread_mutex_lock(&THR_LOCK_charset);
255
239
  if ((cs= all_charsets[cs_number]))
256
240
  {
257
241
    if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED))
268
252
    else
269
253
      cs->state|= MY_CS_READY;
270
254
  }
271
 
  pthread_mutex_unlock(&THR_LOCK_charset);
 
255
 
272
256
  return cs;
273
257
}
274
258
 
275
259
 
276
 
const const CHARSET_INFO *get_charset(uint32_t cs_number, myf flags)
 
260
const CHARSET_INFO *get_charset(uint32_t cs_number)
277
261
{
278
262
  const CHARSET_INFO *cs;
279
263
  if (cs_number == default_charset_info->number)
280
264
    return default_charset_info;
281
265
 
282
266
  (void) init_available_charsets(MYF(0));       /* If it isn't initialized */
283
 
  
 
267
 
284
268
  if (!cs_number || cs_number >= array_elements(all_charsets)-1)
285
269
    return NULL;
286
 
  
 
270
 
287
271
  cs= get_internal_charset(cs_number);
288
272
 
289
 
  if (!cs && (flags & MY_WME))
290
 
  {
291
 
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)], cs_string[23];
292
 
    my_stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
293
 
    cs_string[0]='#';
294
 
    int10_to_str(cs_number, cs_string+1, 10);
295
 
    my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_string, index_file);
296
 
  }
297
273
  return cs;
298
274
}
299
275
 
300
 
const CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
 
276
const CHARSET_INFO *get_charset_by_name(const char *cs_name)
301
277
{
302
278
  uint32_t cs_number;
303
279
  const CHARSET_INFO *cs;
304
280
  (void) init_available_charsets(MYF(0));       /* If it isn't initialized */
305
281
 
306
 
  cs_number=get_collation_number(cs_name);
 
282
  cs_number= get_collation_number(cs_name);
307
283
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
308
284
 
309
 
  if (!cs && (flags & MY_WME))
310
 
  {
311
 
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
312
 
    my_stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
313
 
    my_error(EE_UNKNOWN_COLLATION, MYF(ME_BELL), cs_name, index_file);
314
 
  }
315
 
 
316
285
  return cs;
317
286
}
318
287
 
319
288
 
320
 
const CHARSET_INFO *get_charset_by_csname(const char *cs_name,
321
 
                                    uint32_t cs_flags,
322
 
                                    myf flags)
 
289
const CHARSET_INFO *get_charset_by_csname(const char *cs_name, uint32_t cs_flags)
323
290
{
324
291
  uint32_t cs_number;
325
292
  const CHARSET_INFO *cs;
329
296
  cs_number= get_charset_number(cs_name, cs_flags);
330
297
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
331
298
 
332
 
  if (!cs && (flags & MY_WME))
333
 
  {
334
 
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
335
 
    my_stpcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
336
 
    my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file);
337
 
  }
338
 
 
339
299
  return(cs);
340
300
}
341
301
 
342
302
 
343
 
/**
344
 
  Resolve character set by the character set name (utf8, latin1, ...).
345
 
 
346
 
  The function tries to resolve character set by the specified name. If
347
 
  there is character set with the given name, it is assigned to the "cs"
348
 
  parameter and false is returned. If there is no such character set,
349
 
  "default_cs" is assigned to the "cs" and true is returned.
350
 
 
351
 
  @param[in] cs_name    Character set name.
352
 
  @param[in] default_cs Default character set.
353
 
  @param[out] cs        Variable to store character set.
354
 
 
355
 
  @return false if character set was resolved successfully; true if there
356
 
  is no character set with given name.
357
 
*/
358
 
 
359
 
bool resolve_charset(const char *cs_name,
360
 
                     const CHARSET_INFO *default_cs,
361
 
                     const CHARSET_INFO **cs)
362
 
{
363
 
  *cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0));
364
 
 
365
 
  if (*cs == NULL)
366
 
  {
367
 
    *cs= default_cs;
368
 
    return true;
369
 
  }
370
 
 
371
 
  return false;
372
 
}
373
 
 
374
 
 
375
 
/**
376
 
  Resolve collation by the collation name (utf8_general_ci, ...).
377
 
 
378
 
  The function tries to resolve collation by the specified name. If there
379
 
  is collation with the given name, it is assigned to the "cl" parameter
380
 
  and false is returned. If there is no such collation, "default_cl" is
381
 
  assigned to the "cl" and true is returned.
382
 
 
383
 
  @param[out] cl        Variable to store collation.
384
 
  @param[in] cl_name    Collation name.
385
 
  @param[in] default_cl Default collation.
386
 
 
387
 
  @return false if collation was resolved successfully; true if there is no
388
 
  collation with given name.
389
 
*/
390
 
 
391
 
bool resolve_collation(const char *cl_name,
392
 
                       const CHARSET_INFO *default_cl,
393
 
                       const CHARSET_INFO **cl)
394
 
{
395
 
  *cl= get_charset_by_name(cl_name, MYF(0));
396
 
 
397
 
  if (*cl == NULL)
398
 
  {
399
 
    *cl= default_cl;
400
 
    return true;
401
 
  }
402
 
 
403
 
  return false;
404
 
}
405
 
 
406
 
 
407
 
#ifdef BACKSLASH_MBTAIL
408
 
static CHARSET_INFO *fs_cset_cache= NULL;
409
 
 
410
 
CHARSET_INFO *fs_character_set()
411
 
{
412
 
  if (!fs_cset_cache)
413
 
  {
414
 
    char buf[10]= "cp";
415
 
    GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE,
416
 
                  buf+2, sizeof(buf)-3);
417
 
    /*
418
 
      We cannot call get_charset_by_name here
419
 
      because fs_character_set() is executed before
420
 
      LOCK_THD_charset mutex initialization, which
421
 
      is used inside get_charset_by_name.
422
 
      As we're now interested in cp932 only,
423
 
      let's just detect it using strcmp().
424
 
    */
425
 
    fs_cset_cache= !strcmp(buf, "cp932") ?
426
 
                   &my_charset_cp932_japanese_ci : &my_charset_bin;
427
 
  }
428
 
  return fs_cset_cache;
429
 
}
430
 
#endif
431
 
 
432
303
/*
433
304
  Escape apostrophes by doubling them up
434
305
 
461
332
  const char *to_start= to;
462
333
  const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
463
334
  bool overflow= false;
464
 
#ifdef USE_MB
465
335
  bool use_mb_flag= use_mb(charset_info);
466
 
#endif
467
336
  for (end= from + length; from < end; from++)
468
337
  {
469
 
#ifdef USE_MB
470
338
    int tmp_length;
471
339
    if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
472
340
    {
485
353
      turned into a multi-byte character by the addition of an escaping
486
354
      character, because we are only escaping the ' character with itself.
487
355
     */
488
 
#endif
489
356
    if (*from == '\'')
490
357
    {
491
358
      if (to + 2 > to_end)