English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tratamento de String Dinâmica MySQL DYNAMIC_STRING

No MySQL, é comum ver processamentos de strings dinâmicas, como: DYNAMIC_STRING.

Para registrar o comprimento real da string dinâmica, o comprimento máximo do buffer e alocar memória nova e ajustar o comprimento a tempo quando a string precisa ajustar, o MySQL usa DYNAMIC_STRING para armazenar informações relacionadas a strings dinâmicas:

typedef struct st_dynamic_string
{
 char *str;
 size_t length, max_length, alloc_increment;
}; DYNAMIC_STRING;

Nessa estrutura, str armazena o endereço inicial da string real, length registra o comprimento real da string, max_length registra quantos caracteres o buffer de string pode armazenar no máximo, e alloc_increment representa quantos bytes são alocados a cada vez que a string precisa de mais memória.

Vamos ver o processo de inicialização dessa estrutura:

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 );
}

Pode ver na função acima que, durante a inicialização, o tamanho inicial do buffer de string alocado init_alloc é determinado com base na string inicial necessária. Após a alocação do espaço DYNAMIC_STRING, inicializamos com base no tamanho do buffer, o comprimento real da string e alloc_increment:

length: comprimento real da string

max_length: comprimento máximo do buffer

alloc_increment: tamanho do bloco de memória a ser alocado na próxima vez, quando não houver espaço suficiente

Após inicializar esses conteúdos, se precisar adicionar mais caracteres neste buffer na próxima vez, pode usar esses valores para determinar se é necessário expandir o buffer:

my_bool dynstr_append_mem( DYNAMIC_STRING *str, const char *append, size_t length )
{
 char *new_ptr;
 if (str->length + length >= str->max_length ) /* se a string adicional fizer com que o comprimento total exceda o tamanho do buffer */
 {
/* precisão necessária para alocação de memória, para armazenar a string adicional */
 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;
 }
/* Adicionar o conteúdo recém-alocado, append, ao final de str */
 memcpy(str->str + str->length, append, length );
 str->length += length;               /* O novo comprimento de str após a ampliação */
 str->str[str->length] = 0; /* Segurança para programas C */    /* O último caractere da string é '\0' */
 return(FALSE);
}

Daqui podemos ver que, após a inicialização da string, se precisarmos adicionar novos conteúdos à string, é só reallocar dinamicamente com base nas informações armazenadas anteriormente. Como essa estrutura armazena todo o conteúdo da string, a ampliação dinâmica é muito fácil de lidar.

Claro, além disso, há como cortar strings, inicializar strings, escapar aspas do sistema operacional, etc.:

Cortar a string a partir do deslocamento superior a N.

my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n )
{
 str->length -= n;
 str->str[str->length] = '\0';
 return(FALSE);
}

Retorna o endereço da primeira ocorrência de um caractere na string. Se não houver, retorna o endereço do final da string (aponta para '')

char *strcend(register const char *s, register pchar c )
{
 for (;; )
 {
 if ( *s == (char) c )
  return((char *) s);
 if (!*s++ )
  return((char *) s - 1);
 }
}

Aumento do conteúdo da string:

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 ) /* Se o conteúdo novo da string exceder o comprimento máximo do 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 the string in quotes, escape the single quotes within, mainly used for executing some system commands (system(cmd)).

for example: ls -al becomes 'ls' -al'

for example: ls -a'l becomes '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);
}

Definindo informações de estrutura de strings dinâmicas, cada vez que mais caracteres são adicionados à string, ela se expande dinamicamente com base no comprimento atual da string. Além disso, após cada expansão, o estrutura de dados armazena informações reais da string atual (comprimento da string atual, comprimento que o buffer pode suportar, unidade de comprimento de expansão). Dessa forma, as operações de manipulação de strings dinâmicas tornam-se muito convenientes.

Declaração: o conteúdo deste artigo é de origem na internet, pertencente ao autor original. Foi contribuído e carregado voluntariamente por usuários da internet. Este site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidades legais relacionadas. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie e-mail para: notice#oldtoolbag.com (ao enviar e-mail, troque # por @ para denunciar, e forneça provas relevantes. Atingido, o site deletará imediatamente o conteúdo suspeito de violação de direitos autorais.)

Você Talvez Goste