summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/tanya/container/string.d52
1 files changed, 50 insertions, 2 deletions
diff --git a/source/tanya/container/string.d b/source/tanya/container/string.d
index 07d0c75..75298eb 100644
--- a/source/tanya/container/string.d
+++ b/source/tanya/container/string.d
@@ -5,7 +5,7 @@
/**
* UTF-8 string.
*
- * Copyright: Eugene Wissner 2016-2017.
+ * Copyright: Eugene Wissner 2017.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@@ -51,6 +51,54 @@ struct String
nothrow @trusted @nogc
{
this(allocator);
+
+ bool overflow;
+ auto size = mulu(str.length, 4, overflow);
+ assert(!overflow);
+
+ reserve(size);
+
+ auto s = data;
+ auto sourceLength = str.length;
+ for (auto c = str.ptr; sourceLength != 0; ++c, --sourceLength)
+ {
+ if (*c < 0x80)
+ {
+ *s++ = *c & 0x7f;
+ length_ += 1;
+ }
+ else if (*c < 0x800)
+ {
+ *s++ = 0xc0 | (*c >> 6) & 0xff;
+ *s++ = 0x80 | (*c & 0x3f);
+ length_ += 2;
+ }
+ else if (*c < 0xd800 || *c - 0xe000 < 0x2000)
+ {
+ *s++ = 0xe0 | (*c >> 12) & 0xff;
+ *s++ = 0x80 | ((*c >> 6) & 0x3f);
+ *s++ = 0x80 | (*c & 0x3f);
+ length_ += 3;
+ }
+ else if ((*c - 0xd800) < 2048 && sourceLength > 0 && *(c + 1) - 0xdc00 < 0x400)
+ { // Surrogate pair
+ dchar d = (*c - 0xd800) | ((*c++ - 0xdc00) >> 10);
+
+ *s++ = 0xf0 | (d >> 18);
+ *s++ = 0x80 | ((d >> 12) & 0x3f);
+ *s++ = 0x80 | ((d >> 6) & 0x3f);
+ *s++ = 0x80 | (d & 0x3f);
+ --sourceLength;
+ length_ += 4;
+ }
+ }
+ }
+
+ ///
+ @safe @nogc unittest
+ {
+ auto s = String("\u10437"w);
+ assert("\u10437" == s.get());
}
/// Ditto.
@@ -101,7 +149,7 @@ struct String
@nogc @safe unittest
{
auto s = String("Отказаться от вина - в этом страшная вина."d);
- assert("Отказаться от вина - в этом страшная вина." == s.get);
+ assert("Отказаться от вина - в этом страшная вина." == s.get());
}
/// Ditto.