首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 內核動態字符串實現剖析:DYNAMIC_STRING 結構與核心操作源碼解讀

     編輯:MySQL 資料庫相關知識

一、 DYNAMIC_STRING 結構體定義

typedef struct st_dynamic_string {
    char *str;              // 字符串緩衝區首地址
    size_t length;          // 當前實際長度
    size_t max_length;      // 緩衝區最大容量
    size_t alloc_increment; // 擴容步長
} DYNAMIC_STRING;

設計目標:記錄字符串實時狀態,支援高效動態擴容,避免頻繁 malloc/free 開銷。

二、 初始化:init_dynamic_string

my_bool init_dynamic_string(DYNAMIC_STRING *str,
                            const char *init_str,
                            size_t init_alloc,
                            size_t alloc_increment) {
    if (!alloc_increment) alloc_increment = 128;  // 默認步長 128 字節
    size_t length = 1;  // 至少容納 '\0'
    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))))
        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;
    return FALSE;  // 成功
}

關鍵邏輯:根據初始字符串長度向上對齊 alloc_increment 倍數分配緩衝區,預留擴容空間。

三、 追加內存:dynstr_append_mem

my_bool dynstr_append_mem(DYNAMIC_STRING *str,
                          const char *append, size_t length) {
    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;  // 對齊步長
        char *new_ptr = (char*) my_realloc(str->str, new_length, MYF(MY_WME));
        if (!new_ptr) return TRUE;
        str->str = new_ptr;
        str->max_length = new_length;
    }
    memcpy(str->str + str->length, append, length);
    str->length += length;
    str->str[str->length] = '\0';  // C 字符串安全終止
    return FALSE;
}

擴容策略:按 alloc_increment 向上取整,減少 realloc 頻率,均攤 O(1) 追加複雜度。

四、 輔助操作函數

1. 截斷:dynstr_trunc

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

2. 尋字符:strcend

char *strcend(const char *s, char c) {
    for (;;) {
        if (*s == c) return (char*)s;
        if (!*s++) return (char*)s - 1;  // 到達末尾返回 '\0' 地址
    }
}

3. 顯式擴容:dynstr_realloc

my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size) {
    if (!additional_size) 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))))
            return TRUE;
    }
    return FALSE;
}

4. OS 命令引號轉義:dynstr_append_os_quoted

功能:將多字符串拼接、轉義單引號、整體包裹單引號,產生可安全傳給 system() 的命令字符串。

輸入: ls -a'l  → 輸出: 'ls -a\'l'

核心邏輯:遍歷可變參數列表,遇單引號插入 \' 轉義,首尾加引號。

五、 設計精華總結

  • 元數據自描述:長度、容量、步長三元組,無需外部上下文即可安全操作
  • 幂等擴容:realloc 失敗不修改原指針,調用者可檢測錯誤
  • C 風格安全:始終維護 str[length] = '\0',兼容標準庫函數
  • 內存對齊:按步長對齊分配,減少碎片與系統調用

此結構廣泛用於 MySQL 內部 SQL 構建、錯誤信息格式化、日志生成等高頻字符串操作場景,是 C 語言動態字符串管理的經典範例。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved