English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
В 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 ); }
Из вышеуказанных функций видно, что при инициализации, размер начального распределения буфера init_alloc для строки определяется в зависимости от начальной строки. После распределения пространства DYNAMIC_STRING, мы инициализируем его на основе размера буфера, фактической длины строки и alloc_increment:
length: фактическая длина строки
max_length: максимальная длина буфера
alloc_increment: при нехватке места, размер элемента следующей распределенной памяти.
После инициализации этого содержимого, если в следующий раз нужно добавить больше символов в этот буфер, можно использовать эти значения для определения необходимости расширения буфера:
my_bool dynstr_append_mem( DYNAMIC_STRING *str, const char *append, size_t length ) { char *new_ptr; if ( str->length + length >= str->max_length ) /* Если общая длина строки после добавления нового содержимого exceeds размер буфера */ { /* Сколько памяти нужно выделить в размерах alloc_increment, чтобы хранить строку после добавления нового содержимого */ 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, после str */ memcpy( str->str + str->length, append, length ); str->length += length; /* Новая длина str после расширения */ str->str[str->length] = 0; /* Защита для программ на C */ /* Последний символ строки - '\0' */ return(FALSE); }
Из приведенного кода видно, что после инициализации строки, если нужно добавить новое содержимое к этой строке, достаточно динамически realloc'ить по хранящейся информации. Поскольку структура записывает все相关信息 о строке, динамическое расширение будет очень удобно обрабатывать.
Конечно, помимо этого, есть и такие операции, как усечение строки, инициализация строки, экранирование кавычек ОС и т.д.:
Усечь строку после смещения, превышающего N.
my_bool dynstr_trunc( DYNAMIC_STRING *str, size_t n ) { str->length -= n; str->str[str->length] = '\0'; return(FALSE); }
Возвращает адрес первого occurrence определенного символа в строке. Если его нет, то возвращает адрес конца строки (прямо на '')
char *strcend( register const char *s, register pchar c ) { for (;; ) { if ( *s == (char) c ) return( (char *) s); if ( !*s++ ) return( (char *) s - 1); } }
Увеличение содержимого строки:
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 ) /* если новый контент строки превышает максимальную длину буфера */ { 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 ); }
строка заключена в кавычки, в ней заменяются одинарные кавычки, что используется для выполнения некоторых системных команд(system(cmd)).
например: ls -al станет ‘ls -al'
например: ls -a'l станет 'ls -a\'l'
/* * Соединяет любое количество строк, избегаетany OS quote в результате * окружает все дело еще одним набором кавычек, который в конечном итоге добавляется * к указанному DYNAMIC_STRING. Эта функция особенно полезна когда * создание строк для выполнения с помощью функции system(). * * @param str Динамическая строка, к которой будут добавлены дополнительные строки. * @param append Строка для добавления. * @param ... Дополнительные строки для добавления. * * @note Последний аргумент в списке должен быть NullS, даже если нет дополнительных * передаются параметры. * * @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); /* Начальная кавычка */ va_start(dirty_text, append); while (append != NullS) { const char *cur_pos = append; const char *next_pos = cur_pos; /* Ищем кавычку в каждой строке и заменяем её экранированной кавычкой */ 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 ); /* Заключительный кавычки */ return(ret); }
Определяя структуру типа информации динамической строки, при каждом добавлении более символов в строку, происходит динамическое расширение строки в зависимости от текущей длины строки. Кроме того, после каждого расширения структура записывает текущие данные строки (текущая длина строки, длина буфера, который может容纳 строку, размер элемента расширения). Таким образом, операции обработки динамической строки становятся очень удобными.
Заявление: содержимое статьи взято из сети, авторские права принадлежат соответствующему автору, материалы предоставлены пользователями Интернета, сайт не имеет права собственности, материалы не были отредактированы вручную, также не несет ответственности за соответствующие юридические вопросы. Если вы обнаружите материалы,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (во время отправки письма, пожалуйста, замените # на @) для сообщения о нарушении,并提供 соответствующие доказательства. В случае подтверждения, сайт немедленно удалят涉嫌侵权的内容.