~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_string.cc

  • Committer: Brian Aker
  • Date: 2009-04-27 14:36:40 UTC
  • Revision ID: brian@gaz-20090427143640-f6zjmtt9vm55qgm2
Patch on show processlist from  davi@apache.org

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 */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/* This file is originally from the mysql distribution. Coded by monty */
17
17
 
18
 
#include "config.h"
19
 
 
20
 
#include "drizzled/internal/my_sys.h"
21
 
#include "drizzled/internal/m_string.h"
22
 
#include "drizzled/charset.h"
23
 
#include "drizzled/global_charset_info.h"
 
18
#include "global.h"
 
19
#include <mysys/my_sys.h>
 
20
#include <mystrings/m_string.h>
24
21
 
25
22
#include <algorithm>
26
23
 
27
 
#include "drizzled/sql_string.h"
28
 
 
29
 
using namespace std;
30
 
 
31
 
namespace drizzled
32
 
{
33
 
 
34
 
// Converstion functions to and from std::string.
35
 
 
36
 
std::string String_to_std_string(String const& s)
37
 
{
38
 
   return std::string(s.ptr(), s.length());
39
 
}
40
 
 
41
 
String* set_String_from_std_string(String* s, std::string const& cs)
42
 
{
43
 
   s->set_ascii(cs.c_str(), cs.length());
44
 
   s->copy();
45
 
   return s;
46
 
}
 
24
/*
 
25
  The following extern declarations are ok as these are interface functions
 
26
  required by the string function
 
27
*/
 
28
 
 
29
extern unsigned char* sql_alloc(unsigned size);
 
30
extern void sql_element_free(void *ptr);
 
31
 
 
32
#include "sql_string.h"
47
33
 
48
34
/*****************************************************************************
49
35
** String functions
50
36
*****************************************************************************/
51
37
 
52
 
String::String()
53
 
  : Ptr(NULL),
54
 
    str_length(0),
55
 
    Alloced_length(0),
56
 
    alloced(false),
57
 
    str_charset(&my_charset_bin)
58
 
{ }
59
 
 
60
 
 
61
 
String::String(size_t length_arg)
62
 
  : Ptr(NULL),
63
 
    str_length(0),
64
 
    Alloced_length(0),
65
 
    alloced(false),
66
 
    str_charset(&my_charset_bin)
67
 
{
68
 
  (void) real_alloc(length_arg);
69
 
}
70
 
 
71
 
String::String(const char *str, const CHARSET_INFO * const cs)
72
 
  : Ptr(const_cast<char *>(str)),
73
 
    str_length(static_cast<size_t>(strlen(str))),
74
 
    Alloced_length(0),
75
 
    alloced(false),
76
 
    str_charset(cs)
77
 
{ }
78
 
 
79
 
 
80
 
String::String(const char *str, size_t len, const CHARSET_INFO * const cs)
81
 
  : Ptr(const_cast<char *>(str)),
82
 
    str_length(len),
83
 
    Alloced_length(0),
84
 
    alloced(false),
85
 
    str_charset(cs)
86
 
{ }
87
 
 
88
 
 
89
 
String::String(char *str, size_t len, const CHARSET_INFO * const cs)
90
 
  : Ptr(str),
91
 
    str_length(len),
92
 
    Alloced_length(len),
93
 
    alloced(false),
94
 
    str_charset(cs)
95
 
{ }
96
 
 
97
 
 
98
 
String::String(const String &str)
99
 
  : Ptr(str.Ptr),
100
 
    str_length(str.str_length),
101
 
    Alloced_length(str.Alloced_length),
102
 
    alloced(false),
103
 
    str_charset(str.str_charset)
104
 
{ }
105
 
 
106
 
 
107
 
void *String::operator new(size_t size, memory::Root *mem_root)
108
 
{
109
 
  return mem_root->alloc_root(static_cast<size_t>(size));
110
 
}
111
 
 
112
 
String::~String() { free(); }
113
 
 
114
 
bool String::real_alloc(size_t arg_length)
 
38
bool String::real_alloc(uint32_t arg_length)
115
39
{
116
40
  arg_length=ALIGN_SIZE(arg_length+1);
117
41
  str_length=0;
118
42
  if (Alloced_length < arg_length)
119
43
  {
120
 
    if (Alloced_length > 0)
121
 
      free();
 
44
    free();
122
45
    if (!(Ptr=(char*) malloc(arg_length)))
123
46
      return true;
124
47
    Alloced_length=arg_length;
134
57
** (for C functions)
135
58
*/
136
59
 
137
 
bool String::realloc(size_t alloc_length)
 
60
bool String::realloc(uint32_t alloc_length)
138
61
{
139
 
  size_t len=ALIGN_SIZE(alloc_length+1);
 
62
  uint32_t len=ALIGN_SIZE(alloc_length+1);
140
63
  if (Alloced_length < len)
141
64
  {
142
65
    char *new_ptr;
168
91
 
169
92
bool String::set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs)
170
93
{
171
 
  size_t l=20*cs->mbmaxlen+1;
 
94
  uint32_t l=20*cs->mbmaxlen+1;
172
95
  int base= unsigned_flag ? 10 : -10;
173
96
 
174
97
  if (alloc(l))
175
98
    return true;
176
 
  str_length=(size_t) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
 
99
  str_length=(uint32_t) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
177
100
  str_charset=cs;
178
101
  return false;
179
102
}
180
103
 
181
 
bool String::set_real(double num,size_t decimals, const CHARSET_INFO * const cs)
 
104
bool String::set_real(double num,uint32_t decimals, const CHARSET_INFO * const cs)
182
105
{
183
106
  char buff[FLOATING_POINT_BUFFER];
184
 
  size_t dummy_errors;
 
107
  uint32_t dummy_errors;
185
108
  size_t len;
186
109
 
187
110
  str_charset=cs;
188
111
  if (decimals >= NOT_FIXED_DEC)
189
112
  {
190
 
    len= internal::my_gcvt(num,
191
 
                           internal::MY_GCVT_ARG_DOUBLE,
192
 
                           sizeof(buff) - 1, buff, NULL);
 
113
    len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
193
114
    return copy(buff, len, &my_charset_utf8_general_ci, cs, &dummy_errors);
194
115
  }
195
 
  len= internal::my_fcvt(num, decimals, buff, NULL);
196
 
  return copy(buff, (size_t) len, &my_charset_utf8_general_ci, cs,
 
116
  len= my_fcvt(num, decimals, buff, NULL);
 
117
  return copy(buff, (uint32_t) len, &my_charset_utf8_general_ci, cs,
197
118
              &dummy_errors);
198
119
}
199
120
 
219
140
  return false;
220
141
}
221
142
 
222
 
bool String::copy(const char *str,size_t arg_length, const CHARSET_INFO * const cs)
 
143
bool String::copy(const char *str,uint32_t arg_length, const CHARSET_INFO * const cs)
223
144
{
224
145
  if (alloc(arg_length))
225
146
    return true;
230
151
  return false;
231
152
}
232
153
 
 
154
 
233
155
/*
234
156
  Checks that the source string can be just copied to the destination string
235
157
  without conversion.
240
162
  arg_length            Length of string to copy.
241
163
  from_cs               Character set to copy from
242
164
  to_cs                 Character set to copy to
243
 
  size_t *offset        Returns number of unaligned characters.
 
165
  uint32_t *offset      Returns number of unaligned characters.
244
166
 
245
167
  RETURN
246
168
   0  No conversion needed
252
174
  character_set_results is NULL.
253
175
*/
254
176
 
255
 
bool String::needs_conversion(size_t arg_length,
 
177
bool String::needs_conversion(uint32_t arg_length,
256
178
                              const CHARSET_INFO * const from_cs,
257
179
                              const CHARSET_INFO * const to_cs,
258
 
                              size_t *offset)
 
180
                              uint32_t *offset)
259
181
{
260
182
  *offset= 0;
261
183
  if (!to_cs ||
271
193
 
272
194
 
273
195
 
274
 
bool String::set_or_copy_aligned(const char *str,size_t arg_length,
 
196
bool String::set_or_copy_aligned(const char *str,uint32_t arg_length,
275
197
                                 const CHARSET_INFO * const cs)
276
198
{
277
199
  /* How many bytes are in incomplete character */
278
 
  size_t offset= (arg_length % cs->mbminlen);
 
200
  uint32_t offset= (arg_length % cs->mbminlen);
279
201
 
280
202
  assert(!offset); /* All characters are complete, just copy */
281
203
 
285
207
 
286
208
        /* Copy with charset conversion */
287
209
 
288
 
bool String::copy(const char *str, size_t arg_length,
 
210
bool String::copy(const char *str, uint32_t arg_length,
289
211
                          const CHARSET_INFO * const,
290
 
                                  const CHARSET_INFO * const to_cs, size_t *errors)
 
212
                                  const CHARSET_INFO * const to_cs, uint32_t *errors)
291
213
{
292
214
  *errors= 0;
293
215
  return copy(str, arg_length, to_cs);
313
235
 
314
236
*/
315
237
 
316
 
bool String::set_ascii(const char *str, size_t arg_length)
 
238
bool String::set_ascii(const char *str, uint32_t arg_length)
317
239
{
318
240
  if (str_charset->mbminlen == 1)
319
241
  {
320
242
    set(str, arg_length, str_charset);
321
243
    return 0;
322
244
  }
323
 
  size_t dummy_errors;
 
245
  uint32_t dummy_errors;
324
246
  return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
325
247
}
326
248
 
341
263
  Append an ASCII string to the a string of the current character set
342
264
*/
343
265
 
344
 
bool String::append(const char *s,size_t arg_length)
 
266
bool String::append(const char *s,uint32_t arg_length)
345
267
{
346
268
  if (!arg_length)
347
269
    return false;
348
270
 
349
271
  /*
 
272
    For an ASCII incompatible string, e.g. UCS-2, we need to convert
 
273
  */
 
274
  if (str_charset->mbminlen > 1)
 
275
  {
 
276
    uint32_t add_length=arg_length * str_charset->mbmaxlen;
 
277
    uint32_t dummy_errors;
 
278
    if (realloc(str_length+ add_length))
 
279
      return true;
 
280
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
 
281
                                  s, arg_length, &my_charset_utf8_general_ci,
 
282
                                  &dummy_errors);
 
283
    return false;
 
284
  }
 
285
 
 
286
  /*
350
287
    For an ASCII compatinble string we can just append.
351
288
  */
352
289
  if (realloc(str_length+arg_length))
372
309
  with character set recoding
373
310
*/
374
311
 
375
 
bool String::append(const char *s,size_t arg_length, const CHARSET_INFO * const)
 
312
bool String::append(const char *s,uint32_t arg_length, const CHARSET_INFO * const)
376
313
{
377
314
  if (realloc(str_length + arg_length))
378
315
    return true;
383
320
}
384
321
 
385
322
 
386
 
bool String::append_with_prefill(const char *s,size_t arg_length,
387
 
                 size_t full_length, char fill_char)
 
323
bool String::append_with_prefill(const char *s,uint32_t arg_length,
 
324
                 uint32_t full_length, char fill_char)
388
325
{
389
326
  int t_length= arg_length > full_length ? arg_length : full_length;
390
327
 
400
337
  return false;
401
338
}
402
339
 
403
 
size_t String::numchars()
 
340
uint32_t String::numchars()
404
341
{
405
342
  return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
406
343
}
407
344
 
408
 
int String::charpos(int i,size_t offset)
 
345
int String::charpos(int i,uint32_t offset)
409
346
{
410
347
  if (i <= 0)
411
348
    return i;
412
349
  return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
413
350
}
414
351
 
415
 
int String::strstr(const String &s,size_t offset)
 
352
int String::strstr(const String &s,uint32_t offset)
416
353
{
417
354
  if (s.length()+offset <= str_length)
418
355
  {
443
380
** Search string from end. Offset is offset to the end of string
444
381
*/
445
382
 
446
 
int String::strrstr(const String &s,size_t offset)
 
383
int String::strrstr(const String &s,uint32_t offset)
447
384
{
448
385
  if (s.length() <= offset && offset <= str_length)
449
386
  {
475
412
  If wrong parameter or not enough memory, do nothing
476
413
*/
477
414
 
478
 
bool String::replace(size_t offset,size_t arg_length,const String &to)
 
415
bool String::replace(uint32_t offset,uint32_t arg_length,const String &to)
479
416
{
480
417
  return replace(offset,arg_length,to.ptr(),to.length());
481
418
}
482
419
 
483
 
bool String::replace(size_t offset,size_t arg_length,
484
 
                     const char *to, size_t to_length)
 
420
bool String::replace(uint32_t offset,uint32_t arg_length,
 
421
                     const char *to, uint32_t to_length)
485
422
{
486
423
  long diff = (long) to_length-(long) arg_length;
487
424
  if (offset+arg_length <= str_length)
497
434
    {
498
435
      if (diff)
499
436
      {
500
 
        if (realloc(str_length+(size_t) diff))
 
437
        if (realloc(str_length+(uint32_t) diff))
501
438
          return true;
502
 
        internal::bmove_upp((unsigned char*) Ptr+str_length+diff,
503
 
                            (unsigned char*) Ptr+str_length,
504
 
                            str_length-offset-arg_length);
 
439
        bmove_upp((unsigned char*) Ptr+str_length+diff, (unsigned char*) Ptr+str_length,
 
440
                  str_length-offset-arg_length);
505
441
      }
506
442
      if (to_length)
507
443
        memcpy(Ptr+offset,to,to_length);
508
444
    }
509
 
    str_length+=(size_t) diff;
 
445
    str_length+=(uint32_t) diff;
510
446
  }
511
447
  return false;
512
448
}
560
496
 
561
497
int stringcmp(const String *s,const String *t)
562
498
{
563
 
  size_t s_len= s->length(), t_len= t->length(), len= min(s_len,t_len);
 
499
  uint32_t s_len=s->length(),t_len=t->length(),len=cmin(s_len,t_len);
564
500
  int cmp= memcmp(s->ptr(), t->ptr(), len);
565
501
  return (cmp) ? cmp : (int) (s_len - t_len);
566
502
}
567
503
 
568
504
 
569
 
String *copy_if_not_alloced(String *to,String *from,size_t from_length)
 
505
String *copy_if_not_alloced(String *to,String *from,uint32_t from_length)
570
506
{
571
507
  if (from->Alloced_length >= from_length)
572
508
    return from;
577
513
  }
578
514
  if (to->realloc(from_length))
579
515
    return from;                                // Actually an error
580
 
  if ((to->str_length= min(from->str_length,from_length)))
 
516
  if ((to->str_length=cmin(from->str_length,from_length)))
581
517
    memcpy(to->Ptr,from->Ptr,to->str_length);
582
518
  to->str_charset=from->str_charset;
583
519
  return to;
589
525
****************************************************************************/
590
526
 
591
527
/*
 
528
  copy a string from one character set to another
 
529
 
 
530
  SYNOPSIS
 
531
    copy_and_convert()
 
532
    to                  Store result here
 
533
    to_cs               Character set of result string
 
534
    from                Copy from here
 
535
    from_length         Length of from string
 
536
    from_cs             From character set
 
537
 
 
538
  NOTES
 
539
    'to' must be big enough as form_length * to_cs->mbmaxlen
 
540
 
 
541
  RETURN
 
542
    length of bytes copied to 'to'
 
543
*/
 
544
 
 
545
 
 
546
static uint32_t
 
547
copy_and_convert_extended(char *to, uint32_t to_length,
 
548
                          const CHARSET_INFO * const to_cs,
 
549
                          const char *from, uint32_t from_length,
 
550
                          const CHARSET_INFO * const from_cs,
 
551
                          uint32_t *errors)
 
552
{
 
553
  int         cnvres;
 
554
  my_wc_t     wc;
 
555
  const unsigned char *from_end= (const unsigned char*) from+from_length;
 
556
  char *to_start= to;
 
557
  unsigned char *to_end= (unsigned char*) to+to_length;
 
558
  my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
 
559
  my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
 
560
  uint32_t error_count= 0;
 
561
 
 
562
  while (1)
 
563
  {
 
564
    if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from,
 
565
                                      from_end)) > 0)
 
566
      from+= cnvres;
 
567
    else if (cnvres == MY_CS_ILSEQ)
 
568
    {
 
569
      error_count++;
 
570
      from++;
 
571
      wc= '?';
 
572
    }
 
573
    else if (cnvres > MY_CS_TOOSMALL)
 
574
    {
 
575
      /*
 
576
        A correct multibyte sequence detected
 
577
        But it doesn't have Unicode mapping.
 
578
      */
 
579
      error_count++;
 
580
      from+= (-cnvres);
 
581
      wc= '?';
 
582
    }
 
583
    else
 
584
      break;  // Not enough characters
 
585
 
 
586
outp:
 
587
    if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
 
588
      to+= cnvres;
 
589
    else if (cnvres == MY_CS_ILUNI && wc != '?')
 
590
    {
 
591
      error_count++;
 
592
      wc= '?';
 
593
      goto outp;
 
594
    }
 
595
    else
 
596
      break;
 
597
  }
 
598
  *errors= error_count;
 
599
  return (uint32_t) (to - to_start);
 
600
}
 
601
 
 
602
 
 
603
/*
 
604
  Optimized for quick copying of ASCII characters in the range 0x00..0x7F.
 
605
*/
 
606
uint32_t
 
607
copy_and_convert(char *to, uint32_t to_length, const CHARSET_INFO * const to_cs,
 
608
                 const char *from, uint32_t from_length,
 
609
                                 const CHARSET_INFO * const from_cs, uint32_t *errors)
 
610
{
 
611
  /*
 
612
    If any of the character sets is not ASCII compatible,
 
613
    immediately switch to slow mb_wc->wc_mb method.
 
614
  */
 
615
  if ((to_cs->state | from_cs->state) & MY_CS_NONASCII)
 
616
    return copy_and_convert_extended(to, to_length, to_cs,
 
617
                                     from, from_length, from_cs, errors);
 
618
 
 
619
  uint32_t length= cmin(to_length, from_length), length2= length;
 
620
 
 
621
#if defined(__i386__)
 
622
  /*
 
623
    Special loop for i386, it allows to refer to a
 
624
    non-aligned memory block as UINT32, which makes
 
625
    it possible to copy four bytes at once. This
 
626
    gives about 10% performance improvement comparing
 
627
    to byte-by-byte loop.
 
628
  */
 
629
  for ( ; length >= 4; length-= 4, from+= 4, to+= 4)
 
630
  {
 
631
    if ((*(uint32_t*)from) & 0x80808080)
 
632
      break;
 
633
    *((uint32_t*) to)= *((const uint32_t*) from);
 
634
  }
 
635
#endif
 
636
 
 
637
  for (; ; *to++= *from++, length--)
 
638
  {
 
639
    if (!length)
 
640
    {
 
641
      *errors= 0;
 
642
      return length2;
 
643
    }
 
644
    if (*((unsigned char*) from) > 0x7F) /* A non-ASCII character */
 
645
    {
 
646
      uint32_t copied_length= length2 - length;
 
647
      to_length-= copied_length;
 
648
      from_length-= copied_length;
 
649
      return copied_length + copy_and_convert_extended(to, to_length,
 
650
                                                       to_cs,
 
651
                                                       from, from_length,
 
652
                                                       from_cs,
 
653
                                                       errors);
 
654
    }
 
655
  }
 
656
 
 
657
#ifndef __sun
 
658
  return 0;           // Make compiler happy
 
659
#endif
 
660
}
 
661
 
 
662
 
 
663
/**
 
664
  Copy string with HEX-encoding of "bad" characters.
 
665
 
 
666
  @details This functions copies the string pointed by "src"
 
667
  to the string pointed by "dst". Not more than "srclen" bytes
 
668
  are read from "src". Any sequences of bytes representing
 
669
  a not-well-formed substring (according to cs) are hex-encoded,
 
670
  and all well-formed substrings (according to cs) are copied as is.
 
671
  Not more than "dstlen" bytes are written to "dst". The number
 
672
  of bytes written to "dst" is returned.
 
673
 
 
674
   @param      cs       character set pointer of the destination string
 
675
   @param[out] dst      destination string
 
676
   @param      dstlen   size of dst
 
677
   @param      src      source string
 
678
   @param      srclen   length of src
 
679
 
 
680
   @retval     result length
 
681
*/
 
682
 
 
683
size_t
 
684
my_copy_with_hex_escaping(const CHARSET_INFO * const cs,
 
685
                          char *dst, size_t dstlen,
 
686
                          const char *src, size_t srclen)
 
687
{
 
688
  const char *srcend= src + srclen;
 
689
  char *dst0= dst;
 
690
 
 
691
  for ( ; src < srcend ; )
 
692
  {
 
693
    size_t chlen;
 
694
    if ((chlen= my_ismbchar(cs, src, srcend)))
 
695
    {
 
696
      if (dstlen < chlen)
 
697
        break; /* purecov: inspected */
 
698
      memcpy(dst, src, chlen);
 
699
      src+= chlen;
 
700
      dst+= chlen;
 
701
      dstlen-= chlen;
 
702
    }
 
703
    else if (*src & 0x80)
 
704
    {
 
705
      if (dstlen < 4)
 
706
        break; /* purecov: inspected */
 
707
      *dst++= '\\';
 
708
      *dst++= 'x';
 
709
      *dst++= _dig_vec_upper[((unsigned char) *src) >> 4];
 
710
      *dst++= _dig_vec_upper[((unsigned char) *src) & 15];
 
711
      src++;
 
712
      dstlen-= 4;
 
713
    }
 
714
    else
 
715
    {
 
716
      if (dstlen < 1)
 
717
        break; /* purecov: inspected */
 
718
      *dst++= *src++;
 
719
      dstlen--;
 
720
    }
 
721
  }
 
722
  return dst - dst0;
 
723
}
 
724
 
 
725
/*
592
726
  copy a string,
593
727
  with optional character set conversion,
594
728
  with optional left padding (for binary -> UCS2 conversion)
615
749
*/
616
750
 
617
751
 
618
 
size_t
 
752
uint32_t
619
753
well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
620
 
                        char *to, size_t to_length,
 
754
                        char *to, uint32_t to_length,
621
755
                        const CHARSET_INFO * const from_cs,
622
 
                        const char *from, size_t from_length,
623
 
                        size_t nchars,
 
756
                        const char *from, uint32_t from_length,
 
757
                        uint32_t nchars,
624
758
                        const char **well_formed_error_pos,
625
759
                        const char **cannot_convert_error_pos,
626
760
                        const char **from_end_pos)
627
761
{
628
 
  size_t res;
629
 
 
630
 
  assert((to_cs == &my_charset_bin) ||
631
 
         (from_cs == &my_charset_bin) ||
632
 
         (to_cs == from_cs) ||
633
 
         my_charset_same(from_cs, to_cs));
634
 
 
635
 
  if (to_length < to_cs->mbminlen || !nchars)
636
 
  {
 
762
  uint32_t res;
 
763
 
 
764
  if ((to_cs == &my_charset_bin) ||
 
765
      (from_cs == &my_charset_bin) ||
 
766
      (to_cs == from_cs) ||
 
767
      my_charset_same(from_cs, to_cs))
 
768
  {
 
769
    if (to_length < to_cs->mbminlen || !nchars)
 
770
    {
 
771
      *from_end_pos= from;
 
772
      *cannot_convert_error_pos= NULL;
 
773
      *well_formed_error_pos= NULL;
 
774
      return 0;
 
775
    }
 
776
 
 
777
    if (to_cs == &my_charset_bin)
 
778
    {
 
779
      res= cmin(cmin(nchars, to_length), from_length);
 
780
      memmove(to, from, res);
 
781
      *from_end_pos= from + res;
 
782
      *well_formed_error_pos= NULL;
 
783
      *cannot_convert_error_pos= NULL;
 
784
    }
 
785
    else
 
786
    {
 
787
      int well_formed_error;
 
788
      uint32_t from_offset;
 
789
 
 
790
      if ((from_offset= (from_length % to_cs->mbminlen)) &&
 
791
          (from_cs == &my_charset_bin))
 
792
      {
 
793
        /*
 
794
          Copying from BINARY to UCS2 needs to prepend zeros sometimes:
 
795
          INSERT INTO t1 (ucs2_column) VALUES (0x01);
 
796
          0x01 -> 0x0001
 
797
        */
 
798
        uint32_t pad_length= to_cs->mbminlen - from_offset;
 
799
        memset(to, 0, pad_length);
 
800
        memmove(to + pad_length, from, from_offset);
 
801
        nchars--;
 
802
        from+= from_offset;
 
803
        from_length-= from_offset;
 
804
        to+= to_cs->mbminlen;
 
805
        to_length-= to_cs->mbminlen;
 
806
      }
 
807
 
 
808
      set_if_smaller(from_length, to_length);
 
809
      res= to_cs->cset->well_formed_len(to_cs, from, from + from_length,
 
810
                                        nchars, &well_formed_error);
 
811
      memmove(to, from, res);
 
812
      *from_end_pos= from + res;
 
813
      *well_formed_error_pos= well_formed_error ? from + res : NULL;
 
814
      *cannot_convert_error_pos= NULL;
 
815
      if (from_offset)
 
816
        res+= to_cs->mbminlen;
 
817
    }
 
818
  }
 
819
  else
 
820
  {
 
821
    int cnvres;
 
822
    my_wc_t wc;
 
823
    my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
 
824
    my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
 
825
    const unsigned char *from_end= (const unsigned char*) from + from_length;
 
826
    unsigned char *to_end= (unsigned char*) to + to_length;
 
827
    char *to_start= to;
 
828
    *well_formed_error_pos= NULL;
 
829
    *cannot_convert_error_pos= NULL;
 
830
 
 
831
    for ( ; nchars; nchars--)
 
832
    {
 
833
      const char *from_prev= from;
 
834
      if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from, from_end)) > 0)
 
835
        from+= cnvres;
 
836
      else if (cnvres == MY_CS_ILSEQ)
 
837
      {
 
838
        if (!*well_formed_error_pos)
 
839
          *well_formed_error_pos= from;
 
840
        from++;
 
841
        wc= '?';
 
842
      }
 
843
      else if (cnvres > MY_CS_TOOSMALL)
 
844
      {
 
845
        /*
 
846
          A correct multibyte sequence detected
 
847
          But it doesn't have Unicode mapping.
 
848
        */
 
849
        if (!*cannot_convert_error_pos)
 
850
          *cannot_convert_error_pos= from;
 
851
        from+= (-cnvres);
 
852
        wc= '?';
 
853
      }
 
854
      else
 
855
        break;  // Not enough characters
 
856
 
 
857
outp:
 
858
      if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
 
859
        to+= cnvres;
 
860
      else if (cnvres == MY_CS_ILUNI && wc != '?')
 
861
      {
 
862
        if (!*cannot_convert_error_pos)
 
863
          *cannot_convert_error_pos= from_prev;
 
864
        wc= '?';
 
865
        goto outp;
 
866
      }
 
867
      else
 
868
      {
 
869
        from= from_prev;
 
870
        break;
 
871
      }
 
872
    }
637
873
    *from_end_pos= from;
638
 
    *cannot_convert_error_pos= NULL;
639
 
    *well_formed_error_pos= NULL;
640
 
    return 0;
641
 
  }
642
 
 
643
 
  if (to_cs == &my_charset_bin)
644
 
  {
645
 
    res= min(min(nchars, to_length), from_length);
646
 
    memmove(to, from, res);
647
 
    *from_end_pos= from + res;
648
 
    *well_formed_error_pos= NULL;
649
 
    *cannot_convert_error_pos= NULL;
650
 
  }
651
 
  else
652
 
  {
653
 
    int well_formed_error;
654
 
    size_t from_offset;
655
 
 
656
 
    if ((from_offset= (from_length % to_cs->mbminlen)) &&
657
 
        (from_cs == &my_charset_bin))
658
 
    {
659
 
      /*
660
 
        Copying from BINARY to UCS2 needs to prepend zeros sometimes:
661
 
        INSERT INTO t1 (ucs2_column) VALUES (0x01);
662
 
        0x01 -> 0x0001
663
 
      */
664
 
      size_t pad_length= to_cs->mbminlen - from_offset;
665
 
      memset(to, 0, pad_length);
666
 
      memmove(to + pad_length, from, from_offset);
667
 
      nchars--;
668
 
      from+= from_offset;
669
 
      from_length-= from_offset;
670
 
      to+= to_cs->mbminlen;
671
 
      to_length-= to_cs->mbminlen;
672
 
    }
673
 
 
674
 
    set_if_smaller(from_length, to_length);
675
 
    res= to_cs->cset->well_formed_len(to_cs, from, from + from_length,
676
 
                                      nchars, &well_formed_error);
677
 
    memmove(to, from, res);
678
 
    *from_end_pos= from + res;
679
 
    *well_formed_error_pos= well_formed_error ? from + res : NULL;
680
 
    *cannot_convert_error_pos= NULL;
681
 
    if (from_offset)
682
 
      res+= to_cs->mbminlen;
683
 
  }
684
 
 
685
 
  return res;
 
874
    res= to - to_start;
 
875
  }
 
876
  return (uint32_t) res;
686
877
}
687
878
 
688
879
 
733
924
/* Factor the extern out */
734
925
extern const CHARSET_INFO *system_charset_info, *files_charset_info;
735
926
 
736
 
void String::append_identifier(const char *name, size_t in_length)
 
927
void String::append_identifier(const char *name, uint32_t in_length)
737
928
{
738
929
  const char *name_end;
739
930
  char quote_char;
788
979
  std::swap(str_charset, s.str_charset);
789
980
}
790
981
 
791
 
void String::q_append(const size_t n)
792
 
{
793
 
  int8store(Ptr + str_length, n);
794
 
  str_length += 4;
795
 
}
796
 
void String::q_append(double d)
797
 
{
798
 
  float8store(Ptr + str_length, d);
799
 
  str_length += 8;
800
 
}
801
 
void String::q_append(double *d)
802
 
{
803
 
  float8store(Ptr + str_length, *d);
804
 
  str_length += 8;
805
 
}
806
 
void String::q_append(const char *data, size_t data_len)
807
 
{
808
 
  memcpy(Ptr + str_length, data, data_len);
809
 
  str_length += data_len;
810
 
}
811
 
 
812
 
void String::write_at_position(int position, size_t value)
813
 
{
814
 
  int8store(Ptr + position,value);
815
 
}
816
 
bool check_if_only_end_space(const CHARSET_INFO * const cs, char *str,
817
 
                             char *end)
818
 
{
819
 
  return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end;
820
 
}
821
 
 
822
 
} /* namespace drizzled */
823
 
 
824
 
bool operator==(const drizzled::String &s1, const drizzled::String &s2)
 
982
 
 
983
bool operator==(const String &s1, const String &s2)
825
984
{
826
985
  return stringcmp(&s1,&s2) == 0;
827
986
}
828
987
 
829
 
bool operator!=(const drizzled::String &s1, const drizzled::String &s2)
 
988
bool operator!=(const String &s1, const String &s2)
830
989
{
831
990
  return !(s1 == s2);
832
991
}