English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In MySQL, you often see some processing related to dynamic strings, such as: DYNAMIC_STRING.
To record the actual length of the dynamic string, the maximum length of the buffer, and to allocate new memory and adjust the length in time when 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 structure, str stores the starting address of the actual string, length records the actual length of the string, max_length records the maximum number of characters that the string buffer can store, and alloc_increment indicates how much memory is allocated each time the string needs to allocate memory.
Let's take a look at the initialization process of this structure:
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, it can be seen that when initializing, the initial string buffer size init_alloc will be judged according to the 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: The maximum length of the buffer
alloc_increment: The unit size of memory allocation when space is insufficient for the next allocation.
After initializing these contents, if more characters need to be added to this buffer next time, these values can be used to determine whether the buffer needs to be expanded:
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 after adding the new string exceeds the buffer size */ { /* How much memory needs to be allocated in increments of alloc_increment to accommodate 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, append to str after */ memcpy(str->str + str->length, append, length ); str->length += length; /* The new length of str after expansion */ str->str[str->length] = 0; /* Safety for C programs */ /* The last character of the string is '\0' */ return(FALSE); }
From the above code, it can be seen that after the string is initialized, if new content needs to be added to the string later, it is only necessary to dynamically realloc based on the previously stored information. Since this structure records the complete content related to the string, dynamic expansion will be very convenient to handle.
Of course, in addition to these, there are also such as string truncation, string initialization, escaping OS quotes, etc.:
Truncate the string after the offset N.
my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n) { str->length -= n; str->str[str->length] = '\0'; return(FALSE); }
Returns the address of the first occurrence of a character in the string. If not found, returns the address of 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 resizing:
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 buffer length */ { 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 the string in quotes, escape the single quotes within, mainly used to execute some system commands (system(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 is especially useful when * building strings to be executed with the system() function. * * @param str Dynamic String which will have additional 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 the dynamic string, each time additional characters are added to the string in stages, the dynamic expansion will be performed according to the current length of the string. Moreover, after each expansion, the structure records the actual information of the current string (the current length of the string, the length that the buffer can accommodate the string, and the length of the expansion unit). In this way, the operation of the dynamic string becomes very convenient.
Statement: The content of this article is from the network, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, does not edit the content manually, and does not bear relevant legal liabilities. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (When reporting via email, please replace # with @) for reporting violations, and provide relevant evidence. Once verified, this site will immediately delete the suspected infringing content.