+ case '"':
+ if (type == CYStringTypeDouble)
+ str << "\\\"";
+ else goto simple;
+ break;
+
+ case '\'':
+ if (type == CYStringTypeSingle)
+ str << "\\'";
+ else goto simple;
+ break;
+
+ case '\0':
+ if (mode != CYStringifyModeNative && value[1] >= '0' && value[1] <= '9')
+ str << "\\x00";
+ else
+ str << "\\0";
+ break;
+
+ default:
+ if (next >= 0x20 && next < 0x7f) simple:
+ str << *value;
+ else if (mode == CYStringifyModeNative)
+ str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value & 0xff);
+ else {
+ unsigned levels(1);
+ if ((next & 0x80) != 0)
+ while ((next & 0x80 >> ++levels) != 0);
+
+ unsigned point(next & 0xff >> levels);
+ while (--levels != 0)
+ point = point << 6 | uint8_t(*++value) & 0x3f;
+
+ if (point < 0x100)
+ str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << point;
+ else if (point < 0x10000)
+ str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << point;
+ else {
+ point -= 0x10000;
+ str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xd800 | point >> 0x0a);
+ str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xdc00 | point & 0x3ff);
+ }
+ }
+ } space = false; }
+
+ str << border;
+
+ if (parens)
+ str << ')';
+}
+
+void CYNumerify(std::ostringstream &str, double value) {
+ if (std::isinf(value)) {
+ if (value < 0)
+ str << '-';
+ str << "Infinity";
+ return;
+ }
+
+ char string[32];
+ // XXX: I want this to print 1e3 rather than 1000
+ sprintf(string, "%.17g", value);
+ str << string;
+}
+
+void CYOutput::Terminate() {
+ operator ()(';');
+ mode_ = NoMode;
+}
+
+CYOutput &CYOutput::operator <<(char rhs) {
+ if (rhs == ' ' || rhs == '\n')
+ if (pretty_)
+ operator ()(rhs);
+ else goto done;
+ else if (rhs == '\t')
+ if (pretty_)
+ for (unsigned i(0); i != indent_; ++i)
+ operator ()(" ", 4);
+ else goto done;
+ else if (rhs == '\r') {
+ if (right_) {
+ operator ()('\n');
+ right_ = false;
+ } goto done;
+ } else goto work;
+
+ right_ = true;
+ mode_ = NoMode;
+ goto done;
+
+ work:
+ if (mode_ == Terminated && rhs != '}') {
+ right_ = true;
+ operator ()(';');
+ }
+
+ if (rhs == ';') {
+ if (pretty_)
+ goto none;
+ else {
+ mode_ = Terminated;
+ goto done;
+ }
+ } else if (rhs == '+') {
+ if (mode_ == NoPlus)
+ operator ()(' ');
+ mode_ = NoPlus;
+ } else if (rhs == '-') {
+ if (mode_ == NoHyphen)
+ operator ()(' ');
+ mode_ = NoHyphen;
+ } else if (WordEndRange_[rhs]) {
+ if (mode_ == NoLetter)
+ operator ()(' ');
+ mode_ = NoLetter;
+ } else none:
+ mode_ = NoMode;
+
+ right_ = true;
+ operator ()(rhs);
+ done:
+ return *this;
+}
+
+CYOutput &CYOutput::operator <<(const char *rhs) {
+ size_t size(strlen(rhs));
+
+ if (size == 1)
+ return *this << *rhs;
+
+ if (mode_ == Terminated)
+ operator ()(';');
+ else if (
+ mode_ == NoPlus && *rhs == '+' ||
+ mode_ == NoHyphen && *rhs == '-' ||
+ mode_ == NoLetter && WordEndRange_[*rhs]
+ )
+ operator ()(' ');
+
+ char last(rhs[size - 1]);
+ if (WordEndRange_[last] || last == '/')
+ mode_ = NoLetter;
+ else
+ mode_ = NoMode;
+
+ right_ = true;
+ operator ()(rhs, size);
+ return *this;