~stewart/drizzle/embedded-innodb-create-select-transaction-arrgh

« back to all changes in this revision

Viewing changes to sql/sql_string.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
/* This file is originally from the mysql distribution. Coded by monty */
 
17
 
 
18
#ifdef USE_PRAGMA_IMPLEMENTATION
 
19
#pragma implementation                          // gcc: Class implementation
 
20
#endif
 
21
 
 
22
#include <my_global.h>
 
23
#include <my_sys.h>
 
24
#include <m_string.h>
 
25
#include <m_ctype.h>
 
26
#ifdef HAVE_FCONVERT
 
27
#include <floatingpoint.h>
 
28
#endif
 
29
 
 
30
/*
 
31
  The following extern declarations are ok as these are interface functions
 
32
  required by the string function
 
33
*/
 
34
 
 
35
extern uchar* sql_alloc(unsigned size);
 
36
extern void sql_element_free(void *ptr);
 
37
 
 
38
#include "sql_string.h"
 
39
 
 
40
/*****************************************************************************
 
41
** String functions
 
42
*****************************************************************************/
 
43
 
 
44
bool String::real_alloc(uint32 arg_length)
 
45
{
 
46
  arg_length=ALIGN_SIZE(arg_length+1);
 
47
  str_length=0;
 
48
  if (Alloced_length < arg_length)
 
49
  {
 
50
    free();
 
51
    if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME))))
 
52
      return TRUE;
 
53
    Alloced_length=arg_length;
 
54
    alloced=1;
 
55
  }
 
56
  Ptr[0]=0;
 
57
  return FALSE;
 
58
}
 
59
 
 
60
 
 
61
/*
 
62
** Check that string is big enough. Set string[alloc_length] to 0
 
63
** (for C functions)
 
64
*/
 
65
 
 
66
bool String::realloc(uint32 alloc_length)
 
67
{
 
68
  uint32 len=ALIGN_SIZE(alloc_length+1);
 
69
  if (Alloced_length < len)
 
70
  {
 
71
    char *new_ptr;
 
72
    if (alloced)
 
73
    {
 
74
      if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME))))
 
75
      {
 
76
        Ptr=new_ptr;
 
77
        Alloced_length=len;
 
78
      }
 
79
      else
 
80
        return TRUE;                            // Signal error
 
81
    }
 
82
    else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME))))
 
83
    {
 
84
      if (str_length)                           // Avoid bugs in memcpy on AIX
 
85
        memcpy(new_ptr,Ptr,str_length);
 
86
      new_ptr[str_length]=0;
 
87
      Ptr=new_ptr;
 
88
      Alloced_length=len;
 
89
      alloced=1;
 
90
    }
 
91
    else
 
92
      return TRUE;                      // Signal error
 
93
  }
 
94
  Ptr[alloc_length]=0;                  // This make other funcs shorter
 
95
  return FALSE;
 
96
}
 
97
 
 
98
bool String::set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs)
 
99
{
 
100
  uint l=20*cs->mbmaxlen+1;
 
101
  int base= unsigned_flag ? 10 : -10;
 
102
 
 
103
  if (alloc(l))
 
104
    return TRUE;
 
105
  str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,base,num);
 
106
  str_charset=cs;
 
107
  return FALSE;
 
108
}
 
109
 
 
110
bool String::set_real(double num,uint decimals, CHARSET_INFO *cs)
 
111
{
 
112
  char buff[FLOATING_POINT_BUFFER];
 
113
  uint dummy_errors;
 
114
  size_t len;
 
115
 
 
116
  str_charset=cs;
 
117
  if (decimals >= NOT_FIXED_DEC)
 
118
  {
 
119
    len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
 
120
    return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
 
121
  }
 
122
  len= my_fcvt(num, decimals, buff, NULL);
 
123
  return copy(buff, (uint32) len, &my_charset_latin1, cs,
 
124
              &dummy_errors);
 
125
}
 
126
 
 
127
 
 
128
bool String::copy()
 
129
{
 
130
  if (!alloced)
 
131
  {
 
132
    Alloced_length=0;                           // Force realloc
 
133
    return realloc(str_length);
 
134
  }
 
135
  return FALSE;
 
136
}
 
137
 
 
138
bool String::copy(const String &str)
 
139
{
 
140
  if (alloc(str.str_length))
 
141
    return TRUE;
 
142
  str_length=str.str_length;
 
143
  bmove(Ptr,str.Ptr,str_length);                // May be overlapping
 
144
  Ptr[str_length]=0;
 
145
  str_charset=str.str_charset;
 
146
  return FALSE;
 
147
}
 
148
 
 
149
bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
 
150
{
 
151
  if (alloc(arg_length))
 
152
    return TRUE;
 
153
  if ((str_length=arg_length))
 
154
    memcpy(Ptr,str,arg_length);
 
155
  Ptr[arg_length]=0;
 
156
  str_charset=cs;
 
157
  return FALSE;
 
158
}
 
159
 
 
160
 
 
161
/*
 
162
  Checks that the source string can be just copied to the destination string
 
163
  without conversion.
 
164
 
 
165
  SYNPOSIS
 
166
 
 
167
  needs_conversion()
 
168
  arg_length            Length of string to copy.
 
169
  from_cs               Character set to copy from
 
170
  to_cs                 Character set to copy to
 
171
  uint32 *offset        Returns number of unaligned characters.
 
172
 
 
173
  RETURN
 
174
   0  No conversion needed
 
175
   1  Either character set conversion or adding leading  zeros
 
176
      (e.g. for UCS-2) must be done
 
177
 
 
178
  NOTE
 
179
  to_cs may be NULL for "no conversion" if the system variable
 
180
  character_set_results is NULL.
 
181
*/
 
182
 
 
183
bool String::needs_conversion(uint32 arg_length,
 
184
                              CHARSET_INFO *from_cs,
 
185
                              CHARSET_INFO *to_cs,
 
186
                              uint32 *offset)
 
187
{
 
188
  *offset= 0;
 
189
  if (!to_cs ||
 
190
      (to_cs == &my_charset_bin) || 
 
191
      (to_cs == from_cs) ||
 
192
      my_charset_same(from_cs, to_cs) ||
 
193
      ((from_cs == &my_charset_bin) &&
 
194
       (!(*offset=(arg_length % to_cs->mbminlen)))))
 
195
    return FALSE;
 
196
  return TRUE;
 
197
}
 
198
 
 
199
 
 
200
/*
 
201
  Copy a multi-byte character sets with adding leading zeros.
 
202
 
 
203
  SYNOPSIS
 
204
 
 
205
  copy_aligned()
 
206
  str                   String to copy
 
207
  arg_length            Length of string. This should NOT be dividable with
 
208
                        cs->mbminlen.
 
209
  offset                arg_length % cs->mb_minlength
 
210
  cs                    Character set for 'str'
 
211
 
 
212
  NOTES
 
213
    For real multi-byte, ascii incompatible charactser sets,
 
214
    like UCS-2, add leading zeros if we have an incomplete character.
 
215
    Thus, 
 
216
      SELECT _ucs2 0xAA 
 
217
    will automatically be converted into
 
218
      SELECT _ucs2 0x00AA
 
219
 
 
220
  RETURN
 
221
    0  ok
 
222
    1  error
 
223
*/
 
224
 
 
225
bool String::copy_aligned(const char *str,uint32 arg_length, uint32 offset,
 
226
                          CHARSET_INFO *cs)
 
227
{
 
228
  /* How many bytes are in incomplete character */
 
229
  offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */
 
230
  DBUG_ASSERT(offset && offset != cs->mbmaxlen);
 
231
 
 
232
  uint32 aligned_length= arg_length + offset;
 
233
  if (alloc(aligned_length))
 
234
    return TRUE;
 
235
  
 
236
  /*
 
237
    Note, this is only safe for big-endian UCS-2.
 
238
    If we add little-endian UCS-2 sometimes, this code
 
239
    will be more complicated. But it's OK for now.
 
240
  */
 
241
  bzero((char*) Ptr, offset);
 
242
  memcpy(Ptr + offset, str, arg_length);
 
243
  Ptr[aligned_length]=0;
 
244
  /* str_length is always >= 0 as arg_length is != 0 */
 
245
  str_length= aligned_length;
 
246
  str_charset= cs;
 
247
  return FALSE;
 
248
}
 
249
 
 
250
 
 
251
bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
 
252
                                 CHARSET_INFO *cs)
 
253
{
 
254
  /* How many bytes are in incomplete character */
 
255
  uint32 offset= (arg_length % cs->mbminlen); 
 
256
  
 
257
  if (!offset) /* All characters are complete, just copy */
 
258
  {
 
259
    set(str, arg_length, cs);
 
260
    return FALSE;
 
261
  }
 
262
  return copy_aligned(str, arg_length, offset, cs);
 
263
}
 
264
 
 
265
        /* Copy with charset conversion */
 
266
 
 
267
bool String::copy(const char *str, uint32 arg_length,
 
268
                  CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
 
269
{
 
270
  uint32 offset;
 
271
  if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
 
272
  {
 
273
    *errors= 0;
 
274
    return copy(str, arg_length, to_cs);
 
275
  }
 
276
  if ((from_cs == &my_charset_bin) && offset)
 
277
  {
 
278
    *errors= 0;
 
279
    return copy_aligned(str, arg_length, offset, to_cs);
 
280
  }
 
281
  uint32 new_length= to_cs->mbmaxlen*arg_length;
 
282
  if (alloc(new_length))
 
283
    return TRUE;
 
284
  str_length=copy_and_convert((char*) Ptr, new_length, to_cs,
 
285
                              str, arg_length, from_cs, errors);
 
286
  str_charset=to_cs;
 
287
  return FALSE;
 
288
}
 
289
 
 
290
 
 
291
/*
 
292
  Set a string to the value of a latin1-string, keeping the original charset
 
293
  
 
294
  SYNOPSIS
 
295
    copy_or_set()
 
296
    str                 String of a simple charset (latin1)
 
297
    arg_length          Length of string
 
298
 
 
299
  IMPLEMENTATION
 
300
    If string object is of a simple character set, set it to point to the
 
301
    given string.
 
302
    If not, make a copy and convert it to the new character set.
 
303
 
 
304
  RETURN
 
305
    0   ok
 
306
    1   Could not allocate result buffer
 
307
 
 
308
*/
 
309
 
 
310
bool String::set_ascii(const char *str, uint32 arg_length)
 
311
{
 
312
  if (str_charset->mbminlen == 1)
 
313
  {
 
314
    set(str, arg_length, str_charset);
 
315
    return 0;
 
316
  }
 
317
  uint dummy_errors;
 
318
  return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors);
 
319
}
 
320
 
 
321
 
 
322
/* This is used by mysql.cc */
 
323
 
 
324
bool String::fill(uint32 max_length,char fill_char)
 
325
{
 
326
  if (str_length > max_length)
 
327
    Ptr[str_length=max_length]=0;
 
328
  else
 
329
  {
 
330
    if (realloc(max_length))
 
331
      return TRUE;
 
332
    bfill(Ptr+str_length,max_length-str_length,fill_char);
 
333
    str_length=max_length;
 
334
  }
 
335
  return FALSE;
 
336
}
 
337
 
 
338
void String::strip_sp()
 
339
{
 
340
   while (str_length && my_isspace(str_charset,Ptr[str_length-1]))
 
341
    str_length--;
 
342
}
 
343
 
 
344
bool String::append(const String &s)
 
345
{
 
346
  if (s.length())
 
347
  {
 
348
    if (realloc(str_length+s.length()))
 
349
      return TRUE;
 
350
    memcpy(Ptr+str_length,s.ptr(),s.length());
 
351
    str_length+=s.length();
 
352
  }
 
353
  return FALSE;
 
354
}
 
355
 
 
356
 
 
357
/*
 
358
  Append an ASCII string to the a string of the current character set
 
359
*/
 
360
 
 
361
bool String::append(const char *s,uint32 arg_length)
 
362
{
 
363
  if (!arg_length)
 
364
    return FALSE;
 
365
 
 
366
  /*
 
367
    For an ASCII incompatible string, e.g. UCS-2, we need to convert
 
368
  */
 
369
  if (str_charset->mbminlen > 1)
 
370
  {
 
371
    uint32 add_length=arg_length * str_charset->mbmaxlen;
 
372
    uint dummy_errors;
 
373
    if (realloc(str_length+ add_length))
 
374
      return TRUE;
 
375
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
 
376
                                  s, arg_length, &my_charset_latin1,
 
377
                                  &dummy_errors);
 
378
    return FALSE;
 
379
  }
 
380
 
 
381
  /*
 
382
    For an ASCII compatinble string we can just append.
 
383
  */
 
384
  if (realloc(str_length+arg_length))
 
385
    return TRUE;
 
386
  memcpy(Ptr+str_length,s,arg_length);
 
387
  str_length+=arg_length;
 
388
  return FALSE;
 
389
}
 
390
 
 
391
 
 
392
/*
 
393
  Append a 0-terminated ASCII string
 
394
*/
 
395
 
 
396
bool String::append(const char *s)
 
397
{
 
398
  return append(s, strlen(s));
 
399
}
 
400
 
 
401
 
 
402
/*
 
403
  Append a string in the given charset to the string
 
404
  with character set recoding
 
405
*/
 
406
 
 
407
bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs)
 
408
{
 
409
  uint32 dummy_offset;
 
410
  
 
411
  if (needs_conversion(arg_length, cs, str_charset, &dummy_offset))
 
412
  {
 
413
    uint32 add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
 
414
    uint dummy_errors;
 
415
    if (realloc(str_length + add_length)) 
 
416
      return TRUE;
 
417
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
 
418
                                  s, arg_length, cs, &dummy_errors);
 
419
  }
 
420
  else
 
421
  {
 
422
    if (realloc(str_length + arg_length)) 
 
423
      return TRUE;
 
424
    memcpy(Ptr + str_length, s, arg_length);
 
425
    str_length+= arg_length;
 
426
  }
 
427
  return FALSE;
 
428
}
 
429
 
 
430
 
 
431
#ifdef TO_BE_REMOVED
 
432
bool String::append(FILE* file, uint32 arg_length, myf my_flags)
 
433
{
 
434
  if (realloc(str_length+arg_length))
 
435
    return TRUE;
 
436
  if (my_fread(file, (uchar*) Ptr + str_length, arg_length, my_flags))
 
437
  {
 
438
    shrink(str_length);
 
439
    return TRUE;
 
440
  }
 
441
  str_length+=arg_length;
 
442
  return FALSE;
 
443
}
 
444
#endif
 
445
 
 
446
bool String::append(IO_CACHE* file, uint32 arg_length)
 
447
{
 
448
  if (realloc(str_length+arg_length))
 
449
    return TRUE;
 
450
  if (my_b_read(file, (uchar*) Ptr + str_length, arg_length))
 
451
  {
 
452
    shrink(str_length);
 
453
    return TRUE;
 
454
  }
 
455
  str_length+=arg_length;
 
456
  return FALSE;
 
457
}
 
458
 
 
459
bool String::append_with_prefill(const char *s,uint32 arg_length,
 
460
                 uint32 full_length, char fill_char)
 
461
{
 
462
  int t_length= arg_length > full_length ? arg_length : full_length;
 
463
 
 
464
  if (realloc(str_length + t_length))
 
465
    return TRUE;
 
466
  t_length= full_length - arg_length;
 
467
  if (t_length > 0)
 
468
  {
 
469
    bfill(Ptr+str_length, t_length, fill_char);
 
470
    str_length=str_length + t_length;
 
471
  }
 
472
  append(s, arg_length);
 
473
  return FALSE;
 
474
}
 
475
 
 
476
uint32 String::numchars()
 
477
{
 
478
  return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
 
479
}
 
480
 
 
481
int String::charpos(int i,uint32 offset)
 
482
{
 
483
  if (i <= 0)
 
484
    return i;
 
485
  return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
 
486
}
 
487
 
 
488
int String::strstr(const String &s,uint32 offset)
 
489
{
 
490
  if (s.length()+offset <= str_length)
 
491
  {
 
492
    if (!s.length())
 
493
      return ((int) offset);    // Empty string is always found
 
494
 
 
495
    register const char *str = Ptr+offset;
 
496
    register const char *search=s.ptr();
 
497
    const char *end=Ptr+str_length-s.length()+1;
 
498
    const char *search_end=s.ptr()+s.length();
 
499
skip:
 
500
    while (str != end)
 
501
    {
 
502
      if (*str++ == *search)
 
503
      {
 
504
        register char *i,*j;
 
505
        i=(char*) str; j=(char*) search+1;
 
506
        while (j != search_end)
 
507
          if (*i++ != *j++) goto skip;
 
508
        return (int) (str-Ptr) -1;
 
509
      }
 
510
    }
 
511
  }
 
512
  return -1;
 
513
}
 
514
 
 
515
/*
 
516
** Search string from end. Offset is offset to the end of string
 
517
*/
 
518
 
 
519
int String::strrstr(const String &s,uint32 offset)
 
520
{
 
521
  if (s.length() <= offset && offset <= str_length)
 
522
  {
 
523
    if (!s.length())
 
524
      return offset;                            // Empty string is always found
 
525
    register const char *str = Ptr+offset-1;
 
526
    register const char *search=s.ptr()+s.length()-1;
 
527
 
 
528
    const char *end=Ptr+s.length()-2;
 
529
    const char *search_end=s.ptr()-1;
 
530
skip:
 
531
    while (str != end)
 
532
    {
 
533
      if (*str-- == *search)
 
534
      {
 
535
        register char *i,*j;
 
536
        i=(char*) str; j=(char*) search-1;
 
537
        while (j != search_end)
 
538
          if (*i-- != *j--) goto skip;
 
539
        return (int) (i-Ptr) +1;
 
540
      }
 
541
    }
 
542
  }
 
543
  return -1;
 
544
}
 
545
 
 
546
/*
 
547
  Replace substring with string
 
548
  If wrong parameter or not enough memory, do nothing
 
549
*/
 
550
 
 
551
bool String::replace(uint32 offset,uint32 arg_length,const String &to)
 
552
{
 
553
  return replace(offset,arg_length,to.ptr(),to.length());
 
554
}
 
555
 
 
556
bool String::replace(uint32 offset,uint32 arg_length,
 
557
                     const char *to, uint32 to_length)
 
558
{
 
559
  long diff = (long) to_length-(long) arg_length;
 
560
  if (offset+arg_length <= str_length)
 
561
  {
 
562
    if (diff < 0)
 
563
    {
 
564
      if (to_length)
 
565
        memcpy(Ptr+offset,to,to_length);
 
566
      bmove(Ptr+offset+to_length,Ptr+offset+arg_length,
 
567
            str_length-offset-arg_length);
 
568
    }
 
569
    else
 
570
    {
 
571
      if (diff)
 
572
      {
 
573
        if (realloc(str_length+(uint32) diff))
 
574
          return TRUE;
 
575
        bmove_upp((uchar*) Ptr+str_length+diff, (uchar*) Ptr+str_length,
 
576
                  str_length-offset-arg_length);
 
577
      }
 
578
      if (to_length)
 
579
        memcpy(Ptr+offset,to,to_length);
 
580
    }
 
581
    str_length+=(uint32) diff;
 
582
  }
 
583
  return FALSE;
 
584
}
 
585
 
 
586
 
 
587
// added by Holyfoot for "geometry" needs
 
588
int String::reserve(uint32 space_needed, uint32 grow_by)
 
589
{
 
590
  if (Alloced_length < str_length + space_needed)
 
591
  {
 
592
    if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
 
593
      return TRUE;
 
594
  }
 
595
  return FALSE;
 
596
}
 
597
 
 
598
void String::qs_append(const char *str, uint32 len)
 
599
{
 
600
  memcpy(Ptr + str_length, str, len + 1);
 
601
  str_length += len;
 
602
}
 
603
 
 
604
void String::qs_append(double d)
 
605
{
 
606
  char *buff = Ptr + str_length;
 
607
  str_length+= my_gcvt(d, MY_GCVT_ARG_DOUBLE, FLOATING_POINT_BUFFER - 1, buff, NULL);
 
608
}
 
609
 
 
610
void String::qs_append(double *d)
 
611
{
 
612
  double ld;
 
613
  float8get(ld, (char*) d);
 
614
  qs_append(ld);
 
615
}
 
616
 
 
617
void String::qs_append(int i)
 
618
{
 
619
  char *buff= Ptr + str_length;
 
620
  char *end= int10_to_str(i, buff, -10);
 
621
  str_length+= (int) (end-buff);
 
622
}
 
623
 
 
624
void String::qs_append(uint i)
 
625
{
 
626
  char *buff= Ptr + str_length;
 
627
  char *end= int10_to_str(i, buff, 10);
 
628
  str_length+= (int) (end-buff);
 
629
}
 
630
 
 
631
/*
 
632
  Compare strings according to collation, without end space.
 
633
 
 
634
  SYNOPSIS
 
635
    sortcmp()
 
636
    s           First string
 
637
    t           Second string
 
638
    cs          Collation
 
639
 
 
640
  NOTE:
 
641
    Normally this is case sensitive comparison
 
642
 
 
643
  RETURN
 
644
  < 0   s < t
 
645
  0     s == t
 
646
  > 0   s > t
 
647
*/
 
648
 
 
649
 
 
650
int sortcmp(const String *s,const String *t, CHARSET_INFO *cs)
 
651
{
 
652
 return cs->coll->strnncollsp(cs,
 
653
                              (uchar *) s->ptr(),s->length(),
 
654
                              (uchar *) t->ptr(),t->length(), 0);
 
655
}
 
656
 
 
657
 
 
658
/*
 
659
  Compare strings byte by byte. End spaces are also compared.
 
660
 
 
661
  SYNOPSIS
 
662
    stringcmp()
 
663
    s           First string
 
664
    t           Second string
 
665
 
 
666
  NOTE:
 
667
    Strings are compared as a stream of uchars
 
668
 
 
669
  RETURN
 
670
  < 0   s < t
 
671
  0     s == t
 
672
  > 0   s > t
 
673
*/
 
674
 
 
675
 
 
676
int stringcmp(const String *s,const String *t)
 
677
{
 
678
  uint32 s_len=s->length(),t_len=t->length(),len=min(s_len,t_len);
 
679
  int cmp= memcmp(s->ptr(), t->ptr(), len);
 
680
  return (cmp) ? cmp : (int) (s_len - t_len);
 
681
}
 
682
 
 
683
 
 
684
String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
 
685
{
 
686
  if (from->Alloced_length >= from_length)
 
687
    return from;
 
688
  if (from->alloced || !to || from == to)
 
689
  {
 
690
    (void) from->realloc(from_length);
 
691
    return from;
 
692
  }
 
693
  if (to->realloc(from_length))
 
694
    return from;                                // Actually an error
 
695
  if ((to->str_length=min(from->str_length,from_length)))
 
696
    memcpy(to->Ptr,from->Ptr,to->str_length);
 
697
  to->str_charset=from->str_charset;
 
698
  return to;
 
699
}
 
700
 
 
701
 
 
702
/****************************************************************************
 
703
  Help functions
 
704
****************************************************************************/
 
705
 
 
706
/*
 
707
  copy a string from one character set to another
 
708
  
 
709
  SYNOPSIS
 
710
    copy_and_convert()
 
711
    to                  Store result here
 
712
    to_cs               Character set of result string
 
713
    from                Copy from here
 
714
    from_length         Length of from string
 
715
    from_cs             From character set
 
716
 
 
717
  NOTES
 
718
    'to' must be big enough as form_length * to_cs->mbmaxlen
 
719
 
 
720
  RETURN
 
721
    length of bytes copied to 'to'
 
722
*/
 
723
 
 
724
 
 
725
static uint32
 
726
copy_and_convert_extended(char *to, uint32 to_length, CHARSET_INFO *to_cs, 
 
727
                          const char *from, uint32 from_length,
 
728
                          CHARSET_INFO *from_cs,
 
729
                          uint *errors)
 
730
{
 
731
  int         cnvres;
 
732
  my_wc_t     wc;
 
733
  const uchar *from_end= (const uchar*) from+from_length;
 
734
  char *to_start= to;
 
735
  uchar *to_end= (uchar*) to+to_length;
 
736
  my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
 
737
  my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
 
738
  uint error_count= 0;
 
739
 
 
740
  while (1)
 
741
  {
 
742
    if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
 
743
                                      from_end)) > 0)
 
744
      from+= cnvres;
 
745
    else if (cnvres == MY_CS_ILSEQ)
 
746
    {
 
747
      error_count++;
 
748
      from++;
 
749
      wc= '?';
 
750
    }
 
751
    else if (cnvres > MY_CS_TOOSMALL)
 
752
    {
 
753
      /*
 
754
        A correct multibyte sequence detected
 
755
        But it doesn't have Unicode mapping.
 
756
      */
 
757
      error_count++;
 
758
      from+= (-cnvres);
 
759
      wc= '?';
 
760
    }
 
761
    else
 
762
      break;  // Not enough characters
 
763
 
 
764
outp:
 
765
    if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
 
766
      to+= cnvres;
 
767
    else if (cnvres == MY_CS_ILUNI && wc != '?')
 
768
    {
 
769
      error_count++;
 
770
      wc= '?';
 
771
      goto outp;
 
772
    }
 
773
    else
 
774
      break;
 
775
  }
 
776
  *errors= error_count;
 
777
  return (uint32) (to - to_start);
 
778
}
 
779
 
 
780
 
 
781
/*
 
782
  Optimized for quick copying of ASCII characters in the range 0x00..0x7F.
 
783
*/
 
784
uint32
 
785
copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, 
 
786
                 const char *from, uint32 from_length, CHARSET_INFO *from_cs,
 
787
                 uint *errors)
 
788
{
 
789
  /*
 
790
    If any of the character sets is not ASCII compatible,
 
791
    immediately switch to slow mb_wc->wc_mb method.
 
792
  */
 
793
  if ((to_cs->state | from_cs->state) & MY_CS_NONASCII)
 
794
    return copy_and_convert_extended(to, to_length, to_cs,
 
795
                                     from, from_length, from_cs, errors);
 
796
 
 
797
  uint32 length= min(to_length, from_length), length2= length;
 
798
 
 
799
#if defined(__i386__)
 
800
  /*
 
801
    Special loop for i386, it allows to refer to a
 
802
    non-aligned memory block as UINT32, which makes
 
803
    it possible to copy four bytes at once. This
 
804
    gives about 10% performance improvement comparing
 
805
    to byte-by-byte loop.
 
806
  */
 
807
  for ( ; length >= 4; length-= 4, from+= 4, to+= 4)
 
808
  {
 
809
    if ((*(uint32*)from) & 0x80808080)
 
810
      break;
 
811
    *((uint32*) to)= *((const uint32*) from);
 
812
  }
 
813
#endif
 
814
 
 
815
  for (; ; *to++= *from++, length--)
 
816
  {
 
817
    if (!length)
 
818
    {
 
819
      *errors= 0;
 
820
      return length2;
 
821
    }
 
822
    if (*((unsigned char*) from) > 0x7F) /* A non-ASCII character */
 
823
    {
 
824
      uint32 copied_length= length2 - length;
 
825
      to_length-= copied_length;
 
826
      from_length-= copied_length;
 
827
      return copied_length + copy_and_convert_extended(to, to_length,
 
828
                                                       to_cs,
 
829
                                                       from, from_length,
 
830
                                                       from_cs,
 
831
                                                       errors);
 
832
    }
 
833
  }
 
834
 
 
835
  DBUG_ASSERT(FALSE); // Should never get to here
 
836
  return 0;           // Make compiler happy
 
837
}
 
838
 
 
839
 
 
840
/**
 
841
  Copy string with HEX-encoding of "bad" characters.
 
842
 
 
843
  @details This functions copies the string pointed by "src"
 
844
  to the string pointed by "dst". Not more than "srclen" bytes
 
845
  are read from "src". Any sequences of bytes representing
 
846
  a not-well-formed substring (according to cs) are hex-encoded,
 
847
  and all well-formed substrings (according to cs) are copied as is.
 
848
  Not more than "dstlen" bytes are written to "dst". The number 
 
849
  of bytes written to "dst" is returned.
 
850
  
 
851
   @param      cs       character set pointer of the destination string
 
852
   @param[out] dst      destination string
 
853
   @param      dstlen   size of dst
 
854
   @param      src      source string
 
855
   @param      srclen   length of src
 
856
 
 
857
   @retval     result length
 
858
*/
 
859
 
 
860
size_t
 
861
my_copy_with_hex_escaping(CHARSET_INFO *cs,
 
862
                          char *dst, size_t dstlen,
 
863
                          const char *src, size_t srclen)
 
864
{
 
865
  const char *srcend= src + srclen;
 
866
  char *dst0= dst;
 
867
 
 
868
  for ( ; src < srcend ; )
 
869
  {
 
870
    size_t chlen;
 
871
    if ((chlen= my_ismbchar(cs, src, srcend)))
 
872
    {
 
873
      if (dstlen < chlen)
 
874
        break; /* purecov: inspected */
 
875
      memcpy(dst, src, chlen);
 
876
      src+= chlen;
 
877
      dst+= chlen;
 
878
      dstlen-= chlen;
 
879
    }
 
880
    else if (*src & 0x80)
 
881
    {
 
882
      if (dstlen < 4)
 
883
        break; /* purecov: inspected */
 
884
      *dst++= '\\';
 
885
      *dst++= 'x';
 
886
      *dst++= _dig_vec_upper[((unsigned char) *src) >> 4];
 
887
      *dst++= _dig_vec_upper[((unsigned char) *src) & 15];
 
888
      src++;
 
889
      dstlen-= 4;
 
890
    }
 
891
    else
 
892
    {
 
893
      if (dstlen < 1)
 
894
        break; /* purecov: inspected */
 
895
      *dst++= *src++;
 
896
      dstlen--;
 
897
    }
 
898
  }
 
899
  return dst - dst0;
 
900
}
 
901
 
 
902
/*
 
903
  copy a string,
 
904
  with optional character set conversion,
 
905
  with optional left padding (for binary -> UCS2 conversion)
 
906
  
 
907
  SYNOPSIS
 
908
    well_formed_copy_nchars()
 
909
    to                       Store result here
 
910
    to_length                Maxinum length of "to" string
 
911
    to_cs                    Character set of "to" string
 
912
    from                     Copy from here
 
913
    from_length              Length of from string
 
914
    from_cs                  From character set
 
915
    nchars                   Copy not more that nchars characters
 
916
    well_formed_error_pos    Return position when "from" is not well formed
 
917
                             or NULL otherwise.
 
918
    cannot_convert_error_pos Return position where a not convertable
 
919
                             character met, or NULL otherwise.
 
920
    from_end_pos             Return position where scanning of "from"
 
921
                             string stopped.
 
922
  NOTES
 
923
 
 
924
  RETURN
 
925
    length of bytes copied to 'to'
 
926
*/
 
927
 
 
928
 
 
929
uint32
 
930
well_formed_copy_nchars(CHARSET_INFO *to_cs,
 
931
                        char *to, uint to_length,
 
932
                        CHARSET_INFO *from_cs,
 
933
                        const char *from, uint from_length,
 
934
                        uint nchars,
 
935
                        const char **well_formed_error_pos,
 
936
                        const char **cannot_convert_error_pos,
 
937
                        const char **from_end_pos)
 
938
{
 
939
  uint res;
 
940
 
 
941
  if ((to_cs == &my_charset_bin) || 
 
942
      (from_cs == &my_charset_bin) ||
 
943
      (to_cs == from_cs) ||
 
944
      my_charset_same(from_cs, to_cs))
 
945
  {
 
946
    if (to_length < to_cs->mbminlen || !nchars)
 
947
    {
 
948
      *from_end_pos= from;
 
949
      *cannot_convert_error_pos= NULL;
 
950
      *well_formed_error_pos= NULL;
 
951
      return 0;
 
952
    }
 
953
 
 
954
    if (to_cs == &my_charset_bin)
 
955
    {
 
956
      res= min(min(nchars, to_length), from_length);
 
957
      memmove(to, from, res);
 
958
      *from_end_pos= from + res;
 
959
      *well_formed_error_pos= NULL;
 
960
      *cannot_convert_error_pos= NULL;
 
961
    }
 
962
    else
 
963
    {
 
964
      int well_formed_error;
 
965
      uint from_offset;
 
966
 
 
967
      if ((from_offset= (from_length % to_cs->mbminlen)) &&
 
968
          (from_cs == &my_charset_bin))
 
969
      {
 
970
        /*
 
971
          Copying from BINARY to UCS2 needs to prepend zeros sometimes:
 
972
          INSERT INTO t1 (ucs2_column) VALUES (0x01);
 
973
          0x01 -> 0x0001
 
974
        */
 
975
        uint pad_length= to_cs->mbminlen - from_offset;
 
976
        bzero(to, pad_length);
 
977
        memmove(to + pad_length, from, from_offset);
 
978
        nchars--;
 
979
        from+= from_offset;
 
980
        from_length-= from_offset;
 
981
        to+= to_cs->mbminlen;
 
982
        to_length-= to_cs->mbminlen;
 
983
      }
 
984
 
 
985
      set_if_smaller(from_length, to_length);
 
986
      res= to_cs->cset->well_formed_len(to_cs, from, from + from_length,
 
987
                                        nchars, &well_formed_error);
 
988
      memmove(to, from, res);
 
989
      *from_end_pos= from + res;
 
990
      *well_formed_error_pos= well_formed_error ? from + res : NULL;
 
991
      *cannot_convert_error_pos= NULL;
 
992
      if (from_offset)
 
993
        res+= to_cs->mbminlen;
 
994
    }
 
995
  }
 
996
  else
 
997
  {
 
998
    int cnvres;
 
999
    my_wc_t wc;
 
1000
    my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
 
1001
    my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
 
1002
    const uchar *from_end= (const uchar*) from + from_length;
 
1003
    uchar *to_end= (uchar*) to + to_length;
 
1004
    char *to_start= to;
 
1005
    *well_formed_error_pos= NULL;
 
1006
    *cannot_convert_error_pos= NULL;
 
1007
 
 
1008
    for ( ; nchars; nchars--)
 
1009
    {
 
1010
      const char *from_prev= from;
 
1011
      if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0)
 
1012
        from+= cnvres;
 
1013
      else if (cnvres == MY_CS_ILSEQ)
 
1014
      {
 
1015
        if (!*well_formed_error_pos)
 
1016
          *well_formed_error_pos= from;
 
1017
        from++;
 
1018
        wc= '?';
 
1019
      }
 
1020
      else if (cnvres > MY_CS_TOOSMALL)
 
1021
      {
 
1022
        /*
 
1023
          A correct multibyte sequence detected
 
1024
          But it doesn't have Unicode mapping.
 
1025
        */
 
1026
        if (!*cannot_convert_error_pos)
 
1027
          *cannot_convert_error_pos= from;
 
1028
        from+= (-cnvres);
 
1029
        wc= '?';
 
1030
      }
 
1031
      else
 
1032
        break;  // Not enough characters
 
1033
 
 
1034
outp:
 
1035
      if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
 
1036
        to+= cnvres;
 
1037
      else if (cnvres == MY_CS_ILUNI && wc != '?')
 
1038
      {
 
1039
        if (!*cannot_convert_error_pos)
 
1040
          *cannot_convert_error_pos= from_prev;
 
1041
        wc= '?';
 
1042
        goto outp;
 
1043
      }
 
1044
      else
 
1045
      {
 
1046
        from= from_prev;
 
1047
        break;
 
1048
      }
 
1049
    }
 
1050
    *from_end_pos= from;
 
1051
    res= to - to_start;
 
1052
  }
 
1053
  return (uint32) res;
 
1054
}
 
1055
 
 
1056
 
 
1057
 
 
1058
 
 
1059
void String::print(String *str)
 
1060
{
 
1061
  char *st= (char*)Ptr, *end= st+str_length;
 
1062
  for (; st < end; st++)
 
1063
  {
 
1064
    uchar c= *st;
 
1065
    switch (c)
 
1066
    {
 
1067
    case '\\':
 
1068
      str->append(STRING_WITH_LEN("\\\\"));
 
1069
      break;
 
1070
    case '\0':
 
1071
      str->append(STRING_WITH_LEN("\\0"));
 
1072
      break;
 
1073
    case '\'':
 
1074
      str->append(STRING_WITH_LEN("\\'"));
 
1075
      break;
 
1076
    case '\n':
 
1077
      str->append(STRING_WITH_LEN("\\n"));
 
1078
      break;
 
1079
    case '\r':
 
1080
      str->append(STRING_WITH_LEN("\\r"));
 
1081
      break;
 
1082
    case '\032': // Ctrl-Z
 
1083
      str->append(STRING_WITH_LEN("\\Z"));
 
1084
      break;
 
1085
    default:
 
1086
      str->append(c);
 
1087
    }
 
1088
  }
 
1089
}
 
1090
 
 
1091
 
 
1092
/*
 
1093
  Exchange state of this object and argument.
 
1094
 
 
1095
  SYNOPSIS
 
1096
    String::swap()
 
1097
 
 
1098
  RETURN
 
1099
    Target string will contain state of this object and vice versa.
 
1100
*/
 
1101
 
 
1102
void String::swap(String &s)
 
1103
{
 
1104
  swap_variables(char *, Ptr, s.Ptr);
 
1105
  swap_variables(uint32, str_length, s.str_length);
 
1106
  swap_variables(uint32, Alloced_length, s.Alloced_length);
 
1107
  swap_variables(bool, alloced, s.alloced);
 
1108
  swap_variables(CHARSET_INFO*, str_charset, s.str_charset);
 
1109
}