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

Traitement dynamique des chaînes MySQL DYNAMIC_STRING

在MySQL中,常常会看到一些关于动态字符串的处理,例如:DYNAMIC_STRING。

为了记录动态字符串的实际长度,缓冲区的最大长度,以及每次字符串需要调整时,及时分配新的内存,以及调整长度。MySQL使用了DYNAMIC_STRING来保存动态字符串相关的信息:

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

在这个结构体中,str存储实际字符串的首地址,length记录字符串的实际长度,max_length记录字符串缓冲区最多可以存放多少字符,alloc_increment表示当字符串需要分配内存时,每次分配多少内存。

让我们看看这个结构体的初始化过程:

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

À partir de la fonction ci-dessus, on peut voir que lors de l'initialisation, la taille initiale du tampon de chaîne allouée init_alloc est déterminée en fonction de la chaîne initiale nécessaire. Après avoir alloué l'espace DYNAMIC_STRING, nous initialisons en fonction de la taille du tampon, de la longueur réelle de la chaîne et de alloc_increment :

length:longueur réelle de la chaîne

max_length:longueur maximale du tampon

alloc_increment:taille de l'unité de mémoire allouée la prochaine fois que la mémoire ne sera pas suffisante.

Après avoir initialisé ces informations, si vous devez ajouter plus de caractères dans ce tampon à l'avenir, vous pouvez utiliser ces valeurs pour déterminer si vous devez agrandir le tampon :

my_bool dynstr_append_mem( DYNAMIC_STRING *str, const char *append, size_t length )
{
 char *new_ptr;
 if (str->length + length >= str->max_length ) /* Si la longueur totale de la chaîne ajoutée dépasse la taille du tampon */
 {
/* Combien d'octets de mémoire doit-on allouer pour stocker la nouvelle chaîne après l'ajout? */
 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;
 }
/* Ajouter le contenu nouvellement alloué, append, après str */
 memcpy(str->str + str->length, append, length );
 str->length += length;               /* La nouvelle longueur de str après l'augmentation */
 str->str[str->length] = 0; /* Sécurité pour les programmes C */    /* Le dernier caractère de la chaîne est '\0' */
 return(FALSE);
}

Comme on peut le voir dans le code ci-dessus, après que la chaîne soit initialisée, si on a besoin d'ajouter du nouveau contenu à cette chaîne, il suffit de realloc dynamiquement en fonction des informations stockées précédemment. Étant donné que cette structure enregistre le contenu complet de la chaîne, l'augmentation dynamique de la capacité est très facile à gérer.

Naturellement, en plus de cela, il y a aussi des opérations telles que le tronquage de la chaîne, l'initialisation de la chaîne, l'échappement des guillemets de l'OS, etc. :

Tronquer la chaîne après le décalage de la chaîne supérieur à N.

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

Retourne l'adresse du premier caractère apparaissant dans la chaîne. Si non, retourne l'adresse de la fin de la chaîne (pointant à '')

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

Augmentation de la capacité du contenu de la chaîne

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 ) /* Si le contenu du nouveau chaîne de caractères dépasse la longueur maximale du tampon */
 {
 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 and escape the single quotes within, mainly used to execute 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;
/* Recherche de guillemets dans chaque chaîne et remplacement par des guillemets échappés */
 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 ); /* Guillemet en fin de ligne */
 return(ret);
}

En définissant les informations de structure de la chaîne dynamique, chaque fois que vous ajoutez plus de caractères à la chaîne en plusieurs étapes, elle se réduit dynamiquement en fonction de la longueur actuelle de la chaîne. De plus, après chaque expansion, cette structure enregistre les informations réelles actuelles de la chaîne (la longueur actuelle de la chaîne, la longueur que peut contenir le tampon, la longueur de l'unité d'expansion). De cette manière, les opérations de traitement des chaînes dynamiques deviennent très pratiques.

Déclaration : le contenu de cet article est issu du réseau, la propriété intellectuelle appartient aux auteurs respectifs, le contenu est apporté par les utilisateurs d'Internet de manière volontaire et téléversé. Ce site ne possède pas de propriété intellectuelle, n'a pas été édité par l'homme, ni assume la responsabilité juridique connexe. Si vous trouvez du contenu présumé enfreignant les droits d'auteur, veuillez envoyer un e-mail à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un e-mail pour faire une plainte, et fournir des preuves pertinentes. Une fois vérifié, ce site supprimera immédiatement le contenu présumé enfreignant les droits d'auteur.

Vous pourriez aussi aimer