taoCMS是基于php+sqlite/mysql的国内最小(100Kb左右)的功能完善、开源免费的CMS管理系统

解读zend_api字符串替换之php_str_to_str_ex

2012-04-05

PHPAPI char *php_str_to_str_ex(char *haystack, int length, 
char *needle, int needle_len, char *str, int str_len, int *_new_length, int case_sensitivity, int *replace_count)
{
    定一个新的字符串指针
    char *new_str;
    如果要查找的字符串长度小于原串的长度
if (needle_len < length) {
   char *end, *haystack_dup = NULL, *needle_dup = NULL;
   char *e, *s, *p, *r;
        如果查找的字符串长度等于要替换的字符串长度
   if (needle_len == str_len) {
    从haystack中拷贝length个到new_str,其实就是把haystack字符串赋值给new_str
    new_str = estrndup(haystack, length);
    把长度赋值给_new_length
    *_new_length = length;
            如果区分大小写
    if (case_sensitivity) {
     求得原字符串的末指针
       end = new_str + length;
       其中php_memnstr用来判断是否含有字符串,下边的循环表示从字符串首部开始,然后开始查找找到以后从找到的字符串尾部开始
       直到不在含有目标字符串完为止
     for (p = new_str; (r = php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
      通过循环替换所有的字符串
        memcpy(r, str, str_len);
      记录替换的次数
        if (replace_count) {
       (*replace_count)++;
      }
     }
    如果不区分大小写
    } else {
     做原串的复制
       haystack_dup = estrndup(haystack, length);
     needle_dup = estrndup(needle, needle_len);
     转换成小写
     php_strtolower(haystack_dup, length);
     php_strtolower(needle_dup, needle_len);
     end = haystack_dup + length;
     下边循环的解释同上
     for (p = haystack_dup; (r = php_memnstr(p, needle_dup, needle_len, end)); p = r + needle_len) {
      memcpy(new_str + (r - haystack_dup), str, str_len);
      if (replace_count) {
       (*replace_count)++;
      }
     }
     释放内存efree()用于替代free()
     efree(haystack_dup);
     efree(needle_dup);
    }
    return new_str;
   如果要查找的字符串长度不等于要替换的字符串长度
   } else {
    如果不区分大小写进行一下转换
      if (!case_sensitivity) {
     haystack_dup = estrndup(haystack, length);
     needle_dup = estrndup(needle, needle_len);
     php_strtolower(haystack_dup, length);
     php_strtolower(needle_dup, needle_len);
    }
         
      下边主要处理新字符串的长度 
    如果替换的长度小于查找的长度
    if (str_len < needle_len) {
       申请一块内存
     new_str = emalloc(length + 1);
    如果替换的长度大于查找的长度
    } else {
     int count = 0;
     char *o, *n, *endp;
               根据是否区分大小写来给查找字串还有替换字符串指针赋值
     if (case_sensitivity) {
      o = haystack;
      n = needle;
     } else {
      o = haystack_dup;
      n = needle_dup;
     }
     原字符串末尾指针
     endp = o + length;
                如果能找到查找的字符串,查到以后增加count的次数统计总共找到了多少处
     while ((o = php_memnstr(o, n, needle_len, endp))) {
      o += needle_len;
      count++;
     }
     如果一次没有找到
     if (count == 0) {
      /* Needle doesn't occur, shortcircuit the actual replacement. */
      if (haystack_dup) {
       efree(haystack_dup);
      }
      if (needle_dup) {
       efree(needle_dup);
      }
      新字符串等于原字符串的拷贝
      new_str = estrndup(haystack, length);
      if (_new_length) {
       *_new_length = length;
      }
      return new_str;
     } else {
        如果找到了,猜测是改变新字符串占内存的大小加上变化的大小
        函数safe_emalloc参数分别表示单元的个数,单元的大小,以及偏移。实际分配的空间大小就是size*count+偏移量。
      new_str = safe_emalloc(count, str_len - needle_len, length + 1);
     }
    }
            指针e、s分别指向新字符串的开始
    e = s = new_str;
            如果区分大小写
    if (case_sensitivity) {
     end = haystack + length;
          循环开始累加啦显示无关的加上然后加上替换的然后再加无关的然后再加替换的.......php_memnstr在后边解释
     for (p = haystack; (r = php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
      memcpy(e, p, r - p);
      e += r - p;
      memcpy(e, str, str_len);
      e += str_len;
      if (replace_count) {
       (*replace_count)++;
      }
     }
              如果最后循环还没有到达源字符串的末尾那么还要拷贝末尾的部分不然会丢掉源字符串最后一次匹配的后的部分    
     if (p < end) {
      memcpy(e, p, end - p);
      是否多余?
      e += end - p;
     }
    如果不区分大小写
    } else {
     end = haystack_dup + length;

     for (p = haystack_dup; (r = php_memnstr(p, needle_dup, needle_len, end)); p = r + needle_len) {
      memcpy(e, haystack + (p - haystack_dup), r - p);
      e += r - p;
      memcpy(e, str, str_len);
      e += str_len;
      if (replace_count) {
       (*replace_count)++;
      }
     }

     if (p < end) {
      memcpy(e, haystack + (p - haystack_dup), end - p);
      e += end - p;
     }
    }
            释放内存
    if (haystack_dup) {
     efree(haystack_dup);
    }
    if (needle_dup) {
     efree(needle_dup);
    }
            新串的长度
    *e = '';
    *_new_length = e - s;
            erealloc用于替代 realloc() 重新分配主存 为什么又分配一次啊
    new_str = erealloc(new_str, *_new_length + 1);
    return new_str;
   }
如果要查找的字符串的长度大于原串的长度那就啥就不做
} else if (needle_len > length) {
nothing_todo:
   *_new_length = length;
   new_str = estrndup(haystack, length);
   return new_str;
如果要查找的字符串长度等于原串的长度
} else {
   区分大小写,那么直接比较原串与查找的字符串,不相同哪么什么也不作
     if (case_sensitivity && memcmp(haystack, needle, length)) {
    goto nothing_todo;
    如果不区分大小写,那么都转成小写去比较
   } else if (!case_sensitivity) {
    char *l_haystack, *l_needle;

    l_haystack = estrndup(haystack, length);
    l_needle = estrndup(needle, length);

    php_strtolower(l_haystack, length);
    php_strtolower(l_needle, length);

    if (memcmp(l_haystack, l_needle, length)) {
     efree(l_haystack);
     efree(l_needle);
     goto nothing_todo;
    }
    efree(l_haystack);
    efree(l_needle);
   }
       无论是否区分大小写如果原串与要查找的相同那么新串赋给新串
   *_new_length = str_len;
   new_str = estrndup(str, str_len);

   if (replace_count) {
    (*replace_count)++;
   }
   return new_str;
}

}

类别:技术文章 | 阅读:296455 | 评论:0 | 标签:zend php

想收藏或者和大家分享这篇好文章→

“解读zend_api字符串替换之php_str_to_str_ex”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

taoCMS发布taoCMS 3.0.2(最后更新21年03月15日),请大家速速升级,欢迎大家试用和提出您宝贵的意见建议。

捐助与联系

☟请使用新浪微博联系我☟

☟在github上follow我☟

标签云