Skip to content

Commit 4310ccc

Browse files
author
Julien Pauli
committed
smart_str API chapter
1 parent 4388df9 commit 4310ccc

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,100 @@
11
smart_str API
22
=============
33

4+
That may seem strange, but the C language offers nearly nothing to play with strings (build, concatenate, shrink,
5+
expand, transform, etc...). C is a low level general purpose language one can use to build APIs to deal with more
6+
specific tasks, such as string constructions.
7+
8+
.. note:: Obviously you all got that we talk about ASCII strings, aka bytes. No Unicode in there.
9+
10+
PHP's ``smart_str`` is an API that will help you build strings and especially concatenate chunks of bytes into strings.
11+
This API seats next to :doc:`PHP's special printf() APIs<printing_functions>` and :doc:`zend_string <zend_strings>` to
12+
help with strings management.
13+
14+
smart_str VS smart_string
15+
*************************
16+
17+
Here are the two structures::
18+
19+
typedef struct {
20+
char *c;
21+
size_t len;
22+
size_t a;
23+
} smart_string;
24+
25+
typedef struct {
26+
zend_string *s;
27+
size_t a;
28+
} smart_str;
29+
30+
Like you can see, one will work with traditionnal C strings (as ``char*/size_t``) and the other will make use of the
31+
PHP's specific ``zend_string`` structure.
32+
33+
We will detail the later: ``smart_str``, that works with :doc:`zend_strings`. Both APIs are exactly the same, simply
34+
note that one (the one we'll detail here) starts by ``smart_str_**()`` and the other by ``smart_string_***()``. Don't
35+
confuse !
36+
37+
The ``smart_str`` API is detailed into `Zend/zend_smart_str.h
38+
<https://github.com/php/php-src/blob/509f5097ab0b578adc311c720afcea8de266aadd/Zend/zend_smart_str.h>`_ (also the .c
39+
file).
40+
41+
.. warning:: ``smart_str`` is not to be confused with ``smart_string``.
42+
43+
Basic API usage
44+
***************
45+
46+
So far so good, that API is really easy to manage. You basically stack-allocate a ``smart_str``, and pass its pointer to
47+
``smart_str_***()`` API functions that manage the embedded ``zend_string`` for you. You build your string, use it, and
48+
then you free it. Nothing very strong in there right ?
49+
50+
The embedded ``zend_string`` will be allocated whether
51+
:doc:`permanently or request-bound <../../memory_management/zend_memory_manager>`, that depends on the last extended API
52+
parameter you'll use::
53+
54+
smart_str my_str = {0};
55+
56+
smart_str_appends(&my_str, "Hello, you are using PHP version ");
57+
smart_str_appends(&my_str, PHP_VERSION);
58+
59+
smart_str_appendc(&my_str, '\n');
60+
61+
smart_str_appends(&my_str, "You are using ");
62+
smart_str_append_unsigned(&my_str, zend_hash_num_elements(CG(function_table)));
63+
smart_str_appends(&my_str, " PHP functions");
64+
65+
smart_str_0(&my_str);
66+
67+
/* Use my_str now */
68+
PHPWRITE(ZSTR_VAL(my_str.s), ZSTR_LEN(my_str.s));
69+
70+
/* Don't forget to release/free it */
71+
smart_str_free(&my_str);
72+
73+
74+
We used here the simple API, the extended one ends with ``_ex()``, and allows you to tell if you want a persistent or
75+
a request-bound allocation for the underlying ``zend_string``. Example::
76+
77+
smart_str my_str = {0};
78+
79+
smart_str_appends_ex(&my_str, "Hello world", 1); /* 1 means persistent allocation */
80+
81+
Then, depending on what you want to append, you'll use the right API call. If you append a classical C string, you can
82+
use ``smart_str_appends()``. If you make use of a binary string, and thus know its length, then use
83+
``smart_str_appendl()``.
84+
85+
The less specific ``smart_str_append()`` simply appends a ``zend_string`` to your ``smart_str`` string. And if you come
86+
to play with others ``smart_str``, use ``smart_str_append_smart_str()`` to combine them together.
87+
88+
smart_str specific tricks
89+
*************************
90+
91+
* Never forget to finish your string with a call to ``smart_str_0()``. That puts a *NUL* char at the end of the embed
92+
string and make it compatible with libc string functions.
93+
* Never forget to free your string, with ``smart_str_free()``, once you're done with it.
94+
* ``smart_str`` embeds a ``zend_string``, and then allows you to share that later elsewhere playing with its reference
95+
counter. Please, visit the :doc:`zend_string dedicated chapter <zend_strings>` to know more about it.
96+
* You can play with ``smart_str`` allocations. Look at ``smart_str_alloc()`` and friends.
97+
* ``smart_str`` is heavilly used into PHP's heart. For example, PHP's
98+
:doc:`specific printf() functions <printing_functions>` internally use a ``smart_str`` buffer.
99+
* ``smart_str`` is definitely an easy structure you need to master.
4100

0 commit comments

Comments
 (0)