~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_string.cc

  • Committer: Monty Taylor
  • Date: 2008-08-04 19:37:18 UTC
  • mto: (261.2.2 codestyle)
  • mto: This revision was merged to the branch mainline in revision 262.
  • Revision ID: monty@inaugust.com-20080804193718-f0rz13uli4429ozb
Changed gettext_noop() to N_()

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* This file is originally from the mysql distribution. Coded by monty */
17
17
 
 
18
#ifdef USE_PRAGMA_IMPLEMENTATION
 
19
#pragma implementation                          // gcc: Class implementation
 
20
#endif
 
21
 
18
22
#include "global.h"
19
23
#include <mysys/my_sys.h>
20
24
#include <mystrings/m_string.h>
21
25
 
22
 
#include <algorithm>
23
 
 
24
26
/*
25
27
  The following extern declarations are ok as these are interface functions
26
28
  required by the string function
27
29
*/
28
30
 
29
 
extern unsigned char* sql_alloc(unsigned size);
 
31
extern uchar* sql_alloc(unsigned size);
30
32
extern void sql_element_free(void *ptr);
31
33
 
32
34
#include "sql_string.h"
89
91
  return false;
90
92
}
91
93
 
92
 
bool String::set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs)
 
94
bool String::set_int(int64_t num, bool unsigned_flag, CHARSET_INFO *cs)
93
95
{
94
 
  uint32_t l=20*cs->mbmaxlen+1;
 
96
  uint l=20*cs->mbmaxlen+1;
95
97
  int base= unsigned_flag ? 10 : -10;
96
98
 
97
99
  if (alloc(l))
101
103
  return false;
102
104
}
103
105
 
104
 
bool String::set_real(double num,uint32_t decimals, const CHARSET_INFO * const cs)
 
106
bool String::set_real(double num,uint decimals, CHARSET_INFO *cs)
105
107
{
106
108
  char buff[FLOATING_POINT_BUFFER];
107
 
  uint32_t dummy_errors;
 
109
  uint dummy_errors;
108
110
  size_t len;
109
111
 
110
112
  str_charset=cs;
111
113
  if (decimals >= NOT_FIXED_DEC)
112
114
  {
113
115
    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);
 
116
    return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
115
117
  }
116
118
  len= my_fcvt(num, decimals, buff, NULL);
117
 
  return copy(buff, (uint32_t) len, &my_charset_utf8_general_ci, cs,
 
119
  return copy(buff, (uint32_t) len, &my_charset_latin1, cs,
118
120
              &dummy_errors);
119
121
}
120
122
 
140
142
  return false;
141
143
}
142
144
 
143
 
bool String::copy(const char *str,uint32_t arg_length, const CHARSET_INFO * const cs)
 
145
bool String::copy(const char *str,uint32_t arg_length, CHARSET_INFO *cs)
144
146
{
145
147
  if (alloc(arg_length))
146
148
    return true;
175
177
*/
176
178
 
177
179
bool String::needs_conversion(uint32_t arg_length,
178
 
                              const CHARSET_INFO * const from_cs,
179
 
                              const CHARSET_INFO * const to_cs,
 
180
                              CHARSET_INFO *from_cs,
 
181
                              CHARSET_INFO *to_cs,
180
182
                              uint32_t *offset)
181
183
{
182
184
  *offset= 0;
217
219
*/
218
220
 
219
221
bool String::copy_aligned(const char *str,uint32_t arg_length, uint32_t offset,
220
 
                          const CHARSET_INFO * const cs)
 
222
                          CHARSET_INFO *cs)
221
223
{
222
224
  /* How many bytes are in incomplete character */
223
225
  offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */
232
234
    If we add little-endian UCS-2 sometimes, this code
233
235
    will be more complicated. But it's OK for now.
234
236
  */
235
 
  memset(Ptr, 0, offset);
 
237
  memset((char*) Ptr, 0, offset);
236
238
  memcpy(Ptr + offset, str, arg_length);
237
239
  Ptr[aligned_length]=0;
238
240
  /* str_length is always >= 0 as arg_length is != 0 */
243
245
 
244
246
 
245
247
bool String::set_or_copy_aligned(const char *str,uint32_t arg_length,
246
 
                                 const CHARSET_INFO * const cs)
 
248
                                 CHARSET_INFO *cs)
247
249
{
248
250
  /* How many bytes are in incomplete character */
249
251
  uint32_t offset= (arg_length % cs->mbminlen); 
259
261
        /* Copy with charset conversion */
260
262
 
261
263
bool String::copy(const char *str, uint32_t arg_length,
262
 
                          const CHARSET_INFO * const from_cs,
263
 
                                  const CHARSET_INFO * const to_cs, uint32_t *errors)
 
264
                  CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
264
265
{
265
266
  uint32_t offset;
266
267
  if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
309
310
    set(str, arg_length, str_charset);
310
311
    return 0;
311
312
  }
312
 
  uint32_t dummy_errors;
313
 
  return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
 
313
  uint dummy_errors;
 
314
  return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors);
314
315
}
315
316
 
316
317
 
330
331
  return false;
331
332
}
332
333
 
 
334
void String::strip_sp()
 
335
{
 
336
   while (str_length && my_isspace(str_charset,Ptr[str_length-1]))
 
337
    str_length--;
 
338
}
 
339
 
333
340
bool String::append(const String &s)
334
341
{
335
342
  if (s.length())
358
365
  if (str_charset->mbminlen > 1)
359
366
  {
360
367
    uint32_t add_length=arg_length * str_charset->mbmaxlen;
361
 
    uint32_t dummy_errors;
 
368
    uint dummy_errors;
362
369
    if (realloc(str_length+ add_length))
363
370
      return true;
364
371
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
365
 
                                  s, arg_length, &my_charset_utf8_general_ci,
 
372
                                  s, arg_length, &my_charset_latin1,
366
373
                                  &dummy_errors);
367
374
    return false;
368
375
  }
393
400
  with character set recoding
394
401
*/
395
402
 
396
 
bool String::append(const char *s,uint32_t arg_length, const CHARSET_INFO * const cs)
 
403
bool String::append(const char *s,uint32_t arg_length, CHARSET_INFO *cs)
397
404
{
398
405
  uint32_t dummy_offset;
399
406
  
400
407
  if (needs_conversion(arg_length, cs, str_charset, &dummy_offset))
401
408
  {
402
409
    uint32_t add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
403
 
    uint32_t dummy_errors;
 
410
    uint dummy_errors;
404
411
    if (realloc(str_length + add_length)) 
405
412
      return true;
406
413
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
421
428
{
422
429
  if (realloc(str_length+arg_length))
423
430
    return true;
424
 
  if (my_b_read(file, (unsigned char*) Ptr + str_length, arg_length))
 
431
  if (my_b_read(file, (uchar*) Ptr + str_length, arg_length))
425
432
  {
426
433
    shrink(str_length);
427
434
    return true;
546
553
      {
547
554
        if (realloc(str_length+(uint32_t) diff))
548
555
          return true;
549
 
        bmove_upp((unsigned char*) Ptr+str_length+diff, (unsigned char*) Ptr+str_length,
 
556
        bmove_upp((uchar*) Ptr+str_length+diff, (uchar*) Ptr+str_length,
550
557
                  str_length-offset-arg_length);
551
558
      }
552
559
      if (to_length)
563
570
{
564
571
  if (Alloced_length < str_length + space_needed)
565
572
  {
566
 
    if (realloc(Alloced_length + cmax(space_needed, grow_by) - 1))
 
573
    if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
567
574
      return true;
568
575
  }
569
576
  return false;
595
602
  str_length+= (int) (end-buff);
596
603
}
597
604
 
598
 
void String::qs_append(uint32_t i)
 
605
void String::qs_append(uint i)
599
606
{
600
607
  char *buff= Ptr + str_length;
601
608
  char *end= int10_to_str(i, buff, 10);
621
628
*/
622
629
 
623
630
 
624
 
int sortcmp(const String *s,const String *t, const CHARSET_INFO * const cs)
 
631
int sortcmp(const String *s,const String *t, CHARSET_INFO *cs)
625
632
{
626
633
 return cs->coll->strnncollsp(cs,
627
 
                              (unsigned char *) s->ptr(),s->length(),
628
 
                              (unsigned char *) t->ptr(),t->length(), 0);
 
634
                              (uchar *) s->ptr(),s->length(),
 
635
                              (uchar *) t->ptr(),t->length(), 0);
629
636
}
630
637
 
631
638
 
638
645
    t           Second string
639
646
 
640
647
  NOTE:
641
 
    Strings are compared as a stream of unsigned chars
 
648
    Strings are compared as a stream of uchars
642
649
 
643
650
  RETURN
644
651
  < 0   s < t
649
656
 
650
657
int stringcmp(const String *s,const String *t)
651
658
{
652
 
  uint32_t s_len=s->length(),t_len=t->length(),len=cmin(s_len,t_len);
 
659
  uint32_t s_len=s->length(),t_len=t->length(),len=min(s_len,t_len);
653
660
  int cmp= memcmp(s->ptr(), t->ptr(), len);
654
661
  return (cmp) ? cmp : (int) (s_len - t_len);
655
662
}
666
673
  }
667
674
  if (to->realloc(from_length))
668
675
    return from;                                // Actually an error
669
 
  if ((to->str_length=cmin(from->str_length,from_length)))
 
676
  if ((to->str_length=min(from->str_length,from_length)))
670
677
    memcpy(to->Ptr,from->Ptr,to->str_length);
671
678
  to->str_charset=from->str_charset;
672
679
  return to;
697
704
 
698
705
 
699
706
static uint32_t
700
 
copy_and_convert_extended(char *to, uint32_t to_length,
701
 
                          const CHARSET_INFO * const to_cs, 
 
707
copy_and_convert_extended(char *to, uint32_t to_length, CHARSET_INFO *to_cs, 
702
708
                          const char *from, uint32_t from_length,
703
 
                          const CHARSET_INFO * const from_cs,
704
 
                          uint32_t *errors)
 
709
                          CHARSET_INFO *from_cs,
 
710
                          uint *errors)
705
711
{
706
712
  int         cnvres;
707
713
  my_wc_t     wc;
708
 
  const unsigned char *from_end= (const unsigned char*) from+from_length;
 
714
  const uchar *from_end= (const uchar*) from+from_length;
709
715
  char *to_start= to;
710
 
  unsigned char *to_end= (unsigned char*) to+to_length;
 
716
  uchar *to_end= (uchar*) to+to_length;
711
717
  my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
712
718
  my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
713
 
  uint32_t error_count= 0;
 
719
  uint error_count= 0;
714
720
 
715
721
  while (1)
716
722
  {
717
 
    if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from,
 
723
    if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
718
724
                                      from_end)) > 0)
719
725
      from+= cnvres;
720
726
    else if (cnvres == MY_CS_ILSEQ)
737
743
      break;  // Not enough characters
738
744
 
739
745
outp:
740
 
    if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
 
746
    if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
741
747
      to+= cnvres;
742
748
    else if (cnvres == MY_CS_ILUNI && wc != '?')
743
749
    {
757
763
  Optimized for quick copying of ASCII characters in the range 0x00..0x7F.
758
764
*/
759
765
uint32_t
760
 
copy_and_convert(char *to, uint32_t to_length, const CHARSET_INFO * const to_cs, 
761
 
                 const char *from, uint32_t from_length,
762
 
                                 const CHARSET_INFO * const from_cs, uint32_t *errors)
 
766
copy_and_convert(char *to, uint32_t to_length, CHARSET_INFO *to_cs, 
 
767
                 const char *from, uint32_t from_length, CHARSET_INFO *from_cs,
 
768
                 uint *errors)
763
769
{
764
770
  /*
765
771
    If any of the character sets is not ASCII compatible,
769
775
    return copy_and_convert_extended(to, to_length, to_cs,
770
776
                                     from, from_length, from_cs, errors);
771
777
 
772
 
  uint32_t length= cmin(to_length, from_length), length2= length;
 
778
  uint32_t length= min(to_length, from_length), length2= length;
773
779
 
774
780
#if defined(__i386__)
775
781
  /*
833
839
*/
834
840
 
835
841
size_t
836
 
my_copy_with_hex_escaping(const CHARSET_INFO * const cs,
 
842
my_copy_with_hex_escaping(CHARSET_INFO *cs,
837
843
                          char *dst, size_t dstlen,
838
844
                          const char *src, size_t srclen)
839
845
{
902
908
 
903
909
 
904
910
uint32_t
905
 
well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
906
 
                        char *to, uint32_t to_length,
907
 
                        const CHARSET_INFO * const from_cs,
908
 
                        const char *from, uint32_t from_length,
909
 
                        uint32_t nchars,
 
911
well_formed_copy_nchars(CHARSET_INFO *to_cs,
 
912
                        char *to, uint to_length,
 
913
                        CHARSET_INFO *from_cs,
 
914
                        const char *from, uint from_length,
 
915
                        uint nchars,
910
916
                        const char **well_formed_error_pos,
911
917
                        const char **cannot_convert_error_pos,
912
918
                        const char **from_end_pos)
913
919
{
914
 
  uint32_t res;
 
920
  uint res;
915
921
 
916
922
  if ((to_cs == &my_charset_bin) || 
917
923
      (from_cs == &my_charset_bin) ||
928
934
 
929
935
    if (to_cs == &my_charset_bin)
930
936
    {
931
 
      res= cmin(cmin(nchars, to_length), from_length);
 
937
      res= min(min(nchars, to_length), from_length);
932
938
      memmove(to, from, res);
933
939
      *from_end_pos= from + res;
934
940
      *well_formed_error_pos= NULL;
937
943
    else
938
944
    {
939
945
      int well_formed_error;
940
 
      uint32_t from_offset;
 
946
      uint from_offset;
941
947
 
942
948
      if ((from_offset= (from_length % to_cs->mbminlen)) &&
943
949
          (from_cs == &my_charset_bin))
947
953
          INSERT INTO t1 (ucs2_column) VALUES (0x01);
948
954
          0x01 -> 0x0001
949
955
        */
950
 
        uint32_t pad_length= to_cs->mbminlen - from_offset;
 
956
        uint pad_length= to_cs->mbminlen - from_offset;
951
957
        memset(to, 0, pad_length);
952
958
        memmove(to + pad_length, from, from_offset);
953
959
        nchars--;
974
980
    my_wc_t wc;
975
981
    my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
976
982
    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;
 
983
    const uchar *from_end= (const uchar*) from + from_length;
 
984
    uchar *to_end= (uchar*) to + to_length;
979
985
    char *to_start= to;
980
986
    *well_formed_error_pos= NULL;
981
987
    *cannot_convert_error_pos= NULL;
983
989
    for ( ; nchars; nchars--)
984
990
    {
985
991
      const char *from_prev= from;
986
 
      if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from, from_end)) > 0)
 
992
      if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0)
987
993
        from+= cnvres;
988
994
      else if (cnvres == MY_CS_ILSEQ)
989
995
      {
1007
1013
        break;  // Not enough characters
1008
1014
 
1009
1015
outp:
1010
 
      if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
 
1016
      if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
1011
1017
        to+= cnvres;
1012
1018
      else if (cnvres == MY_CS_ILUNI && wc != '?')
1013
1019
      {
1036
1042
  char *st= (char*)Ptr, *end= st+str_length;
1037
1043
  for (; st < end; st++)
1038
1044
  {
1039
 
    unsigned char c= *st;
 
1045
    uchar c= *st;
1040
1046
    switch (c)
1041
1047
    {
1042
1048
    case '\\':
1043
 
      str->append("\\\\", sizeof("\\\\")-1);
 
1049
      str->append(STRING_WITH_LEN("\\\\"));
1044
1050
      break;
1045
1051
    case '\0':
1046
 
      str->append("\\0", sizeof("\\0")-1);
 
1052
      str->append(STRING_WITH_LEN("\\0"));
1047
1053
      break;
1048
1054
    case '\'':
1049
 
      str->append("\\'", sizeof("\\'")-1);
 
1055
      str->append(STRING_WITH_LEN("\\'"));
1050
1056
      break;
1051
1057
    case '\n':
1052
 
      str->append("\\n", sizeof("\\n")-1);
 
1058
      str->append(STRING_WITH_LEN("\\n"));
1053
1059
      break;
1054
1060
    case '\r':
1055
 
      str->append("\\r", sizeof("\\r")-1);
 
1061
      str->append(STRING_WITH_LEN("\\r"));
1056
1062
      break;
1057
1063
    case '\032': // Ctrl-Z
1058
 
      str->append("\\Z", sizeof("\\Z")-1);
 
1064
      str->append(STRING_WITH_LEN("\\Z"));
1059
1065
      break;
1060
1066
    default:
1061
1067
      str->append(c);
1076
1082
 
1077
1083
void String::swap(String &s)
1078
1084
{
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);
1084
 
}
1085
 
 
1086
 
 
1087
 
bool operator==(const String &s1, const String &s2)
1088
 
{
1089
 
  return stringcmp(&s1,&s2) == 0;
1090
 
}
1091
 
 
1092
 
bool operator!=(const String &s1, const String &s2)
1093
 
{
1094
 
  return !(s1 == s2);
1095
 
}
1096
 
 
 
1085
  swap_variables(char *, Ptr, s.Ptr);
 
1086
  swap_variables(uint32_t, str_length, s.str_length);
 
1087
  swap_variables(uint32_t, Alloced_length, s.Alloced_length);
 
1088
  swap_variables(bool, alloced, s.alloced);
 
1089
  swap_variables(CHARSET_INFO*, str_charset, s.str_charset);
 
1090
}