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

معالجة الأنماط المتحركة في 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 );
}

从上述函数中可以看出,在初始化时,初始分配的字符串缓冲区大小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 ) /* إذا كان طول النص المضاف الجديد يتجاوز حجم الحافز */
 {
/* كم من ذاكرة يجب تخصيصها لتخزين النص المضاف الجديد */
 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; /* Safety for C programs */    /* يجب أن يكون آخر حرف في النص هو '\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);
}

returns the address of the first occurrence of a character in a 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);
 }
}

字符串内容扩容:

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'

/*
 * 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
 * إلى 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 ); /* Trailing quote */
 return(ret);
}

من خلال تعريف معلومات بنية ديناميكية النص، في كل مرة يتم إضافة المزيد من الأحرف إلى النص بشكل جزئي، يتم توسيع حجم النص بناءً على طول النص الحالي. بالإضافة إلى ذلك، يتم تسجيل معلومات النص الفعلي الحالي (طول النص الحالي، طول المخزن المؤقت الذي يمكنه حمل النص، طول وحدة التوسع) بعد كل توسع. بهذا الشكل، تصبح عمليات معالجة النص الديناميكي سهلة للغاية.

بيان: محتوى هذا المقال تم جمعه من الإنترنت، ويتمتع صاحب الحقوق الأصلية بالملكية، ويتم جمع المحتوى من قبل المستخدمين عبر الإنترنت بشكل متعاوني وتحميله بشكل مستقل، ويتمتع هذا الموقع بعدم امتلاك حقوق الملكية، ولا يتم تعديل المحتوى بشكل يدوي، ولا يتحمل هذا الموقع أي مسؤولية قانونية. إذا اكتشفت محتوى يشتبه في انتهاك حقوق النسخ، فلا تتردد في إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال '#' ب '@') للإبلاغ، وتقديم الدليل المتعلق، وسينفذ الموقع إزالة المحتوى المشبوه فور التحقق منه.

من المحتمل أن تفضل