summaryrefslogtreecommitdiff
path: root/sql/sql_string.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_string.cc')
-rw-r--r--sql/sql_string.cc228
1 files changed, 58 insertions, 170 deletions
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 8b00c67c16d..8145c723693 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -41,7 +41,9 @@ bool String::real_alloc(uint32 length)
if (Alloced_length < arg_length)
{
free();
- if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME))))
+ if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME |
+ (thread_specific ?
+ MY_THREAD_SPECIFIC : 0)))))
return TRUE;
Alloced_length=arg_length;
alloced=1;
@@ -74,9 +76,9 @@ bool String::real_alloc(uint32 length)
@retval false Either the copy operation is complete or, if the size of the
new buffer is smaller than the currently allocated buffer (if one exists),
- no allocation occured.
+ no allocation occurred.
- @retval true An error occured when attempting to allocate memory.
+ @retval true An error occurred when attempting to allocate memory.
*/
bool String::realloc_raw(uint32 alloc_length)
{
@@ -89,10 +91,16 @@ bool String::realloc_raw(uint32 alloc_length)
return TRUE; /* Overflow */
if (alloced)
{
- if (!(new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME))))
+ if (!(new_ptr= (char*) my_realloc(Ptr,len,
+ MYF(MY_WME |
+ (thread_specific ?
+ MY_THREAD_SPECIFIC : 0)))))
return TRUE; // Signal error
}
- else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME))))
+ else if ((new_ptr= (char*) my_malloc(len,
+ MYF(MY_WME |
+ (thread_specific ?
+ MY_THREAD_SPECIFIC : 0)))))
{
if (str_length > len - 1)
str_length= 0;
@@ -537,6 +545,24 @@ bool String::append(IO_CACHE* file, uint32 arg_length)
return FALSE;
}
+
+/**
+ Append a parenthesized number to String.
+ Used in various pieces of SHOW related code.
+
+ @param nr Number
+ @param radix Radix, optional parameter, 10 by default.
+*/
+bool String::append_parenthesized(long nr, int radix)
+{
+ char buff[64], *end;
+ buff[0]= '(';
+ end= int10_to_str(nr, buff + 1, radix);
+ *end++ = ')';
+ return append(buff, (uint) (end - buff));
+}
+
+
bool String::append_with_prefill(const char *s,uint32 arg_length,
uint32 full_length, char fill_char)
{
@@ -554,7 +580,7 @@ bool String::append_with_prefill(const char *s,uint32 arg_length,
return FALSE;
}
-uint32 String::numchars()
+uint32 String::numchars() const
{
return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
}
@@ -670,7 +696,7 @@ int String::reserve(uint32 space_needed, uint32 grow_by)
{
if (Alloced_length < str_length + space_needed)
{
- if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
+ if (realloc(Alloced_length + MY_MAX(space_needed, grow_by) - 1))
return TRUE;
}
return FALSE;
@@ -757,7 +783,7 @@ int sortcmp(const String *s,const String *t, CHARSET_INFO *cs)
int stringcmp(const String *s,const String *t)
{
- uint32 s_len=s->length(),t_len=t->length(),len=min(s_len,t_len);
+ uint32 s_len=s->length(),t_len=t->length(),len=MY_MIN(s_len,t_len);
int cmp= memcmp(s->ptr(), t->ptr(), len);
return (cmp) ? cmp : (int) (s_len - t_len);
}
@@ -774,7 +800,7 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
}
if (to->realloc(from_length))
return from; // Actually an error
- if ((to->str_length=min(from->str_length,from_length)))
+ if ((to->str_length=MY_MIN(from->str_length,from_length)))
memcpy(to->Ptr,from->Ptr,to->str_length);
to->str_charset=from->str_charset;
return to;
@@ -785,140 +811,6 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
Help functions
****************************************************************************/
-/*
- copy a string from one character set to another
-
- SYNOPSIS
- copy_and_convert()
- to Store result here
- to_cs Character set of result string
- from Copy from here
- from_length Length of from string
- from_cs From character set
-
- NOTES
- 'to' must be big enough as form_length * to_cs->mbmaxlen
-
- RETURN
- length of bytes copied to 'to'
-*/
-
-
-static uint32
-copy_and_convert_extended(char *to, uint32 to_length, CHARSET_INFO *to_cs,
- const char *from, uint32 from_length,
- CHARSET_INFO *from_cs,
- uint *errors)
-{
- int cnvres;
- my_wc_t wc;
- const uchar *from_end= (const uchar*) from+from_length;
- char *to_start= to;
- uchar *to_end= (uchar*) to+to_length;
- my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
- my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
- uint error_count= 0;
-
- while (1)
- {
- if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
- from_end)) > 0)
- from+= cnvres;
- else if (cnvres == MY_CS_ILSEQ)
- {
- error_count++;
- from++;
- wc= '?';
- }
- else if (cnvres > MY_CS_TOOSMALL)
- {
- /*
- A correct multibyte sequence detected
- But it doesn't have Unicode mapping.
- */
- error_count++;
- from+= (-cnvres);
- wc= '?';
- }
- else
- break; // Not enough characters
-
-outp:
- if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
- to+= cnvres;
- else if (cnvres == MY_CS_ILUNI && wc != '?')
- {
- error_count++;
- wc= '?';
- goto outp;
- }
- else
- break;
- }
- *errors= error_count;
- return (uint32) (to - to_start);
-}
-
-
-/*
- Optimized for quick copying of ASCII characters in the range 0x00..0x7F.
-*/
-uint32
-copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
- const char *from, uint32 from_length, CHARSET_INFO *from_cs,
- uint *errors)
-{
- /*
- If any of the character sets is not ASCII compatible,
- immediately switch to slow mb_wc->wc_mb method.
- */
- if ((to_cs->state | from_cs->state) & MY_CS_NONASCII)
- return copy_and_convert_extended(to, to_length, to_cs,
- from, from_length, from_cs, errors);
-
- uint32 length= min(to_length, from_length), length2= length;
-
-#if defined(__i386__) || defined(__x86_64__)
- /*
- Special loop for i386, it allows to refer to a
- non-aligned memory block as UINT32, which makes
- it possible to copy four bytes at once. This
- gives about 10% performance improvement comparing
- to byte-by-byte loop.
- */
- for ( ; length >= 4; length-= 4, from+= 4, to+= 4)
- {
- if ((*(uint32*)from) & 0x80808080)
- break;
- *((uint32*) to)= *((const uint32*) from);
- }
-#endif
-
- for (; ; *to++= *from++, length--)
- {
- if (!length)
- {
- *errors= 0;
- return length2;
- }
- if (*((unsigned char*) from) > 0x7F) /* A non-ASCII character */
- {
- uint32 copied_length= length2 - length;
- to_length-= copied_length;
- from_length-= copied_length;
- return copied_length + copy_and_convert_extended(to, to_length,
- to_cs,
- from, from_length,
- from_cs,
- errors);
- }
- }
-
- DBUG_ASSERT(FALSE); // Should never get to here
- return 0; // Make compiler happy
-}
-
-
/**
Copy string with HEX-encoding of "bad" characters.
@@ -1036,7 +928,7 @@ well_formed_copy_nchars(CHARSET_INFO *to_cs,
if (to_cs == &my_charset_bin)
{
- res= min(min(nchars, to_length), from_length);
+ res= MY_MIN(MY_MIN(nchars, to_length), from_length);
memmove(to, from, res);
*from_end_pos= from + res;
*well_formed_error_pos= NULL;
@@ -1130,8 +1022,15 @@ well_formed_copy_nchars(CHARSET_INFO *to_cs,
wc= '?';
}
else
- break; // Not enough characters
-
+ {
+ if ((uchar *) from >= from_end)
+ break; // End of line
+ // Incomplete byte sequence
+ if (!*well_formed_error_pos)
+ *well_formed_error_pos= from;
+ from++;
+ wc= '?';
+ }
outp:
if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
to+= cnvres;
@@ -1158,10 +1057,11 @@ outp:
/*
Append characters to a single-quoted string '...', escaping special
- characters as necessary.
+ characters with backslashes as necessary.
Does not add the enclosing quotes, this is left up to caller.
*/
-void String::append_for_single_quote(const char *st, uint len)
+#define APPEND(X) if (append(X)) return 1; else break
+bool String::append_for_single_quote(const char *st, uint len)
{
const char *end= st+len;
for (; st < end; st++)
@@ -1169,31 +1069,19 @@ void String::append_for_single_quote(const char *st, uint len)
uchar c= *st;
switch (c)
{
- case '\\':
- append(STRING_WITH_LEN("\\\\"));
- break;
- case '\0':
- append(STRING_WITH_LEN("\\0"));
- break;
- case '\'':
- append(STRING_WITH_LEN("\\'"));
- break;
- case '\n':
- append(STRING_WITH_LEN("\\n"));
- break;
- case '\r':
- append(STRING_WITH_LEN("\\r"));
- break;
- case '\032': // Ctrl-Z
- append(STRING_WITH_LEN("\\Z"));
- break;
- default:
- append(c);
+ case '\\': APPEND(STRING_WITH_LEN("\\\\"));
+ case '\0': APPEND(STRING_WITH_LEN("\\0"));
+ case '\'': APPEND(STRING_WITH_LEN("\\'"));
+ case '\n': APPEND(STRING_WITH_LEN("\\n"));
+ case '\r': APPEND(STRING_WITH_LEN("\\r"));
+ case '\032': APPEND(STRING_WITH_LEN("\\Z"));
+ default: APPEND(c);
}
}
+ return 0;
}
-void String::print(String *str)
+void String::print(String *str) const
{
str->append_for_single_quote(Ptr, str_length);
}
@@ -1248,7 +1136,7 @@ uint convert_to_printable(char *to, size_t to_len,
char *t= to;
char *t_end= to + to_len - 1; // '- 1' is for the '\0' at the end
const char *f= from;
- const char *f_end= from + (nbytes ? min(from_len, nbytes) : from_len);
+ const char *f_end= from + (nbytes ? MY_MIN(from_len, nbytes) : from_len);
char *dots= to; // last safe place to append '...'
if (!f || t == t_end)