程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> MySQL 之動態字符串處理

MySQL 之動態字符串處理

編輯:關於PHP編程

MySQL 之動態字符串處理


MySQL中,常常會看到一些關於動態字符串的處理,列如:DYNAMIC_STRING。為了記錄動態字符串的實際長度,緩沖區的最大長度,以及每次字符串需要調整時,及時分配新的內存,以及調整長度。MySQL使用了DYNAMIC_STRING來保存動態字符串相關的信息:

  1. typedef struct st_dynamic_string
  2. {
  3. char *str;
  4. size_t length,max_length,alloc_increment;
  5. } DYNAMIC_STRING;
在這個結構體中,str存儲實際字符串的首地址,length記錄字符串的實際長度,max_length記錄字符串緩沖區最多可以存放多少字符,alloc_increment表示當字符串需要分配內存時,每次分配多少內存。

下面看看這個結構體的初始化過程:

  1. my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str,size_t init_alloc, size_t alloc_increment)
  2. {
  3. size_t length;
  4. DBUG_ENTER("init_dynamic_string");

  5. if (!alloc_increment)
  6. alloc_increment=128;
  7. length=1;
  8. if (init_str && (length= strlen(init_str)+1) < init_alloc)
  9. init_alloc=((length+alloc_increment-1)/alloc_increment)*alloc_increment;
  10. if (!init_alloc)
  11. init_alloc=alloc_increment;

  12. if (!(str->str=(char*) my_malloc(init_alloc,MYF(MY_WME))))
  13. DBUG_RETURN(TRUE);
  14. str->length=length-1;
  15. if (init_str)
  16. memcpy(str->str,init_str,length);
  17. str->max_length=init_alloc;
  18. str->alloc_increment=alloc_increment;
  19. DBUG_RETURN(FALSE);
  20. }
從上述函數可以看到,初始化時,初始分配的字符串緩沖區大小init_alloc會根據需要初始的字符串來做判斷。在分配好該DYNAMIC_STRING空間之後,我們會根據緩沖區的大小,字符串的實際長度,以及alloc_increment來初始化:length:字符串的實際長度max_length:緩沖區的最大長度alloc_increment:空間不夠時,下次分配內存的單元大小.

初始化這些內容之後,如果下次需要在該緩沖區添加更多字符,就可以根據這些值來判斷是否需要對該緩沖區擴容:

  1. my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append,
  2. size_t length)
  3. {
  4. char *new_ptr;
  5. if (str->length+length >= str->max_length) //如果新增字符串後,總長度超過緩沖區大小
  6. {
  7. //需要分配多少個alloc_increment 大小的內存,才能存下新增後的字符串
  8. size_t new_length=(str->length+length+str->alloc_increment)/
  9. str->alloc_increment;
  10. new_length*=str->alloc_increment;

  11. if (!(new_ptr=(char*) my_realloc(str->str,new_length,MYF(MY_WME))))
  12. return TRUE;
  13. str->str=new_ptr;
  14. str->max_length=new_length;
  15. }
  16. //將新分配的內容,append到str之後
  17. memcpy(str->str + str->length,append,length);
  18. str->length+=length; //擴容之後str新的長度
  19. str->str[str->length]=0; /* Safety for C programs */ //字符串最後一個字符為’\0'
  20. return FALSE;
  21. }
從上述代碼可以看到,在字符串初始化化好之後,之後如果需要給該字符串增加新的內容,只需要根據之前存儲的信息來動態的realloc就好了。由於該結構體記錄了字符串相關的完整內容,所以動態的擴容會非常方便處理。
當然,除了這些,還有比如字符串截斷,字符串初始設置,轉義OS的引號等等:將字符串偏移大於N之後的截斷。

  1. my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n)
  2. {
  3. str->length-=n;
  4. str->str[str->length]= '\0';
  5. return FALSE;
  6. }
返回字符串中第一次出現某個字符的地址。若沒有,則返回字符串結尾的地址(指向’\0')

  1. char *strcend(register const char *s, register pchar c)
  2. {
  3. for (;;)
  4. {
  5. if (*s == (char) c) return (char*) s;
  6. if (!*s++) return (char*) s-1;
  7. }
  8. }
字符串內容擴容:

  1. my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size)
  2. {
  3. DBUG_ENTER("dynstr_realloc");

  4. if (!additional_size) DBUG_RETURN(FALSE);
  5. if (str->length + additional_size > str->max_length) //如果新的字符串內容超過緩沖區的最大長度
  6. {
  7. str->max_length=((str->length + additional_size+str->alloc_increment-1)/
  8. str->alloc_increment)*str->alloc_increment;
  9. if (!(str->str=(char*) my_realloc(str->str,str->max_length,MYF(MY_WME))))
  10. DBUG_RETURN(TRUE);
  11. }
  12. DBUG_RETURN(FALSE);
  13. }
對字符串用引號括起來,對其中的單引號進行轉義,主要用於執行一些系統命令(system(cmd))。比如:ls -al 會變成 \'ls -al\'比如:ls -a’l會變成\’ls -a\\\’l\'

  1. /*
  2. Concatenates any number of strings, escapes any OS quote in the result then
  3. surround the whole affair in another set of quotes which is finally appended
  4. to specified DYNAMIC_STRING. This function is especially useful when
  5. building strings to be executed with the system() function.

  6. @param str Dynamic String which will have addtional strings appended.
  7. @param append String to be appended.
  8. @param ... Optional. Additional string(s) to be appended.

  9. @note The final argument in the list must be NullS even if no additional
  10. options are passed.

  11. @return True = Success.
  12. */

  13. my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...)
  14. {

  15. const char *quote_str= "\'";
  16. const uint quote_len= 1;
  17. my_bool ret= TRUE;
  18. va_list dirty_text;

  19. ret&= dynstr_append_mem(str, quote_str, quote_len); /* Leading quote */
  20. va_start(dirty_text, append);
  21. while (append != NullS)
  22. {
  23. const char *cur_pos= append;
  24. const char *next_pos= cur_pos;

  25. /* Search for quote in each string and replace with escaped quote */
  26. while(*(next_pos= strcend(cur_pos, quote_str[0])) != '\0')
  27. {
  28. ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos));
  29. ret&= dynstr_append_mem(str ,"\\", 1);
  30. ret&= dynstr_append_mem(str, quote_str, quote_len);
  31. cur_pos= next_pos + 1;
  32. }
  33. ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos));
  34. append= va_arg(dirty_text, char *);
  35. }
  36. va_end(dirty_text);
  37. ret&= dynstr_append_mem(str, quote_str, quote_len); /* Trailing quote */

  38. return ret;
  39. }
通過定義動態字符串的結構體信息,每次分次進行字符串添加更多字符,都會根據字符串的當前的長度動態的擴容。而且每次擴容後,該結構體都記錄的當前字符串的實際信息(當前字符串的長度,緩沖器可容納字符串的長度,進行擴容的單元長度)。這樣,動態字符串的處理操作就變得非常方便了。



  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved