~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
#include "mysys_priv.h"
17
#include "mysys_err.h"
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
18
#include <mystrings/m_ctype.h>
19
#include <mystrings/m_string.h>
1 by brian
clean slate
20
#include <my_dir.h>
21
22
23
/*
24
  The code below implements this functionality:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
25
1 by brian
clean slate
26
    - Initializing charset related structures
27
    - Loading dynamic charsets
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
28
    - Searching for a proper CHARSET_INFO
1 by brian
clean slate
29
      using charset name, collation name or collation ID
30
    - Setting server default character set
31
*/
32
236.3.9 by Andrey Hristov
- Fix build of exotic, mostly non-western, charsets (--with-extra-charsets)
33
bool my_charset_same(const CHARSET_INFO *cs1, const CHARSET_INFO *cs2)
1 by brian
clean slate
34
{
35
  return ((cs1 == cs2) || !strcmp(cs1->csname,cs2->csname));
36
}
37
38
39
static uint
40
get_collation_number_internal(const char *name)
41
{
42
  CHARSET_INFO **cs;
43
  for (cs= all_charsets;
44
       cs < all_charsets+array_elements(all_charsets)-1 ;
45
       cs++)
46
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
47
    if ( cs[0] && cs[0]->name &&
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
48
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->name, name))
1 by brian
clean slate
49
      return cs[0]->number;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
50
  }
1 by brian
clean slate
51
  return 0;
52
}
53
54
146 by Brian Aker
my_bool cleanup.
55
static bool init_state_maps(CHARSET_INFO *cs)
1 by brian
clean slate
56
{
482 by Brian Aker
Remove uint.
57
  uint32_t i;
481 by Brian Aker
Remove all of uchar.
58
  unsigned char *state_map;
59
  unsigned char *ident_map;
1 by brian
clean slate
60
656.3.1 by Monty Taylor
Got rid of my_once_alloc.
61
  if (!(cs->state_map= (unsigned char*) malloc(256)))
1 by brian
clean slate
62
    return 1;
63
    
656.3.1 by Monty Taylor
Got rid of my_once_alloc.
64
  if (!(cs->ident_map= (unsigned char*) malloc(256)))
1 by brian
clean slate
65
    return 1;
66
67
  state_map= cs->state_map;
68
  ident_map= cs->ident_map;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
69
1 by brian
clean slate
70
  /* Fill state_map with states to get a faster parser */
71
  for (i=0; i < 256 ; i++)
72
  {
73
    if (my_isalpha(cs,i))
481 by Brian Aker
Remove all of uchar.
74
      state_map[i]=(unsigned char) MY_LEX_IDENT;
1 by brian
clean slate
75
    else if (my_isdigit(cs,i))
481 by Brian Aker
Remove all of uchar.
76
      state_map[i]=(unsigned char) MY_LEX_NUMBER_IDENT;
1 by brian
clean slate
77
#if defined(USE_MB) && defined(USE_MB_IDENT)
78
    else if (my_mbcharlen(cs, i)>1)
481 by Brian Aker
Remove all of uchar.
79
      state_map[i]=(unsigned char) MY_LEX_IDENT;
1 by brian
clean slate
80
#endif
81
    else if (my_isspace(cs,i))
481 by Brian Aker
Remove all of uchar.
82
      state_map[i]=(unsigned char) MY_LEX_SKIP;
1 by brian
clean slate
83
    else
481 by Brian Aker
Remove all of uchar.
84
      state_map[i]=(unsigned char) MY_LEX_CHAR;
1 by brian
clean slate
85
  }
481 by Brian Aker
Remove all of uchar.
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;
1 by brian
clean slate
102
103
  /*
104
    Create a second map to make it faster to find identifiers
105
  */
106
  for (i=0; i < 256 ; i++)
107
  {
481 by Brian Aker
Remove all of uchar.
108
    ident_map[i]= (unsigned char) (state_map[i] == MY_LEX_IDENT ||
1 by brian
clean slate
109
			   state_map[i] == MY_LEX_NUMBER_IDENT);
110
  }
111
112
  /* Special handling of hex and binary strings */
481 by Brian Aker
Remove all of uchar.
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;
1 by brian
clean slate
115
  return 0;
116
}
117
118
119
#define MY_CHARSET_INDEX "Index.xml"
120
121
const char *charsets_dir= NULL;
122
static int charset_initialized=0;
123
124
125
char *get_charsets_dir(char *buf)
126
{
127
  const char *sharedir= SHAREDIR;
128
  char *res;
129
130
  if (charsets_dir != NULL)
629.5.2 by Toru Maesaka
Second pass of replacing MySQL's strmake() with libc calls
131
    strncpy(buf, charsets_dir, FN_REFLEN-1);
1 by brian
clean slate
132
  else
133
  {
134
    if (test_if_hard_path(sharedir) ||
135
	is_prefix(sharedir, DEFAULT_CHARSET_HOME))
461 by Monty Taylor
Removed NullS. bu-bye.
136
      strxmov(buf, sharedir, "/", CHARSET_DIR, NULL);
1 by brian
clean slate
137
    else
138
      strxmov(buf, DEFAULT_CHARSET_HOME, "/", sharedir, "/", CHARSET_DIR,
461 by Monty Taylor
Removed NullS. bu-bye.
139
	      NULL);
1 by brian
clean slate
140
  }
461 by Monty Taylor
Removed NullS. bu-bye.
141
  res= convert_dirname(buf,buf,NULL);
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
142
  return(res);
1 by brian
clean slate
143
}
144
145
CHARSET_INFO *all_charsets[256];
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
146
const CHARSET_INFO *default_charset_info = &my_charset_utf8_general_ci;
1 by brian
clean slate
147
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
148
void add_compiled_collation(CHARSET_INFO * cs)
1 by brian
clean slate
149
{
150
  all_charsets[cs->number]= cs;
151
  cs->state|= MY_CS_AVAILABLE;
152
}
153
632.1.11 by Monty Taylor
Fixed Sun Studio warnings in mysys.
154
void *cs_alloc(size_t size)
1 by brian
clean slate
155
{
656.3.1 by Monty Taylor
Got rid of my_once_alloc.
156
  return malloc(size);
1 by brian
clean slate
157
}
158
159
146 by Brian Aker
my_bool cleanup.
160
static bool init_available_charsets(myf myflags)
1 by brian
clean slate
161
{
162
  char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
163 by Brian Aker
Merge Monty's code.
163
  bool error=false;
1 by brian
clean slate
164
  /*
165
    We have to use charset_initialized to not lock on THR_LOCK_charset
166
    inside get_internal_charset...
167
  */
168
  if (!charset_initialized)
169
  {
170
    CHARSET_INFO **cs;
171
    /*
172
      To make things thread safe we are not allowing other threads to interfere
173
      while we may changing the cs_info_table
174
    */
175
    pthread_mutex_lock(&THR_LOCK_charset);
176
    if (!charset_initialized)
177
    {
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
178
      memset(&all_charsets, 0, sizeof(all_charsets));
1 by brian
clean slate
179
      init_compiled_charsets(myflags);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
180
1 by brian
clean slate
181
      /* Copy compiled charsets */
182
      for (cs=all_charsets;
183
           cs < all_charsets+array_elements(all_charsets)-1 ;
184
           cs++)
185
      {
186
        if (*cs)
187
        {
188
          if (cs[0]->ctype)
189
            if (init_state_maps(*cs))
190
              *cs= NULL;
191
        }
192
      }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
193
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
194
      strcpy(get_charsets_dir(fname), MY_CHARSET_INDEX);
1 by brian
clean slate
195
      charset_initialized=1;
196
    }
197
    pthread_mutex_unlock(&THR_LOCK_charset);
198
  }
199
  return error;
200
}
201
202
203
void free_charsets(void)
204
{
205
  charset_initialized=0;
206
}
207
208
482 by Brian Aker
Remove uint.
209
uint32_t get_collation_number(const char *name)
1 by brian
clean slate
210
{
211
  init_available_charsets(MYF(0));
212
  return get_collation_number_internal(name);
213
}
214
215
482 by Brian Aker
Remove uint.
216
uint32_t get_charset_number(const char *charset_name, uint32_t cs_flags)
1 by brian
clean slate
217
{
218
  CHARSET_INFO **cs;
219
  init_available_charsets(MYF(0));
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
220
1 by brian
clean slate
221
  for (cs= all_charsets;
222
       cs < all_charsets+array_elements(all_charsets)-1 ;
223
       cs++)
224
  {
225
    if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) &&
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
226
         !my_strcasecmp(&my_charset_utf8_general_ci, cs[0]->csname, charset_name))
1 by brian
clean slate
227
      return cs[0]->number;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
228
  }
1 by brian
clean slate
229
  return 0;
230
}
231
232
482 by Brian Aker
Remove uint.
233
const char *get_charset_name(uint32_t charset_number)
1 by brian
clean slate
234
{
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
235
  const CHARSET_INFO *cs;
1 by brian
clean slate
236
  init_available_charsets(MYF(0));
237
238
  cs=all_charsets[charset_number];
239
  if (cs && (cs->number == charset_number) && cs->name )
240
    return (char*) cs->name;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
241
1 by brian
clean slate
242
  return (char*) "?";   /* this mimics find_type() */
243
}
244
245
482 by Brian Aker
Remove uint.
246
static const CHARSET_INFO *get_internal_charset(uint32_t cs_number)
1 by brian
clean slate
247
{
248
  CHARSET_INFO *cs;
249
  /*
250
    To make things thread safe we are not allowing other threads to interfere
251
    while we may changing the cs_info_table
252
  */
253
  pthread_mutex_lock(&THR_LOCK_charset);
254
  if ((cs= all_charsets[cs_number]))
255
  {
256
    if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED))
257
    {
383.1.7 by Brian Aker
Remove homebrew xml parser.
258
      assert(0);
1 by brian
clean slate
259
    }
260
    cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
261
  }
262
  if (cs && !(cs->state & MY_CS_READY))
263
  {
264
    if ((cs->cset->init && cs->cset->init(cs, cs_alloc)) ||
265
        (cs->coll->init && cs->coll->init(cs, cs_alloc)))
266
      cs= NULL;
267
    else
268
      cs->state|= MY_CS_READY;
269
  }
270
  pthread_mutex_unlock(&THR_LOCK_charset);
271
  return cs;
272
}
273
274
575.3.1 by Monty Taylor
Made mysys and mystrings c++. Fixed the resulting bugs the compiler found.
275
const CHARSET_INFO *get_charset(uint32_t cs_number, myf flags)
1 by brian
clean slate
276
{
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
277
  const CHARSET_INFO *cs;
1 by brian
clean slate
278
  if (cs_number == default_charset_info->number)
279
    return default_charset_info;
280
281
  (void) init_available_charsets(MYF(0));	/* If it isn't initialized */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
282
1 by brian
clean slate
283
  if (!cs_number || cs_number >= array_elements(all_charsets)-1)
284
    return NULL;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
285
383.1.7 by Brian Aker
Remove homebrew xml parser.
286
  cs= get_internal_charset(cs_number);
1 by brian
clean slate
287
288
  if (!cs && (flags & MY_WME))
289
  {
290
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)], cs_string[23];
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
291
    strcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
1 by brian
clean slate
292
    cs_string[0]='#';
293
    int10_to_str(cs_number, cs_string+1, 10);
294
    my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_string, index_file);
295
  }
296
  return cs;
297
}
298
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
299
const CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
1 by brian
clean slate
300
{
482 by Brian Aker
Remove uint.
301
  uint32_t cs_number;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
302
  const CHARSET_INFO *cs;
1 by brian
clean slate
303
  (void) init_available_charsets(MYF(0));	/* If it isn't initialized */
304
305
  cs_number=get_collation_number(cs_name);
383.1.7 by Brian Aker
Remove homebrew xml parser.
306
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
1 by brian
clean slate
307
308
  if (!cs && (flags & MY_WME))
309
  {
310
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
311
    strcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
1 by brian
clean slate
312
    my_error(EE_UNKNOWN_COLLATION, MYF(ME_BELL), cs_name, index_file);
313
  }
314
315
  return cs;
316
}
317
318
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
319
const CHARSET_INFO *get_charset_by_csname(const char *cs_name,
482 by Brian Aker
Remove uint.
320
				    uint32_t cs_flags,
1 by brian
clean slate
321
				    myf flags)
322
{
482 by Brian Aker
Remove uint.
323
  uint32_t cs_number;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
324
  const CHARSET_INFO *cs;
1 by brian
clean slate
325
326
  (void) init_available_charsets(MYF(0));	/* If it isn't initialized */
327
328
  cs_number= get_charset_number(cs_name, cs_flags);
383.1.7 by Brian Aker
Remove homebrew xml parser.
329
  cs= cs_number ? get_internal_charset(cs_number) : NULL;
1 by brian
clean slate
330
331
  if (!cs && (flags & MY_WME))
332
  {
333
    char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
334
    strcpy(get_charsets_dir(index_file),MY_CHARSET_INDEX);
1 by brian
clean slate
335
    my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file);
336
  }
337
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
338
  return(cs);
1 by brian
clean slate
339
}
340
341
342
/**
343
  Resolve character set by the character set name (utf8, latin1, ...).
344
345
  The function tries to resolve character set by the specified name. If
346
  there is character set with the given name, it is assigned to the "cs"
163 by Brian Aker
Merge Monty's code.
347
  parameter and false is returned. If there is no such character set,
348
  "default_cs" is assigned to the "cs" and true is returned.
1 by brian
clean slate
349
350
  @param[in] cs_name    Character set name.
351
  @param[in] default_cs Default character set.
352
  @param[out] cs        Variable to store character set.
353
163 by Brian Aker
Merge Monty's code.
354
  @return false if character set was resolved successfully; true if there
1 by brian
clean slate
355
  is no character set with given name.
356
*/
357
146 by Brian Aker
my_bool cleanup.
358
bool resolve_charset(const char *cs_name,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
359
                     const CHARSET_INFO *default_cs,
360
                     const CHARSET_INFO **cs)
1 by brian
clean slate
361
{
362
  *cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0));
363
364
  if (*cs == NULL)
365
  {
366
    *cs= default_cs;
163 by Brian Aker
Merge Monty's code.
367
    return true;
1 by brian
clean slate
368
  }
369
163 by Brian Aker
Merge Monty's code.
370
  return false;
1 by brian
clean slate
371
}
372
373
374
/**
375
  Resolve collation by the collation name (utf8_general_ci, ...).
376
377
  The function tries to resolve collation by the specified name. If there
378
  is collation with the given name, it is assigned to the "cl" parameter
163 by Brian Aker
Merge Monty's code.
379
  and false is returned. If there is no such collation, "default_cl" is
380
  assigned to the "cl" and true is returned.
1 by brian
clean slate
381
382
  @param[out] cl        Variable to store collation.
383
  @param[in] cl_name    Collation name.
384
  @param[in] default_cl Default collation.
385
163 by Brian Aker
Merge Monty's code.
386
  @return false if collation was resolved successfully; true if there is no
1 by brian
clean slate
387
  collation with given name.
388
*/
389
146 by Brian Aker
my_bool cleanup.
390
bool resolve_collation(const char *cl_name,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
391
                       const CHARSET_INFO *default_cl,
392
                       const CHARSET_INFO **cl)
1 by brian
clean slate
393
{
394
  *cl= get_charset_by_name(cl_name, MYF(0));
395
396
  if (*cl == NULL)
397
  {
398
    *cl= default_cl;
163 by Brian Aker
Merge Monty's code.
399
    return true;
1 by brian
clean slate
400
  }
401
163 by Brian Aker
Merge Monty's code.
402
  return false;
1 by brian
clean slate
403
}
404
405
406
#ifdef BACKSLASH_MBTAIL
407
static CHARSET_INFO *fs_cset_cache= NULL;
408
409
CHARSET_INFO *fs_character_set()
410
{
411
  if (!fs_cset_cache)
412
  {
413
    char buf[10]= "cp";
414
    GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE,
415
                  buf+2, sizeof(buf)-3);
416
    /*
417
      We cannot call get_charset_by_name here
418
      because fs_character_set() is executed before
419
      LOCK_THD_charset mutex initialization, which
420
      is used inside get_charset_by_name.
421
      As we're now interested in cp932 only,
422
      let's just detect it using strcmp().
423
    */
424
    fs_cset_cache= !strcmp(buf, "cp932") ?
425
                   &my_charset_cp932_japanese_ci : &my_charset_bin;
426
  }
427
  return fs_cset_cache;
428
}
429
#endif
430
431
/*
432
  Escape apostrophes by doubling them up
433
434
  SYNOPSIS
236.3.4 by Andrey Hristov
Rename escape_(string|quotes)_for_mysql to escape_(string|quotes)_for_drizzle
435
    escape_quotes_for_drizzle()
1 by brian
clean slate
436
    charset_info        Charset of the strings
437
    to                  Buffer for escaped string
438
    to_length           Length of destination buffer, or 0
439
    from                The string to escape
440
    length              The length of the string to escape
441
442
  DESCRIPTION
443
    This escapes the contents of a string by doubling up any apostrophes that
444
    it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in
445
    effect on the server.
446
447
  NOTE
448
    To be consistent with escape_string_for_mysql(), to_length may be 0 to
449
    mean "big enough"
450
451
  RETURN VALUES
365.2.9 by Monty Taylor
Got rid of all instances of ~0
452
    UINT32_MAX  The escaped string did not fit in the to buffer
1 by brian
clean slate
453
    >=0         The length of the escaped string
454
*/
455
236.3.9 by Andrey Hristov
- Fix build of exotic, mostly non-western, charsets (--with-extra-charsets)
456
size_t escape_quotes_for_drizzle(const CHARSET_INFO *charset_info,
236.3.4 by Andrey Hristov
Rename escape_(string|quotes)_for_mysql to escape_(string|quotes)_for_drizzle
457
                                 char *to, size_t to_length,
458
                                 const char *from, size_t length)
1 by brian
clean slate
459
{
460
  const char *to_start= to;
461
  const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
163 by Brian Aker
Merge Monty's code.
462
  bool overflow= false;
1 by brian
clean slate
463
#ifdef USE_MB
146 by Brian Aker
my_bool cleanup.
464
  bool use_mb_flag= use_mb(charset_info);
1 by brian
clean slate
465
#endif
466
  for (end= from + length; from < end; from++)
467
  {
468
#ifdef USE_MB
469
    int tmp_length;
470
    if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
471
    {
472
      if (to + tmp_length > to_end)
473
      {
163 by Brian Aker
Merge Monty's code.
474
        overflow= true;
1 by brian
clean slate
475
        break;
476
      }
477
      while (tmp_length--)
478
	*to++= *from++;
479
      from--;
480
      continue;
481
    }
482
    /*
483
      We don't have the same issue here with a non-multi-byte character being
484
      turned into a multi-byte character by the addition of an escaping
485
      character, because we are only escaping the ' character with itself.
486
     */
487
#endif
488
    if (*from == '\'')
489
    {
490
      if (to + 2 > to_end)
491
      {
163 by Brian Aker
Merge Monty's code.
492
        overflow= true;
1 by brian
clean slate
493
        break;
494
      }
495
      *to++= '\'';
496
      *to++= '\'';
497
    }
498
    else
499
    {
500
      if (to + 1 > to_end)
501
      {
163 by Brian Aker
Merge Monty's code.
502
        overflow= true;
1 by brian
clean slate
503
        break;
504
      }
505
      *to++= *from;
506
    }
507
  }
508
  *to= 0;
365.2.9 by Monty Taylor
Got rid of all instances of ~0
509
  return overflow ? UINT32_MAX : (uint32_t) (to - to_start);
1 by brian
clean slate
510
}