diff options
Diffstat (limited to 'Build/source/texk/lcdf-typetools/liblcdf/straccum.cc')
-rw-r--r-- | Build/source/texk/lcdf-typetools/liblcdf/straccum.cc | 57 |
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 |