~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_string.cc

  • Committer: Patrick Galbraith
  • Date: 2009-10-08 22:42:05 UTC
  • mto: (1166.5.3 memcached_functions)
  • mto: This revision was merged to the branch mainline in revision 1189.
  • Revision ID: patg@patrick-galbraiths-macbook-pro.local-20091008224205-gq1pehjsivvx0qo9
Starting over with a fresh tree, moved in memcached functions.

Memcached Functions for Drizzle. 

All tests pass.

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 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)
223
148
{
224
149
  if (alloc(arg_length))
225
150
    return true;
230
155
  return false;
231
156
}
232
157
 
 
158
 
233
159
/*
234
160
  Checks that the source string can be just copied to the destination string
235
161
  without conversion.
240
166
  arg_length            Length of string to copy.
241
167
  from_cs               Character set to copy from
242
168
  to_cs                 Character set to copy to
243
 
  size_t *offset        Returns number of unaligned characters.
 
169
  uint32_t *offset      Returns number of unaligned characters.
244
170
 
245
171
  RETURN
246
172
   0  No conversion needed
252
178
  character_set_results is NULL.
253
179
*/
254
180
 
255
 
bool String::needs_conversion(size_t arg_length,
 
181
bool String::needs_conversion(uint32_t arg_length,
256
182
                              const CHARSET_INFO * const from_cs,
257
183
                              const CHARSET_INFO * const to_cs,
258
 
                              size_t *offset)
 
184
                              uint32_t *offset)
259
185
{
260
186
  *offset= 0;
261
187
  if (!to_cs ||
271
197
 
272
198
 
273
199
 
274
 
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,
275
201
                                 const CHARSET_INFO * const cs)
276
202
{
277
203
  /* How many bytes are in incomplete character */
278
 
  size_t offset= (arg_length % cs->mbminlen);
 
204
  uint32_t offset= (arg_length % cs->mbminlen);
279
205
 
280
206
  assert(!offset); /* All characters are complete, just copy */
281
207
 
285
211
 
286
212
        /* Copy with charset conversion */
287
213
 
288
 
bool String::copy(const char *str, size_t arg_length,
 
214
bool String::copy(const char *str, uint32_t arg_length,
289
215
                          const CHARSET_INFO * const,
290
 
                                  const CHARSET_INFO * const to_cs, size_t *errors)
 
216
                                  const CHARSET_INFO * const to_cs, uint32_t *errors)
291
217
{
292
218
  *errors= 0;
293
219
  return copy(str, arg_length, to_cs);
313
239
 
314
240
*/
315
241
 
316
 
bool String::set_ascii(const char *str, size_t arg_length)
 
242
bool String::set_ascii(const char *str, uint32_t arg_length)
317
243
{
318
244
  if (str_charset->mbminlen == 1)
319
245
  {
320
246
    set(str, arg_length, str_charset);
321
247
    return 0;
322
248
  }
323
 
  size_t dummy_errors;
 
249
  uint32_t dummy_errors;
324
250
  return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
325
251
}
326
252
 
341
267
  Append an ASCII string to the a string of the current character set
342
268
*/
343
269
 
344
 
bool String::append(const char *s,size_t arg_length)
 
270
bool String::append(const char *s,uint32_t arg_length)
345
271
{
346
272
  if (!arg_length)
347
273
    return false;
372
298
  with character set recoding
373
299
*/
374
300
 
375
 
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)
376
302
{
377
303
  if (realloc(str_length + arg_length))
378
304
    return true;
383
309
}
384
310
 
385
311
 
386
 
bool String::append_with_prefill(const char *s,size_t arg_length,
387
 
                 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)
388
314
{
389
315
  int t_length= arg_length > full_length ? arg_length : full_length;
390
316
 
400
326
  return false;
401
327
}
402
328
 
403
 
size_t String::numchars()
 
329
uint32_t String::numchars()
404
330
{
405
331
  return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
406
332
}
407
333
 
408
 
int String::charpos(int i,size_t offset)
 
334
int String::charpos(int i,uint32_t offset)
409
335
{
410
336
  if (i <= 0)
411
337
    return i;
412
338
  return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
413
339
}
414
340
 
415
 
int String::strstr(const String &s,size_t offset)
 
341
int String::strstr(const String &s,uint32_t offset)
416
342
{
417
343
  if (s.length()+offset <= str_length)
418
344
  {
443
369
** Search string from end. Offset is offset to the end of string
444
370
*/
445
371
 
446
 
int String::strrstr(const String &s,size_t offset)
 
372
int String::strrstr(const String &s,uint32_t offset)
447
373
{
448
374
  if (s.length() <= offset && offset <= str_length)
449
375
  {
475
401
  If wrong parameter or not enough memory, do nothing
476
402
*/
477
403
 
478
 
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)
479
405
{
480
406
  return replace(offset,arg_length,to.ptr(),to.length());
481
407
}
482
408
 
483
 
bool String::replace(size_t offset,size_t arg_length,
484
 
                     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)
485
411
{
486
412
  long diff = (long) to_length-(long) arg_length;
487
413
  if (offset+arg_length <= str_length)
497
423
    {
498
424
      if (diff)
499
425
      {
500
 
        if (realloc(str_length+(size_t) diff))
 
426
        if (realloc(str_length+(uint32_t) diff))
501
427
          return true;
502
 
        internal::bmove_upp((unsigned char*) Ptr+str_length+diff,
503
 
                            (unsigned char*) Ptr+str_length,
504
 
                            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);
505
430
      }
506
431
      if (to_length)
507
432
        memcpy(Ptr+offset,to,to_length);
508
433
    }
509
 
    str_length+=(size_t) diff;
 
434
    str_length+=(uint32_t) diff;
510
435
  }
511
436
  return false;
512
437
}
560
485
 
561
486
int stringcmp(const String *s,const String *t)
562
487
{
563
 
  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);
564
489
  int cmp= memcmp(s->ptr(), t->ptr(), len);
565
490
  return (cmp) ? cmp : (int) (s_len - t_len);
566
491
}
567
492
 
568
493
 
569
 
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)
570
495
{
571
496
  if (from->Alloced_length >= from_length)
572
497
    return from;
588
513
  Help functions
589
514
****************************************************************************/
590
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
 
591
580
/*
592
581
  copy a string,
593
582
  with optional character set conversion,
615
604
*/
616
605
 
617
606
 
618
 
size_t
 
607
uint32_t
619
608
well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
620
 
                        char *to, size_t to_length,
 
609
                        char *to, uint32_t to_length,
621
610
                        const CHARSET_INFO * const from_cs,
622
 
                        const char *from, size_t from_length,
623
 
                        size_t nchars,
 
611
                        const char *from, uint32_t from_length,
 
612
                        uint32_t nchars,
624
613
                        const char **well_formed_error_pos,
625
614
                        const char **cannot_convert_error_pos,
626
615
                        const char **from_end_pos)
627
616
{
628
 
  size_t res;
 
617
  uint32_t res;
629
618
 
630
619
  assert((to_cs == &my_charset_bin) ||
631
620
         (from_cs == &my_charset_bin) ||
651
640
  else
652
641
  {
653
642
    int well_formed_error;
654
 
    size_t from_offset;
 
643
    uint32_t from_offset;
655
644
 
656
645
    if ((from_offset= (from_length % to_cs->mbminlen)) &&
657
646
        (from_cs == &my_charset_bin))
661
650
        INSERT INTO t1 (ucs2_column) VALUES (0x01);
662
651
        0x01 -> 0x0001
663
652
      */
664
 
      size_t pad_length= to_cs->mbminlen - from_offset;
 
653
      uint32_t pad_length= to_cs->mbminlen - from_offset;
665
654
      memset(to, 0, pad_length);
666
655
      memmove(to + pad_length, from, from_offset);
667
656
      nchars--;
733
722
/* Factor the extern out */
734
723
extern const CHARSET_INFO *system_charset_info, *files_charset_info;
735
724
 
736
 
void String::append_identifier(const char *name, size_t in_length)
 
725
void String::append_identifier(const char *name, uint32_t in_length)
737
726
{
738
727
  const char *name_end;
739
728
  char quote_char;
788
777
  std::swap(str_charset, s.str_charset);
789
778
}
790
779
 
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)
 
780
 
 
781
bool operator==(const String &s1, const String &s2)
825
782
{
826
783
  return stringcmp(&s1,&s2) == 0;
827
784
}
828
785
 
829
 
bool operator!=(const drizzled::String &s1, const drizzled::String &s2)
 
786
bool operator!=(const String &s1, const String &s2)
830
787
{
831
788
  return !(s1 == s2);
832
789
}