~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/sql_string.cc

  • Committer: Monty Taylor
  • Date: 2008-07-12 19:42:00 UTC
  • mto: (77.6.1 glibclient-merge)
  • mto: This revision was merged to the branch mainline in revision 176.
  • Revision ID: monty@inaugust.com-20080712194200-egj34gi1ni29t9uf
Last change to migrate to glib from sql_string.

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 void sql_alloc(size_t 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(longlong num, CHARSET_INFO *cs)
99
 
{
100
 
  uint l=20*cs->mbmaxlen+1;
101
 
 
102
 
  if (alloc(l))
103
 
    return TRUE;
104
 
  str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,-10,num);
105
 
  str_charset=cs;
106
 
  return FALSE;
107
 
}
108
 
 
109
 
bool String::set(ulonglong num, CHARSET_INFO *cs)
110
 
{
111
 
  uint l=20*cs->mbmaxlen+1;
112
 
 
113
 
  if (alloc(l))
114
 
    return TRUE;
115
 
  str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,10,num);
116
 
  str_charset=cs;
117
 
  return FALSE;
118
 
}
119
 
 
120
 
bool String::set(double num,uint decimals, CHARSET_INFO *cs)
121
 
{
122
 
  char buff[331];
123
 
  uint dummy_errors;
124
 
 
125
 
  str_charset=cs;
126
 
  if (decimals >= NOT_FIXED_DEC)
127
 
  {
128
 
    uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME
129
 
    return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
130
 
  }
131
 
#ifdef HAVE_SNPRINTF
132
 
  buff[sizeof(buff)-1]=0;                       // Safety
133
 
  snprintf(buff,sizeof(buff)-1, "%.*f",(int) decimals,num);
134
 
#else
135
 
  sprintf(buff,"%.*f",(int) decimals,num);
136
 
#endif
137
 
  return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs,
138
 
              &dummy_errors);
139
 
}
140
 
 
141
 
 
142
 
bool String::copy()
143
 
{
144
 
  if (!alloced)
145
 
  {
146
 
    Alloced_length=0;                           // Force realloc
147
 
    return realloc(str_length);
148
 
  }
149
 
  return FALSE;
150
 
}
151
 
 
152
 
bool String::copy(const String &str)
153
 
{
154
 
  if (alloc(str.str_length))
155
 
    return TRUE;
156
 
  str_length=str.str_length;
157
 
  bmove(Ptr,str.Ptr,str_length);                // May be overlapping
158
 
  Ptr[str_length]=0;
159
 
  str_charset=str.str_charset;
160
 
  return FALSE;
161
 
}
162
 
 
163
 
bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
164
 
{
165
 
  if (alloc(arg_length))
166
 
    return TRUE;
167
 
  if ((str_length=arg_length))
168
 
    memcpy(Ptr,str,arg_length);
169
 
  Ptr[arg_length]=0;
170
 
  str_charset=cs;
171
 
  return FALSE;
172
 
}
173
 
 
174
 
 
175
 
/*
176
 
  Checks that the source string can be just copied to the destination string
177
 
  without conversion.
178
 
 
179
 
  SYNPOSIS
180
 
 
181
 
  needs_conversion()
182
 
  arg_length            Length of string to copy.
183
 
  from_cs               Character set to copy from
184
 
  to_cs                 Character set to copy to
185
 
  uint32 *offset        Returns number of unaligned characters.
186
 
 
187
 
  RETURN
188
 
   0  No conversion needed
189
 
   1  Either character set conversion or adding leading  zeros
190
 
      (e.g. for UCS-2) must be done
191
 
 
192
 
  NOTE
193
 
  to_cs may be NULL for "no conversion" if the system variable
194
 
  character_set_results is NULL.
195
 
*/
196
 
 
197
 
bool String::needs_conversion(uint32 arg_length,
198
 
                              CHARSET_INFO *from_cs,
199
 
                              CHARSET_INFO *to_cs,
200
 
                              uint32 *offset)
201
 
{
202
 
  *offset= 0;
203
 
  if (!to_cs ||
204
 
      (to_cs == &my_charset_bin) || 
205
 
      (to_cs == from_cs) ||
206
 
      my_charset_same(from_cs, to_cs) ||
207
 
      ((from_cs == &my_charset_bin) &&
208
 
       (!(*offset=(arg_length % to_cs->mbminlen)))))
209
 
    return FALSE;
210
 
  return TRUE;
211
 
}
212
 
 
213
 
 
214
 
/*
215
 
  Copy a multi-byte character sets with adding leading zeros.
216
 
 
217
 
  SYNOPSIS
218
 
 
219
 
  copy_aligned()
220
 
  str                   String to copy
221
 
  arg_length            Length of string. This should NOT be dividable with
222
 
                        cs->mbminlen.
223
 
  offset                arg_length % cs->mb_minlength
224
 
  cs                    Character set for 'str'
225
 
 
226
 
  NOTES
227
 
    For real multi-byte, ascii incompatible charactser sets,
228
 
    like UCS-2, add leading zeros if we have an incomplete character.
229
 
    Thus, 
230
 
      SELECT _ucs2 0xAA 
231
 
    will automatically be converted into
232
 
      SELECT _ucs2 0x00AA
233
 
 
234
 
  RETURN
235
 
    0  ok
236
 
    1  error
237
 
*/
238
 
 
239
 
bool String::copy_aligned(const char *str,uint32 arg_length, uint32 offset,
240
 
                          CHARSET_INFO *cs)
241
 
{
242
 
  /* How many bytes are in incomplete character */
243
 
  offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */
244
 
  DBUG_ASSERT(offset && offset != cs->mbmaxlen);
245
 
 
246
 
  uint32 aligned_length= arg_length + offset;
247
 
  if (alloc(aligned_length))
248
 
    return TRUE;
249
 
  
250
 
  /*
251
 
    Note, this is only safe for little-endian UCS-2.
252
 
    If we add big-endian UCS-2 sometimes, this code
253
 
    will be more complicated. But it's OK for now.
254
 
  */
255
 
  bzero((char*) Ptr, offset);
256
 
  memcpy(Ptr + offset, str, arg_length);
257
 
  Ptr[aligned_length]=0;
258
 
  /* str_length is always >= 0 as arg_length is != 0 */
259
 
  str_length= aligned_length;
260
 
  str_charset= cs;
261
 
  return FALSE;
262
 
}
263
 
 
264
 
 
265
 
bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
266
 
                                 CHARSET_INFO *cs)
267
 
{
268
 
  /* How many bytes are in incomplete character */
269
 
  uint32 offset= (arg_length % cs->mbminlen); 
270
 
  
271
 
  if (!offset) /* All characters are complete, just copy */
272
 
  {
273
 
    set(str, arg_length, cs);
274
 
    return FALSE;
275
 
  }
276
 
  return copy_aligned(str, arg_length, offset, cs);
277
 
}
278
 
 
279
 
        /* Copy with charset convertion */
280
 
 
281
 
bool String::copy(const char *str, uint32 arg_length,
282
 
                  CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
283
 
{
284
 
  uint32 offset;
285
 
  if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
286
 
  {
287
 
    *errors= 0;
288
 
    return copy(str, arg_length, to_cs);
289
 
  }
290
 
  if ((from_cs == &my_charset_bin) && offset)
291
 
  {
292
 
    *errors= 0;
293
 
    return copy_aligned(str, arg_length, offset, to_cs);
294
 
  }
295
 
  uint32 new_length= to_cs->mbmaxlen*arg_length;
296
 
  if (alloc(new_length))
297
 
    return TRUE;
298
 
  str_length=copy_and_convert((char*) Ptr, new_length, to_cs,
299
 
                              str, arg_length, from_cs, errors);
300
 
  str_charset=to_cs;
301
 
  return FALSE;
302
 
}
303
 
 
304
 
 
305
 
/*
306
 
  Set a string to the value of a latin1-string, keeping the original charset
307
 
  
308
 
  SYNOPSIS
309
 
    copy_or_set()
310
 
    str                 String of a simple charset (latin1)
311
 
    arg_length          Length of string
312
 
 
313
 
  IMPLEMENTATION
314
 
    If string object is of a simple character set, set it to point to the
315
 
    given string.
316
 
    If not, make a copy and convert it to the new character set.
317
 
 
318
 
  RETURN
319
 
    0   ok
320
 
    1   Could not allocate result buffer
321
 
 
322
 
*/
323
 
 
324
 
bool String::set_ascii(const char *str, uint32 arg_length)
325
 
{
326
 
  if (str_charset->mbminlen == 1)
327
 
  {
328
 
    set(str, arg_length, str_charset);
329
 
    return 0;
330
 
  }
331
 
  uint dummy_errors;
332
 
  return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors);
333
 
}
334
 
 
335
 
 
336
 
/* This is used by mysql.cc */
337
 
 
338
 
bool String::fill(uint32 max_length,char fill_char)
339
 
{
340
 
  if (str_length > max_length)
341
 
    Ptr[str_length=max_length]=0;
342
 
  else
343
 
  {
344
 
    if (realloc(max_length))
345
 
      return TRUE;
346
 
    bfill(Ptr+str_length,max_length-str_length,fill_char);
347
 
    str_length=max_length;
348
 
  }
349
 
  return FALSE;
350
 
}
351
 
 
352
 
void String::strip_sp()
353
 
{
354
 
   while (str_length && my_isspace(str_charset,Ptr[str_length-1]))
355
 
    str_length--;
356
 
}
357
 
 
358
 
bool String::append(const String &s)
359
 
{
360
 
  if (s.length())
361
 
  {
362
 
    if (realloc(str_length+s.length()))
363
 
      return TRUE;
364
 
    memcpy(Ptr+str_length,s.ptr(),s.length());
365
 
    str_length+=s.length();
366
 
  }
367
 
  return FALSE;
368
 
}
369
 
 
370
 
 
371
 
/*
372
 
  Append an ASCII string to the a string of the current character set
373
 
*/
374
 
 
375
 
bool String::append(const char *s,uint32 arg_length)
376
 
{
377
 
  if (!arg_length)
378
 
    return FALSE;
379
 
 
380
 
  /*
381
 
    For an ASCII incompatible string, e.g. UCS-2, we need to convert
382
 
  */
383
 
  if (str_charset->mbminlen > 1)
384
 
  {
385
 
    uint32 add_length=arg_length * str_charset->mbmaxlen;
386
 
    uint dummy_errors;
387
 
    if (realloc(str_length+ add_length))
388
 
      return TRUE;
389
 
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
390
 
                                  s, arg_length, &my_charset_latin1,
391
 
                                  &dummy_errors);
392
 
    return FALSE;
393
 
  }
394
 
 
395
 
  /*
396
 
    For an ASCII compatinble string we can just append.
397
 
  */
398
 
  if (realloc(str_length+arg_length))
399
 
    return TRUE;
400
 
  memcpy(Ptr+str_length,s,arg_length);
401
 
  str_length+=arg_length;
402
 
  return FALSE;
403
 
}
404
 
 
405
 
 
406
 
/*
407
 
  Append a 0-terminated ASCII string
408
 
*/
409
 
 
410
 
bool String::append(const char *s)
411
 
{
412
 
  return append(s, strlen(s));
413
 
}
414
 
 
415
 
 
416
 
/*
417
 
  Append a string in the given charset to the string
418
 
  with character set recoding
419
 
*/
420
 
 
421
 
bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs)
422
 
{
423
 
  uint32 dummy_offset;
424
 
  
425
 
  if (needs_conversion(arg_length, cs, str_charset, &dummy_offset))
426
 
  {
427
 
    uint32 add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
428
 
    uint dummy_errors;
429
 
    if (realloc(str_length + add_length)) 
430
 
      return TRUE;
431
 
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
432
 
                                  s, arg_length, cs, &dummy_errors);
433
 
  }
434
 
  else
435
 
  {
436
 
    if (realloc(str_length + arg_length)) 
437
 
      return TRUE;
438
 
    memcpy(Ptr + str_length, s, arg_length);
439
 
    str_length+= arg_length;
440
 
  }
441
 
  return FALSE;
442
 
}
443
 
 
444
 
 
445
 
bool String::append(IO_CACHE* file, uint32 arg_length)
446
 
{
447
 
  if (realloc(str_length+arg_length))
448
 
    return TRUE;
449
 
  if (my_b_read(file, (uchar*) Ptr + str_length, arg_length))
450
 
  {
451
 
    shrink(str_length);
452
 
    return TRUE;
453
 
  }
454
 
  str_length+=arg_length;
455
 
  return FALSE;
456
 
}
457
 
 
458
 
bool String::append_with_prefill(const char *s,uint32 arg_length,
459
 
                 uint32 full_length, char fill_char)
460
 
{
461
 
  int t_length= arg_length > full_length ? arg_length : full_length;
462
 
 
463
 
  if (realloc(str_length + t_length))
464
 
    return TRUE;
465
 
  t_length= full_length - arg_length;
466
 
  if (t_length > 0)
467
 
  {
468
 
    bfill(Ptr+str_length, t_length, fill_char);
469
 
    str_length=str_length + t_length;
470
 
  }
471
 
  append(s, arg_length);
472
 
  return FALSE;
473
 
}
474
 
 
475
 
uint32 String::numchars()
476
 
{
477
 
  return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
478
 
}
479
 
 
480
 
int String::charpos(int i,uint32 offset)
481
 
{
482
 
  if (i <= 0)
483
 
    return i;
484
 
  return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
485
 
}
486
 
 
487
 
int String::strstr(const String &s,uint32 offset)
488
 
{
489
 
  if (s.length()+offset <= str_length)
490
 
  {
491
 
    if (!s.length())
492
 
      return ((int) offset);    // Empty string is always found
493
 
 
494
 
    register const char *str = Ptr+offset;
495
 
    register const char *search=s.ptr();
496
 
    const char *end=Ptr+str_length-s.length()+1;
497
 
    const char *search_end=s.ptr()+s.length();
498
 
skip:
499
 
    while (str != end)
500
 
    {
501
 
      if (*str++ == *search)
502
 
      {
503
 
        register char *i,*j;
504
 
        i=(char*) str; j=(char*) search+1;
505
 
        while (j != search_end)
506
 
          if (*i++ != *j++) goto skip;
507
 
        return (int) (str-Ptr) -1;
508
 
      }
509
 
    }
510
 
  }
511
 
  return -1;
512
 
}
513
 
 
514
 
/*
515
 
** Search string from end. Offset is offset to the end of string
516
 
*/
517
 
 
518
 
int String::strrstr(const String &s,uint32 offset)
519
 
{
520
 
  if (s.length() <= offset && offset <= str_length)
521
 
  {
522
 
    if (!s.length())
523
 
      return offset;                            // Empty string is always found
524
 
    register const char *str = Ptr+offset-1;
525
 
    register const char *search=s.ptr()+s.length()-1;
526
 
 
527
 
    const char *end=Ptr+s.length()-2;
528
 
    const char *search_end=s.ptr()-1;
529
 
skip:
530
 
    while (str != end)
531
 
    {
532
 
      if (*str-- == *search)
533
 
      {
534
 
        register char *i,*j;
535
 
        i=(char*) str; j=(char*) search-1;
536
 
        while (j != search_end)
537
 
          if (*i-- != *j--) goto skip;
538
 
        return (int) (i-Ptr) +1;
539
 
      }
540
 
    }
541
 
  }
542
 
  return -1;
543
 
}
544
 
 
545
 
/*
546
 
  Replace substring with string
547
 
  If wrong parameter or not enough memory, do nothing
548
 
*/
549
 
 
550
 
bool String::replace(uint32 offset,uint32 arg_length,const String &to)
551
 
{
552
 
  return replace(offset,arg_length,to.ptr(),to.length());
553
 
}
554
 
 
555
 
bool String::replace(uint32 offset,uint32 arg_length,
556
 
                     const char *to, uint32 to_length)
557
 
{
558
 
  long diff = (long) to_length-(long) arg_length;
559
 
  if (offset+arg_length <= str_length)
560
 
  {
561
 
    if (diff < 0)
562
 
    {
563
 
      if (to_length)
564
 
        memcpy(Ptr+offset,to,to_length);
565
 
      bmove(Ptr+offset+to_length,Ptr+offset+arg_length,
566
 
            str_length-offset-arg_length);
567
 
    }
568
 
    else
569
 
    {
570
 
      if (diff)
571
 
      {
572
 
        if (realloc(str_length+(uint32) diff))
573
 
          return TRUE;
574
 
        bmove_upp((uchar*) Ptr+str_length+diff, (uchar*) Ptr+str_length,
575
 
                  str_length-offset-arg_length);
576
 
      }
577
 
      if (to_length)
578
 
        memcpy(Ptr+offset,to,to_length);
579
 
    }
580
 
    str_length+=(uint32) diff;
581
 
  }
582
 
  return FALSE;
583
 
}
584
 
 
585
 
 
586
 
// added by Holyfoot for "geometry" needs
587
 
int String::reserve(uint32 space_needed, uint32 grow_by)
588
 
{
589
 
  if (Alloced_length < str_length + space_needed)
590
 
  {
591
 
    if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
592
 
      return TRUE;
593
 
  }
594
 
  return FALSE;
595
 
}
596
 
 
597
 
void String::qs_append(const char *str, uint32 len)
598
 
{
599
 
  memcpy(Ptr + str_length, str, len + 1);
600
 
  str_length += len;
601
 
}
602
 
 
603
 
void String::qs_append(double d)
604
 
{
605
 
  char *buff = Ptr + str_length;
606
 
  str_length+= my_gcvt(d, MY_GCVT_ARG_DOUBLE, FLOATING_POINT_BUFFER - 1, buff, NULL);
607
 
}
608
 
 
609
 
void String::qs_append(double *d)
610
 
{
611
 
  double ld;
612
 
  float8get(ld, (char*) d);
613
 
  qs_append(ld);
614
 
}
615
 
 
616
 
void String::qs_append(int i)
617
 
{
618
 
  char *buff= Ptr + str_length;
619
 
  char *end= int10_to_str(i, buff, -10);
620
 
  str_length+= (int) (end-buff);
621
 
}
622
 
 
623
 
void String::qs_append(uint i)
624
 
{
625
 
  char *buff= Ptr + str_length;
626
 
  char *end= int10_to_str(i, buff, 10);
627
 
  str_length+= (int) (end-buff);
628
 
}
629
 
 
630
 
/*
631
 
  Compare strings according to collation, without end space.
632
 
 
633
 
  SYNOPSIS
634
 
    sortcmp()
635
 
    s           First string
636
 
    t           Second string
637
 
    cs          Collation
638
 
 
639
 
  NOTE:
640
 
    Normally this is case sensitive comparison
641
 
 
642
 
  RETURN
643
 
  < 0   s < t
644
 
  0     s == t
645
 
  > 0   s > t
646
 
*/
647
 
 
648
 
 
649
 
int sortcmp(const String *s,const String *t, CHARSET_INFO *cs)
650
 
{
651
 
 return cs->coll->strnncollsp(cs,
652
 
                              (unsigned char *) s->ptr(),s->length(),
653
 
                              (unsigned char *) t->ptr(),t->length(), 0);
654
 
}
655
 
 
656
 
 
657
 
/*
658
 
  Compare strings byte by byte. End spaces are also compared.
659
 
 
660
 
  SYNOPSIS
661
 
    stringcmp()
662
 
    s           First string
663
 
    t           Second string
664
 
 
665
 
  NOTE:
666
 
    Strings are compared as a stream of unsigned chars
667
 
 
668
 
  RETURN
669
 
  < 0   s < t
670
 
  0     s == t
671
 
  > 0   s > t
672
 
*/
673
 
 
674
 
 
675
 
int stringcmp(const String *s,const String *t)
676
 
{
677
 
  uint32 s_len=s->length(),t_len=t->length(),len=min(s_len,t_len);
678
 
  int cmp= memcmp(s->ptr(), t->ptr(), len);
679
 
  return (cmp) ? cmp : (int) (s_len - t_len);
680
 
}
681
 
 
682
 
 
683
 
String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
684
 
{
685
 
  if (from->Alloced_length >= from_length)
686
 
    return from;
687
 
  if (from->alloced || !to || from == to)
688
 
  {
689
 
    (void) from->realloc(from_length);
690
 
    return from;
691
 
  }
692
 
  if (to->realloc(from_length))
693
 
    return from;                                // Actually an error
694
 
  if ((to->str_length=min(from->str_length,from_length)))
695
 
    memcpy(to->Ptr,from->Ptr,to->str_length);
696
 
  to->str_charset=from->str_charset;
697
 
  return to;
698
 
}
699
 
 
700
 
 
701
 
/****************************************************************************
702
 
  Help functions
703
 
****************************************************************************/
704
 
 
705
 
/*
706
 
  copy a string from one character set to another
707
 
  
708
 
  SYNOPSIS
709
 
    copy_and_convert()
710
 
    to                  Store result here
711
 
    to_cs               Character set of result string
712
 
    from                Copy from here
713
 
    from_length         Length of from string
714
 
    from_cs             From character set
715
 
 
716
 
  NOTES
717
 
    'to' must be big enough as form_length * to_cs->mbmaxlen
718
 
 
719
 
  RETURN
720
 
    length of bytes copied to 'to'
721
 
*/
722
 
 
723
 
 
724
 
uint32
725
 
copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, 
726
 
                 const char *from, uint32 from_length, CHARSET_INFO *from_cs,
727
 
                 uint *errors)
728
 
{
729
 
  int         cnvres;
730
 
  my_wc_t     wc;
731
 
  const uchar *from_end= (const uchar*) from+from_length;
732
 
  char *to_start= to;
733
 
  uchar *to_end= (uchar*) to+to_length;
734
 
  my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
735
 
  my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
736
 
  uint error_count= 0;
737
 
 
738
 
  while (1)
739
 
  {
740
 
    if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
741
 
                                      from_end)) > 0)
742
 
      from+= cnvres;
743
 
    else if (cnvres == MY_CS_ILSEQ)
744
 
    {
745
 
      error_count++;
746
 
      from++;
747
 
      wc= '?';
748
 
    }
749
 
    else if (cnvres > MY_CS_TOOSMALL)
750
 
    {
751
 
      /*
752
 
        A correct multibyte sequence detected
753
 
        But it doesn't have Unicode mapping.
754
 
      */
755
 
      error_count++;
756
 
      from+= (-cnvres);
757
 
      wc= '?';
758
 
    }
759
 
    else
760
 
      break;  // Not enough characters
761
 
 
762
 
outp:
763
 
    if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
764
 
      to+= cnvres;
765
 
    else if (cnvres == MY_CS_ILUNI && wc != '?')
766
 
    {
767
 
      error_count++;
768
 
      wc= '?';
769
 
      goto outp;
770
 
    }
771
 
    else
772
 
      break;
773
 
  }
774
 
  *errors= error_count;
775
 
  return (uint32) (to - to_start);
776
 
}
777
 
 
778
 
 
779
 
void String::print(String *str)
780
 
{
781
 
  char *st= (char*)Ptr, *end= st+str_length;
782
 
  for (; st < end; st++)
783
 
  {
784
 
    uchar c= *st;
785
 
    switch (c)
786
 
    {
787
 
    case '\\':
788
 
      str->append(STRING_WITH_LEN("\\\\"));
789
 
      break;
790
 
    case '\0':
791
 
      str->append(STRING_WITH_LEN("\\0"));
792
 
      break;
793
 
    case '\'':
794
 
      str->append(STRING_WITH_LEN("\\'"));
795
 
      break;
796
 
    case '\n':
797
 
      str->append(STRING_WITH_LEN("\\n"));
798
 
      break;
799
 
    case '\r':
800
 
      str->append(STRING_WITH_LEN("\\r"));
801
 
      break;
802
 
    case 26: //Ctrl-Z
803
 
      str->append(STRING_WITH_LEN("\\z"));
804
 
      break;
805
 
    default:
806
 
      str->append(c);
807
 
    }
808
 
  }
809
 
}
810
 
 
811
 
 
812
 
/*
813
 
  Exchange state of this object and argument.
814
 
 
815
 
  SYNOPSIS
816
 
    String::swap()
817
 
 
818
 
  RETURN
819
 
    Target string will contain state of this object and vice versa.
820
 
*/
821
 
 
822
 
void String::swap(String &s)
823
 
{
824
 
  swap_variables(char *, Ptr, s.Ptr);
825
 
  swap_variables(uint32, str_length, s.str_length);
826
 
  swap_variables(uint32, Alloced_length, s.Alloced_length);
827
 
  swap_variables(bool, alloced, s.alloced);
828
 
  swap_variables(CHARSET_INFO*, str_charset, s.str_charset);
829
 
}