summaryrefslogtreecommitdiff
path: root/Build/source/texk/lcdf-typetools/liblcdf/straccum.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/lcdf-typetools/liblcdf/straccum.cc')
-rw-r--r--Build/source/texk/lcdf-typetools/liblcdf/straccum.cc57
1 files changed, 40 insertions, 17 deletions
diff --git a/Build/source/texk/lcdf-typetools/liblcdf/straccum.cc b/Build/source/texk/lcdf-typetools/liblcdf/straccum.cc
index 7f82fc4ef11..e472d3c06d5 100644
--- a/Build/source/texk/lcdf-typetools/liblcdf/straccum.cc
+++ b/Build/source/texk/lcdf-typetools/liblcdf/straccum.cc
@@ -42,20 +42,25 @@
* <h3>Out-of-memory StringAccums</h3>
*
* When there is not enough memory to add requested characters to a
- * StringAccum object, the object becomes a special "out-of-memory" string.
- * Out-of-memory strings are contagious: the result of any concatenation
- * operation involving an out-of-memory string is another out-of-memory
- * string. Calling take_string() on an out-of-memory StringAccum returns an
- * out-of-memory String.
+ * StringAccum object, the object becomes a special "out-of-memory"
+ * StringAccum. Out-of-memory objects are contagious: the result of any
+ * concatenation operation involving an out-of-memory StringAccum is another
+ * out-of-memory StringAccum. Appending an out-of-memory String with "sa <<
+ * s" makes "sa" out-of-memory. (However, other usually-equivalent calls,
+ * such as "sa.append(s.begin(), s.end())", <em>do not</em> make "sa"
+ * out-of-memory.) Calling take_string() on an out-of-memory StringAccum
+ * returns an out-of-memory String.
*
- * Out-of-memory StringAccum objects nominally have zero characters.
+ * Out-of-memory StringAccum objects have length zero.
*/
+
void
StringAccum::assign_out_of_memory()
{
assert(_cap >= 0);
- delete[] _s;
+ if (_cap > 0)
+ delete[] (_s - MEMO_SPACE);
_s = reinterpret_cast<unsigned char *>(const_cast<char *>(String::out_of_memory_data()));
_cap = -1;
_len = 0;
@@ -68,19 +73,21 @@ StringAccum::grow(int want)
if (_cap < 0)
return false;
- int ncap = (_cap ? _cap * 2 : 128);
+ int ncap = (_cap ? (_cap + MEMO_SPACE) * 2 : 128) - MEMO_SPACE;
while (ncap <= want)
- ncap *= 2;
+ ncap = (ncap + MEMO_SPACE) * 2 - MEMO_SPACE;
- unsigned char *n = new unsigned char[ncap];
+ unsigned char *n = new unsigned char[ncap + MEMO_SPACE];
if (!n) {
assign_out_of_memory();
return false;
}
+ n += MEMO_SPACE;
- if (_s)
+ if (_s) {
memcpy(n, _s, _cap);
- delete[] _s;
+ delete[] (_s - MEMO_SPACE);
+ }
_s = n;
_cap = ncap;
return true;
@@ -123,12 +130,28 @@ StringAccum::c_str()
}
void
-StringAccum::append_unsafe_data(const char *s, int len)
+StringAccum::append_internal_data(const char *s, int len)
{
- char *copy = new char[len];
- memcpy(copy, s, len);
- append_safe_data(copy, len);
- delete[] copy;
+ if (out_of_memory())
+ /* do nothing */;
+ else if (!_s || _len + len <= _cap)
+ append_external_data(s, len);
+ else {
+ unsigned char *old_s = _s;
+ int old_len = _len;
+ int old_cap = _cap;
+
+ _s = 0;
+ _len = 0;
+ _cap = 0;
+
+ if (char *new_s = extend(old_len + len)) {
+ memcpy(new_s, old_s, old_len);
+ memcpy(new_s + old_len, s, len);
+ }
+
+ delete[] (old_s - MEMO_SPACE);
+ }
}
String