~drizzle-trunk/drizzle/development

1 by brian
clean slate
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/* This file is originally from the mysql distribution. Coded by monty */
17
212.5.39 by Monty Taylor
Phew. Moved my_base and my_global.
18
#include "global.h"
212.5.13 by Monty Taylor
Moved my_sys/my_pthread/my_nosys and mysys_err to mysys.
19
#include <mysys/my_sys.h>
212.5.45 by Monty Taylor
Removed excess AM_CPPFLAGS from the tree. Now the only thing that should be in the include path should be -I${top_srcdir} and -I${top_builddir}w
20
#include <mystrings/m_string.h>
1 by brian
clean slate
21
398.1.5 by Monty Taylor
Removed C++ includes and std namespace from global.h.
22
#include <algorithm>
23
1067.4.4 by Nathan Williams
The rest of the files in the drizzled directory were purged of the cmin macro and replace with std::min (except for the definition in globals.h and 1 usage in stacktrace.cc).
24
using namespace std;
25
1 by brian
clean slate
26
/*
27
  The following extern declarations are ok as these are interface functions
28
  required by the string function
29
*/
30
481 by Brian Aker
Remove all of uchar.
31
extern unsigned char* sql_alloc(unsigned size);
1 by brian
clean slate
32
extern void sql_element_free(void *ptr);
33
34
#include "sql_string.h"
35
36
/*****************************************************************************
37
** String functions
38
*****************************************************************************/
39
1022.2.29 by Monty Taylor
Fixed some no-inline warnings.
40
String::~String() { free(); }
41
205 by Brian Aker
uint32 -> uin32_t
42
bool String::real_alloc(uint32_t arg_length)
1 by brian
clean slate
43
{
44
  arg_length=ALIGN_SIZE(arg_length+1);
45
  str_length=0;
46
  if (Alloced_length < arg_length)
47
  {
48
    free();
641.3.6 by Monty Taylor
Removed some my_malloc calls.
49
    if (!(Ptr=(char*) malloc(arg_length)))
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
50
      return true;
1 by brian
clean slate
51
    Alloced_length=arg_length;
52
    alloced=1;
53
  }
54
  Ptr[0]=0;
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
55
  return false;
1 by brian
clean slate
56
}
57
58
59
/*
60
** Check that string is big enough. Set string[alloc_length] to 0
61
** (for C functions)
62
*/
63
205 by Brian Aker
uint32 -> uin32_t
64
bool String::realloc(uint32_t alloc_length)
1 by brian
clean slate
65
{
205 by Brian Aker
uint32 -> uin32_t
66
  uint32_t len=ALIGN_SIZE(alloc_length+1);
1 by brian
clean slate
67
  if (Alloced_length < len)
68
  {
69
    char *new_ptr;
70
    if (alloced)
71
    {
656.1.26 by Monty Taylor
Finally removed all of the my_malloc stuff.
72
      if ((new_ptr= (char*) ::realloc(Ptr,len)))
1 by brian
clean slate
73
      {
74
	Ptr=new_ptr;
75
	Alloced_length=len;
76
      }
77
      else
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
78
	return true;				// Signal error
1 by brian
clean slate
79
    }
641.3.6 by Monty Taylor
Removed some my_malloc calls.
80
    else if ((new_ptr= (char*) malloc(len)))
1 by brian
clean slate
81
    {
82
      if (str_length)				// Avoid bugs in memcpy on AIX
83
	memcpy(new_ptr,Ptr,str_length);
84
      new_ptr[str_length]=0;
85
      Ptr=new_ptr;
86
      Alloced_length=len;
87
      alloced=1;
88
    }
89
    else
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
90
      return true;			// Signal error
1 by brian
clean slate
91
  }
92
  Ptr[alloc_length]=0;			// This make other funcs shorter
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
93
  return false;
1 by brian
clean slate
94
}
95
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
96
bool String::set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs)
1 by brian
clean slate
97
{
482 by Brian Aker
Remove uint.
98
  uint32_t l=20*cs->mbmaxlen+1;
1 by brian
clean slate
99
  int base= unsigned_flag ? 10 : -10;
100
101
  if (alloc(l))
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
102
    return true;
205 by Brian Aker
uint32 -> uin32_t
103
  str_length=(uint32_t) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
1 by brian
clean slate
104
  str_charset=cs;
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
105
  return false;
1 by brian
clean slate
106
}
107
482 by Brian Aker
Remove uint.
108
bool String::set_real(double num,uint32_t decimals, const CHARSET_INFO * const cs)
1 by brian
clean slate
109
{
110
  char buff[FLOATING_POINT_BUFFER];
482 by Brian Aker
Remove uint.
111
  uint32_t dummy_errors;
1 by brian
clean slate
112
  size_t len;
113
114
  str_charset=cs;
115
  if (decimals >= NOT_FIXED_DEC)
116
  {
117
    len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
118
    return copy(buff, len, &my_charset_utf8_general_ci, cs, &dummy_errors);
1 by brian
clean slate
119
  }
120
  len= my_fcvt(num, decimals, buff, NULL);
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
121
  return copy(buff, (uint32_t) len, &my_charset_utf8_general_ci, cs,
1 by brian
clean slate
122
              &dummy_errors);
123
}
124
125
126
bool String::copy()
127
{
128
  if (!alloced)
129
  {
130
    Alloced_length=0;				// Force realloc
131
    return realloc(str_length);
132
  }
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
133
  return false;
1 by brian
clean slate
134
}
135
136
bool String::copy(const String &str)
137
{
138
  if (alloc(str.str_length))
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
139
    return true;
1 by brian
clean slate
140
  str_length=str.str_length;
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
141
  memmove(Ptr, str.Ptr, str_length);		// May be overlapping
1 by brian
clean slate
142
  Ptr[str_length]=0;
143
  str_charset=str.str_charset;
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
144
  return false;
1 by brian
clean slate
145
}
146
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
147
bool String::copy(const char *str,uint32_t arg_length, const CHARSET_INFO * const cs)
1 by brian
clean slate
148
{
149
  if (alloc(arg_length))
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
150
    return true;
1 by brian
clean slate
151
  if ((str_length=arg_length))
152
    memcpy(Ptr,str,arg_length);
153
  Ptr[arg_length]=0;
154
  str_charset=cs;
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
155
  return false;
1 by brian
clean slate
156
}
157
158
159
/*
160
  Checks that the source string can be just copied to the destination string
161
  without conversion.
162
163
  SYNPOSIS
164
165
  needs_conversion()
166
  arg_length		Length of string to copy.
167
  from_cs		Character set to copy from
168
  to_cs			Character set to copy to
205 by Brian Aker
uint32 -> uin32_t
169
  uint32_t *offset	Returns number of unaligned characters.
1 by brian
clean slate
170
171
  RETURN
172
   0  No conversion needed
173
   1  Either character set conversion or adding leading  zeros
174
      (e.g. for UCS-2) must be done
175
176
  NOTE
177
  to_cs may be NULL for "no conversion" if the system variable
178
  character_set_results is NULL.
179
*/
180
205 by Brian Aker
uint32 -> uin32_t
181
bool String::needs_conversion(uint32_t arg_length,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
182
			      const CHARSET_INFO * const from_cs,
183
			      const CHARSET_INFO * const to_cs,
205 by Brian Aker
uint32 -> uin32_t
184
			      uint32_t *offset)
1 by brian
clean slate
185
{
186
  *offset= 0;
187
  if (!to_cs ||
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
188
      (to_cs == &my_charset_bin) ||
1 by brian
clean slate
189
      (to_cs == from_cs) ||
190
      my_charset_same(from_cs, to_cs) ||
191
      ((from_cs == &my_charset_bin) &&
192
       (!(*offset=(arg_length % to_cs->mbminlen)))))
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
193
    return false;
194
  return true;
1 by brian
clean slate
195
}
196
197
198
199
205 by Brian Aker
uint32 -> uin32_t
200
bool String::set_or_copy_aligned(const char *str,uint32_t arg_length,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
201
                                 const CHARSET_INFO * const cs)
1 by brian
clean slate
202
{
203
  /* How many bytes are in incomplete character */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
204
  uint32_t offset= (arg_length % cs->mbminlen);
205
910.1.5 by Brian Aker
Remove some dead bits of string (and fix the semi_join test).
206
  assert(!offset); /* All characters are complete, just copy */
207
208
  set(str, arg_length, cs);
209
  return false;
1 by brian
clean slate
210
}
211
212
	/* Copy with charset conversion */
213
205 by Brian Aker
uint32 -> uin32_t
214
bool String::copy(const char *str, uint32_t arg_length,
975.1.2 by Brian Aker
LCOV cleanup (more of...).
215
		          const CHARSET_INFO * const,
482 by Brian Aker
Remove uint.
216
				  const CHARSET_INFO * const to_cs, uint32_t *errors)
1 by brian
clean slate
217
{
975.1.2 by Brian Aker
LCOV cleanup (more of...).
218
  *errors= 0;
219
  return copy(str, arg_length, to_cs);
1 by brian
clean slate
220
}
221
222
223
/*
224
  Set a string to the value of a latin1-string, keeping the original charset
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
225
1 by brian
clean slate
226
  SYNOPSIS
227
    copy_or_set()
228
    str			String of a simple charset (latin1)
229
    arg_length		Length of string
230
231
  IMPLEMENTATION
232
    If string object is of a simple character set, set it to point to the
233
    given string.
234
    If not, make a copy and convert it to the new character set.
235
236
  RETURN
237
    0	ok
238
    1	Could not allocate result buffer
239
240
*/
241
205 by Brian Aker
uint32 -> uin32_t
242
bool String::set_ascii(const char *str, uint32_t arg_length)
1 by brian
clean slate
243
{
244
  if (str_charset->mbminlen == 1)
245
  {
246
    set(str, arg_length, str_charset);
247
    return 0;
248
  }
482 by Brian Aker
Remove uint.
249
  uint32_t dummy_errors;
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
250
  return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
1 by brian
clean slate
251
}
252
253
bool String::append(const String &s)
254
{
255
  if (s.length())
256
  {
257
    if (realloc(str_length+s.length()))
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
258
      return true;
1 by brian
clean slate
259
    memcpy(Ptr+str_length,s.ptr(),s.length());
260
    str_length+=s.length();
261
  }
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
262
  return false;
1 by brian
clean slate
263
}
264
265
266
/*
267
  Append an ASCII string to the a string of the current character set
268
*/
269
205 by Brian Aker
uint32 -> uin32_t
270
bool String::append(const char *s,uint32_t arg_length)
1 by brian
clean slate
271
{
272
  if (!arg_length)
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
273
    return false;
1 by brian
clean slate
274
275
  /*
276
    For an ASCII compatinble string we can just append.
277
  */
278
  if (realloc(str_length+arg_length))
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
279
    return true;
1 by brian
clean slate
280
  memcpy(Ptr+str_length,s,arg_length);
281
  str_length+=arg_length;
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
282
  return false;
1 by brian
clean slate
283
}
284
285
286
/*
287
  Append a 0-terminated ASCII string
288
*/
289
290
bool String::append(const char *s)
291
{
292
  return append(s, strlen(s));
293
}
294
295
296
/*
297
  Append a string in the given charset to the string
298
  with character set recoding
299
*/
300
975.1.2 by Brian Aker
LCOV cleanup (more of...).
301
bool String::append(const char *s,uint32_t arg_length, const CHARSET_INFO * const)
1 by brian
clean slate
302
{
975.1.2 by Brian Aker
LCOV cleanup (more of...).
303
  if (realloc(str_length + arg_length))
304
    return true;
305
  memcpy(Ptr + str_length, s, arg_length);
306
  str_length+= arg_length;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
307
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
308
  return false;
1 by brian
clean slate
309
}
310
311
205 by Brian Aker
uint32 -> uin32_t
312
bool String::append_with_prefill(const char *s,uint32_t arg_length,
313
		 uint32_t full_length, char fill_char)
1 by brian
clean slate
314
{
315
  int t_length= arg_length > full_length ? arg_length : full_length;
316
317
  if (realloc(str_length + t_length))
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
318
    return true;
1 by brian
clean slate
319
  t_length= full_length - arg_length;
320
  if (t_length > 0)
321
  {
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
322
    memset(Ptr+str_length, fill_char, t_length);
1 by brian
clean slate
323
    str_length=str_length + t_length;
324
  }
325
  append(s, arg_length);
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
326
  return false;
1 by brian
clean slate
327
}
328
205 by Brian Aker
uint32 -> uin32_t
329
uint32_t String::numchars()
1 by brian
clean slate
330
{
331
  return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
332
}
333
205 by Brian Aker
uint32 -> uin32_t
334
int String::charpos(int i,uint32_t offset)
1 by brian
clean slate
335
{
336
  if (i <= 0)
337
    return i;
338
  return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
339
}
340
205 by Brian Aker
uint32 -> uin32_t
341
int String::strstr(const String &s,uint32_t offset)
1 by brian
clean slate
342
{
343
  if (s.length()+offset <= str_length)
344
  {
345
    if (!s.length())
346
      return ((int) offset);	// Empty string is always found
347
348
    register const char *str = Ptr+offset;
349
    register const char *search=s.ptr();
350
    const char *end=Ptr+str_length-s.length()+1;
351
    const char *search_end=s.ptr()+s.length();
352
skip:
353
    while (str != end)
354
    {
355
      if (*str++ == *search)
356
      {
357
	register char *i,*j;
358
	i=(char*) str; j=(char*) search+1;
359
	while (j != search_end)
360
	  if (*i++ != *j++) goto skip;
361
	return (int) (str-Ptr) -1;
362
      }
363
    }
364
  }
365
  return -1;
366
}
367
368
/*
369
** Search string from end. Offset is offset to the end of string
370
*/
371
205 by Brian Aker
uint32 -> uin32_t
372
int String::strrstr(const String &s,uint32_t offset)
1 by brian
clean slate
373
{
374
  if (s.length() <= offset && offset <= str_length)
375
  {
376
    if (!s.length())
377
      return offset;				// Empty string is always found
378
    register const char *str = Ptr+offset-1;
379
    register const char *search=s.ptr()+s.length()-1;
380
381
    const char *end=Ptr+s.length()-2;
382
    const char *search_end=s.ptr()-1;
383
skip:
384
    while (str != end)
385
    {
386
      if (*str-- == *search)
387
      {
388
	register char *i,*j;
389
	i=(char*) str; j=(char*) search-1;
390
	while (j != search_end)
391
	  if (*i-- != *j--) goto skip;
392
	return (int) (i-Ptr) +1;
393
      }
394
    }
395
  }
396
  return -1;
397
}
398
399
/*
400
  Replace substring with string
401
  If wrong parameter or not enough memory, do nothing
402
*/
403
205 by Brian Aker
uint32 -> uin32_t
404
bool String::replace(uint32_t offset,uint32_t arg_length,const String &to)
1 by brian
clean slate
405
{
406
  return replace(offset,arg_length,to.ptr(),to.length());
407
}
408
205 by Brian Aker
uint32 -> uin32_t
409
bool String::replace(uint32_t offset,uint32_t arg_length,
410
                     const char *to, uint32_t to_length)
1 by brian
clean slate
411
{
412
  long diff = (long) to_length-(long) arg_length;
413
  if (offset+arg_length <= str_length)
414
  {
415
    if (diff < 0)
416
    {
417
      if (to_length)
418
	memcpy(Ptr+offset,to,to_length);
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
419
      memmove(Ptr+offset+to_length, Ptr+offset+arg_length,
420
              str_length-offset-arg_length);
1 by brian
clean slate
421
    }
422
    else
423
    {
424
      if (diff)
425
      {
205 by Brian Aker
uint32 -> uin32_t
426
	if (realloc(str_length+(uint32_t) diff))
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
427
	  return true;
481 by Brian Aker
Remove all of uchar.
428
	bmove_upp((unsigned char*) Ptr+str_length+diff, (unsigned char*) Ptr+str_length,
1 by brian
clean slate
429
		  str_length-offset-arg_length);
430
      }
431
      if (to_length)
432
	memcpy(Ptr+offset,to,to_length);
433
    }
205 by Brian Aker
uint32 -> uin32_t
434
    str_length+=(uint32_t) diff;
1 by brian
clean slate
435
  }
51.1.74 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
436
  return false;
1 by brian
clean slate
437
}
438
439
440
441
/*
442
  Compare strings according to collation, without end space.
443
444
  SYNOPSIS
445
    sortcmp()
446
    s		First string
447
    t		Second string
448
    cs		Collation
449
450
  NOTE:
451
    Normally this is case sensitive comparison
452
453
  RETURN
454
  < 0	s < t
455
  0	s == t
456
  > 0	s > t
457
*/
458
459
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
460
int sortcmp(const String *s,const String *t, const CHARSET_INFO * const cs)
1 by brian
clean slate
461
{
462
 return cs->coll->strnncollsp(cs,
481 by Brian Aker
Remove all of uchar.
463
                              (unsigned char *) s->ptr(),s->length(),
464
                              (unsigned char *) t->ptr(),t->length(), 0);
1 by brian
clean slate
465
}
466
467
468
/*
469
  Compare strings byte by byte. End spaces are also compared.
470
471
  SYNOPSIS
472
    stringcmp()
473
    s		First string
474
    t		Second string
475
476
  NOTE:
481 by Brian Aker
Remove all of uchar.
477
    Strings are compared as a stream of unsigned chars
1 by brian
clean slate
478
479
  RETURN
480
  < 0	s < t
481
  0	s == t
482
  > 0	s > t
483
*/
484
485
486
int stringcmp(const String *s,const String *t)
487
{
1067.4.4 by Nathan Williams
The rest of the files in the drizzled directory were purged of the cmin macro and replace with std::min (except for the definition in globals.h and 1 usage in stacktrace.cc).
488
  uint32_t s_len= s->length(), t_len= t->length(), len= min(s_len,t_len);
1 by brian
clean slate
489
  int cmp= memcmp(s->ptr(), t->ptr(), len);
490
  return (cmp) ? cmp : (int) (s_len - t_len);
491
}
492
493
205 by Brian Aker
uint32 -> uin32_t
494
String *copy_if_not_alloced(String *to,String *from,uint32_t from_length)
1 by brian
clean slate
495
{
496
  if (from->Alloced_length >= from_length)
497
    return from;
498
  if (from->alloced || !to || from == to)
499
  {
500
    (void) from->realloc(from_length);
501
    return from;
502
  }
503
  if (to->realloc(from_length))
504
    return from;				// Actually an error
1067.4.4 by Nathan Williams
The rest of the files in the drizzled directory were purged of the cmin macro and replace with std::min (except for the definition in globals.h and 1 usage in stacktrace.cc).
505
  if ((to->str_length= min(from->str_length,from_length)))
1 by brian
clean slate
506
    memcpy(to->Ptr,from->Ptr,to->str_length);
507
  to->str_charset=from->str_charset;
508
  return to;
509
}
510
511
512
/****************************************************************************
513
  Help functions
514
****************************************************************************/
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.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
526
  Not more than "dstlen" bytes are written to "dst". The number
1 by brian
clean slate
527
  of bytes written to "dst" is returned.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
528
1 by brian
clean slate
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
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
539
my_copy_with_hex_escaping(const CHARSET_INFO * const cs,
1 by brian
clean slate
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; /* purecov: inspected */
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; /* purecov: inspected */
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; /* purecov: inspected */
573
      *dst++= *src++;
574
      dstlen--;
575
    }
576
  }
577
  return dst - dst0;
578
}
579
580
/*
581
  copy a string,
582
  with optional character set conversion,
583
  with optional left padding (for binary -> UCS2 conversion)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
584
1 by brian
clean slate
585
  SYNOPSIS
586
    well_formed_copy_nchars()
587
    to			     Store result here
588
    to_length                Maxinum length of "to" string
589
    to_cs		     Character set of "to" string
590
    from		     Copy from here
591
    from_length		     Length of from string
592
    from_cs		     From character set
593
    nchars                   Copy not more that nchars characters
594
    well_formed_error_pos    Return position when "from" is not well formed
595
                             or NULL otherwise.
596
    cannot_convert_error_pos Return position where a not convertable
597
                             character met, or NULL otherwise.
598
    from_end_pos             Return position where scanning of "from"
599
                             string stopped.
600
  NOTES
601
602
  RETURN
603
    length of bytes copied to 'to'
604
*/
605
606
205 by Brian Aker
uint32 -> uin32_t
607
uint32_t
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
608
well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
482 by Brian Aker
Remove uint.
609
                        char *to, uint32_t to_length,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
610
                        const CHARSET_INFO * const from_cs,
482 by Brian Aker
Remove uint.
611
                        const char *from, uint32_t from_length,
612
                        uint32_t nchars,
1 by brian
clean slate
613
                        const char **well_formed_error_pos,
614
                        const char **cannot_convert_error_pos,
615
                        const char **from_end_pos)
616
{
482 by Brian Aker
Remove uint.
617
  uint32_t res;
1 by brian
clean slate
618
1034 by Brian Aker
Dead Code
619
  assert((to_cs == &my_charset_bin) ||
620
         (from_cs == &my_charset_bin) ||
621
         (to_cs == from_cs) ||
622
         my_charset_same(from_cs, to_cs));
623
624
  if (to_length < to_cs->mbminlen || !nchars)
625
  {
626
    *from_end_pos= from;
627
    *cannot_convert_error_pos= NULL;
628
    *well_formed_error_pos= NULL;
629
    return 0;
630
  }
631
632
  if (to_cs == &my_charset_bin)
633
  {
1067.4.4 by Nathan Williams
The rest of the files in the drizzled directory were purged of the cmin macro and replace with std::min (except for the definition in globals.h and 1 usage in stacktrace.cc).
634
    res= min(min(nchars, to_length), from_length);
1034 by Brian Aker
Dead Code
635
    memmove(to, from, res);
636
    *from_end_pos= from + res;
637
    *well_formed_error_pos= NULL;
638
    *cannot_convert_error_pos= NULL;
1 by brian
clean slate
639
  }
640
  else
641
  {
1034 by Brian Aker
Dead Code
642
    int well_formed_error;
643
    uint32_t from_offset;
1 by brian
clean slate
644
1034 by Brian Aker
Dead Code
645
    if ((from_offset= (from_length % to_cs->mbminlen)) &&
646
        (from_cs == &my_charset_bin))
1 by brian
clean slate
647
    {
1034 by Brian Aker
Dead Code
648
      /*
649
        Copying from BINARY to UCS2 needs to prepend zeros sometimes:
650
        INSERT INTO t1 (ucs2_column) VALUES (0x01);
651
        0x01 -> 0x0001
652
      */
653
      uint32_t pad_length= to_cs->mbminlen - from_offset;
654
      memset(to, 0, pad_length);
655
      memmove(to + pad_length, from, from_offset);
656
      nchars--;
657
      from+= from_offset;
658
      from_length-= from_offset;
659
      to+= to_cs->mbminlen;
660
      to_length-= to_cs->mbminlen;
1 by brian
clean slate
661
    }
1034 by Brian Aker
Dead Code
662
663
    set_if_smaller(from_length, to_length);
664
    res= to_cs->cset->well_formed_len(to_cs, from, from + from_length,
665
                                      nchars, &well_formed_error);
666
    memmove(to, from, res);
667
    *from_end_pos= from + res;
668
    *well_formed_error_pos= well_formed_error ? from + res : NULL;
669
    *cannot_convert_error_pos= NULL;
670
    if (from_offset)
671
      res+= to_cs->mbminlen;
1 by brian
clean slate
672
  }
1034 by Brian Aker
Dead Code
673
674
  return res;
1 by brian
clean slate
675
}
676
677
678
679
680
void String::print(String *str)
681
{
682
  char *st= (char*)Ptr, *end= st+str_length;
683
  for (; st < end; st++)
684
  {
481 by Brian Aker
Remove all of uchar.
685
    unsigned char c= *st;
1 by brian
clean slate
686
    switch (c)
687
    {
688
    case '\\':
520.4.32 by Monty Taylor
Fixed oops.
689
      str->append("\\\\", sizeof("\\\\")-1);
1 by brian
clean slate
690
      break;
691
    case '\0':
520.4.32 by Monty Taylor
Fixed oops.
692
      str->append("\\0", sizeof("\\0")-1);
1 by brian
clean slate
693
      break;
694
    case '\'':
520.4.32 by Monty Taylor
Fixed oops.
695
      str->append("\\'", sizeof("\\'")-1);
1 by brian
clean slate
696
      break;
697
    case '\n':
520.4.32 by Monty Taylor
Fixed oops.
698
      str->append("\\n", sizeof("\\n")-1);
1 by brian
clean slate
699
      break;
700
    case '\r':
520.4.32 by Monty Taylor
Fixed oops.
701
      str->append("\\r", sizeof("\\r")-1);
1 by brian
clean slate
702
      break;
703
    case '\032': // Ctrl-Z
520.4.32 by Monty Taylor
Fixed oops.
704
      str->append("\\Z", sizeof("\\Z")-1);
1 by brian
clean slate
705
      break;
706
    default:
707
      str->append(c);
708
    }
709
  }
710
}
711
794 by Brian Aker
Refactor append_identifier and remove dead OPTION_QUOTE_SHOW_CREATE option
712
/*
713
  Quote the given identifier.
714
  If the given identifier is empty, it will be quoted.
715
716
  SYNOPSIS
717
  append_identifier()
718
  name                  the identifier to be appended
719
  name_length           length of the appending identifier
720
*/
721
722
/* Factor the extern out */
723
extern const CHARSET_INFO *system_charset_info, *files_charset_info;
724
779.3.10 by Monty Taylor
Turned on -Wshadow.
725
void String::append_identifier(const char *name, uint32_t in_length)
794 by Brian Aker
Refactor append_identifier and remove dead OPTION_QUOTE_SHOW_CREATE option
726
{
727
  const char *name_end;
728
  char quote_char;
729
  int q= '`';
730
731
  /*
732
    The identifier must be quoted as it includes a quote character or
733
   it's a keyword
734
  */
735
779.3.10 by Monty Taylor
Turned on -Wshadow.
736
  reserve(in_length*2 + 2);
794 by Brian Aker
Refactor append_identifier and remove dead OPTION_QUOTE_SHOW_CREATE option
737
  quote_char= (char) q;
738
  append(&quote_char, 1, system_charset_info);
739
779.3.10 by Monty Taylor
Turned on -Wshadow.
740
  for (name_end= name+in_length ; name < name_end ; name+= in_length)
794 by Brian Aker
Refactor append_identifier and remove dead OPTION_QUOTE_SHOW_CREATE option
741
  {
742
    unsigned char chr= (unsigned char) *name;
779.3.10 by Monty Taylor
Turned on -Wshadow.
743
    in_length= my_mbcharlen(system_charset_info, chr);
794 by Brian Aker
Refactor append_identifier and remove dead OPTION_QUOTE_SHOW_CREATE option
744
    /*
745
      my_mbcharlen can return 0 on a wrong multibyte
746
      sequence. It is possible when upgrading from 4.0,
747
      and identifier contains some accented characters.
748
      The manual says it does not work. So we'll just
749
      change length to 1 not to hang in the endless loop.
750
    */
779.3.10 by Monty Taylor
Turned on -Wshadow.
751
    if (!in_length)
752
      in_length= 1;
753
    if (in_length == 1 && chr == (unsigned char) quote_char)
794 by Brian Aker
Refactor append_identifier and remove dead OPTION_QUOTE_SHOW_CREATE option
754
      append(&quote_char, 1, system_charset_info);
779.3.10 by Monty Taylor
Turned on -Wshadow.
755
    append(name, in_length, system_charset_info);
794 by Brian Aker
Refactor append_identifier and remove dead OPTION_QUOTE_SHOW_CREATE option
756
  }
757
  append(&quote_char, 1, system_charset_info);
758
}
759
1 by brian
clean slate
760
761
/*
762
  Exchange state of this object and argument.
763
764
  SYNOPSIS
765
    String::swap()
766
767
  RETURN
768
    Target string will contain state of this object and vice versa.
769
*/
770
771
void String::swap(String &s)
772
{
322.2.2 by Mats Kindahl
Hiding THD::proc_info field and providing a setter and getter.
773
  std::swap(Ptr, s.Ptr);
774
  std::swap(str_length, s.str_length);
775
  std::swap(Alloced_length, s.Alloced_length);
776
  std::swap(alloced, s.alloced);
777
  std::swap(str_charset, s.str_charset);
1 by brian
clean slate
778
}
598.1.1 by Super-User
Fixed solaris build crap.
779
780
781
bool operator==(const String &s1, const String &s2)
782
{
783
  return stringcmp(&s1,&s2) == 0;
784
}
785
786
bool operator!=(const String &s1, const String &s2)
787
{
788
  return !(s1 == s2);
789
}
790