+CYUTF8String CYCastUTF8String(NSString *value) {
+ NSData *data([value dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO]);
+ return CYUTF8String(reinterpret_cast<const char *>([data bytes]), [data length]);
+}
+
+/* JavaScript Stringify {{{ */
+void CYStringify(std::ostringstream &str, const char *data, size_t size) {
+ unsigned quot(0), apos(0);
+ for (const char *value(data), *end(data + size); value != end; ++value)
+ if (*value == '"')
+ ++quot;
+ else if (*value == '\'')
+ ++apos;
+
+ bool single(quot > apos);
+
+ str << (single ? '\'' : '"');
+
+ for (const char *value(data), *end(data + size); value != end; ++value)
+ switch (*value) {
+ case '\\': str << "\\\\"; break;
+ case '\b': str << "\\b"; break;
+ case '\f': str << "\\f"; break;
+ case '\n': str << "\\n"; break;
+ case '\r': str << "\\r"; break;
+ case '\t': str << "\\t"; break;
+ case '\v': str << "\\v"; break;
+
+ case '"':
+ if (!single)
+ str << "\\\"";
+ else goto simple;
+ break;
+
+ case '\'':
+ if (single)
+ str << "\\'";
+ else goto simple;
+ break;
+
+ default:
+ if (*value < 0x20 || *value >= 0x7f)
+ str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value);
+ else simple:
+ str << *value;
+ }
+
+ str << (single ? '\'' : '"');
+}
+/* }}} */
+