~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_string.cc

MergeĀ fromĀ Jim

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#include <mysys/my_sys.h>
20
20
#include <mystrings/m_string.h>
21
21
 
22
 
#include <algorithm>
23
 
 
24
22
/*
25
23
  The following extern declarations are ok as these are interface functions
26
24
  required by the string function
27
25
*/
28
26
 
29
 
extern unsigned char* sql_alloc(unsigned size);
 
27
extern uchar* sql_alloc(unsigned size);
30
28
extern void sql_element_free(void *ptr);
31
29
 
32
30
#include "sql_string.h"
91
89
 
92
90
bool String::set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs)
93
91
{
94
 
  uint32_t l=20*cs->mbmaxlen+1;
 
92
  uint l=20*cs->mbmaxlen+1;
95
93
  int base= unsigned_flag ? 10 : -10;
96
94
 
97
95
  if (alloc(l))
101
99
  return false;
102
100
}
103
101
 
104
 
bool String::set_real(double num,uint32_t decimals, const CHARSET_INFO * const cs)
 
102
bool String::set_real(double num,uint decimals, const CHARSET_INFO * const cs)
105
103
{
106
104
  char buff[FLOATING_POINT_BUFFER];
107
 
  uint32_t dummy_errors;
 
105
  uint dummy_errors;
108
106
  size_t len;
109
107
 
110
108
  str_charset=cs;
111
109
  if (decimals >= NOT_FIXED_DEC)
112
110
  {
113
111
    len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
114
 
    return copy(buff, len, &my_charset_utf8_general_ci, cs, &dummy_errors);
 
112
    return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
115
113
  }
116
114
  len= my_fcvt(num, decimals, buff, NULL);
117
 
  return copy(buff, (uint32_t) len, &my_charset_utf8_general_ci, cs,
 
115
  return copy(buff, (uint32_t) len, &my_charset_latin1, cs,
118
116
              &dummy_errors);
119
117
}
120
118
 
260
258
 
261
259
bool String::copy(const char *str, uint32_t arg_length,
262
260
                          const CHARSET_INFO * const from_cs,
263
 
                                  const CHARSET_INFO * const to_cs, uint32_t *errors)
 
261
                                  const CHARSET_INFO * const to_cs, uint *errors)
264
262
{
265
263
  uint32_t offset;
266
264
  if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
309
307
    set(str, arg_length, str_charset);
310
308
    return 0;
311
309
  }
312
 
  uint32_t dummy_errors;
313
 
  return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
 
310
  uint dummy_errors;
 
311
  return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors);
314
312
}
315
313
 
316
314
 
330
328
  return false;
331
329
}
332
330
 
 
331
void String::strip_sp()
 
332
{
 
333
   while (str_length && my_isspace(str_charset,Ptr[str_length-1]))
 
334
    str_length--;
 
335
}
 
336
 
333
337
bool String::append(const String &s)
334
338
{
335
339
  if (s.length())
358
362
  if (str_charset->mbminlen > 1)
359
363
  {
360
364
    uint32_t add_length=arg_length * str_charset->mbmaxlen;
361
 
    uint32_t dummy_errors;
 
365
    uint dummy_errors;
362
366
    if (realloc(str_length+ add_length))
363
367
      return true;
364
368
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
365
 
                                  s, arg_length, &my_charset_utf8_general_ci,
 
369
                                  s, arg_length, &my_charset_latin1,
366
370
                                  &dummy_errors);
367
371
    return false;
368
372
  }
400
404
  if (needs_conversion(arg_length, cs, str_charset, &dummy_offset))
401
405
  {
402
406
    uint32_t add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
403
 
    uint32_t dummy_errors;
 
407
    uint dummy_errors;
404
408
    if (realloc(str_length + add_length)) 
405
409
      return true;
406
410
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
421
425
{
422
426
  if (realloc(str_length+arg_length))
423
427
    return true;
424
 
  if (my_b_read(file, (unsigned char*) Ptr + str_length, arg_length))
 
428
  if (my_b_read(file, (uchar*) Ptr + str_length, arg_length))
425
429
  {
426
430
    shrink(str_length);
427
431
    return true;
546
550
      {
547
551
        if (realloc(str_length+(uint32_t) diff))
548
552
          return true;
549
 
        bmove_upp((unsigned char*) Ptr+str_length+diff, (unsigned char*) Ptr+str_length,
 
553
        bmove_upp((uchar*) Ptr+str_length+diff, (uchar*) Ptr+str_length,
550
554
                  str_length-offset-arg_length);
551
555
      }
552
556
      if (to_length)
563
567
{
564
568
  if (Alloced_length < str_length + space_needed)
565
569
  {
566
 
    if (realloc(Alloced_length + cmax(space_needed, grow_by) - 1))
 
570
    if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
567
571
      return true;
568
572
  }
569
573
  return false;
595
599
  str_length+= (int) (end-buff);
596
600
}
597
601
 
598
 
void String::qs_append(uint32_t i)
 
602
void String::qs_append(uint i)
599
603
{
600
604
  char *buff= Ptr + str_length;
601
605
  char *end= int10_to_str(i, buff, 10);
624
628
int sortcmp(const String *s,const String *t, const CHARSET_INFO * const cs)
625
629
{
626
630
 return cs->coll->strnncollsp(cs,
627
 
                              (unsigned char *) s->ptr(),s->length(),
628
 
                              (unsigned char *) t->ptr(),t->length(), 0);
 
631
                              (uchar *) s->ptr(),s->length(),
 
632
                              (uchar *) t->ptr(),t->length(), 0);
629
633
}
630
634
 
631
635
 
638
642
    t           Second string
639
643
 
640
644
  NOTE:
641
 
    Strings are compared as a stream of unsigned chars
 
645
    Strings are compared as a stream of uchars
642
646
 
643
647
  RETURN
644
648
  < 0   s < t
649
653
 
650
654
int stringcmp(const String *s,const String *t)
651
655
{
652
 
  uint32_t s_len=s->length(),t_len=t->length(),len=cmin(s_len,t_len);
 
656
  uint32_t s_len=s->length(),t_len=t->length(),len=min(s_len,t_len);
653
657
  int cmp= memcmp(s->ptr(), t->ptr(), len);
654
658
  return (cmp) ? cmp : (int) (s_len - t_len);
655
659
}
666
670
  }
667
671
  if (to->realloc(from_length))
668
672
    return from;                                // Actually an error
669
 
  if ((to->str_length=cmin(from->str_length,from_length)))
 
673
  if ((to->str_length=min(from->str_length,from_length)))
670
674
    memcpy(to->Ptr,from->Ptr,to->str_length);
671
675
  to->str_charset=from->str_charset;
672
676
  return to;
701
705
                          const CHARSET_INFO * const to_cs, 
702
706
                          const char *from, uint32_t from_length,
703
707
                          const CHARSET_INFO * const from_cs,
704
 
                          uint32_t *errors)
 
708
                          uint *errors)
705
709
{
706
710
  int         cnvres;
707
711
  my_wc_t     wc;
708
 
  const unsigned char *from_end= (const unsigned char*) from+from_length;
 
712
  const uchar *from_end= (const uchar*) from+from_length;
709
713
  char *to_start= to;
710
 
  unsigned char *to_end= (unsigned char*) to+to_length;
 
714
  uchar *to_end= (uchar*) to+to_length;
711
715
  my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
712
716
  my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
713
 
  uint32_t error_count= 0;
 
717
  uint error_count= 0;
714
718
 
715
719
  while (1)
716
720
  {
717
 
    if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from,
 
721
    if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
718
722
                                      from_end)) > 0)
719
723
      from+= cnvres;
720
724
    else if (cnvres == MY_CS_ILSEQ)
737
741
      break;  // Not enough characters
738
742
 
739
743
outp:
740
 
    if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
 
744
    if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
741
745
      to+= cnvres;
742
746
    else if (cnvres == MY_CS_ILUNI && wc != '?')
743
747
    {
759
763
uint32_t
760
764
copy_and_convert(char *to, uint32_t to_length, const CHARSET_INFO * const to_cs, 
761
765
                 const char *from, uint32_t from_length,
762
 
                                 const CHARSET_INFO * const from_cs, uint32_t *errors)
 
766
                                 const CHARSET_INFO * const from_cs, uint *errors)
763
767
{
764
768
  /*
765
769
    If any of the character sets is not ASCII compatible,
769
773
    return copy_and_convert_extended(to, to_length, to_cs,
770
774
                                     from, from_length, from_cs, errors);
771
775
 
772
 
  uint32_t length= cmin(to_length, from_length), length2= length;
 
776
  uint32_t length= min(to_length, from_length), length2= length;
773
777
 
774
778
#if defined(__i386__)
775
779
  /*
903
907
 
904
908
uint32_t
905
909
well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
906
 
                        char *to, uint32_t to_length,
 
910
                        char *to, uint to_length,
907
911
                        const CHARSET_INFO * const from_cs,
908
 
                        const char *from, uint32_t from_length,
909
 
                        uint32_t nchars,
 
912
                        const char *from, uint from_length,
 
913
                        uint nchars,
910
914
                        const char **well_formed_error_pos,
911
915
                        const char **cannot_convert_error_pos,
912
916
                        const char **from_end_pos)
913
917
{
914
 
  uint32_t res;
 
918
  uint res;
915
919
 
916
920
  if ((to_cs == &my_charset_bin) || 
917
921
      (from_cs == &my_charset_bin) ||
928
932
 
929
933
    if (to_cs == &my_charset_bin)
930
934
    {
931
 
      res= cmin(cmin(nchars, to_length), from_length);
 
935
      res= min(min(nchars, to_length), from_length);
932
936
      memmove(to, from, res);
933
937
      *from_end_pos= from + res;
934
938
      *well_formed_error_pos= NULL;
937
941
    else
938
942
    {
939
943
      int well_formed_error;
940
 
      uint32_t from_offset;
 
944
      uint from_offset;
941
945
 
942
946
      if ((from_offset= (from_length % to_cs->mbminlen)) &&
943
947
          (from_cs == &my_charset_bin))
947
951
          INSERT INTO t1 (ucs2_column) VALUES (0x01);
948
952
          0x01 -> 0x0001
949
953
        */
950
 
        uint32_t pad_length= to_cs->mbminlen - from_offset;
 
954
        uint pad_length= to_cs->mbminlen - from_offset;
951
955
        memset(to, 0, pad_length);
952
956
        memmove(to + pad_length, from, from_offset);
953
957
        nchars--;
974
978
    my_wc_t wc;
975
979
    my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
976
980
    my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
977
 
    const unsigned char *from_end= (const unsigned char*) from + from_length;
978
 
    unsigned char *to_end= (unsigned char*) to + to_length;
 
981
    const uchar *from_end= (const uchar*) from + from_length;
 
982
    uchar *to_end= (uchar*) to + to_length;
979
983
    char *to_start= to;
980
984
    *well_formed_error_pos= NULL;
981
985
    *cannot_convert_error_pos= NULL;
983
987
    for ( ; nchars; nchars--)
984
988
    {
985
989
      const char *from_prev= from;
986
 
      if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from, from_end)) > 0)
 
990
      if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0)
987
991
        from+= cnvres;
988
992
      else if (cnvres == MY_CS_ILSEQ)
989
993
      {
1007
1011
        break;  // Not enough characters
1008
1012
 
1009
1013
outp:
1010
 
      if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
 
1014
      if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
1011
1015
        to+= cnvres;
1012
1016
      else if (cnvres == MY_CS_ILUNI && wc != '?')
1013
1017
      {
1036
1040
  char *st= (char*)Ptr, *end= st+str_length;
1037
1041
  for (; st < end; st++)
1038
1042
  {
1039
 
    unsigned char c= *st;
 
1043
    uchar c= *st;
1040
1044
    switch (c)
1041
1045
    {
1042
1046
    case '\\':
1043
 
      str->append("\\\\", sizeof("\\\\")-1);
 
1047
      str->append(STRING_WITH_LEN("\\\\"));
1044
1048
      break;
1045
1049
    case '\0':
1046
 
      str->append("\\0", sizeof("\\0")-1);
 
1050
      str->append(STRING_WITH_LEN("\\0"));
1047
1051
      break;
1048
1052
    case '\'':
1049
 
      str->append("\\'", sizeof("\\'")-1);
 
1053
      str->append(STRING_WITH_LEN("\\'"));
1050
1054
      break;
1051
1055
    case '\n':
1052
 
      str->append("\\n", sizeof("\\n")-1);
 
1056
      str->append(STRING_WITH_LEN("\\n"));
1053
1057
      break;
1054
1058
    case '\r':
1055
 
      str->append("\\r", sizeof("\\r")-1);
 
1059
      str->append(STRING_WITH_LEN("\\r"));
1056
1060
      break;
1057
1061
    case '\032': // Ctrl-Z
1058
 
      str->append("\\Z", sizeof("\\Z")-1);
 
1062
      str->append(STRING_WITH_LEN("\\Z"));
1059
1063
      break;
1060
1064
    default:
1061
1065
      str->append(c);
1076
1080
 
1077
1081
void String::swap(String &s)
1078
1082
{
1079
 
  std::swap(Ptr, s.Ptr);
1080
 
  std::swap(str_length, s.str_length);
1081
 
  std::swap(Alloced_length, s.Alloced_length);
1082
 
  std::swap(alloced, s.alloced);
1083
 
  std::swap(str_charset, s.str_charset);
 
1083
  swap_variables(char *, Ptr, s.Ptr);
 
1084
  swap_variables(uint32_t, str_length, s.str_length);
 
1085
  swap_variables(uint32_t, Alloced_length, s.Alloced_length);
 
1086
  swap_variables(bool, alloced, s.alloced);
 
1087
  swap_variables(const CHARSET_INFO *, str_charset, s.str_charset);
1084
1088
}