~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_string.cc

  • Committer: Stewart Smith
  • Date: 2009-06-17 06:44:38 UTC
  • mto: This revision was merged to the branch mainline in revision 1094.
  • Revision ID: stewart@flamingspork.com-20090617064438-062owpgtdzgr4lvx
type_float.test for MyISAM as temp only

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
38
String::~String() { free(); }
113
39
 
114
 
bool String::real_alloc(size_t arg_length)
 
40
bool String::real_alloc(uint32_t arg_length)
115
41
{
116
42
  arg_length=ALIGN_SIZE(arg_length+1);
117
43
  str_length=0;
118
44
  if (Alloced_length < arg_length)
119
45
  {
120
 
    if (Alloced_length > 0)
121
 
      free();
 
46
    free();
122
47
    if (!(Ptr=(char*) malloc(arg_length)))
123
48
      return true;
124
49
    Alloced_length=arg_length;
134
59
** (for C functions)
135
60
*/
136
61
 
137
 
bool String::realloc(size_t alloc_length)
 
62
bool String::realloc(uint32_t alloc_length)
138
63
{
139
 
  size_t len=ALIGN_SIZE(alloc_length+1);
 
64
  uint32_t len=ALIGN_SIZE(alloc_length+1);
140
65
  if (Alloced_length < len)
141
66
  {
142
67
    char *new_ptr;
168
93
 
169
94
bool String::set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs)
170
95
{
171
 
  size_t l=20*cs->mbmaxlen+1;
 
96
  uint32_t l=20*cs->mbmaxlen+1;
172
97
  int base= unsigned_flag ? 10 : -10;
173
98
 
174
99
  if (alloc(l))
175
100
    return true;
176
 
  str_length=(size_t) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
 
101
  str_length=(uint32_t) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
177
102
  str_charset=cs;
178
103
  return false;
179
104
}
180
105
 
181
 
bool String::set_real(double num,size_t decimals, const CHARSET_INFO * const cs)
 
106
bool String::set_real(double num,uint32_t decimals, const CHARSET_INFO * const cs)
182
107
{
183
108
  char buff[FLOATING_POINT_BUFFER];
184
 
  size_t dummy_errors;
 
109
  uint32_t dummy_errors;
185
110
  size_t len;
186
111
 
187
112
  str_charset=cs;
188
113
  if (decimals >= NOT_FIXED_DEC)
189
114
  {
190
 
    len= internal::my_gcvt(num,
191
 
                           internal::MY_GCVT_ARG_DOUBLE,
192
 
                           sizeof(buff) - 1, buff, NULL);
 
115
    len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
193
116
    return copy(buff, len, &my_charset_utf8_general_ci, cs, &dummy_errors);
194
117
  }
195
 
  len= internal::my_fcvt(num, decimals, buff, NULL);
196
 
  return copy(buff, (size_t) len, &my_charset_utf8_general_ci, cs,
 
118
  len= my_fcvt(num, decimals, buff, NULL);
 
119
  return copy(buff, (uint32_t) len, &my_charset_utf8_general_ci, cs,
197
120
              &dummy_errors);
198
121
}
199
122
 
219
142
  return false;
220
143
}
221
144
 
222
 
bool String::copy(const char *str,size_t arg_length, const CHARSET_INFO * const cs)
 
145
bool String::copy(const char *str,uint32_t arg_length, const CHARSET_INFO * const cs)
223
146
{
224
147
  if (alloc(arg_length))
225
148
    return true;
230
153
  return false;
231
154
}
232
155
 
 
156
 
233
157
/*
234
158
  Checks that the source string can be just copied to the destination string
235
159
  without conversion.
240
164
  arg_length            Length of string to copy.
241
165
  from_cs               Character set to copy from
242
166
  to_cs                 Character set to copy to
243
 
  size_t *offset        Returns number of unaligned characters.
 
167
  uint32_t *offset      Returns number of unaligned characters.
244
168
 
245
169
  RETURN
246
170
   0  No conversion needed
252
176
  character_set_results is NULL.
253
177
*/
254
178
 
255
 
bool String::needs_conversion(size_t arg_length,
 
179
bool String::needs_conversion(uint32_t arg_length,
256
180
                              const CHARSET_INFO * const from_cs,
257
181
                              const CHARSET_INFO * const to_cs,
258
 
                              size_t *offset)
 
182
                              uint32_t *offset)
259
183
{
260
184
  *offset= 0;
261
185
  if (!to_cs ||
271
195
 
272
196
 
273
197
 
274
 
bool String::set_or_copy_aligned(const char *str,size_t arg_length,
 
198
bool String::set_or_copy_aligned(const char *str,uint32_t arg_length,
275
199
                                 const CHARSET_INFO * const cs)
276
200
{
277
201
  /* How many bytes are in incomplete character */
278
 
  size_t offset= (arg_length % cs->mbminlen);
 
202
  uint32_t offset= (arg_length % cs->mbminlen);
279
203
 
280
204
  assert(!offset); /* All characters are complete, just copy */
281
205
 
285
209
 
286
210
        /* Copy with charset conversion */
287
211
 
288
 
bool String::copy(const char *str, size_t arg_length,
 
212
bool String::copy(const char *str, uint32_t arg_length,
289
213
                          const CHARSET_INFO * const,
290
 
                                  const CHARSET_INFO * const to_cs, size_t *errors)
 
214
                                  const CHARSET_INFO * const to_cs, uint32_t *errors)
291
215
{
292
216
  *errors= 0;
293
217
  return copy(str, arg_length, to_cs);
313
237
 
314
238
*/
315
239
 
316
 
bool String::set_ascii(const char *str, size_t arg_length)
 
240
bool String::set_ascii(const char *str, uint32_t arg_length)
317
241
{
318
242
  if (str_charset->mbminlen == 1)
319
243
  {
320
244
    set(str, arg_length, str_charset);
321
245
    return 0;
322
246
  }
323
 
  size_t dummy_errors;
 
247
  uint32_t dummy_errors;
324
248
  return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
325
249
}
326
250
 
341
265
  Append an ASCII string to the a string of the current character set
342
266
*/
343
267
 
344
 
bool String::append(const char *s,size_t arg_length)
 
268
bool String::append(const char *s,uint32_t arg_length)
345
269
{
346
270
  if (!arg_length)
347
271
    return false;
372
296
  with character set recoding
373
297
*/
374
298
 
375
 
bool String::append(const char *s,size_t arg_length, const CHARSET_INFO * const)
 
299
bool String::append(const char *s,uint32_t arg_length, const CHARSET_INFO * const)
376
300
{
377
301
  if (realloc(str_length + arg_length))
378
302
    return true;
383
307
}
384
308
 
385
309
 
386
 
bool String::append_with_prefill(const char *s,size_t arg_length,
387
 
                 size_t full_length, char fill_char)
 
310
bool String::append_with_prefill(const char *s,uint32_t arg_length,
 
311
                 uint32_t full_length, char fill_char)
388
312
{
389
313
  int t_length= arg_length > full_length ? arg_length : full_length;
390
314
 
400
324
  return false;
401
325
}
402
326
 
403
 
size_t String::numchars()
 
327
uint32_t String::numchars()
404
328
{
405
329
  return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
406
330
}
407
331
 
408
 
int String::charpos(int i,size_t offset)
 
332
int String::charpos(int i,uint32_t offset)
409
333
{
410
334
  if (i <= 0)
411
335
    return i;
412
336
  return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
413
337
}
414
338
 
415
 
int String::strstr(const String &s,size_t offset)
 
339
int String::strstr(const String &s,uint32_t offset)
416
340
{
417
341
  if (s.length()+offset <= str_length)
418
342
  {
443
367
** Search string from end. Offset is offset to the end of string
444
368
*/
445
369
 
446
 
int String::strrstr(const String &s,size_t offset)
 
370
int String::strrstr(const String &s,uint32_t offset)
447
371
{
448
372
  if (s.length() <= offset && offset <= str_length)
449
373
  {
475
399
  If wrong parameter or not enough memory, do nothing
476
400
*/
477
401
 
478
 
bool String::replace(size_t offset,size_t arg_length,const String &to)
 
402
bool String::replace(uint32_t offset,uint32_t arg_length,const String &to)
479
403
{
480
404
  return replace(offset,arg_length,to.ptr(),to.length());
481
405
}
482
406
 
483
 
bool String::replace(size_t offset,size_t arg_length,
484
 
                     const char *to, size_t to_length)
 
407
bool String::replace(uint32_t offset,uint32_t arg_length,
 
408
                     const char *to, uint32_t to_length)
485
409
{
486
410
  long diff = (long) to_length-(long) arg_length;
487
411
  if (offset+arg_length <= str_length)
497
421
    {
498
422
      if (diff)
499
423
      {
500
 
        if (realloc(str_length+(size_t) diff))
 
424
        if (realloc(str_length+(uint32_t) diff))
501
425
          return true;
502
 
        internal::bmove_upp((unsigned char*) Ptr+str_length+diff,
503
 
                            (unsigned char*) Ptr+str_length,
504
 
                            str_length-offset-arg_length);
 
426
        bmove_upp((unsigned char*) Ptr+str_length+diff, (unsigned char*) Ptr+str_length,
 
427
                  str_length-offset-arg_length);
505
428
      }
506
429
      if (to_length)
507
430
        memcpy(Ptr+offset,to,to_length);
508
431
    }
509
 
    str_length+=(size_t) diff;
 
432
    str_length+=(uint32_t) diff;
510
433
  }
511
434
  return false;
512
435
}
560
483
 
561
484
int stringcmp(const String *s,const String *t)
562
485
{
563
 
  size_t s_len= s->length(), t_len= t->length(), len= min(s_len,t_len);
 
486
  uint32_t s_len=s->length(),t_len=t->length(),len=cmin(s_len,t_len);
564
487
  int cmp= memcmp(s->ptr(), t->ptr(), len);
565
488
  return (cmp) ? cmp : (int) (s_len - t_len);
566
489
}
567
490
 
568
491
 
569
 
String *copy_if_not_alloced(String *to,String *from,size_t from_length)
 
492
String *copy_if_not_alloced(String *to,String *from,uint32_t from_length)
570
493
{
571
494
  if (from->Alloced_length >= from_length)
572
495
    return from;
577
500
  }
578
501
  if (to->realloc(from_length))
579
502
    return from;                                // Actually an error
580
 
  if ((to->str_length= min(from->str_length,from_length)))
 
503
  if ((to->str_length=cmin(from->str_length,from_length)))
581
504
    memcpy(to->Ptr,from->Ptr,to->str_length);
582
505
  to->str_charset=from->str_charset;
583
506
  return to;
588
511
  Help functions
589
512
****************************************************************************/
590
513
 
 
514
 
 
515
 
 
516
/**
 
517
  Copy string with HEX-encoding of "bad" characters.
 
518
 
 
519
  @details This functions copies the string pointed by "src"
 
520
  to the string pointed by "dst". Not more than "srclen" bytes
 
521
  are read from "src". Any sequences of bytes representing
 
522
  a not-well-formed substring (according to cs) are hex-encoded,
 
523
  and all well-formed substrings (according to cs) are copied as is.
 
524
  Not more than "dstlen" bytes are written to "dst". The number
 
525
  of bytes written to "dst" is returned.
 
526
 
 
527
   @param      cs       character set pointer of the destination string
 
528
   @param[out] dst      destination string
 
529
   @param      dstlen   size of dst
 
530
   @param      src      source string
 
531
   @param      srclen   length of src
 
532
 
 
533
   @retval     result length
 
534
*/
 
535
 
 
536
size_t
 
537
my_copy_with_hex_escaping(const CHARSET_INFO * const cs,
 
538
                          char *dst, size_t dstlen,
 
539
                          const char *src, size_t srclen)
 
540
{
 
541
  const char *srcend= src + srclen;
 
542
  char *dst0= dst;
 
543
 
 
544
  for ( ; src < srcend ; )
 
545
  {
 
546
    size_t chlen;
 
547
    if ((chlen= my_ismbchar(cs, src, srcend)))
 
548
    {
 
549
      if (dstlen < chlen)
 
550
        break; /* purecov: inspected */
 
551
      memcpy(dst, src, chlen);
 
552
      src+= chlen;
 
553
      dst+= chlen;
 
554
      dstlen-= chlen;
 
555
    }
 
556
    else if (*src & 0x80)
 
557
    {
 
558
      if (dstlen < 4)
 
559
        break; /* purecov: inspected */
 
560
      *dst++= '\\';
 
561
      *dst++= 'x';
 
562
      *dst++= _dig_vec_upper[((unsigned char) *src) >> 4];
 
563
      *dst++= _dig_vec_upper[((unsigned char) *src) & 15];
 
564
      src++;
 
565
      dstlen-= 4;
 
566
    }
 
567
    else
 
568
    {
 
569
      if (dstlen < 1)
 
570
        break; /* purecov: inspected */
 
571
      *dst++= *src++;
 
572
      dstlen--;
 
573
    }
 
574
  }
 
575
  return dst - dst0;
 
576
}
 
577
 
591
578
/*
592
579
  copy a string,
593
580
  with optional character set conversion,
615
602
*/
616
603
 
617
604
 
618
 
size_t
 
605
uint32_t
619
606
well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
620
 
                        char *to, size_t to_length,
 
607
                        char *to, uint32_t to_length,
621
608
                        const CHARSET_INFO * const from_cs,
622
 
                        const char *from, size_t from_length,
623
 
                        size_t nchars,
 
609
                        const char *from, uint32_t from_length,
 
610
                        uint32_t nchars,
624
611
                        const char **well_formed_error_pos,
625
612
                        const char **cannot_convert_error_pos,
626
613
                        const char **from_end_pos)
627
614
{
628
 
  size_t res;
 
615
  uint32_t res;
629
616
 
630
617
  assert((to_cs == &my_charset_bin) ||
631
618
         (from_cs == &my_charset_bin) ||
642
629
 
643
630
  if (to_cs == &my_charset_bin)
644
631
  {
645
 
    res= min(min(nchars, to_length), from_length);
 
632
    res= cmin(cmin(nchars, to_length), from_length);
646
633
    memmove(to, from, res);
647
634
    *from_end_pos= from + res;
648
635
    *well_formed_error_pos= NULL;
651
638
  else
652
639
  {
653
640
    int well_formed_error;
654
 
    size_t from_offset;
 
641
    uint32_t from_offset;
655
642
 
656
643
    if ((from_offset= (from_length % to_cs->mbminlen)) &&
657
644
        (from_cs == &my_charset_bin))
661
648
        INSERT INTO t1 (ucs2_column) VALUES (0x01);
662
649
        0x01 -> 0x0001
663
650
      */
664
 
      size_t pad_length= to_cs->mbminlen - from_offset;
 
651
      uint32_t pad_length= to_cs->mbminlen - from_offset;
665
652
      memset(to, 0, pad_length);
666
653
      memmove(to + pad_length, from, from_offset);
667
654
      nchars--;
733
720
/* Factor the extern out */
734
721
extern const CHARSET_INFO *system_charset_info, *files_charset_info;
735
722
 
736
 
void String::append_identifier(const char *name, size_t in_length)
 
723
void String::append_identifier(const char *name, uint32_t in_length)
737
724
{
738
725
  const char *name_end;
739
726
  char quote_char;
788
775
  std::swap(str_charset, s.str_charset);
789
776
}
790
777
 
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)
 
778
 
 
779
bool operator==(const String &s1, const String &s2)
825
780
{
826
781
  return stringcmp(&s1,&s2) == 0;
827
782
}
828
783
 
829
 
bool operator!=(const drizzled::String &s1, const drizzled::String &s2)
 
784
bool operator!=(const String &s1, const String &s2)
830
785
{
831
786
  return !(s1 == s2);
832
787
}