~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_string.cc

  • Committer: Brian Aker
  • Date: 2009-10-07 16:55:53 UTC
  • mfrom: (1161.2.1 bug444827)
  • Revision ID: brian@gaz-20091007165553-9tnp7liw1k9g6gvc
Merge Padraig

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
24
using namespace std;
30
25
 
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
 
}
 
26
/*
 
27
  The following extern declarations are ok as these are interface functions
 
28
  required by the string function
 
29
*/
 
30
 
 
31
extern unsigned char* sql_alloc(unsigned size);
 
32
extern void sql_element_free(void *ptr);
 
33
 
 
34
#include "sql_string.h"
47
35
 
48
36
/*****************************************************************************
49
37
** String functions
50
38
*****************************************************************************/
51
39
 
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
40
String::~String() { free(); }
113
41
 
114
 
bool String::real_alloc(size_t arg_length)
 
42
bool String::real_alloc(uint32_t arg_length)
115
43
{
116
44
  arg_length=ALIGN_SIZE(arg_length+1);
117
45
  str_length=0;
118
46
  if (Alloced_length < arg_length)
119
47
  {
120
 
    if (Alloced_length > 0)
121
 
      free();
 
48
    free();
122
49
    if (!(Ptr=(char*) malloc(arg_length)))
123
50
      return true;
124
51
    Alloced_length=arg_length;
134
61
** (for C functions)
135
62
*/
136
63
 
137
 
bool String::realloc(size_t alloc_length)
 
64
bool String::realloc(uint32_t alloc_length)
138
65
{
139
 
  size_t len=ALIGN_SIZE(alloc_length+1);
 
66
  uint32_t len=ALIGN_SIZE(alloc_length+1);
140
67
  if (Alloced_length < len)
141
68
  {
142
69
    char *new_ptr;
168
95
 
169
96
bool String::set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs)
170
97
{
171
 
  size_t l=20*cs->mbmaxlen+1;
 
98
  uint32_t l=20*cs->mbmaxlen+1;
172
99
  int base= unsigned_flag ? 10 : -10;
173
100
 
174
101
  if (alloc(l))
175
102
    return true;
176
 
  str_length=(size_t) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
 
103
  str_length=(uint32_t) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
177
104
  str_charset=cs;
178
105
  return false;
179
106
}
180
107
 
181
 
bool String::set_real(double num,size_t decimals, const CHARSET_INFO * const cs)
 
108
bool String::set_real(double num,uint32_t decimals, const CHARSET_INFO * const cs)
182
109
{
183
110
  char buff[FLOATING_POINT_BUFFER];
184
 
  size_t dummy_errors;
 
111
  uint32_t dummy_errors;
185
112
  size_t len;
186
113
 
187
114
  str_charset=cs;
188
115
  if (decimals >= NOT_FIXED_DEC)
189
116
  {
190
 
    len= internal::my_gcvt(num,
191
 
                           internal::MY_GCVT_ARG_DOUBLE,
192
 
                           sizeof(buff) - 1, buff, NULL);
 
117
    len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
193
118
    return copy(buff, len, &my_charset_utf8_general_ci, cs, &dummy_errors);
194
119
  }
195
 
  len= internal::my_fcvt(num, decimals, buff, NULL);
196
 
  return copy(buff, (size_t) len, &my_charset_utf8_general_ci, cs,
 
120
  len= my_fcvt(num, decimals, buff, NULL);
 
121
  return copy(buff, (uint32_t) len, &my_charset_utf8_general_ci, cs,
197
122
              &dummy_errors);
198
123
}
199
124
 
219
144
  return false;
220
145
}
221
146
 
222
 
bool String::copy(const std::string& arg, const CHARSET_INFO * const cs)        // Allocate new string
223
 
{
224
 
  if (alloc(arg.size()))
225
 
    return true;
226
 
 
227
 
  if ((str_length= arg.size()))
228
 
    memcpy(Ptr, arg.c_str(), arg.size());
229
 
 
230
 
  Ptr[arg.size()]= 0;
231
 
  str_charset= cs;
232
 
 
233
 
  return false;
234
 
}
235
 
 
236
 
bool String::copy(const char *str,size_t arg_length, const CHARSET_INFO * const cs)
 
147
bool String::copy(const char *str,uint32_t arg_length, const CHARSET_INFO * const cs)
237
148
{
238
149
  if (alloc(arg_length))
239
150
    return true;
244
155
  return false;
245
156
}
246
157
 
 
158
 
247
159
/*
248
160
  Checks that the source string can be just copied to the destination string
249
161
  without conversion.
254
166
  arg_length            Length of string to copy.
255
167
  from_cs               Character set to copy from
256
168
  to_cs                 Character set to copy to
257
 
  size_t *offset        Returns number of unaligned characters.
 
169
  uint32_t *offset      Returns number of unaligned characters.
258
170
 
259
171
  RETURN
260
172
   0  No conversion needed
266
178
  character_set_results is NULL.
267
179
*/
268
180
 
269
 
bool String::needs_conversion(size_t arg_length,
 
181
bool String::needs_conversion(uint32_t arg_length,
270
182
                              const CHARSET_INFO * const from_cs,
271
183
                              const CHARSET_INFO * const to_cs,
272
 
                              size_t *offset)
 
184
                              uint32_t *offset)
273
185
{
274
186
  *offset= 0;
275
187
  if (!to_cs ||
285
197
 
286
198
 
287
199
 
288
 
bool String::set_or_copy_aligned(const char *str,size_t arg_length,
 
200
bool String::set_or_copy_aligned(const char *str,uint32_t arg_length,
289
201
                                 const CHARSET_INFO * const cs)
290
202
{
291
203
  /* How many bytes are in incomplete character */
292
 
  size_t offset= (arg_length % cs->mbminlen);
 
204
  uint32_t offset= (arg_length % cs->mbminlen);
293
205
 
294
206
  assert(!offset); /* All characters are complete, just copy */
295
207
 
299
211
 
300
212
        /* Copy with charset conversion */
301
213
 
302
 
bool String::copy(const char *str, size_t arg_length,
 
214
bool String::copy(const char *str, uint32_t arg_length,
303
215
                          const CHARSET_INFO * const,
304
 
                                  const CHARSET_INFO * const to_cs, size_t *errors)
 
216
                                  const CHARSET_INFO * const to_cs, uint32_t *errors)
305
217
{
306
218
  *errors= 0;
307
219
  return copy(str, arg_length, to_cs);
327
239
 
328
240
*/
329
241
 
330
 
bool String::set_ascii(const char *str, size_t arg_length)
 
242
bool String::set_ascii(const char *str, uint32_t arg_length)
331
243
{
332
244
  if (str_charset->mbminlen == 1)
333
245
  {
334
246
    set(str, arg_length, str_charset);
335
247
    return 0;
336
248
  }
337
 
  size_t dummy_errors;
 
249
  uint32_t dummy_errors;
338
250
  return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
339
251
}
340
252
 
355
267
  Append an ASCII string to the a string of the current character set
356
268
*/
357
269
 
358
 
bool String::append(const char *s,size_t arg_length)
 
270
bool String::append(const char *s,uint32_t arg_length)
359
271
{
360
272
  if (!arg_length)
361
273
    return false;
386
298
  with character set recoding
387
299
*/
388
300
 
389
 
bool String::append(const char *s,size_t arg_length, const CHARSET_INFO * const)
 
301
bool String::append(const char *s,uint32_t arg_length, const CHARSET_INFO * const)
390
302
{
391
303
  if (realloc(str_length + arg_length))
392
304
    return true;
397
309
}
398
310
 
399
311
 
400
 
bool String::append_with_prefill(const char *s,size_t arg_length,
401
 
                 size_t full_length, char fill_char)
 
312
bool String::append_with_prefill(const char *s,uint32_t arg_length,
 
313
                 uint32_t full_length, char fill_char)
402
314
{
403
315
  int t_length= arg_length > full_length ? arg_length : full_length;
404
316
 
414
326
  return false;
415
327
}
416
328
 
417
 
size_t String::numchars()
 
329
uint32_t String::numchars()
418
330
{
419
331
  return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
420
332
}
421
333
 
422
 
int String::charpos(int i,size_t offset)
 
334
int String::charpos(int i,uint32_t offset)
423
335
{
424
336
  if (i <= 0)
425
337
    return i;
426
338
  return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
427
339
}
428
340
 
429
 
int String::strstr(const String &s,size_t offset)
 
341
int String::strstr(const String &s,uint32_t offset)
430
342
{
431
343
  if (s.length()+offset <= str_length)
432
344
  {
457
369
** Search string from end. Offset is offset to the end of string
458
370
*/
459
371
 
460
 
int String::strrstr(const String &s,size_t offset)
 
372
int String::strrstr(const String &s,uint32_t offset)
461
373
{
462
374
  if (s.length() <= offset && offset <= str_length)
463
375
  {
489
401
  If wrong parameter or not enough memory, do nothing
490
402
*/
491
403
 
492
 
bool String::replace(size_t offset,size_t arg_length,const String &to)
 
404
bool String::replace(uint32_t offset,uint32_t arg_length,const String &to)
493
405
{
494
406
  return replace(offset,arg_length,to.ptr(),to.length());
495
407
}
496
408
 
497
 
bool String::replace(size_t offset,size_t arg_length,
498
 
                     const char *to, size_t to_length)
 
409
bool String::replace(uint32_t offset,uint32_t arg_length,
 
410
                     const char *to, uint32_t to_length)
499
411
{
500
412
  long diff = (long) to_length-(long) arg_length;
501
413
  if (offset+arg_length <= str_length)
511
423
    {
512
424
      if (diff)
513
425
      {
514
 
        if (realloc(str_length+(size_t) diff))
 
426
        if (realloc(str_length+(uint32_t) diff))
515
427
          return true;
516
 
        internal::bmove_upp((unsigned char*) Ptr+str_length+diff,
517
 
                            (unsigned char*) Ptr+str_length,
518
 
                            str_length-offset-arg_length);
 
428
        bmove_upp((unsigned char*) Ptr+str_length+diff, (unsigned char*) Ptr+str_length,
 
429
                  str_length-offset-arg_length);
519
430
      }
520
431
      if (to_length)
521
432
        memcpy(Ptr+offset,to,to_length);
522
433
    }
523
 
    str_length+=(size_t) diff;
 
434
    str_length+=(uint32_t) diff;
524
435
  }
525
436
  return false;
526
437
}
574
485
 
575
486
int stringcmp(const String *s,const String *t)
576
487
{
577
 
  size_t s_len= s->length(), t_len= t->length(), len= min(s_len,t_len);
 
488
  uint32_t s_len= s->length(), t_len= t->length(), len= min(s_len,t_len);
578
489
  int cmp= memcmp(s->ptr(), t->ptr(), len);
579
490
  return (cmp) ? cmp : (int) (s_len - t_len);
580
491
}
581
492
 
582
493
 
583
 
String *copy_if_not_alloced(String *to,String *from,size_t from_length)
 
494
String *copy_if_not_alloced(String *to,String *from,uint32_t from_length)
584
495
{
585
496
  if (from->Alloced_length >= from_length)
586
497
    return from;
602
513
  Help functions
603
514
****************************************************************************/
604
515
 
 
516
 
 
517
 
 
518
/**
 
519
  Copy string with HEX-encoding of "bad" characters.
 
520
 
 
521
  @details This functions copies the string pointed by "src"
 
522
  to the string pointed by "dst". Not more than "srclen" bytes
 
523
  are read from "src". Any sequences of bytes representing
 
524
  a not-well-formed substring (according to cs) are hex-encoded,
 
525
  and all well-formed substrings (according to cs) are copied as is.
 
526
  Not more than "dstlen" bytes are written to "dst". The number
 
527
  of bytes written to "dst" is returned.
 
528
 
 
529
   @param      cs       character set pointer of the destination string
 
530
   @param[out] dst      destination string
 
531
   @param      dstlen   size of dst
 
532
   @param      src      source string
 
533
   @param      srclen   length of src
 
534
 
 
535
   @retval     result length
 
536
*/
 
537
 
 
538
size_t
 
539
my_copy_with_hex_escaping(const CHARSET_INFO * const cs,
 
540
                          char *dst, size_t dstlen,
 
541
                          const char *src, size_t srclen)
 
542
{
 
543
  const char *srcend= src + srclen;
 
544
  char *dst0= dst;
 
545
 
 
546
  for ( ; src < srcend ; )
 
547
  {
 
548
    size_t chlen;
 
549
    if ((chlen= my_ismbchar(cs, src, srcend)))
 
550
    {
 
551
      if (dstlen < chlen)
 
552
        break;
 
553
      memcpy(dst, src, chlen);
 
554
      src+= chlen;
 
555
      dst+= chlen;
 
556
      dstlen-= chlen;
 
557
    }
 
558
    else if (*src & 0x80)
 
559
    {
 
560
      if (dstlen < 4)
 
561
        break;
 
562
      *dst++= '\\';
 
563
      *dst++= 'x';
 
564
      *dst++= _dig_vec_upper[((unsigned char) *src) >> 4];
 
565
      *dst++= _dig_vec_upper[((unsigned char) *src) & 15];
 
566
      src++;
 
567
      dstlen-= 4;
 
568
    }
 
569
    else
 
570
    {
 
571
      if (dstlen < 1)
 
572
        break;
 
573
      *dst++= *src++;
 
574
      dstlen--;
 
575
    }
 
576
  }
 
577
  return dst - dst0;
 
578
}
 
579
 
605
580
/*
606
581
  copy a string,
607
582
  with optional character set conversion,
629
604
*/
630
605
 
631
606
 
632
 
size_t
 
607
uint32_t
633
608
well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
634
 
                        char *to, size_t to_length,
 
609
                        char *to, uint32_t to_length,
635
610
                        const CHARSET_INFO * const from_cs,
636
 
                        const char *from, size_t from_length,
637
 
                        size_t nchars,
 
611
                        const char *from, uint32_t from_length,
 
612
                        uint32_t nchars,
638
613
                        const char **well_formed_error_pos,
639
614
                        const char **cannot_convert_error_pos,
640
615
                        const char **from_end_pos)
641
616
{
642
 
  size_t res;
 
617
  uint32_t res;
643
618
 
644
619
  assert((to_cs == &my_charset_bin) ||
645
620
         (from_cs == &my_charset_bin) ||
665
640
  else
666
641
  {
667
642
    int well_formed_error;
668
 
    size_t from_offset;
 
643
    uint32_t from_offset;
669
644
 
670
645
    if ((from_offset= (from_length % to_cs->mbminlen)) &&
671
646
        (from_cs == &my_charset_bin))
675
650
        INSERT INTO t1 (ucs2_column) VALUES (0x01);
676
651
        0x01 -> 0x0001
677
652
      */
678
 
      size_t pad_length= to_cs->mbminlen - from_offset;
 
653
      uint32_t pad_length= to_cs->mbminlen - from_offset;
679
654
      memset(to, 0, pad_length);
680
655
      memmove(to + pad_length, from, from_offset);
681
656
      nchars--;
747
722
/* Factor the extern out */
748
723
extern const CHARSET_INFO *system_charset_info, *files_charset_info;
749
724
 
750
 
void String::append_identifier(const char *name, size_t in_length)
 
725
void String::append_identifier(const char *name, uint32_t in_length)
751
726
{
752
727
  const char *name_end;
753
728
  char quote_char;
802
777
  std::swap(str_charset, s.str_charset);
803
778
}
804
779
 
805
 
void String::q_append(const size_t n)
806
 
{
807
 
  int8store(Ptr + str_length, n);
808
 
  str_length += 4;
809
 
}
810
 
void String::q_append(double d)
811
 
{
812
 
  float8store(Ptr + str_length, d);
813
 
  str_length += 8;
814
 
}
815
 
void String::q_append(double *d)
816
 
{
817
 
  float8store(Ptr + str_length, *d);
818
 
  str_length += 8;
819
 
}
820
 
void String::q_append(const char *data, size_t data_len)
821
 
{
822
 
  memcpy(Ptr + str_length, data, data_len);
823
 
  str_length += data_len;
824
 
}
825
 
 
826
 
void String::write_at_position(int position, size_t value)
827
 
{
828
 
  int8store(Ptr + position,value);
829
 
}
830
 
bool check_if_only_end_space(const CHARSET_INFO * const cs, char *str,
831
 
                             char *end)
832
 
{
833
 
  return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end;
834
 
}
835
 
 
836
 
std::ostream& operator<<(std::ostream& output, const String &str)
837
 
{
838
 
  output << "String:(";
839
 
  output <<  const_cast<String&>(str).c_str();
840
 
  output << ", ";
841
 
  output << str.length();
842
 
  output << ")";
843
 
 
844
 
  return output;  // for multiple << operators.
845
 
}
846
 
 
847
 
} /* namespace drizzled */
848
 
 
849
 
bool operator==(const drizzled::String &s1, const drizzled::String &s2)
 
780
 
 
781
bool operator==(const String &s1, const String &s2)
850
782
{
851
783
  return stringcmp(&s1,&s2) == 0;
852
784
}
853
785
 
854
 
bool operator!=(const drizzled::String &s1, const drizzled::String &s2)
 
786
bool operator!=(const String &s1, const String &s2)
855
787
{
856
788
  return !(s1 == s2);
857
789
}