~ubuntu-branches/ubuntu/saucy/drizzle/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/debian-changes-2010.12.06-0ubuntu4/drizzled/sql_string.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2011-01-04 09:31:58 UTC
  • mfrom: (1.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20110104093158-smhgvkfdi2y9au3i
Tags: 2011.01.07-0ubuntu1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
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 */
15
 
 
16
 
/* This file is originally from the mysql distribution. Coded by monty */
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"
24
 
 
25
 
#include <algorithm>
26
 
 
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
 
}
47
 
 
48
 
/*****************************************************************************
49
 
** String functions
50
 
*****************************************************************************/
51
 
 
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
 
String::~String() { free(); }
113
 
 
114
 
bool String::real_alloc(size_t arg_length)
115
 
{
116
 
  arg_length=ALIGN_SIZE(arg_length+1);
117
 
  str_length=0;
118
 
  if (Alloced_length < arg_length)
119
 
  {
120
 
    if (Alloced_length > 0)
121
 
      free();
122
 
    if (!(Ptr=(char*) malloc(arg_length)))
123
 
      return true;
124
 
    Alloced_length=arg_length;
125
 
    alloced=1;
126
 
  }
127
 
  Ptr[0]=0;
128
 
  return false;
129
 
}
130
 
 
131
 
 
132
 
/*
133
 
** Check that string is big enough. Set string[alloc_length] to 0
134
 
** (for C functions)
135
 
*/
136
 
 
137
 
bool String::realloc(size_t alloc_length)
138
 
{
139
 
  size_t len=ALIGN_SIZE(alloc_length+1);
140
 
  if (Alloced_length < len)
141
 
  {
142
 
    char *new_ptr;
143
 
    if (alloced)
144
 
    {
145
 
      if ((new_ptr= (char*) ::realloc(Ptr,len)))
146
 
      {
147
 
        Ptr=new_ptr;
148
 
        Alloced_length=len;
149
 
      }
150
 
      else
151
 
        return true;                            // Signal error
152
 
    }
153
 
    else if ((new_ptr= (char*) malloc(len)))
154
 
    {
155
 
      if (str_length)                           // Avoid bugs in memcpy on AIX
156
 
        memcpy(new_ptr,Ptr,str_length);
157
 
      new_ptr[str_length]=0;
158
 
      Ptr=new_ptr;
159
 
      Alloced_length=len;
160
 
      alloced=1;
161
 
    }
162
 
    else
163
 
      return true;                      // Signal error
164
 
  }
165
 
  Ptr[alloc_length]=0;                  // This make other funcs shorter
166
 
  return false;
167
 
}
168
 
 
169
 
bool String::set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs)
170
 
{
171
 
  size_t l=20*cs->mbmaxlen+1;
172
 
  int base= unsigned_flag ? 10 : -10;
173
 
 
174
 
  if (alloc(l))
175
 
    return true;
176
 
  str_length=(size_t) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
177
 
  str_charset=cs;
178
 
  return false;
179
 
}
180
 
 
181
 
bool String::set_real(double num,size_t decimals, const CHARSET_INFO * const cs)
182
 
{
183
 
  char buff[FLOATING_POINT_BUFFER];
184
 
  size_t dummy_errors;
185
 
  size_t len;
186
 
 
187
 
  str_charset=cs;
188
 
  if (decimals >= NOT_FIXED_DEC)
189
 
  {
190
 
    len= internal::my_gcvt(num,
191
 
                           internal::MY_GCVT_ARG_DOUBLE,
192
 
                           sizeof(buff) - 1, buff, NULL);
193
 
    return copy(buff, len, &my_charset_utf8_general_ci, cs, &dummy_errors);
194
 
  }
195
 
  len= internal::my_fcvt(num, decimals, buff, NULL);
196
 
  return copy(buff, (size_t) len, &my_charset_utf8_general_ci, cs,
197
 
              &dummy_errors);
198
 
}
199
 
 
200
 
 
201
 
bool String::copy()
202
 
{
203
 
  if (!alloced)
204
 
  {
205
 
    Alloced_length=0;                           // Force realloc
206
 
    return realloc(str_length);
207
 
  }
208
 
  return false;
209
 
}
210
 
 
211
 
bool String::copy(const String &str)
212
 
{
213
 
  if (alloc(str.str_length))
214
 
    return true;
215
 
  str_length=str.str_length;
216
 
  memmove(Ptr, str.Ptr, str_length);            // May be overlapping
217
 
  Ptr[str_length]=0;
218
 
  str_charset=str.str_charset;
219
 
  return false;
220
 
}
221
 
 
222
 
bool String::copy(const char *str,size_t arg_length, const CHARSET_INFO * const cs)
223
 
{
224
 
  if (alloc(arg_length))
225
 
    return true;
226
 
  if ((str_length=arg_length))
227
 
    memcpy(Ptr,str,arg_length);
228
 
  Ptr[arg_length]=0;
229
 
  str_charset=cs;
230
 
  return false;
231
 
}
232
 
 
233
 
/*
234
 
  Checks that the source string can be just copied to the destination string
235
 
  without conversion.
236
 
 
237
 
  SYNPOSIS
238
 
 
239
 
  needs_conversion()
240
 
  arg_length            Length of string to copy.
241
 
  from_cs               Character set to copy from
242
 
  to_cs                 Character set to copy to
243
 
  size_t *offset        Returns number of unaligned characters.
244
 
 
245
 
  RETURN
246
 
   0  No conversion needed
247
 
   1  Either character set conversion or adding leading  zeros
248
 
      (e.g. for UCS-2) must be done
249
 
 
250
 
  NOTE
251
 
  to_cs may be NULL for "no conversion" if the system variable
252
 
  character_set_results is NULL.
253
 
*/
254
 
 
255
 
bool String::needs_conversion(size_t arg_length,
256
 
                              const CHARSET_INFO * const from_cs,
257
 
                              const CHARSET_INFO * const to_cs,
258
 
                              size_t *offset)
259
 
{
260
 
  *offset= 0;
261
 
  if (!to_cs ||
262
 
      (to_cs == &my_charset_bin) ||
263
 
      (to_cs == from_cs) ||
264
 
      my_charset_same(from_cs, to_cs) ||
265
 
      ((from_cs == &my_charset_bin) &&
266
 
       (!(*offset=(arg_length % to_cs->mbminlen)))))
267
 
    return false;
268
 
  return true;
269
 
}
270
 
 
271
 
 
272
 
 
273
 
 
274
 
bool String::set_or_copy_aligned(const char *str,size_t arg_length,
275
 
                                 const CHARSET_INFO * const cs)
276
 
{
277
 
  /* How many bytes are in incomplete character */
278
 
  size_t offset= (arg_length % cs->mbminlen);
279
 
 
280
 
  assert(!offset); /* All characters are complete, just copy */
281
 
 
282
 
  set(str, arg_length, cs);
283
 
  return false;
284
 
}
285
 
 
286
 
        /* Copy with charset conversion */
287
 
 
288
 
bool String::copy(const char *str, size_t arg_length,
289
 
                          const CHARSET_INFO * const,
290
 
                                  const CHARSET_INFO * const to_cs, size_t *errors)
291
 
{
292
 
  *errors= 0;
293
 
  return copy(str, arg_length, to_cs);
294
 
}
295
 
 
296
 
 
297
 
/*
298
 
  Set a string to the value of a latin1-string, keeping the original charset
299
 
 
300
 
  SYNOPSIS
301
 
    copy_or_set()
302
 
    str                 String of a simple charset (latin1)
303
 
    arg_length          Length of string
304
 
 
305
 
  IMPLEMENTATION
306
 
    If string object is of a simple character set, set it to point to the
307
 
    given string.
308
 
    If not, make a copy and convert it to the new character set.
309
 
 
310
 
  RETURN
311
 
    0   ok
312
 
    1   Could not allocate result buffer
313
 
 
314
 
*/
315
 
 
316
 
bool String::set_ascii(const char *str, size_t arg_length)
317
 
{
318
 
  if (str_charset->mbminlen == 1)
319
 
  {
320
 
    set(str, arg_length, str_charset);
321
 
    return 0;
322
 
  }
323
 
  size_t dummy_errors;
324
 
  return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
325
 
}
326
 
 
327
 
bool String::append(const String &s)
328
 
{
329
 
  if (s.length())
330
 
  {
331
 
    if (realloc(str_length+s.length()))
332
 
      return true;
333
 
    memcpy(Ptr+str_length,s.ptr(),s.length());
334
 
    str_length+=s.length();
335
 
  }
336
 
  return false;
337
 
}
338
 
 
339
 
 
340
 
/*
341
 
  Append an ASCII string to the a string of the current character set
342
 
*/
343
 
 
344
 
bool String::append(const char *s,size_t arg_length)
345
 
{
346
 
  if (!arg_length)
347
 
    return false;
348
 
 
349
 
  /*
350
 
    For an ASCII compatinble string we can just append.
351
 
  */
352
 
  if (realloc(str_length+arg_length))
353
 
    return true;
354
 
  memcpy(Ptr+str_length,s,arg_length);
355
 
  str_length+=arg_length;
356
 
  return false;
357
 
}
358
 
 
359
 
 
360
 
/*
361
 
  Append a 0-terminated ASCII string
362
 
*/
363
 
 
364
 
bool String::append(const char *s)
365
 
{
366
 
  return append(s, strlen(s));
367
 
}
368
 
 
369
 
 
370
 
/*
371
 
  Append a string in the given charset to the string
372
 
  with character set recoding
373
 
*/
374
 
 
375
 
bool String::append(const char *s,size_t arg_length, const CHARSET_INFO * const)
376
 
{
377
 
  if (realloc(str_length + arg_length))
378
 
    return true;
379
 
  memcpy(Ptr + str_length, s, arg_length);
380
 
  str_length+= arg_length;
381
 
 
382
 
  return false;
383
 
}
384
 
 
385
 
 
386
 
bool String::append_with_prefill(const char *s,size_t arg_length,
387
 
                 size_t full_length, char fill_char)
388
 
{
389
 
  int t_length= arg_length > full_length ? arg_length : full_length;
390
 
 
391
 
  if (realloc(str_length + t_length))
392
 
    return true;
393
 
  t_length= full_length - arg_length;
394
 
  if (t_length > 0)
395
 
  {
396
 
    memset(Ptr+str_length, fill_char, t_length);
397
 
    str_length=str_length + t_length;
398
 
  }
399
 
  append(s, arg_length);
400
 
  return false;
401
 
}
402
 
 
403
 
size_t String::numchars()
404
 
{
405
 
  return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
406
 
}
407
 
 
408
 
int String::charpos(int i,size_t offset)
409
 
{
410
 
  if (i <= 0)
411
 
    return i;
412
 
  return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
413
 
}
414
 
 
415
 
int String::strstr(const String &s,size_t offset)
416
 
{
417
 
  if (s.length()+offset <= str_length)
418
 
  {
419
 
    if (!s.length())
420
 
      return ((int) offset);    // Empty string is always found
421
 
 
422
 
    register const char *str = Ptr+offset;
423
 
    register const char *search=s.ptr();
424
 
    const char *end=Ptr+str_length-s.length()+1;
425
 
    const char *search_end=s.ptr()+s.length();
426
 
skip:
427
 
    while (str != end)
428
 
    {
429
 
      if (*str++ == *search)
430
 
      {
431
 
        register char *i,*j;
432
 
        i=(char*) str; j=(char*) search+1;
433
 
        while (j != search_end)
434
 
          if (*i++ != *j++) goto skip;
435
 
        return (int) (str-Ptr) -1;
436
 
      }
437
 
    }
438
 
  }
439
 
  return -1;
440
 
}
441
 
 
442
 
/*
443
 
** Search string from end. Offset is offset to the end of string
444
 
*/
445
 
 
446
 
int String::strrstr(const String &s,size_t offset)
447
 
{
448
 
  if (s.length() <= offset && offset <= str_length)
449
 
  {
450
 
    if (!s.length())
451
 
      return offset;                            // Empty string is always found
452
 
    register const char *str = Ptr+offset-1;
453
 
    register const char *search=s.ptr()+s.length()-1;
454
 
 
455
 
    const char *end=Ptr+s.length()-2;
456
 
    const char *search_end=s.ptr()-1;
457
 
skip:
458
 
    while (str != end)
459
 
    {
460
 
      if (*str-- == *search)
461
 
      {
462
 
        register char *i,*j;
463
 
        i=(char*) str; j=(char*) search-1;
464
 
        while (j != search_end)
465
 
          if (*i-- != *j--) goto skip;
466
 
        return (int) (i-Ptr) +1;
467
 
      }
468
 
    }
469
 
  }
470
 
  return -1;
471
 
}
472
 
 
473
 
/*
474
 
  Replace substring with string
475
 
  If wrong parameter or not enough memory, do nothing
476
 
*/
477
 
 
478
 
bool String::replace(size_t offset,size_t arg_length,const String &to)
479
 
{
480
 
  return replace(offset,arg_length,to.ptr(),to.length());
481
 
}
482
 
 
483
 
bool String::replace(size_t offset,size_t arg_length,
484
 
                     const char *to, size_t to_length)
485
 
{
486
 
  long diff = (long) to_length-(long) arg_length;
487
 
  if (offset+arg_length <= str_length)
488
 
  {
489
 
    if (diff < 0)
490
 
    {
491
 
      if (to_length)
492
 
        memcpy(Ptr+offset,to,to_length);
493
 
      memmove(Ptr+offset+to_length, Ptr+offset+arg_length,
494
 
              str_length-offset-arg_length);
495
 
    }
496
 
    else
497
 
    {
498
 
      if (diff)
499
 
      {
500
 
        if (realloc(str_length+(size_t) diff))
501
 
          return true;
502
 
        internal::bmove_upp((unsigned char*) Ptr+str_length+diff,
503
 
                            (unsigned char*) Ptr+str_length,
504
 
                            str_length-offset-arg_length);
505
 
      }
506
 
      if (to_length)
507
 
        memcpy(Ptr+offset,to,to_length);
508
 
    }
509
 
    str_length+=(size_t) diff;
510
 
  }
511
 
  return false;
512
 
}
513
 
 
514
 
 
515
 
 
516
 
/*
517
 
  Compare strings according to collation, without end space.
518
 
 
519
 
  SYNOPSIS
520
 
    sortcmp()
521
 
    s           First string
522
 
    t           Second string
523
 
    cs          Collation
524
 
 
525
 
  NOTE:
526
 
    Normally this is case sensitive comparison
527
 
 
528
 
  RETURN
529
 
  < 0   s < t
530
 
  0     s == t
531
 
  > 0   s > t
532
 
*/
533
 
 
534
 
 
535
 
int sortcmp(const String *s,const String *t, const CHARSET_INFO * const cs)
536
 
{
537
 
 return cs->coll->strnncollsp(cs,
538
 
                              (unsigned char *) s->ptr(),s->length(),
539
 
                              (unsigned char *) t->ptr(),t->length(), 0);
540
 
}
541
 
 
542
 
 
543
 
/*
544
 
  Compare strings byte by byte. End spaces are also compared.
545
 
 
546
 
  SYNOPSIS
547
 
    stringcmp()
548
 
    s           First string
549
 
    t           Second string
550
 
 
551
 
  NOTE:
552
 
    Strings are compared as a stream of unsigned chars
553
 
 
554
 
  RETURN
555
 
  < 0   s < t
556
 
  0     s == t
557
 
  > 0   s > t
558
 
*/
559
 
 
560
 
 
561
 
int stringcmp(const String *s,const String *t)
562
 
{
563
 
  size_t s_len= s->length(), t_len= t->length(), len= min(s_len,t_len);
564
 
  int cmp= memcmp(s->ptr(), t->ptr(), len);
565
 
  return (cmp) ? cmp : (int) (s_len - t_len);
566
 
}
567
 
 
568
 
 
569
 
String *copy_if_not_alloced(String *to,String *from,size_t from_length)
570
 
{
571
 
  if (from->Alloced_length >= from_length)
572
 
    return from;
573
 
  if (from->alloced || !to || from == to)
574
 
  {
575
 
    (void) from->realloc(from_length);
576
 
    return from;
577
 
  }
578
 
  if (to->realloc(from_length))
579
 
    return from;                                // Actually an error
580
 
  if ((to->str_length= min(from->str_length,from_length)))
581
 
    memcpy(to->Ptr,from->Ptr,to->str_length);
582
 
  to->str_charset=from->str_charset;
583
 
  return to;
584
 
}
585
 
 
586
 
 
587
 
/****************************************************************************
588
 
  Help functions
589
 
****************************************************************************/
590
 
 
591
 
/*
592
 
  copy a string,
593
 
  with optional character set conversion,
594
 
  with optional left padding (for binary -> UCS2 conversion)
595
 
 
596
 
  SYNOPSIS
597
 
    well_formed_copy_nchars()
598
 
    to                       Store result here
599
 
    to_length                Maxinum length of "to" string
600
 
    to_cs                    Character set of "to" string
601
 
    from                     Copy from here
602
 
    from_length              Length of from string
603
 
    from_cs                  From character set
604
 
    nchars                   Copy not more that nchars characters
605
 
    well_formed_error_pos    Return position when "from" is not well formed
606
 
                             or NULL otherwise.
607
 
    cannot_convert_error_pos Return position where a not convertable
608
 
                             character met, or NULL otherwise.
609
 
    from_end_pos             Return position where scanning of "from"
610
 
                             string stopped.
611
 
  NOTES
612
 
 
613
 
  RETURN
614
 
    length of bytes copied to 'to'
615
 
*/
616
 
 
617
 
 
618
 
size_t
619
 
well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
620
 
                        char *to, size_t to_length,
621
 
                        const CHARSET_INFO * const from_cs,
622
 
                        const char *from, size_t from_length,
623
 
                        size_t nchars,
624
 
                        const char **well_formed_error_pos,
625
 
                        const char **cannot_convert_error_pos,
626
 
                        const char **from_end_pos)
627
 
{
628
 
  size_t res;
629
 
 
630
 
  assert((to_cs == &my_charset_bin) ||
631
 
         (from_cs == &my_charset_bin) ||
632
 
         (to_cs == from_cs) ||
633
 
         my_charset_same(from_cs, to_cs));
634
 
 
635
 
  if (to_length < to_cs->mbminlen || !nchars)
636
 
  {
637
 
    *from_end_pos= from;
638
 
    *cannot_convert_error_pos= NULL;
639
 
    *well_formed_error_pos= NULL;
640
 
    return 0;
641
 
  }
642
 
 
643
 
  if (to_cs == &my_charset_bin)
644
 
  {
645
 
    res= min(min(nchars, to_length), from_length);
646
 
    memmove(to, from, res);
647
 
    *from_end_pos= from + res;
648
 
    *well_formed_error_pos= NULL;
649
 
    *cannot_convert_error_pos= NULL;
650
 
  }
651
 
  else
652
 
  {
653
 
    int well_formed_error;
654
 
    size_t from_offset;
655
 
 
656
 
    if ((from_offset= (from_length % to_cs->mbminlen)) &&
657
 
        (from_cs == &my_charset_bin))
658
 
    {
659
 
      /*
660
 
        Copying from BINARY to UCS2 needs to prepend zeros sometimes:
661
 
        INSERT INTO t1 (ucs2_column) VALUES (0x01);
662
 
        0x01 -> 0x0001
663
 
      */
664
 
      size_t pad_length= to_cs->mbminlen - from_offset;
665
 
      memset(to, 0, pad_length);
666
 
      memmove(to + pad_length, from, from_offset);
667
 
      nchars--;
668
 
      from+= from_offset;
669
 
      from_length-= from_offset;
670
 
      to+= to_cs->mbminlen;
671
 
      to_length-= to_cs->mbminlen;
672
 
    }
673
 
 
674
 
    set_if_smaller(from_length, to_length);
675
 
    res= to_cs->cset->well_formed_len(to_cs, from, from + from_length,
676
 
                                      nchars, &well_formed_error);
677
 
    memmove(to, from, res);
678
 
    *from_end_pos= from + res;
679
 
    *well_formed_error_pos= well_formed_error ? from + res : NULL;
680
 
    *cannot_convert_error_pos= NULL;
681
 
    if (from_offset)
682
 
      res+= to_cs->mbminlen;
683
 
  }
684
 
 
685
 
  return res;
686
 
}
687
 
 
688
 
 
689
 
 
690
 
 
691
 
void String::print(String *str)
692
 
{
693
 
  char *st= (char*)Ptr, *end= st+str_length;
694
 
  for (; st < end; st++)
695
 
  {
696
 
    unsigned char c= *st;
697
 
    switch (c)
698
 
    {
699
 
    case '\\':
700
 
      str->append("\\\\", sizeof("\\\\")-1);
701
 
      break;
702
 
    case '\0':
703
 
      str->append("\\0", sizeof("\\0")-1);
704
 
      break;
705
 
    case '\'':
706
 
      str->append("\\'", sizeof("\\'")-1);
707
 
      break;
708
 
    case '\n':
709
 
      str->append("\\n", sizeof("\\n")-1);
710
 
      break;
711
 
    case '\r':
712
 
      str->append("\\r", sizeof("\\r")-1);
713
 
      break;
714
 
    case '\032': // Ctrl-Z
715
 
      str->append("\\Z", sizeof("\\Z")-1);
716
 
      break;
717
 
    default:
718
 
      str->append(c);
719
 
    }
720
 
  }
721
 
}
722
 
 
723
 
/*
724
 
  Quote the given identifier.
725
 
  If the given identifier is empty, it will be quoted.
726
 
 
727
 
  SYNOPSIS
728
 
  append_identifier()
729
 
  name                  the identifier to be appended
730
 
  name_length           length of the appending identifier
731
 
*/
732
 
 
733
 
/* Factor the extern out */
734
 
extern const CHARSET_INFO *system_charset_info, *files_charset_info;
735
 
 
736
 
void String::append_identifier(const char *name, size_t in_length)
737
 
{
738
 
  const char *name_end;
739
 
  char quote_char;
740
 
  int q= '`';
741
 
 
742
 
  /*
743
 
    The identifier must be quoted as it includes a quote character or
744
 
   it's a keyword
745
 
  */
746
 
 
747
 
  reserve(in_length*2 + 2);
748
 
  quote_char= (char) q;
749
 
  append(&quote_char, 1, system_charset_info);
750
 
 
751
 
  for (name_end= name+in_length ; name < name_end ; name+= in_length)
752
 
  {
753
 
    unsigned char chr= (unsigned char) *name;
754
 
    in_length= my_mbcharlen(system_charset_info, chr);
755
 
    /*
756
 
      my_mbcharlen can return 0 on a wrong multibyte
757
 
      sequence. It is possible when upgrading from 4.0,
758
 
      and identifier contains some accented characters.
759
 
      The manual says it does not work. So we'll just
760
 
      change length to 1 not to hang in the endless loop.
761
 
    */
762
 
    if (!in_length)
763
 
      in_length= 1;
764
 
    if (in_length == 1 && chr == (unsigned char) quote_char)
765
 
      append(&quote_char, 1, system_charset_info);
766
 
    append(name, in_length, system_charset_info);
767
 
  }
768
 
  append(&quote_char, 1, system_charset_info);
769
 
}
770
 
 
771
 
 
772
 
/*
773
 
  Exchange state of this object and argument.
774
 
 
775
 
  SYNOPSIS
776
 
    String::swap()
777
 
 
778
 
  RETURN
779
 
    Target string will contain state of this object and vice versa.
780
 
*/
781
 
 
782
 
void String::swap(String &s)
783
 
{
784
 
  std::swap(Ptr, s.Ptr);
785
 
  std::swap(str_length, s.str_length);
786
 
  std::swap(Alloced_length, s.Alloced_length);
787
 
  std::swap(alloced, s.alloced);
788
 
  std::swap(str_charset, s.str_charset);
789
 
}
790
 
 
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)
825
 
{
826
 
  return stringcmp(&s1,&s2) == 0;
827
 
}
828
 
 
829
 
bool operator!=(const drizzled::String &s1, const drizzled::String &s2)
830
 
{
831
 
  return !(s1 == s2);
832
 
}
833