In MySQL, you will often see some processing of dynamic strings, such as: Dynamic_string.
In order to record the actual length of the dynamic string, the maximum length of the buffer, and each time the string needs to be adjusted, the new memory is allocated in time, and the length is adjusted. MySQL uses dynamic_string to save dynamic string-related information:
typedef struct st_dynamic_string
{
Char *str;
size_t length, max_length, alloc_increment;
} dynamic_string;
In this struct, STR stores the first address of the actual string, length records the actual length of the string, how many characters the Max_length record string buffer can hold, and alloc_increment indicates how much memory is allocated each time the string needs to allocate memory.
Here's a look at the initialization process for this struct:
My_bool init_dynamic_string( dynamic_string *str, const Char *init_str , size_t init_alloc, size_t alloc_increment )
{
size_t length;
dbug_enter( "init_dynamic_string" );
if ( ! Alloc_increment )
alloc_increment = ;
length = 1;
if ( init_str && (length = strlen( init _str ) + 1) < init_alloc )
Init_alloc = ( (length + alloc_increment - 1) / alloc_increment ) * alloc_increment;
if ( ! Init_alloc )
init_alloc = alloc_increment;
if ( ! (STR-str = (char *) my_malloc( init_alloc, MYF( MY_wme ))))
Dbug_return( TRUE );
str --length = length - 1;
if ( init_str )
memcpy(str , str, init_str, length );
STR--max_length = init_alloc;
STR--alloc_increment = alloc_increment;
Dbug_return( FALSE );
}
As you can see from the above function, when initializing, the initial allocated string buffer size Init_alloc will be judged based on the string that needs to be initialized. After allocating the dynamic_string space, we initialize it according to the size of the buffer, the actual length of the string, and the alloc_increment:
Length: The actual length of the string
Max_length: Maximum length of buffer
Alloc_increment: When space is not enough, the next time you allocate memory for the cell size.
After initializing the content, if you need to add more characters to the buffer next time, you can determine whether the buffer needs to be expanded by these values:
My_bool dynstr_append_mem( dynamic_string *str, const char *Append , size_t length )
{
Char *new_ptr;
if ( str,length + length >= str,Max_length )/ * If a new string is added, the total length exceeds the buffer size * /
{
/* How many alloc_increment-sized memory should be allocated to save the new string */
size_t new_length = (str--length + length + str-- alloc_increment) /
STR--alloc_increment;
new_length *= str--- alloc_increment;
if ( ! (new_ptr = (char *) my_realloc(str ,str, new_length, MYF( MY_wme ) )))
return(TRUE);
STR- str = new_ptr;
STR--max_length = new_length;
}
/* Append the newly allocated content to STR */
memcpy (str-STR + str--Length, append , length );
Str-length + = length; / * New length of str after expansion * /
STR- str[STR-alength] = 0; / * Safety for C programs */// * The last character of the string is ' + ' * /
return(FALSE);
}
As can be seen from the above code, after the initialization of the string, and then if you need to add new content to the string, just based on the previously stored information to the dynamic realloc. Because the structure records the complete string-related content, dynamic expansion is very easy to handle.
Of course, in addition to these, there are, for example, string truncation, string initial settings, escaping the OS quotes, and so on:
Truncate after the string is offset greater than N.
My_bool dynstr_trunc( dynamic_string *str, size_t n )
{
Str-Length- = n;
STR- str[str, length] = ' + ';
return(FALSE);
}
Returns the address of the first occurrence of a character in a string. If not, returns the address at the end of the string (pointing to ")
Char *strcend( Register const Char *s, Register Pchar C )
{
for (;; )
{
if ( *s = = (char) C )
return( (char *) s);
if ( !*s+ + )
return( (char *) s - 1);
}
}
String Content Expansion:
My_bool dynstr_realloc( dynamic_string *str, size_t additional_size )
{
dbug_enter( "Dynstr_realloc" );
if ( ! Additional_size )
Dbug_return( FALSE );
if ( str,length + additional_size > str - Max_length )/ * If the new string content exceeds the maximum length of the buffer * /
{
str --max_length = ( (str,length + additional_size + str --alloc_increment- 1) /
Str-alloc_increment) * STR--- alloc_increment;
if ( ! (STR-STR = (char *) my_realloc( str - Str, str-max_length, MYF( MY_wme ) ) ) )< /c25>
Dbug_return( TRUE );
}
Dbug_return( FALSE );
}
Enclose the string in quotation marks, escaping the single quotation mark, which is used primarily to execute some system commands (systems (CMD)).
For example: Ls-al will become ' Ls-al '
For example: Ls-a ' L will become ' ls-a\ ' l '
/*
* concatenates any number of strings, escapes any OS quote in the result then
* Surround the whole affair in another set of quotes which is finally appended
* to specified dynamic_string. This function was especially useful when
* Building strings to is executed with the system () function.
*
* @param str Dynamic String which would have addtional strings appended.
* @param append String to be appended.
* @param ... Optional. Additional string (s) to is appended.
*
* @ Note The final argument in the list must is NullS even if no additional
* Options are passed.
*
* @return True = Success.
*/
My_bool dynstr_append_os_quoted( dynamic_string *str, const Char * Append, ... )
{
Const Char *quote_str = "\";
Const uint Quote_len = 1;
my_bool ret = TRUE;
va_list dirty_text;
ret &= dynstr_append_mem( str, quote_str, quote_len ); / * Leading quote * /
va_start( dirty_text, append );
while ( append! = NullS )
{
Const Char *cur_pos = append;
Const Char *next_pos = cur_pos;
/* Search for quote in each string and replace with escaped quote */
while ( *(next_pos = strcend( cur_pos, quote_ STR[0]) )! = ' + ' )
{
ret &= dynstr_append_mem( str, cur_pos, (uint) (next_pos - cur_pos) );
ret &= dynstr_append_mem( str, "\ \", 1 );
ret &= dynstr_append_mem( str, quote_str, Quote _len );
Cur_pos = next_pos + 1;
}
ret &= dynstr_append_mem( str, cur_pos, (UINT ) (next_pos - cur_pos) );
Append = va_arg( dirty_text, Char * );
}
va_end( dirty_text );
ret &= dynstr_append_mem( str, quote_str, quote_len ); / * Trailing quote * /
return(ret);
}
By defining the structure information of a dynamic string, each time a string is added more characters, it is dynamically expanded according to the current length of the string. And after each expansion, the struct records the actual information of the current string (the length of the current string, the buffer can hold the length of the string, the unit length for expansion). This makes it very convenient to manipulate dynamic strings.
MySQL Dynamic string processing dynamic_string