The template for a string that may grow in size is:
unsigned long new_size = <new_size_calculation>; resize(new_size + 1); unsigned long buff_size = buffSize(); <manipulate string data here> size_and_flags = (size_and_flags & ~STR_SIZE_MASK) | new_size; markExtraBuffer(buff_size);
The resize()
will resize the buffer if it is smaller than
new_size
and will allocate new data if data = NULL
.
The resulting buff_size
is stored away for later use. It is
important to capture buff_size
before changing
size_and_flags
or data
.
Next, the function can manipulate data
and change the string's length to
new_size
. There is a good chance that one of these two
operations corrupted our buffer size data at the end of the string
(if it exists), so the function calls markExtraBuffer()
to restore it. Note
that even if there is no room for buff_size
at the end of the
string data, calling markExtraBuffer()
is safe.
For a string that can only get smaller, you can use the previous template but this one is slightly more efficient:
if (data) { unsigned long new_size = <new_size_calculation>; unsigned long buff_size = buffSize(); <manipulate string data here> size_and_flags = (size_and_flags & ~STR_SIZE_MASK) | new_size; markExtraBuffer(buff_size); }
Since the string will never exceed the current buffer, the call to
resize()
is not needed. Because resize()
was skipped, however, the
function needs to ensure that data != NULL
. The rest of the code is the same.
For a string that does not change in size, either of the above templates will work but this one is slightly more efficient:
if (data) { <manipulate string data here> }
Here all of the code to adjust the string length and the buffer size is
no longer needed, but the function still needs to check for data != NULL
.