MySQL dynamic string processing DYNAMIC_STRING, dynamic into string
In MySQL, we 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 the new memory allocated and the length adjusted each time the string needs to be adjusted. MySQL uses DYNAMIC_STRING to save information related to dynamic strings:
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, and max_length records the maximum number of characters that can be stored in the string buffer. alloc_increment indicates that when the string needs to be allocated memory, memory size allocated each time.
Let's take a look at the initialization process of 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 = 128; 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 );}
From the above function, we can see that during initialization, the size of the initially allocated string buffer init_alloc will be determined based on the required initial string. After the DYNAMIC_STRING space is allocated, we will initialize it based on the buffer size, the actual length of the string, and alloc_increment:
Length: the actual length of the string.
Max_length: Maximum length of the buffer.
Alloc_increment: memory unit size allocated next time when space is insufficient.
After initializing the content, if you need to add more characters to the buffer next time, you can determine whether to resize the buffer based on 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 the total length of a new string exceeds the buffer size */{/* How many memories of alloc_increment need to be allocated, the new string */size_t new_length = (str-> 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 str length after resizing */str-> str [str-> length] = 0; /* Safety for C programs * // * The last character of the string is '\ 0' */return (FALSE );}
From the code above, we can see that after the string is initialized, if you need to add new content to the string, you just need to dynamically realloc it based on the information stored previously. This struct records the complete string-related content, so dynamic resizing is very convenient.
Of course, in addition to these, there are also such as string truncation, initial string setting, and quotation marks for escape OS:
Truncation after the string offset is greater than N.
my_bool dynstr_trunc( DYNAMIC_STRING *str, size_t n ){ str->length -= n; str->str[str->length] = '\0'; return(FALSE);}
Returns the first occurrence of a character in a string. If no, the end address of the string is returned (pointing '')
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 content of the new string 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) DBUG_RETURN (TRUE );} DBUG_RETURN (FALSE );}
Enclose strings in quotation marks and escape the single quotation marks. It is mainly used to execute some system commands (system (cmd )).
For example, if ls-al is changed to 'LS-al'
For example, if ls-a' l is used, it will be changed to '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 is especially useful when * building strings to be executed with the system() function. * * @param str Dynamic String which will have addtional strings appended. * @param append String to be appended. * @param ... Optional. Additional string(s) to be appended. * * @ note The final argument in the list must be 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] ) ) != '\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 you add more characters to the string in multiple times, the string is dynamically resized based on the current length. And after each expansion, the structure records the actual information of the current string (the length of the current string, the buffer can accommodate the length of the string, the length of the expansion unit ). In this way, it is very convenient to process dynamic strings.