Ben Griffin wrote:
For the last few weeks, we have been using XMLString::catString() for
fast appends to textnodes; something like:
//Only reachable by nodes that support setNodeValue()
append(DOMNode*& pt,XMLCh*& addon) {
if (addon != NULL and *addon != 0 ) {
XMLCh* orig = XMLString::replicate(pt->getNodeValue());
XMLString::catString(orig, addon);
pt->setNodeValue(orig);
XMLString::release(&orig);
XMLString::release(&addon);
}
}
However, we began to notice occasional crashes, and worked out that
XMLString::catString does not check for memory overflow.
How could it check for memory overflow? It has no idea how much memory
was allocated, and XMLString::replicate() doesn't allocated extra memory
anyway. Here's the documentation of the function:
/** Concatenates two strings.
*
* catString appends src to target and
* terminates the resulting string with a null character. The initial
character of
* src overwrites the terminating character of target.
* No overflow checking is performed when strings are copied or appended.
* The behavior of catString is undefined if source and destination
* strings overlap.
*
* @param target Null-terminated destination string
* @param src Null-terminated source string
*/
Is there a means of being able to guarantee additional memory for
catString, so that we do not have to transcode everything first?
There is no need to do any transcoding here, since all of the strings
are encoded in UTF-16.
You could use std::vector:
const XMLCh* const base = pt->getNodeValue();
const XMLSize_t baseLength = XMLString::strLength(base);
const XMLSize_t addonLength = XMLString::strLength(addon);
std::vector<XMLCh> buffer;
buffer.reserve(baseLength + addonLength + 1);
buffer.append(
buffer.end(),
base,
base + baseLength);
buffer.append(
buffer.end(),
addon,
addon + addonLength + 1);
pt->setNodeValue(&*buffer.begin());
XMLString::release(&addon);
Dave