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.cc201
1 files changed, 201 insertions, 0 deletions
diff --git a/Build/source/texk/lcdf-typetools/liblcdf/straccum.cc b/Build/source/texk/lcdf-typetools/liblcdf/straccum.cc
new file mode 100644
index 00000000000..1f4020cfce4
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/liblcdf/straccum.cc
@@ -0,0 +1,201 @@
+// -*- related-file-name: "../include/lcdf/straccum.hh" -*-
+/*
+ * straccum.{cc,hh} -- build up strings with operator<<
+ * Eddie Kohler
+ *
+ * Copyright (c) 1999-2000 Massachusetts Institute of Technology
+ * Copyright (c) 2001-2006 Eddie Kohler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, subject to the conditions
+ * listed in the Click LICENSE file. These conditions include: you must
+ * preserve this copyright notice, and you cannot mention the copyright
+ * holders in advertising related to the Software without their permission.
+ * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
+ * notice is a summary of the Click LICENSE file; the license in that file is
+ * legally binding.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <lcdf/straccum.hh>
+#include <lcdf/vector.hh>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+StringAccum::StringAccum(const char *s)
+ : _s(0), _len(0), _cap(0)
+{
+ *this << s;
+}
+
+StringAccum::StringAccum(const String &s)
+ : _s(0), _len(0), _cap(0)
+{
+ *this << s;
+}
+
+#ifdef HAVE_PERMSTRING
+StringAccum::StringAccum(PermString s)
+ : _s(0), _len(0), _cap(0)
+{
+ *this << s;
+}
+#endif
+
+void
+StringAccum::make_out_of_memory()
+{
+ assert(_cap >= 0);
+ delete[] _s;
+ _s = reinterpret_cast<unsigned char *>(const_cast<char *>(String::out_of_memory_data()));
+ _cap = -1;
+ _len = 0;
+}
+
+bool
+StringAccum::grow(int want)
+{
+ // can't append to out-of-memory strings
+ if (_cap < 0)
+ return false;
+
+ int ncap = (_cap ? _cap * 2 : 128);
+ while (ncap <= want)
+ ncap *= 2;
+
+ unsigned char *n = new unsigned char[ncap];
+ if (!n) {
+ make_out_of_memory();
+ return false;
+ }
+
+ if (_s)
+ memcpy(n, _s, _cap);
+ delete[] _s;
+ _s = n;
+ _cap = ncap;
+ return true;
+}
+
+void
+StringAccum::append_utf8_hard(uint32_t ch)
+{
+ if (ch < 0x80)
+ append((unsigned char) ch);
+ else if (ch < 0x800) {
+ append((unsigned char) (0xC0 + ((ch >> 6) & 0x1F)));
+ append((unsigned char) (0x80 + (ch & 0x3F)));
+ } else if (ch < 0x10000) {
+ append((unsigned char) (0xE0 + ((ch >> 12) & 0x0F)));
+ append((unsigned char) (0x80 + ((ch >> 6) & 0x3F)));
+ append((unsigned char) (0x80 + (ch & 0x3F)));
+ } else if (ch < 0x110000) {
+ append((unsigned char) (0xF0 + ((ch >> 18) & 0x07)));
+ append((unsigned char) (0x80 + ((ch >> 12) & 0x3F)));
+ append((unsigned char) (0x80 + ((ch >> 6) & 0x3F)));
+ append((unsigned char) (0x80 + (ch & 0x3F)));
+ } else
+ append((unsigned char) '?');
+}
+
+const char *
+StringAccum::c_str()
+{
+ if (_len < _cap || grow(_len))
+ _s[_len] = '\0';
+ return reinterpret_cast<char *>(_s);
+}
+
+String
+StringAccum::take_string()
+{
+ int len = length();
+ if (len) {
+ int capacity = _cap;
+ return String::claim_string(reinterpret_cast<char *>(take_bytes()), len, capacity);
+ } else if (out_of_memory())
+ return String::out_of_memory_string();
+ else
+ return String();
+}
+
+StringAccum &
+operator<<(StringAccum &sa, long i)
+{
+ if (char *x = sa.reserve(24)) {
+ int len = sprintf(x, "%ld", i);
+ sa.forward(len);
+ }
+ return sa;
+}
+
+StringAccum &
+operator<<(StringAccum &sa, unsigned long u)
+{
+ if (char *x = sa.reserve(24)) {
+ int len = sprintf(x, "%lu", u);
+ sa.forward(len);
+ }
+ return sa;
+}
+
+StringAccum &
+operator<<(StringAccum &sa, double d)
+{
+ if (char *x = sa.reserve(256)) {
+ int len = sprintf(x, "%.12g", d);
+ sa.forward(len);
+ }
+ return sa;
+}
+
+StringAccum &
+StringAccum::snprintf(int n, const char *format, ...)
+{
+ va_list val;
+ va_start(val, format);
+ if (char *x = reserve(n + 1)) {
+#ifdef HAVE_VSNPRINTF
+ int len = vsnprintf(x, n + 1, format, val);
+#else
+ int len = vsprintf(x, format, val);
+ assert(len <= n);
+#endif
+ forward(len);
+ }
+ va_end(val);
+ return *this;
+}
+
+void
+StringAccum::append_break_lines(const String& text, int linelen, const String &leftmargin)
+{
+ if (text.length() == 0)
+ return;
+ const char* line = text.begin();
+ const char* ends = text.end();
+ linelen -= leftmargin.length();
+ for (const char* s = line; s < ends; s++) {
+ const char* start = s;
+ while (s < ends && isspace(*s))
+ s++;
+ const char* word = s;
+ while (s < ends && !isspace(*s))
+ s++;
+ if (s - line > linelen && start > line) {
+ *this << leftmargin;
+ append(line, start - line);
+ *this << '\n';
+ line = word;
+ }
+ }
+ if (line < text.end()) {
+ *this << leftmargin;
+ append(line, text.end() - line);
+ *this << '\n';
+ }
+}