3.3. smart_str API
这听起来似乎很奇怪,但是 C 语言几乎不提供操作字符串的方法(构建、连接、收缩、扩展、转换等等)。C 语言是低级通用语言,可以使用它来构建 API,去处理更多的特殊任务,比如字符串拼接。
注意
显然大家都知道我们谈论的是 ASCII 字符串,即字节。在这里没有 Unicode。
PHP 的smart_str
是一个 API,可以帮你构建字符串,特别是将字节块连接到字符串中。该 API 位于 PHP 的特殊 printf() API和 zend_string的旁边,以帮助进行字符串管理。
smart_str VS smart_string
这里有两个结构:
typedef struct {
char *c;
size_t len;
size_t a;
} smart_string;
typedef struct {
zend_string *s;
size_t a;
} smart_str;
就像你看到的,一个使用传统的 C 字符串(就像 char*/size_t
),另一个使用 PHP 的特殊 zend_string
结构。
我们将详细介绍后者:smart_str
,它和 zend_strings一起使用。这两个 API 实际上是一样的,只需注意一个以 smart_str_**()
开头,另一个则以 smart_string_***()
开头。不要混淆!
smart_str
API 在 Zend/zend_smart_str.h 中会详细介绍。(还有 .c 文件) 。
警告
smart_str
不要和smart_string
混淆。
基本的 API 使用
到目前为止,该 API 确实容易管理。你基本上可以堆栈分配smart_str
,并将其指针传递给 smart_str_***()
API函数,该函数可以为你管理嵌入式 zend_string
。生成你的字符串,使用它,然后释放它。这并没有很强大,对吧?
嵌入式的 zend_string
的分配方式是永久地还是请求绑定的,取决于你使用的最后一个扩展 API 参数:
smart_str my_str = {0};
smart_str_appends(&my_str, "Hello, you are using PHP version ");
smart_str_appends(&my_str, PHP_VERSION);
smart_str_appends(&my_str, "\n");
smart_str_appends(&my_str, "You are using ");
smart_str_append_unsigned(&my_str, zend_hash_num_elements(CG(function_table)));
smart_str_appends(&my_str, " PHP functions");
smart_str_0(&my_str);
/* 现在使用 my_str */
PHPWRITE(ZSTR_VAL(my_str.s), ZSTR_LEN(my_str.s));
/* 不要忘记释放它 */
smart_str_free(&my_str);
我们在这里使用了简单的 API,, 扩展名以 _ex()
结尾,并且允许你在使用底层 zend_string
时,告知它你想要永久或者请求绑定的分配。例子:
smart_str my_str = {0};
smart_str_appends_ex(&my_str, "Hello world", 1); /* 1表示永久分配*/
然后,根据你想要追加的,使用正确的 API 调用。如果追加一个传统的 C 字符串,可以使用 smart_str_appends(smart_str *dst, const char *src)
。如果使用一个二进制字符串,并且知道它的长度,则使用 smart_str_appendl(smart_str *dst, const char *src, size_t len)
。
不太特殊的smart_str_append(smart_str *dest, const zend_string *src)
简单地将 zend_string
追加到你的 smart_str
字符串。如果你使用其他 smart_str
,可使用smart_str_append_smart_str(smart_str *dst, const smart_str *src)
将它们合并起来。
smart_str 具体技巧
- 不要忘记调用
smart_str_0()
结束你的字符串。该函数在嵌入字符串的末尾增加了一个 NUL 字符,使它兼容 libc 字符串函数。 - 当你完成后,不要忘记使用
smart_str_free()
释放你的字符串。 smart_str
嵌入了zend_string
,并且允许共享,你之后可以在别处使用其引用计数。请访问 zend_string 专用章节了解更多。- 你可以使用
smart_str
分配。 看下smart_str_alloc()
和朋友们。 smart_str
在 PHP 中大量地使用。例如,PHP 的printf() 函数 在内部使用了smart_str
块。smart_str
肯定你需要掌握的简单结构。