~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/charset.cc

  • Committer: Monty Taylor
  • Date: 2009-03-02 23:14:32 UTC
  • mto: This revision was merged to the branch mainline in revision 910.
  • Revision ID: mordred@inaugust.com-20090302231432-i35xehp7uzo6hjjw
Updated build system to use new version numbering. Just remember to run ./config/autorun.sh before running make distcheck for release and all should be peachy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
 
 
16
 
#include <config.h>
17
 
 
18
 
#include <drizzled/charset.h>
19
 
#include <drizzled/error.h>
20
 
#include <drizzled/charset_info.h>
21
 
#include <drizzled/internal/m_string.h>
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#include "mysys_priv.h"
 
17
#include "mysys_err.h"
 
18
#include <mystrings/m_ctype.h>
 
19
#include <mystrings/m_string.h>
22
20
#include <drizzled/configmake.h>
23
 
#include <vector>
24
 
 
25
 
#include <drizzled/visibility.h>
26
 
 
27
 
using namespace std;
28
 
 
29
 
namespace drizzled
30
 
{
31
 
 
32
 
/*
33
 
  We collect memory in this vector that we free on delete.
34
 
*/
35
 
static vector<unsigned char*> memory_vector;
 
21
 
36
22
 
37
23
/*
38
24
  The code below implements this functionality:
53
39
static uint
54
40
get_collation_number_internal(const char *name)
55
41
{
56
 
  for (CHARSET_INFO **cs= all_charsets;
57
 
       cs < all_charsets+array_elements(all_charsets)-1;
 
42
  CHARSET_INFO **cs;
 
43
  for (cs= all_charsets;
 
44
       cs < all_charsets+array_elements(all_charsets)-1 ;
58
45
       cs++)
59
46
  {
60
 
    if ( cs[0] && cs[0]->name && !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->name, name))
61
 
    {
 
47
    if ( cs[0] && cs[0]->name &&
 
48
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->name, name))
62
49
      return cs[0]->number;
63
 
    }
64
50
  }
65
51
  return 0;
66
52
}
67
53
 
68
 
static unsigned char *cs_alloc(size_t size)
69
 
{
70
 
  memory_vector.push_back(new unsigned char[size]);
71
 
  return memory_vector.back();
72
 
}
73
54
 
74
55
static bool init_state_maps(CHARSET_INFO *cs)
75
56
{
76
 
  if (!(cs->state_map= cs_alloc(256)))
 
57
  uint32_t i;
 
58
  unsigned char *state_map;
 
59
  unsigned char *ident_map;
 
60
 
 
61
  if (!(cs->state_map= (unsigned char*) malloc(256)))
77
62
    return 1;
78
63
    
79
 
  if (!(cs->ident_map= cs_alloc(256)))
 
64
  if (!(cs->ident_map= (unsigned char*) malloc(256)))
80
65
    return 1;
81
66
 
82
 
  unsigned char *state_map= cs->state_map;
83
 
  unsigned char *ident_map= cs->ident_map;
 
67
  state_map= cs->state_map;
 
68
  ident_map= cs->ident_map;
84
69
 
85
70
  /* Fill state_map with states to get a faster parser */
86
 
  for (int i= 0; i < 256; i++)
 
71
  for (i=0; i < 256 ; i++)
87
72
  {
88
73
    if (my_isalpha(cs,i))
89
 
      state_map[i]= MY_LEX_IDENT;
 
74
      state_map[i]=(unsigned char) MY_LEX_IDENT;
90
75
    else if (my_isdigit(cs,i))
91
 
      state_map[i]= MY_LEX_NUMBER_IDENT;
 
76
      state_map[i]=(unsigned char) MY_LEX_NUMBER_IDENT;
 
77
#if defined(USE_MB) && defined(USE_MB_IDENT)
92
78
    else if (my_mbcharlen(cs, i)>1)
93
 
      state_map[i]= MY_LEX_IDENT;
 
79
      state_map[i]=(unsigned char) MY_LEX_IDENT;
 
80
#endif
94
81
    else if (my_isspace(cs,i))
95
 
      state_map[i]= MY_LEX_SKIP;
 
82
      state_map[i]=(unsigned char) MY_LEX_SKIP;
96
83
    else
97
 
      state_map[i]= MY_LEX_CHAR;
 
84
      state_map[i]=(unsigned char) MY_LEX_CHAR;
98
85
  }
99
 
  state_map['_']=state_map['$']= MY_LEX_IDENT;
100
 
  state_map['\'']= MY_LEX_STRING;
101
 
  state_map['.']= MY_LEX_REAL_OR_POINT;
102
 
  state_map['>']=state_map['=']=state_map['!']=  MY_LEX_CMP_OP;
103
 
  state_map['<']=  MY_LEX_LONG_CMP_OP;
104
 
  state_map['&']=state_map['|']= MY_LEX_BOOL;
105
 
  state_map['#']= MY_LEX_COMMENT;
106
 
  state_map[';']= MY_LEX_SEMICOLON;
107
 
  state_map[':']= MY_LEX_SET_VAR;
108
 
  state_map[0]= MY_LEX_EOL;
109
 
  state_map['\\']=  MY_LEX_ESCAPE;
110
 
  state_map['/']=  MY_LEX_LONG_COMMENT;
111
 
  state_map['*']=  MY_LEX_END_LONG_COMMENT;
112
 
  state_map['@']=  MY_LEX_USER_END;
113
 
  state_map['`']=  MY_LEX_USER_VARIABLE_DELIMITER;
114
 
  state_map['"']=  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;
115
102
 
116
103
  /*
117
104
    Create a second map to make it faster to find identifiers
118
105
  */
119
 
  for (int i= 0; i < 256; i++)
 
106
  for (i=0; i < 256 ; i++)
120
107
  {
121
 
    ident_map[i]= state_map[i] == MY_LEX_IDENT || state_map[i] == MY_LEX_NUMBER_IDENT;
 
108
    ident_map[i]= (unsigned char) (state_map[i] == MY_LEX_IDENT ||
 
109
                           state_map[i] == MY_LEX_NUMBER_IDENT);
122
110
  }
123
111
 
124
112
  /* Special handling of hex and binary strings */
125
 
  state_map['x']= state_map['X']=  MY_LEX_IDENT_OR_HEX;
126
 
  state_map['b']= state_map['B']=  MY_LEX_IDENT_OR_BIN;
 
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;
127
115
  return 0;
128
116
}
129
117
 
 
118
 
130
119
static bool charset_initialized= false;
131
120
 
132
 
DRIZZLED_API CHARSET_INFO *all_charsets[256];
133
 
const DRIZZLED_API CHARSET_INFO *default_charset_info = &my_charset_utf8_general_ci;
 
121
CHARSET_INFO *all_charsets[256];
 
122
const CHARSET_INFO *default_charset_info = &my_charset_utf8_general_ci;
134
123
 
135
124
void add_compiled_collation(CHARSET_INFO * cs)
136
125
{
138
127
  cs->state|= MY_CS_AVAILABLE;
139
128
}
140
129
 
 
130
void *cs_alloc(size_t size)
 
131
{
 
132
  return malloc(size);
 
133
}
 
134
 
 
135
 
141
136
static bool init_available_charsets(myf myflags)
142
137
{
143
138
  bool error= false;
172
167
}
173
168
 
174
169
 
175
 
void free_charsets()
 
170
void free_charsets(void)
176
171
{
177
 
  charset_initialized= false;
178
 
 
179
 
  while (not memory_vector.empty())
180
 
  {
181
 
    delete[] memory_vector.back();
182
 
    memory_vector.pop_back();
183
 
  }
 
172
  charset_initialized= true;
184
173
}
185
174
 
186
175
 
200
189
       cs < all_charsets+array_elements(all_charsets)-1 ;
201
190
       cs++)
202
191
  {
203
 
    if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) && !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->csname, charset_name))
 
192
    if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) &&
 
193
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->csname, charset_name))
204
194
      return cs[0]->number;
205
195
  }
206
196
  return 0;
209
199
 
210
200
const char *get_charset_name(uint32_t charset_number)
211
201
{
 
202
  const CHARSET_INFO *cs;
212
203
  init_available_charsets(MYF(0));
213
204
 
214
 
  const CHARSET_INFO *cs= all_charsets[charset_number];
 
205
  cs=all_charsets[charset_number];
215
206
  if (cs && (cs->number == charset_number) && cs->name )
216
 
    return cs->name;
 
207
    return (char*) cs->name;
217
208
 
218
 
  return "?";   /* this mimics find_type() */
 
209
  return (char*) "?";   /* this mimics find_type() */
219
210
}
220
211
 
221
212
 
269
260
  const CHARSET_INFO *cs;
270
261
  (void) init_available_charsets(MYF(0));       /* If it isn't initialized */
271
262
 
272
 
  cs_number= get_collation_number(cs_name);
 
263
  cs_number=get_collation_number(cs_name);
273
264
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
274
265
 
275
266
  return cs;
290
281
}
291
282
 
292
283
 
 
284
/**
 
285
  Resolve character set by the character set name (utf8, latin1, ...).
 
286
 
 
287
  The function tries to resolve character set by the specified name. If
 
288
  there is character set with the given name, it is assigned to the "cs"
 
289
  parameter and false is returned. If there is no such character set,
 
290
  "default_cs" is assigned to the "cs" and true is returned.
 
291
 
 
292
  @param[in] cs_name    Character set name.
 
293
  @param[in] default_cs Default character set.
 
294
  @param[out] cs        Variable to store character set.
 
295
 
 
296
  @return false if character set was resolved successfully; true if there
 
297
  is no character set with given name.
 
298
*/
 
299
 
 
300
bool resolve_charset(const char *cs_name,
 
301
                     const CHARSET_INFO *default_cs,
 
302
                     const CHARSET_INFO **cs)
 
303
{
 
304
  *cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY);
 
305
 
 
306
  if (*cs == NULL)
 
307
  {
 
308
    *cs= default_cs;
 
309
    return true;
 
310
  }
 
311
 
 
312
  return false;
 
313
}
 
314
 
 
315
 
 
316
/**
 
317
  Resolve collation by the collation name (utf8_general_ci, ...).
 
318
 
 
319
  The function tries to resolve collation by the specified name. If there
 
320
  is collation with the given name, it is assigned to the "cl" parameter
 
321
  and false is returned. If there is no such collation, "default_cl" is
 
322
  assigned to the "cl" and true is returned.
 
323
 
 
324
  @param[out] cl        Variable to store collation.
 
325
  @param[in] cl_name    Collation name.
 
326
  @param[in] default_cl Default collation.
 
327
 
 
328
  @return false if collation was resolved successfully; true if there is no
 
329
  collation with given name.
 
330
*/
 
331
 
 
332
bool resolve_collation(const char *cl_name,
 
333
                       const CHARSET_INFO *default_cl,
 
334
                       const CHARSET_INFO **cl)
 
335
{
 
336
  *cl= get_charset_by_name(cl_name);
 
337
 
 
338
  if (*cl == NULL)
 
339
  {
 
340
    *cl= default_cl;
 
341
    return true;
 
342
  }
 
343
 
 
344
  return false;
 
345
}
 
346
 
 
347
 
 
348
#ifdef BACKSLASH_MBTAIL
 
349
static CHARSET_INFO *fs_cset_cache= NULL;
 
350
 
 
351
CHARSET_INFO *fs_character_set()
 
352
{
 
353
  if (!fs_cset_cache)
 
354
  {
 
355
    char buf[10]= "cp";
 
356
    GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE,
 
357
                  buf+2, sizeof(buf)-3);
 
358
    /*
 
359
      We cannot call get_charset_by_name here
 
360
      because fs_character_set() is executed before
 
361
      LOCK_THD_charset mutex initialization, which
 
362
      is used inside get_charset_by_name.
 
363
      As we're now interested in cp932 only,
 
364
      let's just detect it using strcmp().
 
365
    */
 
366
    fs_cset_cache= !strcmp(buf, "cp932") ?
 
367
                   &my_charset_cp932_japanese_ci : &my_charset_bin;
 
368
  }
 
369
  return fs_cset_cache;
 
370
}
 
371
#endif
 
372
 
293
373
/*
294
374
  Escape apostrophes by doubling them up
295
375
 
322
402
  const char *to_start= to;
323
403
  const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
324
404
  bool overflow= false;
 
405
#ifdef USE_MB
325
406
  bool use_mb_flag= use_mb(charset_info);
 
407
#endif
326
408
  for (end= from + length; from < end; from++)
327
409
  {
 
410
#ifdef USE_MB
328
411
    int tmp_length;
329
412
    if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
330
413
    {
343
426
      turned into a multi-byte character by the addition of an escaping
344
427
      character, because we are only escaping the ' character with itself.
345
428
     */
 
429
#endif
346
430
    if (*from == '\'')
347
431
    {
348
432
      if (to + 2 > to_end)
364
448
    }
365
449
  }
366
450
  *to= 0;
367
 
  return overflow ? UINT32_MAX : to - to_start;
 
451
  return overflow ? UINT32_MAX : (uint32_t) (to - to_start);
368
452
}
369
 
 
370
 
} /* namespace drizzled */